Integre ESP8266 e Android usando o reconhecimento de voz no Android

Tempo de leitura: 6 minutes

Este tutorial de programação ESP8266 descreve como usar a integração do ESP8266 e do Android usando comandos de voz. Em outras palavras, neste artigo, usaremos nossa voz para enviar um conjunto de comandos a um dispositivo IoT. Durante esta postagem, construiremos um projeto IoT ativado por voz usando ESP8266 e Android. Este é um tópico interessante porque este projeto usa uma maneira diferente de interagir com o dispositivo IoT. Normalmente, estamos acostumados a interagir com um dispositivo usando uma interface de usuário simples exposta pelo dispositivo ou usando um aplicativo de smartphone que envia comandos para o dispositivo

 

Como usar ESP8266 com Android

A ideia que está por trás deste tutorial de programação do ESP8266 é a integração entre o ESP8266 e o Android usando comandos de voz. Usando esses comandos, é possível controlar um dispositivo como o Arduino ou ESP8266. Para construir este projeto ativado por voz, desenvolvemos um aplicativo Android que é o meio que captura a voz do usuário e a transforma em um conjunto de comandos que são enviados para o ESP8266. A imagem abaixo descreve a visão geral do projeto:

Em mais detalhes, este projeto é feito por dois subsistemas diferentes:

  • App Android
  • Aplicativo IoT

O app Android se preocupa em interagir com o usuário e ouvir os comandos de voz. Em seguida, o aplicativo traduz os comandos de voz em comandos que o dispositivo IoT pode entender. Neste artigo, como dispositivo IoT, usaremos um WeMos ESP8266 que controla um anel NeoPixel. Você pode usar um Arduino Uno em vez do ESP ou um MKR1000.

 

Como desenvolver um aplicativo de reconhecimento de voz para Android para conectar ESP8266 e Android

A primeira etapa neste projeto é desenvolver um aplicativo Android que reconhece a fala do usuário. Felizmente, o Android oferece um sistema integrado que é capaz de reconhecer as palavras do usuário. A interface de usuário do aplicativo é muito simples. Existe apenas um botão que usamos para começar a enviar comandos:

O layout é muito simples, conforme mostrado abaixo:

<android.support.constraint.ConstraintLayout
   xmlns:android=’http://schemas.android.com/apk/res/android’
   xmlns:app=’http://schemas.android.com/apk/res-auto’
   xmlns:tools=’http://schemas.android.com/tools’
   android:layout_width=’match_parent’
   android:layout_height=’match_parent’
   tools:context=br.com.capsistema.voice.MainActivity’
   android:id=’@+id/mainView’
   android:background=’@drawable/bg_gradient’>

<Button android:layout_width=’wrap_content’
   android:layout_height=’wrap_content’
   app:layout_constraintLeft_toRightOf=’parent’
   app:layout_constraintRight_toLeftOf=’parent’
   android:text=’Enviar comando’
   android:id=’@+id/btnCommand’
   app:layout_constraintBottom_toBottomOf=’parent’
   android:layout_marginBottom=’15dp’/>

</android.support.constraint.ConstraintLayout>

A próxima etapa é substituir no MainActivity.java o método onCreate:

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);  
   setContentView(R.layout.activity_main);
   btn = (Button) findViewById(R.id.btnCommand);
   btn.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
         startVoiceCommand();
      }
}

onde startVoiceCommand () é o método que controla a interação de voz com o usuário. Neste contexto, para capturar a voz do usuário, o aplicativo usa um Intent delegando todo o trabalho árduo ao sistema operacional Android:

private void startVoiceCommand() {
  Log.d(TAG, &quot;Starting Voice intent…&quot;);
  Intent i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
  i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
  RecognizerIntent.LANGUAGE_MODE);
  i.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
  i.putExtra(RecognizerIntent.EXTRA_PROMPT, "Diga-me, estou pronto!");   
  try {
     startActivityForResult(i, REQ_SPEECH_RESULT);
   } catch (Exception e) {
     Snackbar.make(v, "Fala para texto não suportada",
     Snackbar.LENGTH_LONG).show();
   }
}

Este método é muito simples, ele invoca o intent RecognizerIntent.ACTION_RECOGNIZE_SPEECH fornecendo alguns parâmetros de configuração como o local atual e a mensagem que queremos mostrar ao usuário. Quando o usuário clica no botão, o aplicativo mostra a caixa de diálogo aguardando a entrada de voz. Por fim, o aplicativo inicia o intent aguardando o resultado:

Para isso, o aplicativo substitui o método onActivityResult:

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);
   // Verifique o código de solicitação
   if (requestCode == REQ_SPEECH_RESULT) {
      Log.d(TAG, "Solicitar resultado de fala..");
      ArrayList<String> results =
      data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
      String command = results.get(0);
      Log.d(TAG, "Comando atual["+command+"]");
      // Agora enviamos comandos para o dispositivo IoT
    }
}

No método acima, o aplicativo extrai o comando e de acordo com ele invoca o ESP8266 para definir a cor dos LEDs do anel. Neste exemplo, o aplicativo de voz Android IoT lida com comandos simples como Vermelho, Verde, Azul e assim por diante.

 

Troca de dados entre ESP8266 e app Android

Nesta etapa deste projeto de programação ESP8266, implementamos a comunicação de rede entre o Android e o ESP8266. Agora, podemos supor que o ESP8266 expõe um método invocado pelo aplicativo Android para definir as cores do anel. Nesse contexto, podemos supor que o ESP8266 expõe uma API RESTful. Para invocar essa API, o aplicativo Android usa uma conexão HTTP.

Para tanto, é necessário criar uma nova classe chamada IoTConnectionHandler que trate de todos os detalhes da rede. A classe é mostrada abaixo:

public class IoTConnectionHandler {
  private static IoTConnectionHandler me;
  private OkHttpClient client;
  private static final String TAG = IoTConnectionHandler.class.getName();
  private static final String IOT_URL ="http://192.168.1.9:8080/ring?param=0";

  private IoTConnectionHandler() {
     client = new OkHttpClient();
  }

  public static IoTConnectionHandler getInstance() {
    if (me == null)
       me = new IoTConnectionHandler();
    return me;
  }

  public void sendData(String data) {
     Request req = new Request.Builder().url(IOT_URL + data).build();
     client.newCall(req).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
          Log.e(TAG, "Erro de conexão", e);
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
           Log.i(TAG, "Comando enviado");
        }
      });
   }
}

É muito simples e usa a biblioteca OkHTTP. Observe que o parâmetro data contém o código hexadecimal de cores recuperado do comando de voz. A próxima parte é implementar o lado IoT do projeto que recebe o código hexadecimal de cores usando a API exposta pelo dispositivo e define a cor dos LEDs.

 

Integrando ESP8266 e Android

Nesta etapa deste dispositivo IoT controlado por voz, desenvolveremos o código necessário para:

  • expor uma API em ESP8266 invocada pelo aplicativo Android
  • controlar um anel RGB Neopixel

Antes de mergulhar nos detalhes do projeto IoT, é útil saber como conectar o ESP8266 ao anel RGB Neopixel:

Para simplificar o desenvolvimento de código, os dispositivos IoT usam estas duas bibliotecas:

O primeiro é usado para controlar o anel de LEDs, enquanto a segunda biblioteca é necessária para expor algumas funções no sketch como API.

O código abaixo é o sketch:

#include <Adafruit_NeoPixel.h>
#include <ESP8266WiFi.h>
#include <aREST.h>
#define PIN D2
#define NUMS 12
#define SERVER_PORT 8080

// anéis de neopixel
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(12, PIN, NEO_GRB + NEO_KHZ800);
aREST rest = aREST();

char *ssid = "xxxxx"
char *pwd = "xxx"

// Vamos criar o servidor
WiFiServer server(SERVER_PORT);

void setup() {
  Serial.begin(9600);
  pixels.begin();
  pixels.setBrightness(85);

  // Registre a função
  rest.function("ring", setColor);
  WiFi.begin(ssid, pwd);
  Serial.println("Conectando ao WiFi…");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Tente novamente….");
  }
  Serial.println("Wi-Fi conectado ...");
  // vamos iniciar o servidor server.begin();
}

void loop() {
  WiFiClient client = server.available();
  if (!client) { return ; }
    while (!client.available()) { delay(1); }
    rest.handle(client);
  }

  int setColor(String color) {
  Serial.println(&quot;Hex color [‘ + color + ‘]’);
  long tmpColor = strtol( ‘(‘#’ + color)[1], NULL, 16);
  Serial.println("Int ["+String(tmpColor)+"]");
  int r = tmpColor << 16;
  int g = tmpColor << 8 && 0xFF;
  int b = tmpColor & 0xFF;
  Serial.print(‘Red [‘ + String(r) +’]’);
  Serial.print(‘Green [‘ + String(g) + ‘]’);
  Serial.println(‘Blue [‘ + String(b) +’]’);
  for (int i = 0; i < 12; i++)
     pixels.setPixelColor(i, pixels.Color(r,g,b));
  pixels.show();
  return 1;
}

Em detalhes, no início, o sketch tenta se conectar à rede WiFi. Para tal, tem de fornecer o SSID WiFi e a palavra-passe. Uma vez que a conexão é estabelecida, o sketch configura o servidor e sua porta. Além disso, declara a função que desejamos exportar como API.

A última parte é o método usado para controlar o anel de Neopixel.

Assim que enviamos um comando de voz para o aplicativo do dispositivo IoT mostra estes registros:

 

Resumo

No final deste tutorial de programação do ESP8266, você sabe como usar a voz para controlar um dispositivo IoT que integra o ESP8266 e o aplicativo Android. Em mais detalhes, você explorou como conectar um aplicativo Android com um ESP8266 e como usar a voz para interagir com ele.

Visits: 2 Visits: 1194623