lunes, 15 de diciembre de 2014

Domos Automatizando el móvil

En el proyecto Domos quiero utilizar el móvil Android como puente de comunicación entre los sensores (Arduino) y el servidor Web. Lo mismo para los actuadores.

Lo que pretendo es tener una aplicación que cada cierto tiempo (Pongamos cada 10 minutos) realice una medida de los sensores y envíe los resultados al servidor, y también pregunte al servidor qué estado quiere que tengan los actuadores para decírselo a Arduino.

Como aún no tengo el arduino voy a jugar con la cámara a intentar enviar una foto desde el móvil al servidor cada cierto tiempo y poder consultarla en el servidor. (Vamos , una especie de WebCam). Así prácticaré con temporizadores y con mantener el movil vivo, etc...

En Internet hay varios artículos interesantes sobre como hacer tareas periódicamente en el movil:

http://android.stackexchange.com/questions/79532/how-to-watch-a-periodically-shot-image-on-other-pc-smartphone-via-internet-no-l

http://stackoverflow.com/questions/2775628/android-how-to-periodically-send-location-to-a-server

Por otra parte, de paso ha aparecido una aplicación que hace de IP WebCam muy interesante: https://play.google.com/store/apps/details?id=com.pas.webcam&hl=es. Es un enfoque diferente ya que esta aplicación crea un servidor web en el movil que realiza la foto a petición de un cliente Web. Este enfoque estaría muy bien pero tiene dos pegas:


  1. No es fácil saber la IP del móvil ya que puede cambiar y tener cortafuegos que impidan alcanzarla. Quizás tendría que hacer otro servicio que periódicamente informe a un servidor de la URL.
  2. No me permite guardar estadísticas de los datos tomados de los sensores ya que solamente se tomaría bajo petición.
Este es el código fuente de la primera prueba, que se limita a sacar una foto periódicamente pero que aún no hace nada con ella.


public class Main extends Activity implements OnClickListener, SurfaceHolder.Callback {
Button sacarFoto;

Camera camara;
SurfaceHolder holder;
SurfaceView   visor;
private Handler tomaFotoCallback = new Handler() {
public void handleMessage(android.os.Message msg) {
Main.this.doSacarFoto();
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
sacarFoto=initButton(R.id.sacarFoto);

visor=(SurfaceView)findViewById(R.id.visor);
holder=visor.getHolder();
initCamera();
Thread thread=new Thread() {
public void run() {
for(;;) {
try { Thread.sleep(10 * 1000); } catch(InterruptedException e) {};
tomaFotoCallback.sendEmptyMessage(0);
}
}
};
thread.start();
}
@Override
public void onDestroy() {
   stopCamera();
}

public void surfaceChanged(SurfaceHolder holder, int format, int width,
       int height) {

   startCamera(holder, width, height);
}

public void surfaceCreated(SurfaceHolder holder) {
   // TODO Auto-generated method stub
   camara = Camera.open();
   try {
       camara.setPreviewDisplay(holder);
   } catch (IOException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
   }
}

public void surfaceDestroyed(SurfaceHolder holder) {
   // TODO Auto-generated method stub

}

private void initCamera() {
   holder.addCallback(this);
   holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}


private void startCamera(SurfaceHolder sh, int width, int height) {
//    Camera.Parameters p = camara.getParameters();
//    // Camera.Size s = p.getSupportedPreviewSizes().get(0);
//    p.setPreviewSize(width, height);
//
//    camara.setParameters(p);

   try {
       camara.setPreviewDisplay(sh);
   } catch (Exception e) {
   }

   camara.startPreview();
}

private void stopCamera() {
   holder.removeCallback(this);

   camara.stopPreview();
   camara.release();
}
public Button initButton(int id) {
Button boton=(Button)findViewById(id);
boton.setOnClickListener(this);
return boton;
}
@Override
public void onClick(View v) {
if(v==sacarFoto) {
doSacarFoto();
}
}

public void doSacarFoto() {
camara.takePicture(null, null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Toast.makeText(Main.this, "FOTO SACADA!!!", Toast.LENGTH_LONG).show();
}
});

}

}


Ahora vamos a crear una tabla en nuestro servidor php:

   create table imagen ( id integer, imagen blob, hora timestamp);

Para enviar la imagen desde la parte Android voy a intentar seguir los consejos de esta página: http://stackoverflow.com/questions/2935946/sending-images-using-http-post.


miércoles, 10 de diciembre de 2014

domos Segundo paso - Crear la aplicación php

Ayer dí de alta el servidor web que va a concentrar los datos recibidos de los sensores y que nos permitiría actuar sobre los actuadores.

Hoy ha tocado crear la base de datos MySql asociada al sitio. Esto ha resultado muy sencillo con OPenShift. Basta ir a http://openshift.com y crear el Cartridge MySql. Además he creado el cartridge phpAdmin para poder gestionar la base de datos desde una página web:

Esta URL me permite gestionar la base de datos:

    https://php-domos.rhcloud.com/phpmyadmin/

(EL usuario y la contraseña no os lo puedo decir).

Utilizando el mismo phpmyadmin he creado las dos tablas necesarias para los sensores y sus lecturas:

Más o menos las tablas son así:


  • create table sensor ( id integer primary key, nombre varchar(100));
  • create table lectura ( idsensor integer, hora timestamp, valor float );
  • create table actuador (id integer, nombre varchar(100), estado varchar(3)) primary key(id)
  • insert into sensor values ( 9856, 'Temperatura interior');
  • insert into actuador values ( 1, 'Estufa', 'OFF');
(Se pueden mejorar añadiendo las constraints correspondientes :)). De momento quedan así...

Ahora creamos las siguientes páginas en nuestro servidor Web:


  1. insert.php que se encargará de recibir y procesar las peticiones de actualización desde los dispositivos sensores.
  2. query.php La página de consulta de los usuarios donde se mostrará el estado de los sensores y los botones de los actuadores.
Para realizar una inserción de una lectura de un sensor utilizaremos la siguiente URL:

  • http://php-domos.rhcloud.com/insert.php?sensor=xxx&valor=yyy

Para consultar la situación actual utilizaremos la siguiente SQL:

Siguientes pasos:


  • Implementar la página "set.php" que establezca el valor de estado requerido del actuador para que más adelante pueda leerlo desde el dispositivo y actuar en consecuencia. Tengo que añadir una columna a la entidad Actuador que sea el estado_requerido para diferenciarlo del estado real que tendré que actualizarlo mediante un sensor.
  • Empezar la aplicación Android que haga de puente entre el Arduino (Mediante bluetooth) y el servidor Web. Será una aplicación sin interfaz de usuario. Simplemente cada cierto tiempo consulta en la web el estado requerido de los actuadores y lo enviara por bluetooth al dispositivo Arduino y viceversa, leerá del bluetooth el valor de los sensores y lo enviará al servidor web. Hay que recordar que el móvil que ejecute esta aplicación estará dedicado en exclusiva a hacer de puente de comunicaciones, asi que nos valdrá cualquier móvil Android que tenga bluetooth.




martes, 9 de diciembre de 2014

domos Usando Open Shift como servidor PHP

Ya os dije que para el proyecto Domos quería utilizar un servidor Web gratuito que me permitiera crear páginas PHP con algo de persistencia.

Encontré OpenShift y tras un par de horas pegándome con él he podido subir mi primera página php.

