#include <FS.h>
#include <FSImpl.h>
#include <vfs_api.h>
//Inclusão de bibliotecas
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiMulti.h>
#include <MD_MAX72xx.h>
#include <time.h>
#include <driver/rtc_io.h>
//---------------------------------------------------------------------
//Constantes para NTP/Relógio base/url: https://randomnerdtutorials.com/esp32-date-time-ntp-client-server-arduino/
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 0; //Variável define o deslocamento em segundos entre seu fuso horário e GMT
const int daylight0ffset_sec = 3600; //Variável define o deslocamento em segundos para o horário de verão, geralmente é uma hora, que corresponde a 3600 segundos.
//---------------------------------------------------------------------
//Definindo botões
#define botao1 13
#define botao2 4
#define botao3 12
int intensidadeX=0;
//----------------------------------------------------------------------
//Ativar instruções de depuração para a saída serial
#define DEBUG 1
#if DEBUG
#define PRINT(s, x) { Serial.print(F(s)); Serial.print(x); }
#define PRINTS(x) Serial.print(F(x))
#define PRINTD(x) Serial.println(x)
#else
#define PRINT(s, x)
#define PRINTS(x)
#define PRINTD(x)
#endif
//----------------------------------------------------------------------
//Definindo pinos para a biblioteca MD_MAX72xx.h
//Pino 23 = DIN, Pino 18 = CLK, Pino 5 = CS. 4 = Quantidade de displays
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 16
#define CLK_PIN 18
#define DATA_PIN 23
#define CS_PIN 5
//-----------------------------------------------------------------------
// SPI hardware interface
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
//MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
//Sempre esperamos um pouco entre as atualizações do display
#define DELAYTIME 100 //em milissegundosAdd your Token number that bot has sent you on WhatsApp messenger
//Definir modo de transição de texto, elemento pixel para esquerda.
#define MODO_TSL MD_MAX72XX::TSL
//-----------------------------------------------------------------------
WiFiMulti wifiMulti;
//-----------------------------------------------------------------------
//Definições para comunicação com API
String apiKey = "803710"; //Adicione o número do Token que o bot enviou para você no WhatsApp messenger
String phone_number = "+5511984657053"; //Adicione seu número de telefone registrado no aplicativo WhatsApp (mesmo número que o bot lhe envia na url)
String telegram_grupo = "LTEwMDE1ODM2NzkzNjU"; //Adicione o token do grupo do telegram.
String url; //url String será usado para armazenar o URL final gerado
//-----------------------------------------------------------------------
// 3 funções para API Whatsapp e Telegram. Função de concatenação para URL da API; função para request
void message_to_telegram(String message)//função de definição do usuário para enviar mensagem para o aplicativo WhatsApp
{
url = "https://api.callmebot.com/telegram/group.php?apikey=" + telegram_grupo + "&text=" + urlencode(message);
postData();//chamando postData para executar o URL gerado acima uma vez para que você receba uma mensagem.
};
/*void message_to_whatsapp(String message)//função de definição do usuário para enviar mensagem para o aplicativo WhatsApp
{
url = "https://api.callmebot.com/whatsapp.php?phone=" + phone_number + "&text=" + urlencode(message) + "&apikey=" + apiKey;
postData();//chamando postData para executar o URL gerado acima uma vez para que você receba uma mensagem.
};*/
void postData() //userDefine function used to call api(POST data)
{
int httpCode; // variável usada para obter o código http de resposta após chamar a api
HTTPClient http; // Declare object of class HTTPClient
http.begin(url); // inicie o objeto HTTPClient com url gerado
httpCode = http.POST(url); // Post URL com esta função e ela armazenará o status http
if (httpCode == 200) // Verifique se o código http de resposta é 200
{
Serial.println("Sent ok."); // imprimir mensagem enviada ok mensagem
}
else //se o código HTTP de resposta não for 200, significa que há algum erro.
{
Serial.println("Error."); // imprimir mensagem de erro.
}
http.end(); // Depois de chamar a API, encerre o objeto cliente HTTP.
}
String urlencode(String str) // Função usada para codificar o URL
{
String encodedString="";
char c;
char code0;
char code1;
char code2;
for (int i =0; i < str.length(); i++){
c=str.charAt(i);
if (c == ' '){
encodedString+= '+';
} else if (isalnum(c)){
encodedString+=c;
} else{
code1=(c & 0xf)+'0';
if ((c & 0xf) >9){
code1=(c & 0xf) - 10 + 'A';
}
c=(c>>4)&0xf;
code0=c+'0';
if (c > 9){
code0=c - 10 + 'A';
}
code2='\0';
encodedString+='%';
encodedString+=code0;
encodedString+=code1;
//encodedString+=code2;
}
yield();
}
return encodedString;
}
//-----------------------------------------------------------------------
//Vetor que contém todos os projetos
const char* projeto[] {
"http://google.com.br",
"http://alegria.objectdata.com.br",
"http://alpes.objectdata.com.br",
"http://alphavale.objectdata.com.br",
"http://altec.objectdata.com.br",
"http://ambar.objectdata.com.br",
"http://amplanetwork.objectdata.com.br",
"http://app.objectdata.com.br",
"http://apresentacao.objectdata.com.br",
"http://asolucao.objectdata.com.br",
"http://auroraspferramentas.objectdata.com.br",
"http://bagdagames.objectdata.com.br",
"http://becodosfogoes.objectdata.com.br",
"http://bettermicro.objectdata.com.br",
"http://birobert.objectdata.com.br",
"http://boxup.objectdata.com.br",
"http://braprintcomercio.objectdata.com.br",
"http://btminformatica.objectdata.com.br",
"http://cabosfron.objectdata.com.br",
"http://carolinfo.objectdata.com.br",
"http://casemall.objectdata.com.br",
"http://cavaltec.objectdata.com.br",
"http://cddistribuidor.objectdata.com.br",
"http://cdparceiro.objectdata.com.br",
"http://centralcabos.objectdata.com.br",
"http://ceretti.objectdata.com.br",
"http://cerettinlc.objectdata.com.br",
"http://chykhd.objectdata.com.br",
"http://claramed.objectdata.com.br",
"http://conceptfour.objectdata.com.br",
"http://controlbr.objectdata.com.br",
"http://cristalmax.objectdata.com.br",
"http://dainyinformatica.objectdata.com.br",
"http://deluma.objectdata.com.br",
"http://development.objectdata.com.br",
"http://dicomp.objectdata.com.br",
"http://displaymax.objectdata.com.br",
"http://distribuidoracerqueira.objectdata.com.br",
"http://domax.objectdata.com.br",
"http://ducorte.objectdata.com.br",
"http://edifier.objectdata.com.br",
"http://eletrocantins.objectdata.com.br",
"http://eletrovolt.objectdata.com.br",
"http://ervadoce.objectdata.com.br",
"http://f3.objectdata.com.br",
"http://fafcoffees.objectdata.com.br",
"http://feasso.objectdata.com.br",
"http://ferrawidia.objectdata.com.br",
"http://fornell.objectdata.com.br",
"http://frodo.objectdata.com.br",
"http://furyinformatica.objectdata.com.br",
"http://globalcomponentes.objectdata.com.br",
"http://globaltime.objectdata.com.br",
"http://globomaster.objectdata.com.br",
"http://gmt.objectdata.com.br",
"http://gowest.objectdata.com.br",
"http://groupyou.objectdata.com.br",
"http://grupotech.objectdata.com.br",
"http://gveletro.objectdata.com.br",
"http://hardseg.objectdata.com.br",
"http://hotpower.objectdata.com.br",
"http://infinitycftv.objectdata.com.br",
"http://infocross.objectdata.com.br",
"http://infogordo.objectdata.com.br",
"http://infopride.objectdata.com.br",
"http://inforwaste.objectdata.com.br",
"http://inmark.objectdata.com.br",
"http://innovamed.objectdata.com.br",
"http://inove.objectdata.com.br",
"http://intely.objectdata.com.br",
"http://iotec.objectdata.com.br",
"http://jginfo.objectdata.com.br",
"http://jikatec.objectdata.com.br",
"http://kaessi.objectdata.com.br",
"http://kingpower.objectdata.com.br",
"http://klvnotebook.objectdata.com.br",
"http://kwasar.objectdata.com.br",
"http://lasuprimentos.objectdata.com.br",
"http://lexamoveis.objectdata.com.br",
"http://ligatudo.objectdata.com.br",
"http://ljsuprimentos.objectdata.com.br",
"http://lpi.objectdata.com.br",
"http://luttitime.objectdata.com.br",
"http://lys.objectdata.com.br",
"http://maisgames.objectdata.com.br",
"http://mamute.objectdata.com.br",
"http://masternote.objectdata.com.br",
"http://medalpha.objectdata.com.br",
"http://medmax.objectdata.com.br",
"http://mgimports.objectdata.com.br",
"http://mi6.objectdata.com.br",
"http://midas.objectdata.com.br",
"http://minika.objectdata.com.br",
"http://mkgames.objectdata.com.br",
"http://mmeletronicos.objectdata.com.br",
"http://mmeletronicosmm.objectdata.com.br",
"http://modaconcept.objectdata.com.br",
"http://monsternetwork.objectdata.com.br",
"http://mscn.objectdata.com.br",
"http://mstech.objectdata.com.br",
"http://multcomercial.objectdata.com.br:9090",
"http://mxaprint.objectdata.com.br",
"http://najainformatica.objectdata.com.br",
"http://netceretti.objectdata.com.br",
"http://netconect.objectdata.com.br",
"http://newstartx.objectdata.com.br",
"http://nisew.objectdata.com.br",
"http://norteplac.objectdata.com.br",
"http://noteplace.objectdata.com.br",
"http://odison.objectdata.com.br",
"http://omsecurity.objectdata.com.br",
"http://opoen.objectdata.com.br",
"http://p5distribuidora.objectdata.com.br",
"http://pcmaster.objectdata.com.br",
"http://pontoeletronico.objectdata.com.br",
"http://proimagem.objectdata.com.br",
"http://projeto765.objectdata.com.br",
"http://projeto767.objectdata.com.br",
"http://projeto768.objectdata.com.br",
"http://projeto772.objectdata.com.br",
"http://projeto774.objectdata.com.br",
"http://projeto781.objectdata.com.br",
"http://projeto784.objectdata.com.br",
"http://projeto789.objectdata.com.br",
"http://projeto792.objectdata.com.br",
"http://projeto796.objectdata.com.br",
"http://projeto797.objectdata.com.br",
"http://projeto802.objectdata.com.br",
"http://projeto803.objectdata.com.br",
"http://projeto804.objectdata.com.br",
"http://projeto814.objectdata.com.br",
"http://projeto816.objectdata.com.br",
"http://projeto818.objectdata.com.br",
"http://projeto821.objectdata.com.br",
"http://projeto822.objectdata.com.br",
"http://projeto823.objectdata.com.br",
"http://projeto824.objectdata.com.br",
"http://projeto826.objectdata.com.br",
"http://projeto827.objectdata.com.br",
"http://projeto828.objectdata.com.br",
"http://projeto829.objectdata.com.br",
"http://projeto830.objectdata.com.br",
"http://projeto833.objectdata.com.br",
"http://projeto834.objectdata.com.br",
"http://projeto835.objectdata.com.br",
"http://projeto836.objectdata.com.br",
"http://projeto841.objectdata.com.br",
"http://projeto842.objectdata.com.br",
"http://projeto843.objectdata.com.br",
"http://projeto844.objectdata.com.br",
"http://projeto845.objectdata.com.br",
"http://projeto846.objectdata.com.br",
"http://projeto847.objectdata.com.br",
"http://projeto848.objectdata.com.br",
"http://projeto849.objectdata.com.br",
"http://projeto850.objectdata.com.br",
"http://quality.objectdata.com.br",
"http://r3sistemas.objectdata.com.br",
"http://redacomp.objectdata.com.br",
"http://reidoscomponentes.objectdata.com.br",
"http://rfmrepresentacoes.objectdata.com.br",
"http://rioxi.objectdata.com.br",
"http://roth.objectdata.com.br",
"http://rsl.objectdata.com.br",
"http://samysshop.objectdata.com.br",
"http://scalaseguranca.objectdata.com.br",
"http://servfitness.objectdata.com.br",
"http://shoopingsublimacao.objectdata.com.br",
"http://showdigital.objectdata.com.br",
"http://smartprint.objectdata.com.br",
"http://solcd.objectdata.com.br",
"http://solucao.objectdata.com.br",
"http://solutech.objectdata.com.br",
"http://solutions.objectdata.com.br",
"http://sosapple.objectdata.com.br",
"http://spet.objectdata.com.br",
"http://standnetwork.objectdata.com.br",
"http://stargdl.objectdata.com.br",
"http://starmundial.objectdata.com.br",
"http://staropen.objectdata.com.br",
"http://supersaldo.objectdata.com.br",
"http://svpimentel.objectdata.com.br",
"http://tabacariafullpower.objectdata.com.br",
"http://taichi.objectdata.com.br",
"http://taking.objectdata.com.br",
"http://tayyarcell.objectdata.com.br",
"http://techform.objectdata.com.br",
"http://tecnomult.objectdata.com.br",
"http://test.objectdata.com.br",
"http://thor.objectdata.com.br",
"http://tn4tech.objectdata.com.br",
"http://torex.objectdata.com.br",
"http://treinamento.objectdata.com.br",
"http://trelik.objectdata.com.br",
"http://twjseguranca.objectdata.com.br",
"http://universodascameras.objectdata.com.br",
"http://valeverde.objectdata.com.br",
"http://valvolandia.objectdata.com.br",
"http://varotti.objectdata.com.br",
"http://venturi.objectdata.com.br",
"http://vlc.objectdata.com.br",
"http://wolfbrasil.objectdata.com.br",
"http://wondernetwork.objectdata.com.br",
"http://workfasten.objectdata.com.br",
"http://xegames.objectdata.com.br",
"http://z11.objectdata.com.br",
"http://zacinformatica.objectdata.com.br",
"http://zimaq.objectdata.com.br",
"http://zmeletronicos.objectdata.com.br",
};
//-----------------------------------------------------------------------
//Função para requisição NTP
/*void requestNTP(){
configTime(gmt0ffset_sec, daylightOffset_set, ntpServer); //Inicia e obtém as horas
struct tm timeinfo; //uma estrutura de tempo (struct tm) chamado 'timeinfo' que contém todos os detalhes sobre a hora (min, seg, hora, etc…).
O'tm' estrutura contém uma data e hora do calendário dividida em seus componentes
tm_sec: segundos após o minuto;
tm_min: minutos após a hora;
tm_hour: horas desde a meia-noite;
tm_mday: dia do mês;
tm_ano: anos desde 1900;
tm_wday: dias desde domingo;
tm_yday: dias desde 1º de janeiro;
tm_isdst: Sinalizador de horário de verão;
if(!getLocalTime(&timeinfo)){
Serial.println("Falha ao obter tempo.");
return;
}
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
Serial.print("Day of week: ");
Serial.println(&timeinfo, "%A");
Serial.print("Month: ");
Serial.println(&timeinfo, "%B");
Serial.print("Day of Month: ");
Serial.println(&timeinfo, "%d");
Serial.print("Year: ");
Serial.println(&timeinfo, "%Y");
Serial.print("Hour: ");
Serial.println(&timeinfo, "%H");
Serial.print("Hour (12 hour format): ");
Serial.println(&timeinfo, "%I");
Serial.print("Minute: ");
Serial.println(&timeinfo, "%M");
Serial.print("Second: ");
Serial.println(&timeinfo, "%S");
Serial.println("Váriaveis de tempo");
char timeHour[3];
strftime(timeHour,3, "%H", &timeinfo);
Serial.println(timeHour);
char timeWeekDay[10];
strftime(timeWeekDay,10, "%A", &timeinfo);
Serial.println(timeWeekDay);
Serial.println();
}*/
//-----------------------------------------------------------------------
//Funções para limpar modulo led(display) individualmente.
void clearDisplay1(){
uint8_t dev0 = 0;
uint8_t dev3 = 3;
mx.clear(dev0,dev3);}
void clearDisplay2(){
uint8_t dev4 = 4;
uint8_t dev7 = 7;
mx.clear(dev4,dev7);}
void clearDisplay3e4(){
uint8_t dev8 = 8;
uint8_t dev15 = 15;
mx.clear(dev8,dev15);}
//-----------------------------------------------------------------------
void iniciaWifi()
{
funcaobotao();
wifiMulti.addAP("RafaelMobile 2G", "23456789");
wifiMulti.addAP("Rafael 2G", "23456789");
wifiMulti.addAP("Objectdata-vivo", "objdt256");
if(WiFi.status() != WL_CONNECTED) {
PRINTD("Connecting Wifi...");
scrollText("Conectando Wifi...");
wifiMulti.run();
PRINTS(".");
delay(1000);
clearDisplay1();
}
if (WiFi.status() == WL_CONNECTED){
scrollText("Wifi conectado!!!");
PRINTD("");
PRINTD("WiFi connected");
PRINTD("IP address: ");
PRINTD(WiFi.localIP());
char ipTexto[20];
sprintf(ipTexto, "IP: %03d:%03d:%03d:%03d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);
scrollText(ipTexto);
delay(2000);
clearDisplay3e4();
}
}
//-----------------------------------------------------------------------
void loopProjeto(){
voltaLoop:
int i = 0; //208
const uint16_t maxCol = 4 * ROW_SIZE;
if ((wifiMulti.run() == WL_CONNECTED)) { //Check the current connection status
HTTPClient http;
for (uint16_t col=maxCol -1; col >= 0; col--)
{
for (uint8_t row=0; row < ROW_SIZE; row++)
{
funcaobotao();
mx.setPoint(row,col,false);
i++;
int contadorRequest = 0;
voltaRequest:
contadorRequest++;
http.begin(projeto[i]); //Especifique a URL
int httpCode = http.GET(); //Fazendo a resquest
if (httpCode == 200 || 302 == httpCode || -1 == httpCode ) { //Checando o retorno do status
PRINTS(projeto[i]);
PRINTS(": Status ");
PRINTD(httpCode);
mx.setPoint(row,col,true);
}
else {
if(contadorRequest < 3 ){
delay(200);
goto voltaRequest;};
mx.setPoint(row,col,true);
PRINTS(projeto[i]);
PRINTS(": Status ");
PRINTD(httpCode);
std::string tmp = std::to_string(httpCode);
const char* httpStatus = tmp.c_str();
const char* statusTexto = "Status: ";
std::string result = std::string(statusTexto) + std::string(httpStatus);
const char* statusConcatenado = result.c_str();
std::string contador = std::to_string(contadorRequest);
PRINTD("Error on HTTP request");
delay(35);
mx.setPoint(row,col,false);
std::string appMsg = "Site: " + std::string(projeto[i]) + "\n" + std::string(statusConcatenado) + "\n" + "Qtd. request: " + std::string(contador);
message_to_telegram(appMsg.c_str());
//message_to_whatsapp(appMsg.c_str());
scrollText(projeto[i]);
scrollText(statusConcatenado);
delay(1000);
clearDisplay3e4();
//scrollText(httpStatus);
if(WiFi.status() != WL_CONNECTED){
iniciaWifi();
};
}
if(i > 207)
{
PRINTD("fim do loop");
goto voltaLoop;
http.end(); //Liberando recursos do http
}
delay(DELAYTIME);
}
}
}
}
//-----------------------------------------------------------------------
//Função em desenvolvimento
//-----------------------------------------------------------------------
/*void loopSemDisplay(){
int i = 0; //208
if ((wifiMulti.run() == WL_CONNECTED)) {
HTTPClient http
for (i = 208, i >= 0, i++){
http.begin(projeto[i]);
int httpCode = http.GET();
if(httpCode == 200 || 302 == httpCode || -1 == httpCode){
PRINTS(projeto[i]);
PRINTS(": Status ");
PRINTD(httpCode);
}
else{
PRINTS(projeto[i]);
PRINTS(": Status ");
PRINTD(httpCode);
if(WiFi.status() != WL_CONNECTED){
iniciaWifi();
};
};
};
};
};*/
//-----------------------------------------------------------------------
//Função texto display 2
//-----------------------------------------------------------------------
//Função texto scroll display 3 e 4
void scrollText(const char *p)
{
uint8_t charWidth;
uint8_t cBuf[8]; // isso deve ser bom para todas as fontes internas
uint8_t startDev = 8;
uint8_t endDev = 15;
PRINTS("\nScrolling text");
clearDisplay3e4();
while (*p != '\0')
{
charWidth = mx.getChar(*p++, sizeof(cBuf) / sizeof(cBuf[0]), cBuf);
for (uint8_t i=0; i<=charWidth; i++) // permitir espaço entre os caracteres
{
mx.transform(startDev, endDev, MODO_TSL);
if (i < charWidth)
mx.setColumn(64, cBuf[i]);
funcaobotao();
delay(DELAYTIME);
}
}
}
void funcaobotao(){
if (digitalRead(botao1)==0){
Serial.println(intensidadeX);
mx.control(MD_MAX72XX::INTENSITY,intensidadeX );
intensidadeX++;
delay(50);
if (intensidadeX >= 15) intensidadeX = 0;
}
if (digitalRead(botao2)==0){
scrollText("MODO SLEEP");
clearDisplay1();
clearDisplay2();
clearDisplay3e4();
esp_deep_sleep_start();
}
/*if em desenvolvimento
if (digitalRead(botao3)==0){
scrollText("MODO DISPLAY OFF/ON");
delay(4000);
mx.control(8,MD_MAX72XX::SHUTDOWN,true);
};*/
}
void setup()
{
pinMode(botao1, INPUT_PULLUP);
pinMode(botao2, INPUT_PULLUP);
pinMode(botao3, INPUT_PULLUP);
mx.begin();
mx.control(MD_MAX72XX::INTENSITY,intensidadeX);
#if DEBUG
Serial.begin(115200);
#endif
scrollText("OBJECT RESPONSE");
delay(2000);
clearDisplay3e4();
iniciaWifi();
}
//-----------------------------------------------------------------------
void loop()
{
loopProjeto();
}
//-----------------------------------------------------------------------