Publicidade:

quarta-feira, 17 de junho de 2015

Arduino - Ethernet Shield + SDCard + Arquivos


Nesse vídeo mostro como incluir imagens, javascript, e outros tipos de arquivos e mídias na sua aplicação web baseada no Ethernet Shield W5100


31/10/2016 - Observação
Erro de login

Várias pessoas têm me relatado problemas no login, e eu não havia conseguido achar o problema, mas o Rodrigo (nos comentários abaixo) encontrou o problema e postou a solução. Vou manter o código original, e se quem tiver erros, siga o que o Rodrigo recomendou:

//Descobri o problema e mudei o meu código. 
//A função base64_encode não retorna corretamente o primeiro byte codificado, 
//por isso a função validar_usuario sempre recebia a string "out" errada. 
//Tive que trocar a função base64_encode para uma que retornasse o valor 
//inteiro de "out" codificado. Dai minha função validar_usuario ficou assim:

boolean validar_usuario(char * linebuf) {
  char usuario_senha[] = "admin:admin"; //"admin:admin";
  byte t = strlen(usuario_senha);
  int tamanhoEnc = (((t-1) / 3) + 1) * 4; //tamanho da string codificada
  char *out = base64_encode(usuario_senha, t);
  char out2[tamanhoEnc];

  for (t=0; t<(tamanhoEnc); t++) {
    out2[t] = linebuf[21+t];
  }
  return (strstr(out2, out)>0);
} 


Entenda o Mime Types:
https://pt.wikipedia.org/wiki/MIME

Lista de todos (acredito eu) os Mime Types de Arquivos:
http://www.sitepoint.com/web-foundations/mime-types-complete-list/



Para rodar a aplicação, copie os seguintes arquivos para dentro do SDCard



atmel.pdf

Qualquer arquivo PDF chamado atmel.pdf (cuidado com o tamanho do arquivo)

favicon.ico

qualquer arquivo do tipo ico, chamado favicon.ico

uno.jpg

qualquer imagem do tipo jpg, chamada uno.jpg


os demais arquivos, devem ser conforme mostrados abaixo


HTML - index.htm

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" type="text/css" href="/css.css">
  <script src="/js.js"></script>
</head>
<body onload="init();">
  <h1>ARDUINO - ETHERNET SHIELD + SDCARD + ARQUIVOS</h1>
  <br>
  <img src="/uno.jpg" />
  <br>
  <a href="/atmel.pdf">Download datasheet</a> | <a href='/logoff'>Logoff</a>
  <br>
</body>
</html>


Javascript - js.js

function init(){
  window.alert("hello world!");
}



CSS - css.css

body {
    background-color: #FAEBD7;
}
h1 {
    margin-left: 40px;
} 




Sketch - código-fonte:

/*
 Web Server - HTTP Autentication
 Baseado na versão de exemplo do Arduino.
 
   - exemplo que mostra como incluir html, css, 
   javascript e imagem em arquivos no sdcard e também
   como fazer download de um arquivo pdf do sdcard.
  
   by Fabiano A. Arndt (fabianoallex)
*/

/**********************************************************************************
************************************BIBLIOTECAS************************************
**********************************************************************************/

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

/**********************************************************************************
********************************FIM BIBLIOTECAS************************************
**********************************************************************************/

/**********************************************************************************
*************************ROTINAS USUARIO E SENHA***********************************
***********************************************************************************/

boolean validar_usuario(char * linebuf) {
  /*
  nesse exemplo o usuario e senha estão definidos dentro do código fonte.
  mas o usuário e senha poderiam ser autenticados de diversas maneiras,
  lendo os dados de um servidor web, arquivo texto, etc, bastando apenas atribuir
  o valor lido para a variável usuario_senha. 
  */
  
  char usuario_senha[] = "admin:admin";                           //usuario e senha para acessar a pagina
  int t = strlen(usuario_senha);
  
  int tamanhoEnc = (((t-1) / 3) + 1) * 4;   //tamanho da string codificada
  char out[tamanhoEnc];
  base64_encode(out, usuario_senha, t+1 );
  
  //---desconta é usado pra eliminar os caracteres '='
  int desconta = 0;
  if ((t%3) == 1) { desconta = 2; }
  if ((t%3) == 2) { desconta = 1; }
  
  char out2[tamanhoEnc-desconta];
  
  byte i;
  for (i=0; i<(tamanhoEnc-desconta);i++){ out2[i] = out[i]; }
  out2[i] = '\0';
  
  return ( strstr(linebuf, out2)>0 );
}

/**********************************************************************************
*************************FIM ROTINA USUARIO E SENHA********************************
***********************************************************************************/

/****************************************************************************************
 ****************************SD CARD INICIO***********************************************
 ****************************************************************************************/

#define PIN_SD_CARD 4
 
boolean iniciar_sd_card() {
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
   
  if (!SD.begin(PIN_SD_CARD)) { return false; }
   
  return true;
}

 
/****************************************************************************************
 ****************************SD CARD FIM**************************************************
 ****************************************************************************************/
 

/**********************************************************************************
***********************************PAGINAS HTML************************************
***********************************************************************************/
EthernetServer * server;

void write_from_file(EthernetClient &client, char * filename){
  File webFile = SD.open(filename);
  if (webFile) {
    while(webFile.available()) {
      client.write(webFile.read()); 
    }
    webFile.close();
  } else {
    Serial.print("Erro SD CARD: ");
    Serial.println(filename);
  }
}

void iniciar_ethernet_01(){
  byte ip[4]      = {192,168,200,25};                    //definir aqui o ip
  byte gateway[4] = {192,168,200,254};
  byte subnet[4]  = {255,255,255,0};
  byte mac[6]     = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
  int  porta      = 80;

  server = new EthernetServer(porta);

  Ethernet.begin(mac, ip, gateway, subnet);         //caso necessario gateway utilizar essa linha
  server->begin();
}

void iniciar_ethernet_02(){
  byte ip[4]      = {192,168,200,25};                    //definir aqui o ip
  byte mac[6]     = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
  int  porta      = 80;

  server = new EthernetServer(porta);

  Ethernet.begin(mac, ip);
  server->begin();
}

void iniciar_ethernet() {              //escolher apenas um dos dois modos de iniciar o ethernet shield
  iniciar_ethernet_01();               //inicia com ip, gateway, mascara e porta
  //iniciar_ethernet_02();             //inicia só com ip e porta
}

void html_cab_200_ok(EthernetClient &client){
  
  client.println(F("HTTP/1.1 200 OK\n"
                   "Content-Type: text/html\n"
                   "Connection: keep-alive\n\n"));
}


void html_logoff(EthernetClient &client){
    client.print(F(
                 "HTTP/1.1 401 Authorization Required\n"  
                 "Content-Type: text/html\n"  
                 "Connnection: close\n\n"  
                 "<!DOCTYPE HTML>\n"  
                 "<html><head><title>Logoff</title>\n"  
                 "<script>document.execCommand('ClearAuthenticationCache', 'false');</script>"  //IE logoff
                 "<script>try {"                                                                //mozila logoff
                 "   var agt=navigator.userAgent.toLowerCase();"
                 "   if (agt.indexOf(\"msie\") != -1) { document.execCommand(\"ClearAuthenticationCache\"); }"
                 "   else {"
                 "     var xmlhttp = createXMLObject();"
                 "      xmlhttp.open(\"GET\",\"URL\",true,\"logout\",\"logout\");"
                 "     xmlhttp.send(\"\");"
                 "     xmlhttp.abort();"
                 "   }"
                 " } catch(e) {"
                 "   alert(\"erro ao fazer logoff\");"
                 " }"
                 "function createXMLObject() {"
                 "  try {if (window.XMLHttpRequest) {xmlhttp = new XMLHttpRequest();} else if (window.ActiveXObject) {xmlhttp=new ActiveXObject(\"Microsoft.XMLHTTP\");}} catch (e) {xmlhttp=false;}"
                 "  return xmlhttp;"
                 "}</script>"
                 "</head><body><h1>Voce nao esta mais conectado</h1></body></html>\n"));
}

void html_autenticar(EthernetClient &client) {
  client.print(F("HTTP/1.1 401 Authorization Required\n"  
               "WWW-Authenticate: Basic realm=\"Area Restrita\"\n"  
               "Content-Type: text/html\n"  
               "Connnection: close\n\n"  
               "<!DOCTYPE HTML>\n"  
               "<html><head><title>Error</title>\n"  
               "</head><body><h1>401 Acesso nao autorizado</h1></body></html>\n"));
}