Los pasos que seguí , mas o menos han sido los siguientes:


  1. Darme de alta en OpenShift
  2. Crear una aplicación php (La llamé http://php-domos.rhcloud.com )
  3. Open Shift utiliza GITC para coger de él la aplicación a subir. Cuando creas una aplicación él te crea un repositorio GITC de donde puedes descargar la copia local y empezar a desarrollar con ella, pero antes....
  4. Hay que crear una clave pública lo que te obliga a seguir varios pasos que resumidamente son los siguientes (Se pueden ver detalladamente en https://developers.openshift.com/en/getting-started-client-tools.html)
  5. Instalar Ruby y meterlo en el PATH
  6. Instalar GITC y meterlo en el PATH
  7. Instalar RHC (RedHat Cloud client tools) usando "gem install rhc". Para instalar esto me topé con un problema que tiene RUBY que impide una conexión SSL a su servidor GEM. Para arreglarlo me tuve que descargar un certificado desde http://curl.haxx.se/ca/cacert.pem (Ver explicación detallada aquí; https://gist.github.com/fnichol/867550). Para ejecutar el gem install rhc antes hay que establecer la variable de entorno: set SSL_CERT_FILE=C:\tmp\cacert.pem
  8. Luego ejecutamos el RHC SETUP y seguimos los pasos que nos pida. Nos conduce a acabar creando y subiendo al servidor la clave pública que necesita para poder continuar subiendo código fuente.
  9. Una vez que tenemos el rhc setup ya podemos trabajar con el código fuente de nuestra aplicacioón pero necesitamos saber cuál es la URL del repositorio GITC de código fuente de nuestra aplicación para poder clonarlo. Para saber cuál es esta URL ejecutaremos el comando "rhc apps" que nos muestra la URL de GITC que podemos usar.
  10. Ahora podemos descargar nuestra copia local de la aplicación. Vamos a nuestro directorio local favorito y ejecutamos "git clone <url> <carpetaLocal>". Así creamos nuestro sistema de archivos con el proyecto. Nos descargará el index.php.
  11. Creamos nuestra primera página "Hola.php" y escribimos en ella un poco de código php para demostrar que funciona.
  12. Ejecutamos "git add hola.php".
  13. Ejecutamos "git commit" (Nos dará error porque antes necesitamos ejecutar "gitc --global user.email miemail@gmail.com).
  14. Ejecutamos "git push" (LO que hace esto es pasarlo a producción redesplegando la aplicación).
  15. A continación ya podemos navegar a http://php-domos.rhcloud.com/hola.php.

Ufff porfin...

Ya tengo un servidor PHP, ahora como no tengo ni idea de PHP tengo que aprender cómo crear una variable global que perdure mientras el servidor esté activo para guardar la temperatura. No necesito de momento usar bases de datos porque no aspiro a tanto. Me será suficiente con guardar un valor en memoria y recuperarlo dentro de un rato. Voy a experimentar las variables globales de PHP.

domos Jugando a la domótica

Me he propuesto introducirme en el mundo de la domótica, los circuitos sencillos y el control remoto.

Me he puesto como objetivo tener un sistema para conocer de forma remota la temperatura que tengo en casa y arrancar desde el móvil la calefacción.

Lo primero que necesito es un servidor web que me permita centralizar la información y que sirva de nodo central al cual se comunican los sensores, actuadores y el controlador.

Tengo dos opciones:

1. Crear un servidor web en mi casa
2. Utilizar un hosting (Gratuito).

Decido utilizar un hosting gratuito ya que en casa no tengo IP fija y no me apatece torear este problema.

Al final voy a tener los siguientes elementos:


  1. Un circuito arduino con su sensores y actuadores necesarios que ya veremos (LO tengo pedido y estoy esperando a que llegue). COncretamente usaré un sensor de Infrarrojos para copiar la señal del mando a distancia de una estufa , un diodo led de infrarrojos, un módulo bluetooth para comunicarme con el móvil.
  2. Un móvil android antiguo que se comunicará por Bluetooth con el proyecto Arduino. A este móvil le pondré una tarjeta 3G con conexión a Internet Pepehone por 6€ al mes. Si hago pruebas donde tenga Wifi, pues me ahorraré la tarjeta 3G. Tendré que desarrollar una aplicación Android que se comunicarña por un lado con el Arduino a través de bluetooth para leer la temperatura y enviarle órdenes de on y off y por otro lado se comunicará con la aplicación web para subir al servidor los datos y escuchar órdenes.
  3. Un servidor Web PHP al cual se comunicará tanto el Móvil para aportar sus datos y escuchar órdenes como cualquier navegador web para poder actuar sobre él.
Como aún no tengo en mis manos el chip Arduino voy a comenzar experimentando con el servidor Web PHP. Decido usar PHP para poder ponerme a programar inmediatamente. Quiero un servidor gratuito. Decido usar https://www.openshift.com

Me doy de alta, y para crear mi primera aplicación PHP tengo que hacer unas cuantas cosas antes:

https://developers.openshift.com/en/getting-started-overview.html#step3

Instalar Ruby, Gitc, ... ya veremos cómo acaba esto. El objetivo de hoy es tener una página PHP que sea capaz de guardar en memoria un valor (La temperatura actual),...

lunes, 17 de noviembre de 2014

Acelerando el emulador

En Internet te puedes encontrar multitud de artículos donde te explica cómo configurar tu Android-SDK para que aproveche las capacidades de virtualización por hardware que pueda tener tu equipo.

Un barato Intel N2830 tiene la tecnología VT-x que permite esta aceleración. Pero configurarlo puede resultar un poco frustante.

Primero, el arranque del Emulador sigue siendo bastante lento, aunque luego sí se nota la diferencia de velocidad al ejecutar la aplicación.


Yo hice varias pruebas, con diversas combinaciones de versión del IDE, de 32 ó 64bits, de la versión del SDK y finalmente conseguí que fuera suficientemente fino con la siguiente combinación:

  • EClipse Juno de 32Bits con el SDK de Android descargado todo junto desde aquí: https://developer.android.com/sdk/index.html?hl=i#download. He de decir que lo intenté con Java8 64bits+Eclipse de 64 bits  pero no conseguí poner a funcionar el Device con aceleración por hw.
  • Java6 de 32 Bits
  • Instaladas todos los recursos de la API 10 de Android, especialmente incluyendo la máquina x86.
  • Declarado un Dispositivo con las siguientes características:
    • Device: UN 5.1" 800x480 genérico.
    • Target: Google API - API Level 10
    • CPU : Google API Intel Atom (x86_64). Ojo aquí porque haciendolo con el x86 de 32 bits no va fino.