Manual

do

Maker

.

com

Dicas rápidas com Sming no ESP8266

Dicas rápidas com Sming no ESP8266

Pessoal, me perdoem por ter diminuido a freqüência dos artigos nessas últimas duas semanas. Prometo que a partir da semana que vem teremos belos e novos artigos divertidíssimos com sensores e controladores. A razão desse atraso nos artigos é justamente um dos projetos que peguei que acabei passando por essa dificuldade com o Sming, pois apesar de ser C++, tem características próprias. Devido a isso, vou deixar aqui algumas dicas sobre os pontos que me tomaram muitas horas.

Sobre o Sming

Nos 4 artigos anteriores você terá toda a informação necessária para compilar seu firmware para o ESP8266, seja ele qual for. Recomendo fortemente a utilização do Sming, sendo que uma das vantagens que você encontra nele é a possibilidade de utilizar o NetBeans como IDE, evitando assim a utilização da IDE do Arduino. Outra vantagem é o auto-complete para comandos, documentação e debug.

Escrever arquivos no Sming

Não é muito prático e tive problemas para escrever e ler um único byte em arquivo. Utilizei todos os métodos possíveis, mas a grande questão estava mesmo era na leitura. Para depurar, logo que escrevi o arquivo já fiz sua leitura, e para isso utilizei a função fileSeek(). Então consegui perceber que realmente o arquivo estava recebendo o respectivo conteúdo, por isso passei a utilizar essa função também no momento da leitura do arquivo em outro ponto. Para escrever com um pseudo debug, utilizei o seguinte código, devidamente comentado:

/*Aqui recebo uma string, nao da pra escapar disso porque vem do MQTT*/
void defineProgram(String flag){
    char data[5] = "";
    
    /*Sempre que essa função é chamada, o conteúdo do arquivo é trocado,
    portanto preferi excluir um arquivo pré-existente.*/
    if (fileExist(INI_FILE)){
        Serial.println("Removendo arquivo anterior...");
        fileDelete(INI_FILE);
    }
    /*A abertura do arquivo recebe as flags de leitura e escrita, além de
    garantir que o arquivo seja criado em caso de não existir.*/
    file_t program_ini = fileOpen(INI_FILE,eFO_ReadWrite | eFO_CreateIfNotExist);
    
    /*Qualquer valor negativo é erro. Comento no artigo mais adiante.*/
    if (program_ini < 0){
        Serial.print("Erro ao abrir arquivo");
        return;
    }
    
    /* Aqui só quero o primeiro byte, então pego da string e guardo em um
    char. Claro que poderia fazer isso diretamente na chamada abaixo, mas
    assim ficaria mais claro no momento do debug.*/
    char teste = flag.charAt(0);
    
    /*Repare que o formato de escrita é a indicação do descritor seguido
    seguido pelo endereço da variável contendo o valor (isso porque o 
    parâmetro esperado é um const char*). O último parâmetro é o número
    de bytes a escrever.*/
    fileWrite(program_ini,&teste,1);
    
    /*Agora o conteúdo deverá estar no arquivo. Para confirmar, vamos
    posicionar o cursor na posição desejada do arquivo, seguido pela
    direção que o cursor deve andar.*/
    fileSeek(program_ini,0,eSO_FileStart);

    /*Após o posicionamento do cursor, podemos fazer a leitura do
    arquivo. Sempre passamos o descritor do arquivo como primeiro
    parâmetro. No caso da leitura, seguindo o const char* e o número
    de bytes a ler.*/
    char wrote;
    int content = fileRead(program_ini,&wrote,1);
    /*Agora podemos apresentar na tela o conteúdo e ver se está tudo
    Ok!*/
    Serial.print("Content: ");
    Serial.println(content);
    Serial.print("Arquivo contem: ");
    Serial.println(wrote);
    
    /*Quando o arquivo não for mais utilizado, SEMPRE deve ser fechado.*/
    fileClose(program_ini);
    
    /* E o programLoader faz parte do programa principal, que apesar de 
    ainda não estar finalizado, já está no github do Ye Vesta.*/
    programLoader();
}