void html_autenticado(EthernetClient &client, char * filename){
  client.println(F("HTTP/1.1 200 OK\n"
                   "Content-Type: text/html\n"
                   "Connection: keep-alive\n"));

  write_from_file(client, filename);
}


void js_file(EthernetClient &client, char * filename){
  client.println(F("HTTP/1.1 200 OK\n"
                   "Content-Type: text/javascript\n"
                   "Connection: keep-alive\n"));

  write_from_file(client, filename);
}

void css_file(EthernetClient &client, char * filename){
  client.println(F("HTTP/1.1 200 OK\n"
                   "Content-Type: text/css\n"
                   "Connection: keep-alive\n"));

  write_from_file(client, filename);
}

void favicon_file(EthernetClient &client, char * filename){
  client.println(F("HTTP/1.1 200 OK\n"
                   "Content-Type: image/x-icon\n"
                   "Connection: keep-alive\n"));

  write_from_file(client, filename);
}


void pdf_file_download(EthernetClient &client, char * filename){
  client.println(F("HTTP/1.1 200 OK\n"
                   "Content-Type: application/download\n"
                   "Connection: close\n"));
    
  write_from_file(client, filename);
}

void jpg_file(EthernetClient &client, char * filename){
  client.println(F("HTTP/1.1 200 OK\n"
                   "Content-Type: file/jpg\n"
                   "Connection: close\n"));
    
  write_from_file(client, filename);
}


void exec_ethernet() {
  EthernetClient client = server->available();
  if (client) {
    char linebuf[80];
    memset(linebuf, 0, sizeof(linebuf));
    
    int     charCount          = 0;
    boolean autenticado        = false;
    boolean currentLineIsBlank = true;
    boolean logoff             = false;
    boolean indCss             = false;
    boolean indJs              = false;
    boolean indPdfDataSheet    = false;
    boolean indJpgUno          = false;
    boolean indFavicon         = false;
    
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        
        linebuf[charCount] = c;
        
        if (charCount<sizeof(linebuf)-1) { charCount++; }
        Serial.write(c);
        
        if (c == '\n' && currentLineIsBlank) {
          if (autenticado && !logoff ) {
            if (indJs){
              js_file(client, "js.js");                          //js file
            } else if(indCss){
              css_file(client, "css.css");                       //css file
            } else if(indPdfDataSheet){
              pdf_file_download(client, "atmel.pdf");        //datasheet download
            } else if(indJpgUno){
              jpg_file(client, "uno.jpg");                       //jpg file
            } else if(indFavicon){
              jpg_file(client, "favicon.ico");                   //icone do browser
            } else {
              html_autenticado(client, "index.htm");             //página inicial
            }
          } else {
            logoff ? html_logoff(client) : html_autenticar(client);
          }
          break;
        }
        if (c == '\n') { 
          currentLineIsBlank = true;               
          
          if (strstr(linebuf, "GET /logoff"         )>0 ) { logoff = true; }
          if (strstr(linebuf, "Authorization: Basic")>0 ) { if ( validar_usuario(linebuf) )   {  autenticado = true;   } }  
          if (strstr(linebuf, "GET /css.css"        )>0 ) { indCss = true; }
          if (strstr(linebuf, "GET /js.js"          )>0 ) { indJs = true; }
          if (strstr(linebuf, "GET /atmel.pdf"      )>0 ) { indPdfDataSheet = true; }
          if (strstr(linebuf, "GET /uno.jpg"        )>0 ) { indJpgUno = true; }
          if (strstr(linebuf, "GET /favicon.ico"    )>0 ) { indFavicon = true; }
          
          
          memset(linebuf, 0, sizeof(linebuf));
          charCount = 0;
        } else if (c != '\r') {
          currentLineIsBlank = false;    // you've gotten a character on the current line
        }
      }
    }
    
    delay(1);           
    client.stop();      
  }
}
/**********************************************************************************
**************************************** FIM PAGINAS HTML**************************
***********************************************************************************/


/**********************************************************************************
*************************BASE 64 CODE/DECODE DO USUARIO E SENHA********************
***********************************************************************************/

void a3_to_a4(unsigned char * a4, unsigned char * a3);
void a4_to_a3(unsigned char * a3, unsigned char * a4);
unsigned char b64_lookup(char c);

int base64_encode(char *output, char *input, int inputLen) {
  const char b64_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  int i=0, j=0, encLen=0;
  unsigned char a3[3], a4[4];

  while(inputLen--) {
    a3[i++] = *(input++);
    if(i == 3) {
      a3_to_a4(a4, a3);
      for(i=0; i<4; i++) { output[encLen++] = b64_alphabet[a4[i]]; }
      i = 0;
    }
  }

  if (i) {
    for(j = i; j < 3; j++)     { a3[j] = '\0';                           }
    a3_to_a4(a4, a3);
    for(j = 0; j < i + 1; j++) { output[encLen++] = b64_alphabet[a4[j]]; }
    while((i++ < 3))           { output[encLen++] = '=';                 }
  }
  output[encLen] = '\0';
  return encLen;
}

/*
int base64_decode(char * output, char * input, int inputLen) {
  int i = 0, j = 0;
  int decLen = 0;
  unsigned char a3[3];
  unsigned char a4[4];
  while (inputLen--) {
    if (*input == '=') { break; }
    a4[i++] = *(input++);
    if (i == 4) {
      for (i = 0; i <4; i++)  { a4[i] = b64_lookup(a4[i]); }
      a4_to_a3(a3,a4);
      for (i = 0; i < 3; i++) { output[decLen++] = a3[i];  }
      i = 0;
    }
  }

  if (i) {
    for (j=i; j<4; j++)   { a4[j] = '\0';             }
    for (j=0; j<4; j++)   { a4[j] = b64_lookup(a4[j]);}
    a4_to_a3(a3,a4);
    for (j=0; j<i-1; j++) { output[decLen++] = a3[j]; }
  }
  output[decLen] = '\0';
  return decLen;
}
*/

//int base64_enc_len(int plainLen) {
//  int n = plainLen;
//  return (n + 2 - ((n + 2) % 3)) / 3 * 4;
//}

//int base64_dec_len(char * input, int inputLen) {
//  int i = 0;
//  int numEq = 0;
//  for(i = inputLen - 1; input[i] == '='; i--) { numEq++; }
//  return ((6 * inputLen) / 8) - numEq;
//}

void a3_to_a4(unsigned char * a4, unsigned char * a3) {
  a4[0] = (a3[0]  & 0xfc) >> 2;
  a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
  a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
  a4[3] = (a3[2] & 0x3f);
}

//void a4_to_a3(unsigned char * a3, unsigned char * a4) {
//  a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
//  a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
//  a3[2] = ((a4[2] & 0x3) << 6) + a4[3];
//}

unsigned char b64_lookup(char c) {
  if(c >='A' && c <='Z') return c - 'A';
  if(c >='a' && c <='z') return c - 71;
  if(c >='0' && c <='9') return c + 4;
  if(c == '+') return 62;
  if(c == '/') return 63;
  return -1;
}

/**********************************************************************************
*************************FIM BASE 64 CODE/DECODE DO USUARIO E SENHA****************
***********************************************************************************/

/**********************************************************************************
**************************************** VOID / LOOP ******************************
***********************************************************************************/

void setup() {
  Serial.begin(9600);
  iniciar_sd_card();
  iniciar_ethernet();
}

void loop() {
  exec_ethernet();
}

/**********************************************************************************
*************************************FIM VOID / LOOP*******************************
***********************************************************************************/

36 comentários:

  1. Fabiano, poderia passar onde entraria o código no arquivo.ino para acionar as lâmpadas por exemplo.

    ResponderExcluir
    Respostas
    1. no html vc vai incluir o código que envia os comandos que vc quer executar, algo assim:

      < form method="GET" action="/comandos" >
      < input type="checkbox" name="led7" > Ligar led 7



      < input type="submit" value="Submit">
      < /form >


      e no scketch vc vai incluir um if nessa lista abaixo:

      if (strstr(linebuf, "GET /logoff" )>0 ) { logoff = true; }
      if (strstr(linebuf, "Authorization: Basic")>0 ) { if ( validar_usuario(linebuf) ) { autenticado = true; } }
      if (strstr(linebuf, "GET /css.css" )>0 ) { indCss = true; }
      if (strstr(linebuf, "GET /js.js" )>0 ) { indJs = true; }
      if (strstr(linebuf, "GET /atmel.pdf" )>0 ) { indPdfDataSheet = true; }
      if (strstr(linebuf, "GET /uno.jpg" )>0 ) { indJpgUno = true; }
      if (strstr(linebuf, "GET /favicon.ico" )>0 ) { indFavicon = true; }
      if (strstr(linebuf, "GET /comandos" )>0 ) { executa_comandos(linebuf); }


      veja que a ultima linha acima foi incluida pra tratar os comandos

      ai vc cria a função que ira tratar os comandos recebidos

      void executa_comandos(char * linebuf) {
      pinMode(7, OUTPUT);
      if (strstr(linebuf, "led13=on" )>0 ) {
      digitalWrite(7, LOW);
      } else {
      digitalWrite(7, HIGH);
      }

      //aqui vc coloca os demais comandos que serão recebidos do html
      }


      qualquer duvida só falar.

      Excluir
    2. corrigindo...

      void executa_comandos(char * linebuf) {
      pinMode(7, OUTPUT);
      if (strstr(linebuf, "led7=on" )>0 ) {
      digitalWrite(7, HIGH);
      } else {
      digitalWrite(7, LOW);
      }

      //aqui vc coloca os demais comandos que serão recebidos do html
      }

      Excluir
    3. eu estou apanhando nesse mesmo lugar!!! por favor poderia me explicar melhor?
      meu email é gtautomotivo@hotmail.com

      muito obrigado
      william

      Excluir
    4. to fazendo um artigo novo sobre ethernet shiedl, com mais alguns detalhes, mas to meio sem tempo de terminar, mas assim que der ele vai tá no ar, acho que vai ajudar nessas dúvidas.

      Excluir
  2. Olá fabiano como eu conseguiria ler um sensor na porta analógica? Poderia me mandar um email com o código fbramos27@gmail.com

    ResponderExcluir
  3. Nesta linha "//aqui vc coloca os demais comandos que serão recebidos do html" os "comandos" são obrigatórios ou opcionais?
    Se obrigatórios, poderia dizer quais são?

    ResponderExcluir
    Respostas
    1. na verdade são os parâmetros que serão passados do html para o arduino. no exemplo, led7=on significa que é pra ligar um led. Ou seja, tem um parâmetro que é passado, e que quando recebido ele executa um comando, que seria ligar o led, poderia ser qualquer outra coisa. Não são obrigatórios.

      Excluir
    2. Fabiano, muito obrigado pela atenção e presteza.

      Já consegui acionar até 3 relés com os códigos "htm" inseridos no próprio sketch. Mas, utiliza muita memória e não consigo aumentar a quantidade de relés.

      Estou tentando fazer acionar 4 relés e para isso preciso escrever os códigos da página "htm", gravar no SDCard e trazer os comandos para o sketch interpretar.

      Caso você possua alguma coisa que possa compartilhar faça esse favor. Vou continuar procurando solução, caso obtenha, posto aqui.

      De antemão, mais uma vez, obrigado!


      Excluir
    3. to fazendo um artigo novo sobre ethernet shiedl, com mais alguns detalhes, mas to meio sem tempo de terminar, mas assim que der ele vai tá no ar, acho que vai ajudar nessas dúvidas.

      Excluir
    4. Bom dia Fabiano.
      Seria de grande ajuda se você puder explicar sobre este ponto.
      Preciso enviar um sinal de valor lógico 1 por um botão contido nessa página.
      Parabéns pela qualidade dos seus trabalhos!

      Excluir
    5. Lembrando que a sua explicação a esta questão ao colega que lhe perguntou eu testei exatamente e não acendeu o led. Obrigado.

      Obs: existem outros exemplos que acende um led pelo webserver do arduino, porém é mais complicado de achar quando a página é gerada pelo código html dentro do cartão SD.

      Excluir
    6. a questão aqui é que exige conhecimentos um pouco mais avançados. No meu exemplo, to mostrando como carregar arquivos do cartão, no caso dos arquivos html, eles são estáticos, não dinâmicos, apenas pra exemplificar como carregar algo do cartão de memória.

      a ideia é mostrar alguns conceitos, e não aprofundar tudo que é possível fazer.

      pra incluir dinamicidade às páginas é preciso usar outros recursos, como javascript, ajax, requisições assíncronas, etc.

      mas isso já são questões de desenvolvimento web, e eu não queria misturar os conceitos. Seria interessante buscar esses conhecimentos sem serem especificamente voltados para Arduino. Por isso não quis misturar as coisas, pra não bagunçar.

      eu to com outro artigo pra terminar que queria tratar um pouco desses outros detalhes, mas to sem tempo, e por enquanto ainda não tenho previsão de terminar.

      Excluir
  4. Fantastic exemplo! ¡Fantástico ejemplo! Fantastic example!

    ResponderExcluir
  5. boa tarde
    muito bom o exemplo criado por voce
    e temos que agradecer a iniciativa de compartilhar seu conhecimento
    seria possivel me auxiliar em uma duvida
    quando envio valor led7=on toda pagina e recarregada

    ResponderExcluir
    Respostas
    1. bom dia, valeu. quanto a sua dúvida, só verificando o código pra eu conseguir saber o que pode estar errado. qualquer coisa manda um email pra fabianoallex@gmail.com. abraço

      Excluir
  6. Boa noite.
    Tentei usar seu código para um teste, e não sai da pagina de login.
    oque pode ser?

    ResponderExcluir
    Respostas
    1. ta dando alguma mensagem de erro?

      Excluir
    2. Boa Noite....

      Então, Não aparece mensagem de erro... apos fazer a autenticação (admin admin) ele voltar na pagina para autenticar novamente, vira um ciclo.

      Estou testando com o arduino mega 2560 e shield Ethernet w5100
      muda alguma configuração por ser no mega?



      Excluir
    3. O meu está com o mesmo problema. Só fica pedindo usuario e senha....

      Excluir
    4. O meu uno também está com o mesmo problema.

      Excluir
    5. Acho que o problema está na função validar_usuario, pois ela nunca retorna true. Tentei debugar o código, e aparentemente a string out2 nunca está contida na string linebuf. Alguma luz aí?

      Excluir
    6. Descobri o problema e mudei o meu código. A função base64_encode não retorna corretamente o primeiro byte codificado, por isso a função validar_usuario sempre recebia a string "out" errada. Tive que trocar a função base64_encode para uma que retornasse o valor inteiro de "out" codificado. Dai minha função validar_usuario ficou assim:

      boolean validar_usuario(char * linebuf) {
      char usuario_senha[] = "admin:admin"; //"admin:admin";
      byte t = strlen(usuario_senha);
      int tamanhoEnc = (((t-1) / 3) + 1) * 4; //tamanho da string codificada
      char *out = base64_encode(usuario_senha, t);
      char out2[tamanhoEnc];

      for (t=0; t<(tamanhoEnc); t++) {
      out2[t] = linebuf[21+t];
      }
      return (strstr(out2, out)>0);
      }

      Excluir
    7. obrigado Rodrigo, várias pessoas tem relatado esse problema, mas ainda não tinha conseguido um tempo pra verificar o que poderia ser. Vou editar no artigo pra quem estiver com problema seguir sua solução.

      Excluir
    8. Rodrigo, tentei esse cod que vc deixou acima, mas da um erro, -> invalid convertion fron 'byte {aka unsigned char}' to 'char*'[-fpermissive] <- esse erro da na linha : char out = base64_encode(usuario_senha, t); , se puder me ajudar eu agradeço

      Excluir
  7. Bom dia amigo. Preciso enviar dados de um banco de dados para o meu arduino, como por exemplo o usuário e senha. Você tem ideia de como eu fazer? Consigo enviar do arduino para o banco de dados o qual estão atrelados por um servidor php, mas o contrário eu não consigo.
    Gostaria de saber se existe algum comando ou algo do tipo.

    Muito obrigado.

    ResponderExcluir
  8. Boa tarde Fabiano, ainda não consegui fazer com que meu html acione minha saída, teria como você mandar um exemplo para meu email..
    eduardoewertoncruzdelima@gmail.com
    Muito show o post, porém ainda tenho dificuldades com a programação.
    Vlw

    ResponderExcluir
    Respostas
    1. Olá Fabiano. Sei que não é exatamente sobre o assunto desse post, mas estou a bastante tempo pesquisando e até agora não achei nenhuma resposta descente. Como faço para jogar valores de variáveis de sensores, para uma pagina HTML que esta sendo lida de dentro do cartão SD(index.htm)? obs: estou usando o shield ethernet.

      Excluir
  9. Bom dia Fabiano/Rodrigo,

    Ainda estou com o probleminha do login, ja fiz a alteração da função validar o usuario, quanto a alteração da função base64_encode não sei como editá-la, poderia me ajudar com o código?

    ResponderExcluir
  10. Boa tarde! O meu problema é : entro com senha e login, mas ele entra em uma tela branca, poderia me ajudar ?

    ResponderExcluir
  11. Ola boa tarde!
    Fabiano eu estou usando a placa Mega 2560 com Eth Shield e não estou tendo sucesso em rodar este seu escript. Vi que no codigo você usa os pinos 4 e 10 do arduino UNO para habilitar/desabiltar o cartão SD e a ETH. Me pareceu que no Mega 2560 o pino 53 tem a mesma função do pino 4 do UNO, mas o pino 10, não consigo encontrar equivalente. Tambem não sei se só seria este dois os pontos. Gravei os arquivos no SD e no PC estão funcionando como esperado, porem no Arduino não passam do Login, rejeitando o usuario e senha admin:admin.. Vc pode me ajudar?? Obrigado

    ResponderExcluir
  12. Galera, consegui achar a função que transforma o login_senha para base64.
    Primeiro: Substituam a função validar_usuario exatamente como o Rodrigo postou.
    Segundo: Tirem toda aquela parte entre /**** BASE 64 ****/ e /**** FIM DA BASE64 ****/
    Terceiro: Coloquem o codigo abaixo nesse lugar. PS: obrigado ao Fabiano por postar esse código para nós!!!

    static const char b64all[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
    "ghijklmnopqrstuvwxyz0123456789+/";

    const char *base64_encode(const char *original, int length) {
    // Se o tamanho não for informado, consideramos uma string bem
    // formada
    if (length == 0)
    length = strlen(original);

    // Inteiro com o tamanho do código a ser gerado
    int b64length = ((length + 2) / 3) * 4 + 1;

    // Contadores para percorrer as strings
    int i=0, j=0;

    // Alocando memória para o código
    char *b64 = (char *) malloc(sizeof(char) * b64length);
    memset(b64, 0, b64length);

    while (i < length) {
    // Codifica um grupo de três bytes...
    _encode(
    (uint8_t *) b64 + j,
    (const uint8_t *) original + i,
    (length - i)
    );

    // E segue para o próximo grupo
    i += 3;
    j += 4;
    }

    // Retorna o código
    return (const char *) b64;
    }

    void _encode(uint8_t *dest, const uint8_t *src, int len) {
    // Menor que 1, nada a fazer
    if (len < 1)
    return;

    // Dados a serem retornados
    int aux[] = { 0, 0, 0, 0 };

    // Primeiro elemento: os 6 bits mais significativos do primeiro
    // byte
    aux[0] = src[0] >> 2;

    // Segundo elemento: os 2 bits menos significativos do primeiro e
    // os quatro bits mais significativos do segundo byte
    aux[1] = (src[0] & 0x03) << 4;

    if (len > 1) {
    // SE houver um segundo...
    aux [1] |= (src[1] & 0xf0) >> 4;

    // Terceiro elemento: os quatro bits menos significativos do
    // segundo e os dois mais significativos do terceiro byte
    aux [2] = (src[1] & 0x0f) << 2;

    if (len > 2) {
    // Se houver um terceiro...
    aux[2] |= src[2] >> 6;

    // Quarto elemento: os seis bits menos significatos do
    // terceiro byte
    aux[3] = src[2] & 0x3f;
    }
    }

    // Codifica agora os valores numéricos para string
    dest[0] = b64all[aux[0]];
    dest[1] = b64all[aux[1]];
    dest[2] = '=';
    dest[3] = '=';
    if (len > 1) {
    dest[2] = b64all[aux[2]];
    if (len > 2)
    dest[3] = b64all[aux[3]];
    }
    }

    ResponderExcluir
    Respostas
    1. aqui pra mim mesmo seguindo isso ainda da errado

      Excluir
  13. why i cant use admin admin for enter ?

    ResponderExcluir