//Projeto vídeo
//https://youtu.be/9_CbZ1ZLsyQ?si=94pUE0PClGFwfAoM
//API whatsapp
//https://www.callmebot.com/blog/free-api-whatsapp-messages/
//https://api.callmebot.com/whatsapp.php?phone=5512992245039&text=This+is+a+test&apikey=4992937
//CodeSys
//https://youtu.be/2OlclPNeI6g?si=MHAk5OuaRbn4maME
#include <WiFiManager.h>
#include <ModbusIP_ESP8266.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <HTTPClient.h>
#include <UrlEncode.h>
AsyncWebServer server(80);
const int DiscreteInputsAddresses[] = {0, 1}; // Endereços Modbus das entradas digitais
const int DiscreteInputPins[] = {32, 33}; // Pinos que serão utilizados como entradas digitais
const int CoilsAddresses[] = {5, 6}; // Endereços Modbus das saídas digitais
const int CoilsPins[] = {25, 26}; // Pinos que serão utilizados como saídas digitais
const int AnalogInputPins[] = {36}; // Pinos que serão utilizados como entradas analógicas
const int AnalogInputsAddresses[] = {0}; // Endereços Modbus das entradas analógicas
const int AnalogOutputPins[] = {27}; // Pinos que serão utilizados como saídas analógicas
const int AnalogOutputAddresses[] = {5}; // Endereços Modbus das saídas analógicas
const int WebServerRegisterAddresses[] = {2, 3}; // Endereço das entradas analógicas do webservidor
const int WebServerDiscreteAddresses[] = {9}; // Endereço das entradas digitais do webservidor
ModbusIP mb; // ModbusIP object
String phoneNumber = "NUMEROCELULAR"; // exemplo: +5591xxxxxxxx (número do celular sem o 9 na frente)
String apiKey = "APIKEY";
void sendMessage(String message, String phoneNumber, String apiKey) {
String url = "https://api.callmebot.com/whatsapp.php?phone=" + phoneNumber + "&apikey=" + apiKey + "&text=" + urlEncode(message);
HTTPClient http;
http.begin(url);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpResponseCode = http.POST(url);
if (httpResponseCode == 200) {
Serial.println("Mensagem enviada com sucesso");
} else {
Serial.println("Erro no envio da mensagem");
Serial.print("HTTP response code: ");
Serial.println(httpResponseCode);
}
http.end();
}
void setup() {
Serial.begin(921600);
// Configura as entradas digitais
for (int i = 0; i < sizeof(DiscreteInputPins) / sizeof(DiscreteInputPins[0]); i++) {
pinMode(DiscreteInputPins[i], INPUT_PULLUP);
mb.addIsts(DiscreteInputsAddresses[i]);
}
// Configura as saídas digitais
for (int i = 0; i < sizeof(CoilsPins) / sizeof(CoilsPins[0]); i++) {
pinMode(CoilsPins[i], OUTPUT);
mb.addCoil(CoilsAddresses[i]);
}
// Configura as entradas analógicas
for (int i = 0; i < sizeof(AnalogInputPins) / sizeof(AnalogInputPins[0]); i++) {
pinMode(AnalogInputPins[i], INPUT);
mb.addIreg(AnalogInputsAddresses[i]);
}
// Configura as saídas analógicas
for (int i = 0; i < sizeof(AnalogOutputPins) / sizeof(AnalogOutputPins[0]); i++) {
pinMode(AnalogOutputPins[i], OUTPUT);
mb.addHreg(AnalogOutputAddresses[i]);
}
// Configura os registradores do webservidor
for (int i = 0; i < sizeof(WebServerRegisterAddresses) / sizeof(WebServerRegisterAddresses[0]); i++) {
mb.addHreg(WebServerRegisterAddresses[i]);
}
// Configura as entradas digitais do webservidor
for (int i = 0; i < sizeof(WebServerDiscreteAddresses) / sizeof(WebServerDiscreteAddresses[0]); i++) {
mb.addIsts(WebServerDiscreteAddresses[i]);
}
WiFiManager wm;
//wm.resetSettings();
bool res = wm.autoConnect("AutoConnectAP","password");
Serial.println(res ? "Conectado com sucesso" : "Falha ao conectar");
// Configurações do WebServer
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
String html = "<style>.element {width: 300px; height: 80px; font-size: 28px; margin-bottom: 10px;}</style>"; // Definindo largura, altura e tamanho da fonte para todos os elementos
html += "<style>.container {display: flex; flex-direction: row; align-items: flex-start;}</style>"; // Flexível para duas colunas
html += "<style>.column {display: flex; flex-direction: column; margin-right: 20px;}</style>"; // Coluna para alinhamento
html += "<style>.header {background-color: black; color: white; text-align: center; padding: 10px; margin-bottom: 20px;}</style>"; // Estilizando o cabeçalho
// Cabeçalho com retângulo preto
html += "<div class='header'><h1>Automação e Simulação</h1></div>";
// Início do container flexível
html += "<div class='container' style='background-color: #f0f0f0; padding: 20px;'>"; // Adicionando o retângulo cinza claro como background
// Primeira coluna
html += "<div class='column'>";
html += "<div class='element' style='background-color: black; color: white; display: flex; justify-content: center; align-items: center;'>Produção Desejada</div>";
html += "<input type='number' id='textBox' min='0' max='255' value='128' class='element' style='font-size: 28px;'>";
html += "<button onclick='updateValue()' class='element'>Atualizar Valor</button>";
html += "<div id='textBoxValue' style='font-size: 24px;'></div>"; // Div para mostrar o valor numérico da caixa de texto
html += "</div>"; // Fim da primeira coluna
// Segunda coluna
html += "<div class='column'>";
html += "<div class='element' style='background-color: black; color: white; display: flex; justify-content: center; align-items: center;'>Total Produzido</div>";
html += "<input type='text' id='readOnlyBox' value='0' class='element' style='font-size: 28px;' readonly>";
html += "<div id='readOnlyBoxValue' style='font-size: 24px;'></div>"; // Div para mostrar o valor numérico da caixa de texto de leitura
html += "</div>"; // Fim da segunda coluna
// Terceira coluna
html += "<div class='column'>";
html += "<div class='element' style='background-color: black; color: white; display: flex; justify-content: center; align-items: center;'>Zerar Contador</div>";
html += "<button onmousedown='resetCounter(true)' onmouseup='resetCounter(false)' class='element' style='background-color: blue; color: white;'>Reset</button>";
html += "</div>"; // Fim da terceira coluna
html += "<script>function updateValue() { var value = document.getElementById('textBox').value; document.getElementById('textBoxValue').innerHTML = value; fetch('/updateValue?value=' + value); }</script>"; // Script JavaScript para atualizar o valor
html += "<script>setInterval(function() { fetch('/updateClientValue').then(response => response.text()).then(data => { document.getElementById('readOnlyBox').value = data; document.getElementById('readOnlyBoxValue').innerHTML = data; }); }, 1000);</script>"; // Script JavaScript para atualizar a caixa de leitura e a div de leitura
html += "<script>function resetCounter(state) { fetch('/resetCounter?state=' + state); }</script>"; // Script JavaScript para o botão de reset
request->send(200, "text/html; charset=utf-8", html);
});
server.on("/updateValue", HTTP_GET, [](AsyncWebServerRequest *request){
if (request->hasParam("value")) {
String value = request->getParam("value")->value();
int intValue = value.toInt();
mb.Hreg(WebServerRegisterAddresses[0], intValue);
}
request->send(200, "text/plain", "OK");
});
server.on("/updateClientValue", HTTP_GET, [](AsyncWebServerRequest *request){
int clientValue = mb.Hreg(WebServerRegisterAddresses[1]); // Lendo o valor do novo registrador
request->send(200, "text/plain", String(clientValue));
});
server.on("/resetCounter", HTTP_GET, [](AsyncWebServerRequest *request){
if (request->hasParam("state")) {
String state = request->getParam("state")->value();
bool boolState = (state == "true");
mb.Ists(WebServerDiscreteAddresses[0], boolState);
}
request->send(200, "text/plain", "OK");
});
server.begin();
mb.server();
}
void loop() {
mb.task();
// Atualiza os valores das entradas digitais
for (int i = 0; i < sizeof(DiscreteInputsAddresses) / sizeof(DiscreteInputsAddresses[0]); i++) {
mb.Ists(DiscreteInputsAddresses[i], digitalRead(DiscreteInputPins[i]));
}
// Atualiza os valores das saídas digitais
for (int i = 0; i < sizeof(CoilsAddresses) / sizeof(CoilsAddresses[0]); i++) {
digitalWrite(CoilsPins[i], mb.Coil(CoilsAddresses[i]));
}
// Atualiza os valores das entradas analógicas
for (int i = 0; i < sizeof(AnalogInputsAddresses) / sizeof(AnalogInputsAddresses[0]); i++) {
mb.Ireg(AnalogInputsAddresses[i], analogRead(AnalogInputPins[i]));
}
// Atualiza os valores das saídas analógicas
for (int i = 0; i < sizeof(AnalogOutputAddresses) / sizeof(AnalogOutputAddresses[0]); i++) {
analogWrite(AnalogOutputPins[i], mb.Hreg(AnalogOutputAddresses[i]));
}
int value1 = mb.Hreg(WebServerRegisterAddresses[0]);
int value2 = mb.Hreg(WebServerRegisterAddresses[1]);
static bool productionStarted = false;
static bool productionFinished = false;
// Check if production started
if (value2 == 1 && !productionStarted) {
sendMessage("Produção iniciada", phoneNumber, apiKey);
productionStarted = true;
productionFinished = false;
}
if (productionFinished == false && value1 != 0 && value2 != 0 && value1 == value2) {
sendMessage("Produção finalizada", phoneNumber, apiKey);
productionFinished = true;
productionStarted = false;
}
}