Interessante o bastante pra você? Eu passei uns 3 dias só lidando com as funcionalidades relacionadas ao controle de leitura e escrita de arquivos porque não encontrei uma explicação ou documentação clara o suficiente para executar diretamente, por isso acho válido dizer que essas dicas de hoje são preciosas tanto para mim quanto para você, caso pretenda utilizar Sming.

Ler arquivos no Sming

Uma leitura direta não estava dando certo. Também foi necessário posicionar o cursor no arquivo e definir a leitura em detalhes. O código para a leitura ficou desse jeito:

/* O parâmetro da função é string porque é o nome do arquivo.*/
void readFile(String fileToRead){
    /*Essa é uma função para ler os arquivos existentes no sistema de
    arquivos*/
    ls();
    Serial.println("Abrindo arquivo...");
    file_t fileChoose = fileOpen(fileToRead,eFO_ReadOnly);
    //Esses códigos de erro serão citados logo após esse bloco de código.
    if (fileChoose == -10002){
        Serial.println("Arquivo nao encontrado. Conteudo existente:");
        ls();
        return;
    }
    else if (fileChoose == -10010){
        Serial.println("Descritor de arquivo incorreto");
        ls();
        return;
    }
    char result[2] = {'\0'};
    Serial.println("Lendo conteudo...");
    
    fileSeek(fileChoose,0,eSO_FileStart);
    char wrote;
    int content = fileRead(fileChoose,&wrote,1);
    Serial.print("Conteudo do arquivo: ");
    Serial.println(wrote);
    fileClose(fileChoose);
}

Você deve ter reparado nos códigos de erro. Esse foi outro problema que tive, porque não entendia o que significavam e não encontrei esses códigos de erro na documentação, então procurei no framework do Sming e os encontrei no arquivo spiffs.h. Lá tem os defines de todos os códigos de erro e assim fica fácil entender o que está acontecendo.

Listar arquivos no sistema de arquivos spiffs

A primeira coisa que você deve ter em mente é que o sistema de arquivos fica em "/flash". Segunda coisa que você deve ter em mente é que o sistema de arquivos precisa ser montado de forma semelhante ao que é feito no Linux, utilzando a função "spiffs_mount()" dentro da função init(). Para listar os arquivos, fiz essa função:

void ls(){
    Vector<String> files = fileList();
    Serial.println("Listando arquivos:");
    for (int i=0; i<files.count(); i++){
        Serial.println(files.get(i) + " - " + String(fileGetSize(files.get(i))) + " Bytes");
    }
}

Ela devolve o nome do arquivo seguido pelo seu tamanho em Bytes. Repare que a função fileList() retorna um vetor de String, que seria algo como uma lista em Python ou um StringList em Qt.

Configuração do WiFi

Quando você inicia o sistema pela primeira vez, uma configuração se faz necessária; habilitar o modo station, desabilitar o modo access point etc. Para resolver essa questão de forma transparente, fiz a função de controle do WiFi:

void sta_if(){
    if (!WifiStation.isEnabled()){
        WifiStation.enable(true);
        Serial.println("Ativando interface sta...");
    }
    if (!WifiStation.isConnected()){
        WifiStation.config(MY_SSID,MY_PASSWD,true);
        Serial.println("Conectando ao SSID...");
    }
    if (WifiAccessPoint.isEnabled() && WifiStation.isConnected()){
        WifiAccessPoint.enable(false);
        Serial.println("Desativando AP...");
    }

    /* Essa função recebe duas outras funções especificadas por você.
    Em caso de sucesso, sucessful() é executado, senão failed() é
    chamado. O conteúdo dessas funções fica a seu critério, sendo a
    melhor forma de executar alguma rotina somente após garantir a
    conexão.*/
    WifiStation.waitConnection(successful,20,failed);
}

Esse programa é o controlador do kegerator que estou trabalhando nele e tão logo esteja funcional, disponibilizo video e um novo artigo a respeito.

Inscreva-se no nosso canal Manual do Maker no YouTube.

Também estamos no Instagram.

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.