Advertisement
Guest User

Untitled

a guest
Dec 14th, 2017
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.77 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. //Arquivo: MQTT_WiFiManager_Rele.ino
  3. //Tipo: Exemplo de uso das bibliotecas WiFiManager e PubSubClient para ESP8266 na IDE do Arduino
  4. //Autor: Marco Rabelo para o canal Infortronica Para Zumbis (www.youtube.com/c/InfortronicaParaZumbis)
  5. //Descricao: Curso de ESP8266 - Utilizando MQTT e gerenciador de wifi para controlar um relé.
  6. //Video: https://youtu.be/oX4ttJEULmA
  7. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  8.  
  9. /*
  10. Equivalencia das saidas Digitais entre NodeMCU e ESP8266 (na IDE do Arduino)
  11. NodeMCU - ESP8266
  12. D0 = 16;
  13. D1 = 5;
  14. D2 = 4;
  15. D3 = 0;
  16. D4 = 2;
  17. D5 = 14;
  18. D6 = 12;
  19. D7 = 13;
  20. D8 = 15;
  21. D9 = 3;
  22. D10 = 1;
  23. */
  24.  
  25. #include <FS.h> //Esta precisa ser a primeira referência, ou nada dará certo e sua vida será arruinada. kkk
  26. #include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
  27. #include <DNSServer.h>
  28. #include <ESP8266WebServer.h>
  29. #include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
  30. #include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson
  31. #include <PubSubClient.h>
  32. #include <EEPROM.h>
  33.  
  34. #define DEBUG //Se descomentar esta linha vai habilitar a 'impressão' na porta serial
  35.  
  36. //Coloque os valores padrões aqui, porém na interface eles poderão ser substituídos.
  37. #define servidor_mqtt "m14.cloudmqtt.com" //URL do servidor MQTT
  38. #define servidor_mqtt_porta "17037" //Porta do servidor (a mesma deve ser informada na variável abaixo)
  39. #define servidor_mqtt_usuario "rmjpppbl" //Usuário
  40. #define servidor_mqtt_senha "qDrCJUDT6cC2" //Senha
  41. #define mqtt_topico_sub "esp8266/pincmd" //Tópico para subscrever o comando a ser dado no pino declarado abaixo
  42.  
  43. //Declaração do pino que será utilizado e a memória alocada para armazenar o status deste pino na EEPROM
  44. #define pino 2 //Pino que executara a acao dado no topico "esp8266/pincmd" e terá seu status informado no tópico "esp8266/pinstatus"
  45. #define memoria_alocada 4 //Define o quanto sera alocado na EEPROM (valores entre 4 e 4096 bytes)
  46.  
  47. WiFiClient espClient; //Instância do WiFiClient
  48. PubSubClient client(espClient); //Passando a instância do WiFiClient para a instância do PubSubClient
  49.  
  50. uint8_t statusAnt = 0; //Variável que armazenará o status do pino que foi gravado anteriormente na EEPROM
  51. bool precisaSalvar = false; //Flag para salvar os dados
  52.  
  53. //Função para imprimir na porta serial
  54. void imprimirSerial(bool linha, String mensagem){
  55. #ifdef DEBUG
  56. if(linha){
  57. Serial.println(mensagem);
  58. }else{
  59. Serial.print(mensagem);
  60. }
  61. #endif
  62. }
  63.  
  64. //Função de retorno para notificar sobre a necessidade de salvar as configurações
  65. void precisaSalvarCallback() {
  66. imprimirSerial(true, "As configuracoes tem que ser salvas.");
  67. precisaSalvar = true;
  68. }
  69.  
  70. //Função que reconecta ao servidor MQTT
  71. void reconectar() {
  72. //Repete até conectar
  73. while (!client.connected()) {
  74. imprimirSerial(false, "Tentando conectar ao servidor MQTT...");
  75.  
  76. //Tentativa de conectar. Se o MQTT precisa de autenticação, será chamada a função com autenticação, caso contrário, chama a sem autenticação.
  77. bool conectado = strlen(servidor_mqtt_usuario) > 0 ?
  78. client.connect("ESP8266Client", servidor_mqtt_usuario, servidor_mqtt_senha) :
  79. client.connect("ESP8266Client");
  80.  
  81. if(conectado) {
  82. imprimirSerial(true, "Conectado!");
  83. //Subscreve para monitorar os comandos recebidos
  84. client.subscribe(mqtt_topico_sub, 1); //QoS 1
  85. } else {
  86. imprimirSerial(false, "Falhou ao tentar conectar. Codigo: ");
  87. imprimirSerial(false, String(client.state()).c_str());
  88. imprimirSerial(true, " tentando novamente em 5 segundos");
  89. //Aguarda 5 segundos para tentar novamente
  90. delay(5000);
  91. }
  92. }
  93. }
  94.  
  95. //Função que verifica qual foi o último status do pino antes do ESP ser desligado
  96. void lerStatusAnteriorPino(){
  97. EEPROM.begin(memoria_alocada); //Aloca o espaco definido na memoria
  98. statusAnt = EEPROM.read(0); //Le o valor armazenado na EEPROM e passa para a variável "statusAnt"
  99. if(statusAnt > 1){
  100. statusAnt = 0; //Provavelmente é a primeira leitura da EEPROM, passando o valor padrão para o pino.
  101. EEPROM.write(0,statusAnt);
  102. }
  103. digitalWrite(pino, statusAnt);
  104. EEPROM.end();
  105. }
  106.  
  107. //Função que grava status do pino na EEPROM
  108. void gravarStatusPino(uint8_t statusPino){
  109. EEPROM.begin(memoria_alocada);
  110. EEPROM.write(0, statusPino);
  111. EEPROM.end();
  112. }
  113.  
  114. //Função que será chamada ao receber mensagem do servidor MQTT
  115. void retorno(char* topico, byte* mensagem, unsigned int tamanho) {
  116. //Convertendo a mensagem recebida para string
  117. mensagem[tamanho] = '\0';
  118. String strMensagem = String((char*)mensagem);
  119. strMensagem.toLowerCase();
  120. //float f = s.toFloat();
  121.  
  122. imprimirSerial(false, "Mensagem recebida! Topico: ");
  123. imprimirSerial(false, topico);
  124. imprimirSerial(false, ". Tamanho: ");
  125. imprimirSerial(false, String(tamanho).c_str());
  126. imprimirSerial(false, ". Mensagem: ");
  127. imprimirSerial(true, strMensagem);
  128.  
  129. //Executando o comando solicitado
  130. imprimirSerial(false, "Status do pino antes de processar o comando: ");
  131. imprimirSerial(true, String(digitalRead(pino)).c_str());
  132.  
  133. if(strMensagem == "liga"){
  134. imprimirSerial(true, "Colocando o pino em estado ALTO...");
  135. digitalWrite(pino, HIGH);
  136. gravarStatusPino(HIGH);
  137. }else if(strMensagem == "desliga"){
  138. imprimirSerial(true, "Colocando o pino em estado BAIXO...");
  139. digitalWrite(pino, LOW);
  140. gravarStatusPino(LOW);
  141. }else{
  142. imprimirSerial(true, "Trocando o estado do pino...");
  143. digitalWrite(pino, !digitalRead(pino));
  144. gravarStatusPino(digitalRead(pino));
  145. }
  146.  
  147. imprimirSerial(false, "Status do pino depois de processar o comando: ");
  148. imprimirSerial(true, String(digitalRead(pino)).c_str());
  149. }
  150.  
  151. //Função inicial (será executado SOMENTE quando ligar o ESP)
  152. void setup() {
  153. #ifdef DEBUG
  154. Serial.begin(115200);
  155. #endif
  156. imprimirSerial(true, "...");
  157.  
  158. //Fazendo o pino ser de saída, pois ele irá "controlar" algo.
  159. pinMode(pino, OUTPUT);
  160.  
  161. //Formatando a memória interna
  162. //(descomente a linha abaixo enquanto estiver testando e comente ou apague quando estiver pronto)
  163. //SPIFFS.format();
  164.  
  165. //Iniciando o SPIFSS (SPI Flash File System)
  166. imprimirSerial(true, "Iniciando o SPIFSS (SPI Flash File System)");
  167. if (SPIFFS.begin()) {
  168. imprimirSerial(true, "Sistema de arquivos SPIFSS montado!");
  169. if (SPIFFS.exists("/config.json")) {
  170. //Arquivo de configuração existe e será lido.
  171. imprimirSerial(true, "Abrindo o arquivo de configuracao...");
  172. File configFile = SPIFFS.open("/config.json", "r");
  173. if (configFile) {
  174. imprimirSerial(true, "Arquivo de configuracao aberto.");
  175. size_t size = configFile.size();
  176.  
  177. //Alocando um buffer para armazenar o conteúdo do arquivo.
  178. std::unique_ptr<char[]> buf(new char[size]);
  179.  
  180. configFile.readBytes(buf.get(), size);
  181. DynamicJsonBuffer jsonBuffer;
  182. JsonObject& json = jsonBuffer.parseObject(buf.get());
  183. json.printTo(Serial);
  184. if (json.success()) {
  185. //Copiando as variáveis salvas previamente no aquivo json para a memória do ESP.
  186. imprimirSerial(true, "arquivo json analisado.");
  187. strcpy(servidor_mqtt, json["servidor_mqtt"]);
  188. strcpy(servidor_mqtt_porta, json["servidor_mqtt_porta"]);
  189. strcpy(servidor_mqtt_usuario, json["servidor_mqtt_usuario"]);
  190. strcpy(servidor_mqtt_senha, json["servidor_mqtt_senha"]);
  191. strcpy(mqtt_topico_sub, json["mqtt_topico_sub"]);
  192.  
  193. } else {
  194. imprimirSerial(true, "Falha ao ler as configuracoes do arquivo json.");
  195. }
  196. }
  197. }
  198. } else {
  199. imprimirSerial(true, "Falha ao montar o sistema de arquivos SPIFSS.");
  200. }
  201. //Fim da leitura do sistema de arquivos SPIFSS
  202.  
  203. //Parâmetros extras para configuração
  204. //Depois de conectar, parameter.getValue() vai pegar o valor configurado.
  205. //Os campos do WiFiManagerParameter são: id do parâmetro, nome, valor padrão, comprimento
  206. WiFiManagerParameter custom_mqtt_server("server", "Servidor MQTT", servidor_mqtt, 40);
  207. WiFiManagerParameter custom_mqtt_port("port", "Porta", servidor_mqtt_porta, 6);
  208. WiFiManagerParameter custom_mqtt_user("user", "Usuario", servidor_mqtt_usuario, 20);
  209. WiFiManagerParameter custom_mqtt_pass("pass", "Senha", servidor_mqtt_senha, 20);
  210. WiFiManagerParameter custom_mqtt_topic_sub("topic_sub", "Topico para subscrever", mqtt_topico_sub, 30);
  211.  
  212. //Inicialização do WiFiManager. Uma vez iniciado não é necessário mantê-lo em memória.
  213. WiFiManager wifiManager;
  214.  
  215. //Definindo a função que informará a necessidade de salvar as configurações
  216. wifiManager.setSaveConfigCallback(precisaSalvarCallback);
  217.  
  218. //Adicionando os parâmetros para conectar ao servidor MQTT
  219. wifiManager.addParameter(&custom_mqtt_server);
  220. wifiManager.addParameter(&custom_mqtt_port);
  221. wifiManager.addParameter(&custom_mqtt_user);
  222. wifiManager.addParameter(&custom_mqtt_pass);
  223. wifiManager.addParameter(&custom_mqtt_topic_sub);
  224.  
  225. //Busca o ID e senha da rede wifi e tenta conectar.
  226. //Caso não consiga conectar ou não exista ID e senha,
  227. //cria um access point com o nome "AutoConnectAP" e a senha "senha123"
  228. //E entra em loop aguardando a configuração de uma rede WiFi válida.
  229. if (!wifiManager.autoConnect("AutoConnectAP", "senha123")) {
  230. imprimirSerial(true, "Falha ao conectar. Excedeu o tempo limite para conexao.");
  231. delay(3000);
  232. //Reinicia o ESP e tenta novamente ou entra em sono profundo (DeepSleep)
  233. ESP.reset();
  234. delay(5000);
  235. }
  236.  
  237. //Se chegou até aqui é porque conectou na WiFi!
  238. imprimirSerial(true, "Conectado!! :)");
  239.  
  240. //Lendo os parâmetros atualizados
  241. strcpy(servidor_mqtt, custom_mqtt_server.getValue());
  242. strcpy(servidor_mqtt_porta, custom_mqtt_port.getValue());
  243. strcpy(servidor_mqtt_usuario, custom_mqtt_user.getValue());
  244. strcpy(servidor_mqtt_senha, custom_mqtt_pass.getValue());
  245. strcpy(mqtt_topico_sub, custom_mqtt_topic_sub.getValue());
  246.  
  247. //Salvando os parâmetros informados na tela web do WiFiManager
  248. if (precisaSalvar) {
  249. imprimirSerial(true, "Salvando as configuracoes");
  250. DynamicJsonBuffer jsonBuffer;
  251. JsonObject& json = jsonBuffer.createObject();
  252. json["servidor_mqtt"] = servidor_mqtt;
  253. json["servidor_mqtt_porta"] = servidor_mqtt_porta;
  254. json["servidor_mqtt_usuario"] = servidor_mqtt_usuario;
  255. json["servidor_mqtt_senha"] = servidor_mqtt_senha;
  256. json["mqtt_topico_sub"] = mqtt_topico_sub;
  257.  
  258. File configFile = SPIFFS.open("/config.json", "w");
  259. if (!configFile) {
  260. imprimirSerial(true, "Houve uma falha ao abrir o arquivo de configuracao para incluir/alterar as configuracoes.");
  261. }
  262.  
  263. json.printTo(Serial);
  264. json.printTo(configFile);
  265. configFile.close();
  266. }
  267.  
  268. imprimirSerial(false, "IP: ");
  269. imprimirSerial(true, WiFi.localIP().toString());
  270.  
  271. //Informando ao client do PubSub a url do servidor e a porta.
  272. int portaInt = atoi(servidor_mqtt_porta);
  273. client.setServer(servidor_mqtt, portaInt);
  274. client.setCallback(retorno);
  275.  
  276. //Obtendo o status do pino antes do ESP ser desligado
  277. lerStatusAnteriorPino();
  278. }
  279.  
  280. //Função de repetição (será executado INFINITAMENTE até o ESP ser desligado)
  281. void loop() {
  282. if (!client.connected()) {
  283. reconectar();
  284. }
  285. client.loop();
  286. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement