На всякий случай сюда положу - мало кому захочется сделать полноценный мониторинг Ютуб канала Отображение количества просмотров, лайков, дизлайков, коментариев: за текущие 5 минут (M+) за предыдущие 5 минут (M-) за текущий час (H+) за предыдущий час (H-) за текущие сутки (D+) за предыдущие сутки (D-) счетчик подписчиков количество видео на канале световая индикация в случае появления нового комментария (максимальное время обновления 5 минут) возможность отключение дисплея сенсорный интерфейс возможность отключения питания (сохранение данных за час и сутки) Код разбит на отдельные разделы. Все написано в среде Arduino IDE Код (C++): #define RedL 17 #define GreL 16 #define BluL 2 #include <WiFi.h> #include <HTTPClient.h> #include "time.h" #include <SPI.h> #include <U8g2lib.h> #include <EEPROM.h> U8G2_SSD1309_128X64_NONAME0_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 5, /* dc=*/ 4, /* reset=*/ 15); const char* ssid = ""; // ssid const char* password = ""; // пароль const char* ntpServer = "pool.ntp.org"; // сервер времени const long gmtOffset_sec = 10800; // 3600*3=10800 (UTC+3) Москва const int daylightOffset_sec = 0; // переход на летнее время String youtubeApiKey = ""; String youtubeNameChammel = "UCWnYJoytogNmXg4BHZV8XLg"; String AllVideoList = ""; // Список всех видео на канале uint32_t AllVideoCount = 0; // Количество видео на канале // Переменные для отображения полученной статистики uint32_t ShowwC = 0; // Количество просмотров uint32_t ShowlC = 0; // Количество лайков uint32_t ShowdC = 0; // Количество дизлайков uint32_t ShowcC = 0; // Количество комментариев uint32_t OldShowcC = 0; // Переменная для проверки изменения количества комментариев uint32_t ShowsC = 0; // Количество подписчиков uint32_t ShowvC = 0; // Количество видео для обработки // Агрегатные переменные uint32_t wC = 0; // Количество просмотров uint32_t lC = 0; // Количество лайков 2,3 uint32_t dC = 0; // Количество дизлайков 4,6 uint32_t cC = 0; // Количество комментариев 6,7 // Переменные для отображения разницы между текущим и предыдущим int32_t DwC = 0; // Дельта Количество просмотров [1] - [0] int32_t DlC = 0; // Дельта Количество лайков [3] - [2] int32_t DdC = 0; // Дельта Количество дизлайков [5] - [4] int32_t DcC = 0; // Дельта Количество комментариев [7] - [6] uint32_t Last5Min [] = {0, 0, 0, 0, 0, 0 , 0, 0}; // Статистика за последние 5 минут uint32_t Last1Hour [] = {0, 0, 0, 0, 0, 0, 0, 0}; int Last1HourADDR = 0; // Адрес хранения массива во флеше uint8_t *Last1HourPTR = (uint8_t*)&Last1Hour; // Указатель на массив Last1Hour uint32_t Last1Day [] = {0, 0, 0, 0, 0, 0, 0, 0}; int Last1DayADDR = 32; // Адрес хранения массива во флеше uint8_t *Last1DayPTR = (uint8_t*)&Last1Day; // Указатель на массив Last1Day boolean wifiOK = false; void wifiShow () { u8g2.setFont(u8g2_font_open_iconic_all_1x_t); if (wifiOK) { u8g2.setCursor(119, 9); u8g2.write(253); // wifi OK } else { u8g2.setCursor(119, 9); u8g2.write(121); // wifi no OK } } boolean refreshOK = false; void refreshShow () { u8g2.setFont(u8g2_font_open_iconic_all_1x_t); if (refreshOK) { u8g2.setCursor(119, 20); u8g2.write(243); // идет обновление данных } else { u8g2.setCursor(119, 20); u8g2.write(115); // обновление данных закончено } } TaskHandle_t Task1; TaskHandle_t Task2; #include "ESP32_Task1code.h" #include "ESP32_Task2code.h" void setup() { Serial.begin(115200); EEPROM.begin(64); pinMode (RedL, OUTPUT); pinMode (GreL, OUTPUT); pinMode (BluL, OUTPUT); u8g2.begin(); u8g2.setFont(u8g2_font_profont12_mr); // Устанавливаем шрифт (высота 8 пикселей) u8g2.clearBuffer(); // очищаем память дисплея и картинку u8g2.sendBuffer(); // обновляем дисплей u8g2.setCursor(0, 8); u8g2.print(ssid); wifiShow (); u8g2.setFont(u8g2_font_profont12_mr); u8g2.sendBuffer(); u8g2.setCursor(0, 19); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); u8g2.print("."); u8g2.sendBuffer(); } u8g2.clearBuffer(); u8g2.setCursor(0, 8); u8g2.print(WiFi.localIP()); // Печатаем IP - шник wifiOK = true; wifiShow (); u8g2.sendBuffer(); delay(5000); //восстанавливаем данные за час и сутки если было отключение питания for (byte i = 0; i < 32; i++) { *(Last1HourPTR + i) = EEPROM.read(Last1HourADDR + i); } for (byte i = 0; i < 32; i++) { *(Last1DayPTR + i) = EEPROM.read(Last1DayADDR + i); } configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); // Синхронизируем внутренние часы с временем из интернета //delay(2000); xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, &Task1, 0); //ядро 0 delay(500); xTaskCreatePinnedToCore(Task2code, "Task2", 10000, NULL, 1, &Task2, 1); //ядро 1 delay(500); } void loop() { }
ESP32_Task1code.h Код (C++): // Ядро 0 отображаем часы, данные на дисплее, опрашиваем сенсорные кнопки #include "ESP32_fourBtSens.h" uint8_t ShowDisp = 0; // Переменная для обновления дисплея 0.5 сек boolean dot = false; // Точки на часах const uint8_t Yico[] = {0x00, 0x7E, 0xF7, 0xE7, 0xC7, 0xE7, 0xF7, 0x7E}; // Иконка Ютуба uint8_t sectionI = 0; // Секция отображения const char *sectionS[] = { // Массив секции для отображения "M+", // 0 статистика за 5 минут "M-", // 1 статистика за 1 час "H+", // 2 статистика за 1 день "H-", // 0 статистика за 5 минут "D+", // 1 статистика за 1 час "D-", // 2 статистика за 1 день }; boolean powerSave = false; // Отображаем / спим uint8_t BtSt1and3 = 0; // Фильтр для 2-х нажатых кнопок // Распечатываем страничку с Ютубе Аналитикой (общие параметры) void printYoutubeA() { struct tm timeinfo; // получаем дату и время if (!getLocalTime(&timeinfo)) { Serial.println("Failed to obtain time"); return; } if (sectionI == 0) { // рассчитываем дельту для странички за последние 5 минут (M+) DwC = ShowwC - Last5Min [1]; // Дельта Количество просмотров DlC = ShowlC - Last5Min [3]; // Дельта Количество лайков DdC = ShowdC - Last5Min [5]; // Дельта Количество дизлайков DcC = ShowcC - Last5Min [7]; // Дельта Количество комментариев } if (sectionI == 1) { // рассчитываем дельту для странички за предудущие за последними 5 минут (M-) DwC = Last5Min [1] - Last5Min [0]; // Дельта Количество просмотров DlC = Last5Min [3] - Last5Min [2]; // Дельта Количество лайков DdC = Last5Min [5] - Last5Min [4]; // Дельта Количество дизлайков DcC = Last5Min [7] - Last5Min [6]; // Дельта Количество комментариев } if (sectionI == 2) { // рассчитываем дельту для странички за текущий час (H+) DwC = ShowwC - Last1Hour [1]; // Дельта Количество просмотров DlC = ShowlC - Last1Hour [3]; // Дельта Количество лайков DdC = ShowdC - Last1Hour [5]; // Дельта Количество дизлайков DcC = ShowcC - Last1Hour [7]; // Дельта Количество комментариев } if (sectionI == 3) { // рассчитываем дельту для странички за предыдущий час (H-) DwC = Last1Hour [1] - Last1Hour [0]; // Дельта Количество просмотров DlC = Last1Hour [3] - Last1Hour [2]; // Дельта Количество лайков DdC = Last1Hour [5] - Last1Hour [4]; // Дельта Количество дизлайков DcC = Last1Hour [7] - Last1Hour [6]; // Дельта Количество комментариев } if (sectionI == 4) { // рассчитываем дельту для странички за текущие сутки (D+) DwC = ShowwC - Last1Day [1]; // Дельта Количество просмотров DlC = ShowlC - Last1Day [3]; // Дельта Количество лайков DdC = ShowdC - Last1Day [5]; // Дельта Количество дизлайков DcC = ShowcC - Last1Day [7]; // Дельта Количество комментариев } if (sectionI == 5) { // рассчитываем дельту для странички за предудущие сутки (D-) DwC = Last1Day [1] - Last1Day [0]; // Дельта Количество просмотров DlC = Last1Day [3] - Last1Day [2]; // Дельта Количество лайков DdC = Last1Day [5] - Last1Day [4]; // Дельта Количество дизлайков DcC = Last1Day [7] - Last1Day [6]; // Дельта Количество комментариев } u8g2.clearBuffer(); // очищаем экран wifiShow (); // отображаем статус Wi Fi refreshShow (); // отображаем процесс обновления данных u8g2.setFont(u8g2_font_open_iconic_human_1x_t); u8g2.setCursor(0, 8); u8g2.print(char(64)); // ico просмотры u8g2.setCursor(0, 52); u8g2.print(char(68)); // ico подписчики u8g2.setFont(u8g2_font_open_iconic_www_1x_t); u8g2.setCursor(0, 19); u8g2.print("I"); // ico дайки u8g2.setCursor(0, 30); u8g2.print("R"); // ico дизлайки u8g2.setCursor(0, 41); u8g2.print("K"); // ico комментарии u8g2.drawXBMP(0, 56, 8, 8, Yico); // ico Ютуба u8g2.setFont(u8g2_font_profont12_mr); u8g2.setCursor(12, 8); u8g2.print(ShowwC); // Количество просмотров u8g2.print(" +"); u8g2.print(DwC); u8g2.setCursor(12, 19); u8g2.print(ShowlC); // Количество лайков u8g2.print(" +"); u8g2.print(DlC); u8g2.setCursor(12, 30); u8g2.print(ShowdC); // Количество дизлайков u8g2.print(" +"); u8g2.print(DdC); u8g2.setCursor(12, 41); u8g2.print(ShowcC); // Количество комментариев u8g2.print(" +"); u8g2.print(DcC); u8g2.setCursor(12, 52); u8g2.print(ShowsC); // Количество подписчиков u8g2.setCursor(12, 64); u8g2.print(ShowvC); // Количество видео в файле u8g2.setCursor(45, 64); // Распечатываем дату и время u8g2.print(&timeinfo, "%H"); if (dot) u8g2.print(':'); else u8g2.print(' '); dot = !dot; u8g2.print(&timeinfo, "%M"); //u8g2.print(':'); //u8g2.print(&timeinfo, "%S"); u8g2.print(' '); u8g2.print(&timeinfo, "%d"); u8g2.print('.'); u8g2.print(&timeinfo, "%m"); //u8g2.print('.'); //u8g2.print(&timeinfo, "%Y"); u8g2.print(" "); u8g2.print(sectionS[sectionI]); u8g2.sendBuffer(); // отображаем содержимое экрана } void Task1code( void * pvParameters ) { for (;;) { //бесконечный цикл readBtSens (); // обновляем переменную StBt if (bitRead(StBt, 0) && !bitRead(StBt, 1)) { // Обрабатываем только одно прикосновение 1-я кнопка bitSet(StBt, 1); // пока не отпустят кнопку - больше не реагируем if (sectionI != 5) sectionI++; // меню листать вперед } if (bitRead(StBt, 2) && !bitRead(StBt, 3)) { // Обрабатываем только одно прикосновение 2-я кнопка bitSet(StBt, 3); // пока не отпустят кнопку - больше не реагируем digitalWrite(BluL,LOW); // Гасим светодиод комментариев } if (bitRead(StBt, 4) && !bitRead(StBt, 5)) { // Обрабатываем только одно прикосновение 3-я кнопка bitSet(StBt, 5); // пока не отпустят кнопку - больше не реагируем if (sectionI != 0) sectionI--; // меню листать назад } if (bitRead(StBt, 6) && !bitRead(StBt, 7)) { // Обрабатываем только одно прикосновение 4-я кнопка bitSet(StBt, 7); // пока не отпустят кнопку - больше не реагируем // заначка } if ((StBt == B00110011) && (BtSt1and3 == 0 )) { // Нажаты 1 и 3 кнопка одновременно вкл/выкл дисплея powerSave = !powerSave; u8g2.setPowerSave(powerSave); BtSt1and3 = 100; // Не реагируем 1 секунду } else { if (BtSt1and3 != 0) BtSt1and3--; } delay(10); ShowDisp ++; // Обновляем содержимое дисплея 1 раз в 0.5 сек if (ShowDisp >= 50) { printYoutubeA(); ShowDisp = 0; } } }
ESP32_Task2code.h Код (C++): String httpGETRequest(const char* serverName) { HTTPClient http; // Your IP address with path or Domain name with URL path http.begin(serverName); // Send HTTP POST request int httpResponseCode = http.GET(); String payload = "{}"; if (httpResponseCode > 0) { //Serial.print("HTTP Response code: "); //Serial.println(httpResponseCode); payload = http.getString(); } else { //Serial.print("Error code: "); //Serial.println(httpResponseCode); } // Free resources http.end(); return payload; } #include "ESP32_youtubeA.h" // набор функций для сбора статистики Ютуба // таймер 1 минута int Now1Min = 0; int Old1Min = 0; // таймер 5 минут int Old5Min = 0; // таймер 10 минут int Old10Min = 0; // таймер 1 час int Now1Hour = 0; int Old1Hour = 0; // таймер 1 день int Now1Day = 0; int Old1Day = 0; void Task2code( void * pvParameters ) { refreshOK = true; getYoutubeChanel(); // Получаем количество подписчиков makeVideoList(); // Создаем лист с ID видео на канале refreshA (); // Обновляем статистику ShowwC = wC; // Количество просмотров - отдаем для отображения ShowlC = lC; // Количество лайков - отдаем для отображения ShowdC = dC; // Количество дизлайков - отдаем для отображения ShowcC = cC; // Количество комментариев - отдаем для отображения // зануляем 5 минутную статистику (данные будут доступны через 5+5 минут) Last5Min [1] = ShowwC; Last5Min [3] = ShowlC; Last5Min [5] = ShowdC; Last5Min [7] = ShowcC; Last5Min [0] = ShowwC; Last5Min [2] = ShowlC; Last5Min [4] = ShowdC; Last5Min [6] = ShowcC; struct tm timeinfo; // получаем дату и время if (!getLocalTime(&timeinfo)) { Serial.println("Failed to obtain time"); return; } // все события не должны произойти при первом включении Now1Min = timeinfo.tm_min; Old1Min = Now1Min; Now1Hour = timeinfo.tm_hour; Old1Hour = Now1Hour; Now1Day = timeinfo.tm_mday; Old1Day = Now1Day; refreshOK = false; for (;;) { //бесконечный цикл struct tm timeinfo; // получаем дату и время if (!getLocalTime(&timeinfo)) { Serial.println("Failed to obtain time"); return; } Now1Min = timeinfo.tm_min; Now1Hour = timeinfo.tm_hour; Now1Day = timeinfo.tm_mday; if (Now1Min != Old1Min) { // код который срабатывает 1 раз 1 минуту //Serial.println("Now1Min"); Old1Min = Now1Min; } if ((Now1Min % 5 == 0) && (Now1Min != Old5Min)) { // код который срабатывает 1 раз в 5 минут (5 минут статистика) //Serial.println("Now5Min"); Old5Min = Now1Min; refreshOK = true; // Отображаем на дисплее запрос данных OldShowcC = ShowcC; // Сохраняем текущее значение комментариев getYoutubeChanel(); // Получаем количество подписчиков // обнуляем переменные для промежуточных расчетов wC = 0; // Количество просмотров lC = 0; // Количество лайков dC = 0; // Количество дизлайков cC = 0; // Количество комментариев // обновляем статистику по всем видео канала refreshA (); // Обновляем статистику // сохраняем предыдущую статистику (-10 минут) Last5Min [0] = Last5Min [1]; // Количество просмотров OLD Last5Min [2] = Last5Min [3]; // Количество просмотров OLD Last5Min [4] = Last5Min [5]; // Количество лайков OLD Last5Min [6] = Last5Min [7]; // Количество комментариев OLD // сохраняем сохраняем текущую статистику (последние -5 минут) Last5Min [1] = ShowwC; // Количество просмотров NEW Last5Min [3] = ShowlC; // Количество просмотров NEW Last5Min [5] = ShowdC; // Количество лайков NEW Last5Min [7] = ShowcC; // Количество комментариев NEW // обновляем данные 0 минут ShowwC = wC; // Количество просмотров - отдаем для отображения ShowlC = lC; // Количество лайков - отдаем для отображения ShowdC = dC; // Количество дизлайков - отдаем для отображения ShowcC = cC; // Количество комментариев - отдаем для отображения // если написали/удалили новый коментарий зажигаем синий светодиод if (OldShowcC != ShowcC) digitalWrite (BluL,HIGH); refreshOK = false; // Данные получены } if ((Now1Min % 10 == 0) && (Now1Min != Old10Min)) { // код который срабатывает 1 раз в 10 минут (прогноз погоды) Serial.println("Now10Min"); Old10Min = Now1Min; } if (Now1Hour != Old1Hour) { // код который срабатывает 1 раз в час (статистика за 1 час) Serial.println("Now1Hour"); Old1Hour = Now1Hour; // сохраняем предыдущую статистику (предыдущий час) Last1Hour [0] = Last1Hour [1]; // Количество просмотров OLD Last1Hour [2] = Last1Hour [3]; // Количество просмотров OLD Last1Hour [4] = Last1Hour [5]; // Количество лайков OLD Last1Hour [6] = Last1Hour [7]; // Количество комментариев OLD // сохраняем сохраняем текущую статистику (текущий час) Last1Hour [1] = ShowwC; // Количество просмотров NEW Last1Hour [3] = ShowlC; // Количество просмотров NEW Last1Hour [5] = ShowdC; // Количество лайков NEW Last1Hour [7] = ShowcC; // Количество комментариев NEW // сохраняем статиситку за час во внутреннюю флеш память for (uint8_t i = 0; i < 32; i++) { EEPROM.write((Last1HourADDR + i), (*(Last1HourPTR + i))); EEPROM.commit(); } } if (Now1Day != Old1Day) { // код который срабатывает 1 раз в сутки (статистика за 1 сутки) // синхронизируем внутренние часы со временем из интернет configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); Serial.println("Now1Day"); Old1Day = Now1Day; // сохраняем предыдущую статистику (предыдущие сутки до 00:00) Last1Day [0] = Last1Day [1]; // Количество просмотров OLD Last1Day [2] = Last1Day [3]; // Количество просмотров OLD Last1Day [4] = Last1Day [5]; // Количество лайков OLD Last1Day [6] = Last1Day [7]; // Количество комментариев OLD // сохраняем сохраняем текущую статистику (текущие сутки до 00:00) Last1Day [1] = ShowwC; // Количество просмотров NEW Last1Day [3] = ShowlC; // Количество просмотров NEW Last1Day [5] = ShowdC; // Количество лайков NEW Last1Day [7] = ShowcC; // Количество комментариев NEW // сохраняем статиситку за день во внутреннюю флеш память for (uint8_t i = 0; i < 32; i++) { EEPROM.write((Last1DayADDR + i), (*(Last1DayPTR + i))); EEPROM.commit(); } } delay(10); } }
ESP32_fourBtSens.h Код (C++): #define bt1 14 //Кнопка 1 GPIO 14 #define bt2 27 //Кнопка 2 GPIO 27 #define bt3 12 //Кнопка 3 GPIO 12 #define bt4 13 //Кнопка 4 GPIO 13 uint8_t BtF1 = 1; // Фильтр от ложных срабатываний Кнопка 1 uint8_t BtF2 = 1; // Фильтр от ложных срабатываний Кнопка 2 uint8_t BtF3 = 1; // Фильтр от ложных срабатываний Кнопка 3 uint8_t BtF4 = 1; // Фильтр от ложных срабатываний Кнопка 4 uint8_t StBt = 0; // переменная для хранения статуса 4х кнопок младший бит нажата/старший обработана 2х4=8 const uint8_t SensThreshold = 50; //порог срабатывания сенсора const uint8_t filtrCount = 3; // сколько проверок выполнять для определения состояния кнопки (max7 bit) // если будут самонажиматься кнопки - увеличить число (максимум до 7) // возвращаем статус 4х кнопок младший бит нажата/старший обработана 2х4=8 void readBtSens () { // Если прикоснулись к 1-й сенсорной кнопке if ((touchRead(bt1)) < SensThreshold) { if (bitRead(BtF1, filtrCount)) bitSet(StBt, 0); else BtF1 <<= 1; } else { // Не касаемся сенсорной кнопки if (bitRead(BtF1, 0)) { bitClear(StBt, 0); bitClear(StBt, 1); } else BtF1 >>= 1; } // Если прикоснулись к 2-й сенсорной кнопке if ((touchRead(bt2)) < SensThreshold) { if (bitRead(BtF2, filtrCount)) bitSet(StBt, 2); else BtF2 <<= 1; } else { // Не касаемся сенсорной кнопки if (bitRead(BtF2, 0)) { bitClear(StBt, 2); bitClear(StBt, 3); } else BtF2 >>= 1; } // Если прикоснулись к 3-й сенсорной кнопке if ((touchRead(bt3)) < SensThreshold) { if (bitRead(BtF3, filtrCount)) bitSet(StBt, 4); else BtF3 <<= 1; } else { // Не касаемся сенсорной кнопки if (bitRead(BtF3, 0)) { bitClear(StBt, 4); bitClear(StBt, 5); } else BtF3 >>= 1; } // Если прикоснулись к 4-й сенсорной кнопке if ((touchRead(bt4)) < SensThreshold) { if (bitRead(BtF4, filtrCount)) bitSet(StBt, 6); else BtF4 <<= 1; } else { // Не касаемся сенсорной кнопки if (bitRead(BtF4, 0)) { bitClear(StBt, 6); bitClear(StBt, 7); } else BtF4 >>= 1; } }
ESP32_youtubeA.h Код (C++): // Создание полного списка видео void makeVideoList () { if (WiFi.status() == WL_CONNECTED) { wifiOK = true; AllVideoList = ""; // Обнуляем существующий список видео AllVideoCount = 0; // Обнуляем количество найденых и внесенных видео в файле int32_t findStart = 0; int32_t findNext = 0; int32_t findEnd = 0; // Получаем ссылку на плейлист "загрузки" String serverPath = "https://www.googleapis.com/youtube/v3/channels?part=contentDetails&id=" + youtubeNameChammel + "&key=" + youtubeApiKey; String S = httpGETRequest(serverPath.c_str()); String uploads = ""; findStart = S.indexOf("\"uploads", findNext); findNext = findStart + 12; findEnd = S.indexOf("\"", findNext); uploads = S.substring(findNext, findEnd); delay(25); // Получаем и сохраняем ID первые 30 видео и получаем ссылку на следующие 30 serverPath = "https://www.googleapis.com/youtube/v3/playlistItems?playlistId=" + uploads + "&maxResults=30&key=" + youtubeApiKey + "&part=contentDetails"; S = httpGETRequest(serverPath.c_str()); // херачим найденые видео в список по 11 символов + запятая findStart = 0; findNext = 0; findEnd = 0; findStart = S.indexOf("\"videoId", findNext); while ( findStart != -1) { findNext = findStart + 12; findEnd = S.indexOf("\"", findNext); AllVideoList = AllVideoList + S.substring(findNext, findEnd); AllVideoList = AllVideoList + ","; AllVideoCount++; ShowvC = AllVideoCount; //отдаем на отображение findStart = S.indexOf("\"videoId", findEnd); } // получаем ссылку на следующую страничку String nextPageToken = ""; findStart = 0; findNext = 0; findEnd = 0; findStart = S.indexOf("\"nextPageToken", findNext); if (findStart == -1) return; //на канале меньше 30 видео - миссия комплит findNext = findStart + 18; findEnd = S.indexOf("\"", findNext); nextPageToken = S.substring(findNext, findEnd); label: serverPath = "https://www.googleapis.com/youtube/v3/playlistItems?playlistId=" + uploads + "&maxResults=30&key=" + youtubeApiKey + "&part=contentDetails&pageToken=" + nextPageToken; S = httpGETRequest(serverPath.c_str()); // херачим найденые видео в список по 11 символов + запятая findStart = 0; findNext = 0; findEnd = 0; findStart = S.indexOf("\"videoId", findNext); while ( findStart != -1) { findNext = findStart + 12; findEnd = S.indexOf("\"", findNext); AllVideoList = AllVideoList + S.substring(findNext, findEnd); AllVideoList = AllVideoList + ","; AllVideoCount++; ShowvC = AllVideoCount; //отдаем на отображение findStart = S.indexOf("\"videoId", findEnd); } // получаем ссылку на следующую страничку nextPageToken = ""; findStart = 0; findNext = 0; findEnd = 0; findStart = S.indexOf("\"nextPageToken", findNext); if (findStart == -1) return; // nextPageToken не найден - дошли до последней странички findNext = findStart + 18; findEnd = S.indexOf("\"", findNext); nextPageToken = S.substring(findNext, findEnd); delay(25); goto label; } else { // нет подключения wifiOK = false; } } // Запрос статистики по каналу void getYoutubeChanel() { if (WiFi.status() == WL_CONNECTED) { wifiOK = true; // информация о количестве подписчиков String serverPath = "https://www.googleapis.com/youtube/v3/channels?part=statistics&id=" + youtubeNameChammel + "&key=" + youtubeApiKey; // Запрашиваем строку json String S = httpGETRequest(serverPath.c_str()); // Получаем количество подписчиков String s; int32_t findStart = 0; int32_t findNext = 0; int32_t findEnd = 0; findStart = S.indexOf("\"subscriberCount", findNext); findNext = findStart + 20; findEnd = S.indexOf("\"", findNext); s = S.substring(findNext, findEnd); ShowsC = s.toInt(); delay(25); } else { // нет подключения wifiOK = false; } } // Запрос агрегатной статистики от 1 до 50-ти видео // Входной параметр сторока вида: idvideo1,idvideo2,....,idvideo50 void getYoutubeVideoS(String listVideo) { if (WiFi.status() == WL_CONNECTED) { wifiOK = true; String serverPath = "https://www.googleapis.com/youtube/v3/videos?id=" + listVideo + "&key=" + youtubeApiKey + "&part=statistics"; String S = httpGETRequest(serverPath.c_str()); String s = ""; int32_t findStart = 0; int32_t findNext = 0; int32_t findEnd = 0; uint32_t viewCount = 0; //парсим количество просмотров findStart = S.indexOf("\"viewCount", findNext); while ( findStart != -1) { findNext = findStart + 14; findEnd = S.indexOf("\"", findNext); s = S.substring(findNext, findEnd); viewCount = viewCount + s.toInt(); //Serial.println(s.toInt()); findStart = S.indexOf("\"viewCount", findEnd); } s = ""; findStart = 0; findNext = 0; findEnd = 0; uint32_t likeCount = 0; //парсим количество лайков findStart = S.indexOf("\"likeCount", findNext); while ( findStart != -1) { findNext = findStart + 14; findEnd = S.indexOf("\"", findNext); s = S.substring(findNext, findEnd); likeCount = likeCount + s.toInt(); //Serial.print(s.toInt()); Serial.print(" - "); findStart = S.indexOf("\"likeCount", findNext); } s = ""; findStart = 0; findNext = 0; findEnd = 0; uint32_t dislikeCount = 0; //парсим количество дизлайков findStart = S.indexOf("\"dislikeCount", findNext); while ( findStart != -1) { findNext = findStart + 17; findEnd = S.indexOf("\"", findNext); s = S.substring(findNext, findEnd); dislikeCount = dislikeCount + s.toInt(); //Serial.print(s.toInt()); Serial.print(" - "); findStart = S.indexOf("\"dislikeCount", findNext); } s = ""; findStart = 0; findNext = 0; findEnd = 0; uint32_t commentCount = 0; //парсим количество коментариев findStart = S.indexOf("\"commentCount", findNext); while ( findStart != -1) { findNext = findStart + 17; findEnd = S.indexOf("\"", findNext); s = S.substring(findNext, findEnd); commentCount = commentCount + s.toInt(); //Serial.print(s.toInt()); Serial.println(" - "); findStart = S.indexOf("\"commentCount", findNext); } wC = wC + viewCount; // Количество просмотров lC = lC + likeCount; // Количество лайков dC = dC + dislikeCount; // Количество дизлайков cC = cC + commentCount; // Количество комментариев } else { // нет подключения - придумаю чуть позже wifiOK = false; } } void refreshA () { uint32_t remainVideo = AllVideoCount; String S = AllVideoList; String s = ""; label: if (remainVideo <= 30) { // Разбираем остаток S.remove(S.lastIndexOf(',')); // Удаляем последнюю запятую getYoutubeVideoS(S); return; } do { // Делаем запрос по 30 видео s = S.substring(0, 360); s.remove(s.lastIndexOf(',')); S.remove(0, 360); getYoutubeVideoS(s); remainVideo = remainVideo - 30; delay(25); } while (remainVideo > 30); goto label; }