Objetivo:
Comunicar un dispositivo Android y una Raspberry Pi por medio de sockets para encender y apagar un led a través de la red local usando.
Materiales:
- 1 LED
- Raspberry Pi [Cualquier modelo]
- Resistor 330 Ohms
- Protoboard
- Jumper Hembra Macho [para la conexión Raspberry Pi a protoboard]
Breve explicación:
El método usado para la comunicación entre los dispositivos esta vez fueron los sockets.
La Raspberry Pi corre un pequeño script en python que está a la espera de una conexión entrante, que en nuestro caso sería el dispositivo Android. Cuando recibe una conexión, la RPi crea un nuevo socket, un canal de comunicación, donde recibe un caracter enviado por el dispotivo Android. Hay dos posibles caracteres que pueden ser enviados, 'A' o 'B'. Si se recibe A, el LED enciende; con B, éste se apaga.
En la aplicación en Android, tenemos tres elementos sencillos: dos campos de texto y un botón. El primero para la IP de la RPi, el segundo para el puerto (Nota: El número de puerto debe ser el mismo que el declarado en el script de la RPi, y se recomienda uno que sea distinto a los reservados para otras conexiones. En este caso, yo opté por el puerto 1000) y, finalmente, el botón de On/Of. Este botón es el encargado de llamar a la función que tratará de conectarse a la RPi y enviar los datos. El socket se destruye al finalizar la comunicación, así que cada vez que presionamos el botón se crea uno nuevo.
Ejemplo de uso:
Esquemático y conexiones:
No he podido crear un esquemático por falta de tiempo, en cuánto pueda lo haré.
El LED se conecta al resistor de 330 Ohms y ésta está conectada al GPIO 17 de la RPi, el número de pin puede ser cambiado por cualquier otro disponible. El cátodo del LED se conecta a algún pin GND de la RPi.
Esquemático de GPIO:
http://www.peatonet.com/wp/wp-content/uploads/2014/08/PinoutRaspberry-1.jpeg
Proyecto en Android Studio:
1. Crea una nuevo proyecto en Android Studio que tenga una actividad en blanco. Elige el SDK al que quieras compilar la aplicación.
2. Modifica el AndroidManifest.xml agregando los siguientes permisos:
3. Modifica el archivo xml de tu actividad prinicipal de la siguiente forma:
4. Modifica tu actividad principal con el siguiente código:
Breve explicación:
El método usado para la comunicación entre los dispositivos esta vez fueron los sockets.
La Raspberry Pi corre un pequeño script en python que está a la espera de una conexión entrante, que en nuestro caso sería el dispositivo Android. Cuando recibe una conexión, la RPi crea un nuevo socket, un canal de comunicación, donde recibe un caracter enviado por el dispotivo Android. Hay dos posibles caracteres que pueden ser enviados, 'A' o 'B'. Si se recibe A, el LED enciende; con B, éste se apaga.
En la aplicación en Android, tenemos tres elementos sencillos: dos campos de texto y un botón. El primero para la IP de la RPi, el segundo para el puerto (Nota: El número de puerto debe ser el mismo que el declarado en el script de la RPi, y se recomienda uno que sea distinto a los reservados para otras conexiones. En este caso, yo opté por el puerto 1000) y, finalmente, el botón de On/Of. Este botón es el encargado de llamar a la función que tratará de conectarse a la RPi y enviar los datos. El socket se destruye al finalizar la comunicación, así que cada vez que presionamos el botón se crea uno nuevo.
Ejemplo de uso:
Esquemático y conexiones:
No he podido crear un esquemático por falta de tiempo, en cuánto pueda lo haré.
El LED se conecta al resistor de 330 Ohms y ésta está conectada al GPIO 17 de la RPi, el número de pin puede ser cambiado por cualquier otro disponible. El cátodo del LED se conecta a algún pin GND de la RPi.
Esquemático de GPIO:
http://www.peatonet.com/wp/wp-content/uploads/2014/08/PinoutRaspberry-1.jpeg
Proyecto en Android Studio:
1. Crea una nuevo proyecto en Android Studio que tenga una actividad en blanco. Elige el SDK al que quieras compilar la aplicación.
2. Modifica el AndroidManifest.xml agregando los siguientes permisos:
<uses-permission android:name="android.permission.INTERNET" > </uses-permission> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" > </uses-permission>
3. Modifica el archivo xml de tu actividad prinicipal de la siguiente forma:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".Main" android:id="@+id/relativeLayout"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Introduzca la ip" android:inputType="numberDecimal" android:digits="0123456789." android:id="@+id/editText1" /> <EditText android:id="@+id/editText2" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Introduzca el puerto" android:inputType="number" android:layout_below="@+id/editText1" android:layout_alignParentStart="true" /> <Button style="?android:attr/buttonStyleSmall" android:layout_width="200dp" android:layout_height="wrap_content" android:text="On/Off" android:id="@+id/buttonLed" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="201dp" android:onClick="togLed" /> </RelativeLayout>
import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; public class Main extends ActionBarActivity { private LedToggle ledToggle; private boolean ledState = true; private Button button; private EditText ipText; private EditText portText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.buttonLed); ipText = (EditText) findViewById(R.id.editText1); portText = (EditText) findViewById(R.id.editText2); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } public void togLed(View view) { try { String ipAddr = ipText.getText().toString(); int nPuerto = Integer.parseInt(portText.getText().toString()); if (ledState == false) ledState = true; else ledState = false; ledToggle = new LedToggle(ipAddr, nPuerto); ledToggle.execute(ledState); } catch (Exception e) { e.printStackTrace(); } } }
5. Crea una nueva clase que será el controlador encargado de enviar los datos y pedir conexión a la RPi, llamada LedToggle. Esta clase extiende de AsyncTask, para poder manejar la petición en un hilo distinto al principal.
import android.os.AsyncTask; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; /** * */public class LedToggle extends AsyncTask<Boolean, Void, Void>{ private Socket socket = null; private OutputStream outputStream = null; private String sockeAdd = null; private int portNum; public LedToggle(String s, int p) { sockeAdd = s; portNum = p; } @Override protected Void doInBackground(Boolean... params) { try { socket = new Socket(sockeAdd, portNum); outputStream = socket.getOutputStream(); if(params[0] == true) outputStream.write('A'); else outputStream.write('B'); outputStream.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } return null; } }6. El siguiente script de python debe estar corriendo en la Raspberry Pi.Más adelante escribiré un post explicando más a detalle los temas. Cualquier duda, sugerencia o comentario son bienvenidos :-D


1 comentario: