Tutorial Threejs – Parte I , Introducción

image_pdf

Hola a todos.

Vamos a comenzar una serie de posts dedicados a Threejs , que espero que sea de vuestro agrado.

¿Que es Threejs?


Threejs
es motor 3D ligero para javascript .

Funciona muy bien bajo webGL , aprovechando la aceleración de nuestra tarjeta gráfica , dando unos resultados espectaculares.

Podemos encontrar unos ejemplos de lo que se puede hacer en la página de ejemplos oficial de Threejs.

Ésta serie de artículos pretende explicar el funcionamiento de Threejs , que hacer , como empezar , como crear escenas , importar objetos , etc , etc.

Empezaremos explicando un poco que es necesario para empezar:

Un navegador con soporte webGL , actualmente los mejores resultados los da Google Chrome , aunque se puede utilizar Mozilla Firefox , aunque es más pesado y por lo tanto un poco más lento , no olvidemos que Chrome utiliza el motor webkit que utilizan también muchos smartphones , mientras que Mozilla utiliza el motor Gecko , basado en java .

Conocimientos de programación , javascript , y html5 .

Nociones de 3D , para no perderse , o mucha paciencia para absorver conceptos nuevos.

Descargar la librería Threejs con los ejemplos y herramientas que iremos utilizando y explicando.

Que podemos hacer !

Con Threejs podemos hacer casi cualquier cosa que podemos hacer con un motor 3D , vamos a explicarlo para que sirva también como tutorial de iniciación al 3D.

Básicamente consiste en crear una escena , con objetos dentro que visualizaremos en la pantalla , en nuestro caso en un canvas de html5 , a través de cámaras e iluminados por luces .

La escena

Es la representación del mundo virtual tridimensional , donde se irán colocando los demás elementos , es algo así como un contenedor del espacio en 3D , que empieza estando vacío .

Este espacio está vacío , no tiene nada , iremos colocando por turno los objetos que deseamos visualizar , basándonos en que la escena se pude medir , con eje de coordenadas virtual a partir del cual iremos posicionando los objetos en las 3 dimensiones básicas .

Gracias a esta referencia dentro de la escena podemos rotar los objetos , desplazarlos , etc , etc.

La escena tiene un fondo que se puede personalizar , que sería un poco así lo que sería el horizonte , se pude dejar un color plano , o una imagen , depende de lo que se quiera hacer.

La cámara

La cámara nos permite visualizar la escena desde un punto de vista concreto .
Se comporta como un objeto más , se puede rotar , desplazar , pero además tiene algunas propiedades más , propias de una cámara .

Podemos tener varias cámaras y utilizar una u otra según convenga.

Las luces

Las luces son objetos que irradian luz y nos permiten visualizar los objetos gracias a la reflexión de la luz en ellos.

Hay varios tipos de luz , de punto (Point), solar (sun), foco (Spot) , en otras aplicaciones podemos encontrar más tipos de luz.

La intensidad y el color de las luces son configurables y nos permiten una multitud de posibilidades y pueden provocar sombras sobre los objetos de la escena.

Cada objeto reacciona diferente a la luz según sus valores para la luz de difusión (color reflejado) , especular (color refractado) y emisión (color emitido por ejemplo una bombilla ) , variando según el color e intensidad.

Para una iluminación correcta es necesario el uso de normales , que son el cálculo de la perpendicular de cada cara visible del objeto .

Para empezar , la mayoría de aplicaciones comienzan con un escena que contiene una cámara y una luz , en muchos casos incluye un objeto en modo de ejemplo que suele ser un cubo o una esfera .

Los objetos

Los objetos son una representación de arrays de vértices que forman líneas y caras.
Jeje que fácil no ,

Los vértices son puntos que ocupan unas coordenadas .
La unión de 2 vértices forma líneas.
La unión de varias líneas forman planos que se suelen llamar caras.

Las caras se suelen formar por 3 o 4 líneas que le dan forma , y obviamente una cara/plano de 4 líneas se puede representar como 2 caras/planos de 3 líneas , así que lo más normal es encontrarnos con modelos de objetos formados por arrays de vértices que representan estos triángulos .

En la mayoría de aplicaciones para modelar se especifica al exportar si se quieren crear triángulos (3 líneas) en aquellas caras que son romboides (4 líneas) , para su uso posterior.

Este array de vértices que comentamos no es más que la forma del objeto , hay que posicionar el objeto en la escena .

Los objetos están hechos con uno o varios materiales a los que hay que asignarle valores según tenga que reaccionar a la luz un color de difusión , otro de especular y el color de emisión si emite luz.

Cada material puede tener una textura , que puede ser una imagen , hasta en ocasiones un vídeo.

Las texturas dan el toque de calidad a los objetos , siendo unos de los temas más importantes del desarrollo en 3d ,por ejemplo podemos aplicar transparencias gracias a las texturas , o de un plano básico aplicarle una textura para que parezca una casa.

Los objetos pueden ser de formas básicas como un cubo o una esfera , o puede ser una figura compleja , pero en el caso de ser una figura compleja mejor crearla con un editor externo (no con código me refiero) , e importarlo como un modelo.

Los modelos

Los modelos 3D son objetos pre-diseñados que se utilizan para incorporar en la escena. Pueden incluir sus propias texturas , y estar formados por uno o varios objetos , a su vez con sus propias texturas.

Los modelos se comportan como una unidad , y se ubican a partir de un punto que es su centro de coordenadas , que se suele ubicar abajo , pero puede variar según el creador.

Podemos diseñar objetos en aplicaciones como Blender , con la comodidad que ello aporta , y exportarlos para el uso en nuestras aplicaciones , Threejs nos aporta herramientas para convertir objetos en formato obj en objetos en formato compatible para Threejs en json.

Los modelos pueden tener animaciones programadas preparadas para nuestro uso , por ejemplo ficheros md2 con acciones como saltar , correr , cargar , etc .

Threejs nos aporta una herramienta para crear modelos en formato Threejs , muy útil y práctica.

Resumiendo un poco , ya sabemos que tenemos que crear una escena , añadirle una cámara , una luz , y los objetos y modelos que queramos.

Bueno hasta aquí la introducción , en el próximo artículo pasaremos a la acción creando la primera escena .

Saludos ,
Scuraki

Recuperar Lg Optimus 3D (Unbrick, Unroot, UnRecovery)

image_pdf

 

 

Introducción

En este post voy a mostrar como recuperar un Lg Optimus 3D que no arranca. Lo primero es coger un poco de aire. Es importante (aunque sea difícil de conseguir) tranquilizarse un poco para seguir los pasos adecuadamente. Por suerte este dispositivo tiene un modo de recuperación que se ejecuta a muy bajo nivel, así que es muy difíl (que no imposible) dar por perdido por completo el dispositivo. Al acabar el proceso, si todo ha ido adecuadamente, tendremos nuestro Lg funcionando sin acceso a root, con el recovery original y la versión más actualizada de la Rom ofrecida por Lg.

 

Consideraciones previas:

Bien en ningún caso me hago responsable de ningún daño ocasionado a algún terminal. Esta guía y las aplicaciones que se mencionan en ella carecen de cualquier tipo de garantía (un software de LG que decir…). Es decir, bajo vuestra responsabilidad queda lo que hagáis con vuestro terminal.

– Requisitos:

  • Herramienta de recuperación oficial -> B2CAppSetup.
  • Un pc con Windows. Si lo sé, pero que le haremos la herramienta de recuperación es para windows y el que se encuentre en esta situación no esta para experimentos con wine. También puntualizar que con màquina virtual no funciona (por lo menos con VirtualBox).
  • El dispositivo debería tener suficiente batería (en torno un 50%), es un requerimiento difícil pero de lo contrario podríamos quedarnos a media instalación.
  • Conexión a internet, la rom oficial que se instalará será bajada de internet.
  • Necesitaremos el IMEI y el Numero de serie, podemos encontrarlos debajo de la batería.

 

Pasos a seguir

  • Instalar drivers -> Arrancaremos B2CAppSetup y clicamos en install drivers.

 

 

 

 

 

 

 

 

 

 

 

 

 

  • Seguidamente seleccionamos LGP-920 e instalamos el driver.

 

 

 

 

 

 

 

 

 

 

 

 

  •   Arrancar Lg Optimus 3D en modo recuperación
  1. Con el dispositivo desconectado del ordenador le quitamos la bateria y la volvemos a poner.
  2. Introducimos la batería y conectamos el dispositivo al ordenador. E$l dispositivo arrancara saldrá el logo de LG seguidamente la batería y se apagará.
  3. Presiona el botón de subir el volumen y el botón de encendido y no los sueltes hasta que salga el logo de LG y se vuelva apagar la pantalla. Con la pantalla apagada vuelve presionar los botones hasta que en la barra de notificaciones de windows veas que se empiezan a instalar los drivers. Puede ser que no te salga el símbolo de la batería, si a la primera no funciona tomatelo con calma y repite los pasos.
  4. Una vez instalado el driver en el programa de recuperación de LG nos saldrá que el dispositivo está conectado.
  • Recuperación
      1. Cuando el programa nos haya reconocido el dispositivo debemos selecionar  Recovery Phone

    1. Seguidamente una nueva ventana nos pedirá que introduzcamos el IMEI y el Numero de serie, que previamente hemos apuntado, una vez introducidos clica en el CHECK del IMEI y automáticamente comenzará el proceso de recuperación. Hay que tener en cuenta que se bajará la Rom de internet, esto quiere decir  que dependiendo de tu connexión el proceso puede tardar más o menos (unos 30 min.), paciencia.
    2. Una vez acabada la instalación desconnecta el dispositivo del ordenador, quita la batería, ponla, arranca y listo.

Observaciones
Espero que esto pueda servir de ayuda. Normalmente esto ocurre cuando se flashean Roms de diferente baseband. Se debe tener cuidado siempre que flasheemos una Rom para evitar estos problemas. No nos veríamos en estas situaciónes (bricks producidos por instalar roms funcionales) si Lg tuviera un poco más en cuenta la calidad de su software…

 

Ruben.

Root, CyanogenMod 7, Ultra Smooth CyanogenMod 9.1 para HTC WildFire

image_pdf

 

Introducción

En este post voy a mostrar como  trastear un HTC WildFire. Hace ya tiempo adquirí uno de estos terminales. Con amargura vi como se quedaba en la versión 2.2 y nunca se iba a actualizar a la versión 2.3.x de Android.  Esto implicaría perder las siguientes mejoras:

  • Función copiar y pegar mejorada
  • Teclado rediseñado
  • Gestor de descargas
  • Manejo de energía mejorado y control de aplicaciones

Ciertamente la parte más importante es la del manejo de aplicaciones i gestión de la batería. Aunque la mejoras de usablidad siempre son bienvenidas, la verdad. También hay que tener en cuenta que estas no son todas las diferencias pero si las que se aplican a este terminal. Ademas esta rom nos permite personalizar muchos aspectos como transición entre pantallas, menús… Incluye AWD Launcher que no esta nada mal y podemos personalizarla con multitud de temas.

Después de mucho pensarlo decidí dar el paso rootear el terminal e instalar alguna rom que me permitiera disfrutar de la nuevas mejoras. El proceso fué un poco complicado e implica cierto riesgo, pero la mejora es incerible. La verdad después de probar CyanogenMod aunque la rom oficial se actualizase a 2.3 no cambiaría.

 

Consideraciones previas

Bien en ningún caso me hago responsable de ningún daño ocasionado a algun terminal. Esta guía y las aplicaciones que se mencionan en ella carecen de cualquier tipo de garantía. Es decir, bajo vuestra responsabilidad queda lo que hagáis con vuestro terminal.

Es recomendable que la batería del termina este cargada,  realizar backups y asegurarse de que en la sd tenemos espacio para estos y las bajada que vamos a realizar. A continuación mostraremos algunas aplicaciones que nos pueden ser de ayuda:

  • Contactos del teléfono -> No requiere aplicación externa. Simplemente entrar en la lista de contactos, apretar el botón de menú de Android y seleccionar Importar/exportar -> Exporta a la tarjeta SD.
  • Aplicaciones -> MyBackup (ATENCION!! Esta es una versión de prueba funcional solo durante 30 días.)

 

S-OFF e instalación de un custom recovery

Esta parte es un poco complicada conviene seguir todos los pasos con paciencia y asegurándonos que realizamos cada uno correctamente.

  • Debemos descargar Revolutionary.
  • En cuanto empiece la descarga, la pagina se actualizará. Para poder utilizar el programa necesitamos una beta key. Para conseguirla es necesario rellenar el formulario que aparecerá introduciendo nuestra versión de HBOOT y número de serie.
    • HBOOT -> para encontrar la versión de HBOOT debemos apagar el terminal y encenderlo apretando el botón de volumen hacia abajo y el botón de encendido. Aparecerá una pantalla parecida a la siguiente en la que podemos ver la versión de HBOOT.

  •  El número de serie lo podemos encontrar debajo de la batería o bien, con el terminal conectado por usb, ejecutando en un terminal de pc
    ./adb devices
  • Una vez realizados los pasos anteriores, debemos ejecutar Revolutionary
    ./revolutionary

    desde un terminal de pc, con nuestro WildFire conectado por usb, e introducir la beta key.

  • Nuestro terminal se reiniciará en poco tiempo. El proceso puede no funcionar a la primera, repetidlo. En caso de tener algún problema podéis encontrar información en la wiki de Revolutionary o en su canal de irc.

 

Instalar CyanogenMod 7 (Android 2.3.7) y GoogleApps

Hace pocos días el Team de CyanogenMod sacó la versión 7.2 estable. Lo cual es una gran noticia. Las versiones estables son realmente buenas. Normalmente la segunda release candidate de una versión ya suele estar muy bien.

Bien podemos realizar este proceso desde Rom Manager:

  • Arrancamos la aplicación y seleccionamos Download Rom.
  • Seguidamente en el apartado Free seleccionamos CyanogenMod.
  • Seleccionamos la última stable release, en este caso la 7.2.0. y la opción de GoogleApps.
  • Cuando finalicen las descargas debemos seleccionar Wipe Data y Wipe Cache, seria muy recomendable realizar un backup de la rom existente si queréis hacerlo seleccionad Backup Existing ROM.
  • La aplicación SuperUser nos preguntará si queremos dar permisos a Rom Manager, aceptamos.
  • Nuestro terminal se reiniciará en modo recovery hará un wipe de cache y data, a continuación se instalará CyanogenMod y las GoogleApps. Cuando finalice la instalación el terminal se reiniciará otra vez y CyanogenMod arrancará por primera vez.

 

O bien manualmente, es recomendable utilizar Rom Manager puesto que simplifica el proceso. En este caso debemos descargar:

  • La rom cm-7.2.0-buzz
  • Las GoogleApps gapps-gb-20110828-signed
  • Una vez descargadas debemos copiarlas a la raiz de la targeta SD, entrar en Rom Manager y seleccionar Reboot into Recovery.
  • Una vez en el recovery debemos utilizar las teclas de volumen para navegar y el botón de encendido o el trackball como enter.
  • Bien si queréis realizar un backup de la rom actual (cosa recomendable porque es la original) entrad en backup and restore  y seleccionad backup. Finalmente seleccionad +++++Go Back+++++ para volver al menú principal.
  • En el menú principal seleccionad Wipe data/factory reset y seguidamente Wipe cache partition.
  • Seleccionad Install zip from sdcard y Choose zip from sdcard.
  • Seleccionad cm-7.2.0-buzz.zip y esperad a que acabe el proceso de instalación.
  • Bien para instalar las GoogleApps el proceso es el mismo que con la rom, simplemente debemos seleccionar gapps-gb-20110828-signed.
  • Finalizada la instalación seleccionamos +++++Go Back+++++ para ir al menú principal y finalmente Reboot system now option. Nuestro terminal se reiniciará y CyanogenMod arrancará por primera vez

 

Tips & tricks

Hay algunas cosas a tener en cuenta:

  • Ubuntu no reconoce el terminal. Debéis situaros en la carpeta donde se encuentra adb. Matar el servidor y arrancarlo como root
    ./adb kill-server
    sudo ./adb start-server
  • Puede que el gps no coja señal. Eso es debido a que hay que flashear una nueva radio. Podéis descargar la radio des de aquí . Una vez descargada la radio debéis descargar el siguiente ejecutable FastBoot. Debéis apagar el teléfono, y estando este conectado por usb, arrancar presionando el botón de encendido y volumen abajo. Entrareis en la siguiente pantalla.
  • Con las teclas de volumen debéis seleccionar FASTBOOT  y clicar el botón de encendido. Llegareis a esta nueva pantalla.

  • Llegados a este punto des de un terminal en el pc debéis ejecutar
    ./fastboot flash radio radio.img

    Una vez acabe la instalación seleccionáis con los botones de menú REBOOT y presionáis el botón de encendido para reiniciar el terminal, con esto el gps debería funcionar perfectamente. Si aún así continuáis teniendo problemas podéis encontrar soporte en este foro CyanogenMod Forum.

  • La aplicación de GoogleMpas se queda colgada. Desafortunadamente nuestro terminal no soporta la última versión de google mpas. Podéis descargar el apk des de aquí, es la versión 5.0.0 que funciona perfectamente.
  • No se puede instalar flash. Podéis descargar una versión funcional de flash para este terminal des de aquí

 

Actualización a ICS

Recientemente he estado probando otra Rom,  Ultra Smooth CyanogenMod 9.1.Tanto su estabilidad, eficiencia y compatibilidad con el hardware del terminal son impresionantes. La camara funciona bastante bien (excepto la gravación de video) y youtube (excepto el visionado en HD) . Algunos consejos:

– En opciones -> Performance  -> Processor podéis modificar la velocidad del procesador entre 352 y 710 MHz  y el governor SMARTASSV2 (estaremos realizando overclocking esto comporta cierto riesgo pero dentro de unos valores razonables).

– Podéis modificar en las opciones del launcher (menu de android -> launcher settings – Desktop settings) Wallpaper scrolling para desactivarlo.

– Podéis encontrar unas tiny google apps aquí simplemente una vez cargada la página de Google Docs persionad Ctrl+s o en el menu File->download

– En este post podéis encontrar como instalar Google VoiceSearch

– Es recomendable utilizar Seeder(consigue reducir el Lag notablemente)

 

Observaciones
Bien, el proceso es un poco complicado y algunos pasos son críticos, pero a mi me mereció la pena el cambio. Ahora estoy muy contento con mi terminal, hay muchas opciones que la rom oficial no ofrece, la estabilidad es muy buena así como también el ahorro de barrería y la gestión de memoria (cuando htc sence desaparece, de las entrañas de nuestro terminal memoria ram aflora). También cabe tener en cuenta el echo de ser root. Se pueden realizar backups de todo, hay muchas aplicaciones que explotan esta funcionalidad, pero esta parte os la dejo para vosotros.
En la nueva parte para instalar ICS podemos observar varios ajustes, seamos realista estamos hablando de correr una ICS 4.0.4 en un HTC WildFire sorprendente es que funcione y lo bien que lo hace la Rom Ultra Smooth CyanogenMod 9.1, en la fuentes se encuentra el link al post de xda del creador y colaboradores de la rom.

Fuentes

Ruben.

Montar BlackBerry PlayBook en Ubuntu

image_pdf

Introducción

En este post voy a mostrar como montar una BlackBerry PlayBook a Ubuntu.Algo que a priori debería ser sencillo y lo es con un perqueño workaround.

Cuando se conecta la PlayBook mediante cable usb a Ubuntu una pantalla nos indica que se están instalando los drivers… eso no va a ocurrir en Ubuntu, simplemente cerramos esa pantalla.

Bien la idea consiste en conectarla por red, los pasos a seguir son realmente sencillos.

 

Preparar la PlayBook

  • Iremos a Configuración -> Almacenamiento y uso compartido. En conexión usb seleccionaremos Conectarse a Windows.
  • Seguidamente iremos (dentro de Configuración) a  -> Sobre (la sección donde encontramos la información relacionada con el dispositivo). En Visualizar Información de la tablet seleccionaremos Red. Deberemos apuntarnos la dirección IP de la PlayBook para usarla después.

Conectarnos con Ubuntu

  • Iremos a Lugares -> Conectarnos a un Servidor.
  • En el formulario de conexión seleccionaremos Recurso Compartido de Windows e introduciremos la IP que anteriormente hemos apuntado y con esto accederemos mediante red al almacenamiento masivo de la PlayBooK.

 

Observaciones
Bien, esto no es más que un truquillo simple pero a su vez muy útil. Próximamente mostraré como portar una aplicación Android a PlayBook y las limitaciones que existen.

 

Ruben.

Tutorial Arduino parte 4

image_pdf

Hola a todos .

Este es el cuarto tutorial sobre Arduino , en este tutorial vamos a continuar el tutorial 3 , creando una aplicación 3d para Android , que encienda la bombilla de forma remota .

Creamos un proyecto Android nuevo en eclipse con Android SDK.

Continuando como teníamos en el tutorial 3 , en la parte del servidor php , el fichero que recibía una variable GET y encendía o apagaba la bombilla si la variable es high o low.

En este primer código podemos ver como desde el proyecto Android podemos realizar la conexión con el servidor PHP para que envíe la señal a la placa Arduino.

El fichero PHP ha de estar en modo servicio , con las lineas //die… descomentadas , para que nos devuelva una respuesta.

 private void lighting()
 {
     ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
     if (cm != null) {
         boolean connected=false;
         
                NetworkInfo[] info = cm.getAllNetworkInfo();
                if (info != null) {
                    for (int i = 0; i < info.length; i++) {
                       if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                          connected = true;
                       }
                    }
                 }  
             if(connected)
             {
                 String destiny="http://192.168.0.131/arduino/service.php?check=on";
                 String missatxe="Signal CHECK sended. Click again to switch ON";

                 cambiarTextoBoton("Switch ON");
                 switch(estado)
                    {
                        case 0:
                                    destiny ="http://192.168.0.131/arduino/service.php?hight=on";
                                    missatxe="Signal ON sended. Click again to switch OFF";
                                    cambiarTextoBoton("Switch OFF");
                                   
                                    break;
                        case 1:
                                    destiny ="http://192.168.0.131/arduino/service.php?low=on";
                                    missatxe="Signal OFF sended. Click again to switch ON";
                                    cambiarTextoBoton("Switch ON");
                                break;
                   
                    }  
   
               
                 escribir(missatxe);
   
                 
                 InputStream is = null;
                 
                 
                //initialize
                String result = "";
       
                try{
                    HttpClient httpclient = new DefaultHttpClient();
                    HttpPost httppost = new HttpPost(destiny);
                    HttpResponse response = httpclient.execute(httppost);
                    HttpEntity entity = response.getEntity();
                    is = entity.getContent();
       
                    //convert response to string
                    try{
                        BufferedReader reader = new BufferedReader(new InputStreamReader(is,"UTF-8"),8);
                        StringBuilder sb = new StringBuilder();
                        String line = null;
                        while ((line = reader.readLine()) != null) {
                            sb.append(line + "\n");
                        }
                        is.close();
                        result=sb.toString();
                       
                        ArrayList<String> message=this.parse( result);
                        String status=message.get(0).toString();
                        String signal=message.get(1).toString();
                        String mensage=message.get(2).toString();
                        if(signal.compareTo("1")==0)
                        {
                            checkOK=1;
                            estado=0;
                        }
                        else
                        {
                            if(signal.compareTo("2")==0)
                            {  
                                checkOK=2;
                                estado=1;
                            }
                            else
                            {
                                if(signal.compareTo("-1")==0)
                                {      
                                    checkOK=-1;
                                    estado=-1;
                                }
                            }  
                       
                        }
                    }catch(Exception e){
                        Log.e("log_tag", "Error converting result "+e.toString());
                         escribir("Error converting result "+e.toString());
                    }
                }catch(Exception e){
                    Log.e("log_tag", "Error in http connection "+e.toString());
                     escribir("Error in http connection "+e.toString());
                }
             }
     }
     
 }

Bien , ya podemos comunicarnos con el servidor , pero bueno un poco rancia la aplicación , no?

¿Falta un botón , un poco de color o algo no?

Puesto a investigar un poco pués encontré una librería que permitía crear aplicaciones OPENGL de manera un poco más sencilla de lo normal , con un lenguage más para un principiante como yo que ir directamente a OPENGL de Android , que es un poco más rudo para alguien que no lo usa muy a menudo.

Esa librería es Min3D.

Min3D nos permite crear escenas 3D e importar objetos 3DS o OBJ , así como texturas y objetos básicos como esferas y cubos.

Tras descargar min3d de su repositorio , incluimos la carpeta al proyecto y podemos ver y probar los ejemplos.

Partiendo del ejemplo ExampleLoadObjFileMultiple.java , donde podemos ver como cargar un objeto desde un fichero .OBJ .

En este fichero podemos ver que hereda de la clase

 extends RendererActivity

, y lo aplicaremos a la clase que estemos utilizando .

El método initScene() es el encargado de crear la escena , en este método es donde colocaremos todos los objetos de la escena , cargaremos todos los ficheros necesarios , .OBJ , .PNG , y crearemos las esferas y rectángulos que necesitemos.

Este método es llamado al iniciar la aplicación y cada vez que el dispositivo entra en modo PAUSE , o se bloquea la pantalla.

Como en toda aplicación 3D , además de una escena necesitamos una cámara y luces para iluminar nuestros objetos.

En este método asignaremos un color de fondo , o una textura , situaremos las luces , los objetos y situaremos y enfocaremos la cámara , para obtener la perspectiva adecuada.

El método updateScene() se ejecuta en cada frame , sería el equivalente al típico evento draw() de repintado de la pantalla en aplicaciones 2D , osea que se ejecuta cada vez que se pinta la pantalla.

Éste método es el encargado de las instrucciones de las animaciones , por ejemplo si queremos rotar un objeto , en este método calculamos el valor nuevo de la rotación y se le asigna.

Para cargar los ficheros .OBJ en la aplicación Android es necesario modificar los nombres de los archivos.

Los ficheros .OBJ suelen ir acompañados de un fichero con el mismo nombre con extensión .mtl con la definición de los materiales de los grupos de los objetos que hayan definidos en el fichero .OBJ , además de las imágenes de las texturas.

Osea que el fichero .OBJ tiene objetos , valores de vértices y objetos y el fichero .mtl los materiales.

Las imágenes de las texturas las colocaremos en la carpeta res/drawable… .

Los ficheros .OBJ y .MTL los renombramos sustituyendo el punto por un «_» osea un guión bajo , para evitar los conocidos conflictos de ficheros con el mismo nombre y diferente extensión que tiene la programación con Android.

Para este tutorial hemos creado una farola , con una esfera que hace de bombilla , y una esfera con una textura con transparencia .PNG , que hará el efecto de que la farola está encendida.

También se ha creado una especie de bullofa que emite unas esfera con transparencia , emulando el envío de ondas , dando a entender que se está comunicando con el servidor , una esfera nos indicará según la textura que tenga el texto ON de color verde , o el texto OFF de color roja o de color ambar si no hay conexión con el servidor ,a además hay otra bola que nos indicará según su textura , si estamos a más de cierta distancia de la bombilla , si hay cobertura GPS .

Bueno abrimos blender y creamos una lámpara y una bullofa (algo que de el efecto de ser un emisor de ondas) , y las exportamos en formato wavefront .OBJ .

Si no queremos utilizar blender o otro software para crear objetos 3D , los podemos descargar de alguna página , por ejemplo ésta , que ofrezcan objetos 3D en formato .OBJ .

Podemos ver como asignar el color de fondo:

scene.backgroundColor().setAll(0xfff2d533);

Asignar una textura a un rectángulo:

Bitmap b = Utils.makeBitmapFromResourceId(this, R.drawable.scuraki);
    float w = 20f;
    float h = w * (float)b.getHeight() / (float)b.getWidth();
    Rectangle suelo = new Rectangle(w, h, 1,1, new Color4());
    suelo.doubleSidedEnabled(true); // ... so that the back of the plane is visible
    suelo.normalsEnabled(false);
    scene.addChild(suelo);

    Shared.textureManager().addTextureId(b, "scuraki", false);
    suelo.textures().addById("scuraki");

Asignar una textura a una esfera:

b = Utils.makeBitmapFromResourceId(R.drawable.bolaroja);
    Shared.textureManager().addTextureId(b, "bolaroja", false);
    bolarojaTexture = new TextureVo("bolaroja");
        esfera.textures().addReplace(bolarojaTexture);

Iluminar la escena:

luzobj = new Light();
    luzobj.ambient.setAll(new Color4 (128,128,128,128));
    luzobj.diffuse.setAll(new Color4 (64,64,164, 128));
    luzobj.emissive.setAll(new Color4 (0,0,0,255));
    luzobj.specular.setAll(new Color4 (0,0,0,255));
    luzobj.type(LightType.POSITIONAL);
    scene.lights().add(luzobj);
    luzobj.position.setAll(0.65f, -0.85f, 3.5f);

Añadir un objeto .OBJ a la escena:

parser2 = Parser.createParser(Parser.Type.OBJ, getResources(), "adictosalainformatica.min3DAdictos:raw/fanal_obj", true);
   
    parser2.parse();
   
    fanal = parser2.getParsedObject();
    fanal.scale().y = 0.25f;
    fanal.scale().z = 0.25f;
    fanal.scale().x = 0.25f;
    fanal.shadeModel(ShadeModel.SMOOTH);
    fanal.vertexColorsEnabled(true);
    fanal.normalsEnabled(true);
    fanal.colorMaterialEnabled(false);
   
    scene.addChild(fanal);
    fanal.position().x=0.0f;
    fanal.position().y=1.6f;
    fanal.position().z=-5f;
    fanal.rotation().x=25f;

Controlar la rotación de los objetos en el método updateScene:

bombilla.rotation().y=yrot;
        bombilla.rotation().x=xrot;
        receptor.rotation().y=yrot;
        receptor.rotation().x=xrot;
       
       
        xrot += xspeed;
        yrot += yspeed;
        _count++;

Para dar un toque de color la bullofa cambia el valor de escalado cada cierto tiempo , y se crean unas esferas con transparencia , que viajan desde la bullofa (que está cerca de la cámara) hasta la lámpara (que está al fondo de la escena), emulando el envio de ondas.

Un array de esferas ameniza la pantalla , desplazandose .

La clase Burbuja es la encargada de controlar estas esferas:

package adictosalainformatica.min3DAdictos;

import android.graphics.Bitmap;
import min3d.Shared;
import min3d.Utils;
import min3d.core.Scene;
import min3d.objectPrimitives.Sphere;
import min3d.vos.Color4;
import min3d.vos.TextureVo;
public class Burbuja {
private float velocidad_x=.000f;
private float velocidad_y=0.02f;
private float velocidad_z=0.04f;
private float posicion_x=0.45f;
private float posicion_y=-0.25f;
private float posicion_z=0.3f;
private float variacion_x=0.45f;
private float variacion_y=-0.25f;
private float variacion_z=0.6f;
private float limite_x=4.01f;
private float limite_y=4.01f;
private float limite_z=4.8f;
private Color4 color=null;
private Sphere esfera =null;
long _index;
private float contador=0;
public Burbuja(long index)
{
    this._index=index;
}
public void make(Scene scene  )
{
    if(esfera!=null)
    {
        esfera.clear();
    }
    esfera=null;
    TextureVo textura=null;
    esfera = new Sphere(1.5f, 20,20);
    esfera.scale().x = esfera.scale().y = esfera.scale().z = .1f;
    esfera.position().setAll(posicion_x, posicion_y, posicion_z);
    Bitmap b = Utils.makeBitmapFromResourceId(R.drawable.tscuraki);
    Shared.textureManager().addTextureId(b, "burbuja0" + _index, false);
    b.recycle();   
    textura = new TextureVo("burbuja0" + _index);
    esfera.textures().addReplace(textura);
    esfera.colorMaterialEnabled(false);
    esfera.vertexColorsEnabled(false);
    esfera.lightingEnabled();
    scene.addChild(esfera);
   
     //Log.v(Min3d.TAG, "ReCrea Burbuja=" + _index);
   
}

public int mover()
{
    int moviendo=1;
    posicion_x=variacion_x + ( contador * velocidad_x);
    posicion_y=variacion_y + ( contador * velocidad_y);
    posicion_z=variacion_z - ( contador * velocidad_z);
    esfera.position().setAll(posicion_x, posicion_y, posicion_z);
    if((posicion_x>limite_x)||(posicion_y>limite_y)||(posicion_z * -1 > limite_z ))
    {
        esfera.clear();
       
        moviendo=0;
    }
    //Log.v(Min3d.TAG, "Mueve Burbuja=" + _index + " posiciónx="+ posicion_x + " posicióny=" + posicion_y + " posiciónz=" + posicion_z);
    esfera.rotation().x=contador * -1.3f ;
    esfera.rotation().y=contador * -1.3f;
    esfera.rotation().z=contador * -1.3f;
    esfera.scale().x = esfera.scale().y = esfera.scale().z = .1f + (contador * 0.001f);
    contador++;
    return moviendo;
       
}


public float getLimite_x() {
    return limite_x;
}
public void setLimite_x(float limite_x) {
    this.limite_x = limite_x;
}
public float getLimite_y() {
    return limite_y;
}
public void setLimite_y(float limite_y) {
    this.limite_y = limite_y;
}
public float getLimite_z() {
    return limite_z;
}
public void setLimite_z(float limite_z) {
    this.limite_z = limite_z;
}
public Color4 getColor() {
    return color;
}
public void setColor(Color4 color) {
    this.color = color;
}
public float getVelocidad_x() {
    return velocidad_x;
}
public void setVelocidad_x(float velocidad_x) {
    this.velocidad_x = velocidad_x;
}
public float getVelocidad_y() {
    return velocidad_y;
}
public void setVelocidad_y(float velocidad_y) {
    this.velocidad_y = velocidad_y;
}
public float getVelocidad_z() {
    return velocidad_z;
}
public void setVelocidad_z(float velocidad_z) {
    this.velocidad_z = velocidad_z;
}
public float getPosicion_x() {
    return posicion_x;
}
public void setPosicion_x(float posicion_x) {
    this.posicion_x = posicion_x;
}
public float getPosicion_y() {
    return posicion_y;
}
public void setPosicion_y(float posicion_y) {
    this.posicion_y = posicion_y;
}
public float getPosicion_z() {
    return posicion_z;
}
public void setPosicion_z(float posicion_z) {
    this.posicion_z = posicion_z;
}
public float getVariacion_x() {
    return variacion_x;
}
public void setVariacion_x(float variacion_x) {
    this.variacion_x = variacion_x;
}
public float getVariacion_y() {
    return variacion_y;
}
public void setVariacion_y(float variacion_y) {
    this.variacion_y = variacion_y;
}
public float getVariacion_z() {
    return variacion_z;
}
public void setVariacion_z(float variacion_z) {
    this.variacion_z = variacion_z;
}
public Sphere getEsfera() {
    return esfera;
}
public void setEsfera(Sphere esfera) {
    this.esfera = esfera;
}
public long getIndex() {
    return _index;
}
public void setIndex(long _index) {
    this._index = _index;
}

}

Finalmente controlamos la distancia a la bombilla gracias al sensor GPS , activándolo si es necesario.

Podemos decidir activar la bombilla a cierta distancia , útil para luces de garages , por ejemplo que se encienda cuando falta 2 kilómetros para llegar con el coche.

En nuestro caso tenemos la esfera que nos indica la distancia , modificamos la textura para que nos muestre FAR si está lejos y NEAR si está cerca.

private void loadJipiEs()
 {
    // Acquire a reference to the system Location Manager
    this.locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

    if (!this.locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
    {
         createGpsDisabledAlert();
    }
    else
    {
                // List all providers:
                List<String> providers = this.locationManager.getAllProviders();
               
               
       
                Criteria criteria = new Criteria();
                criteria.setAccuracy(Criteria.ACCURACY_FINE);
               
               
                this.bestProvider = this.locationManager.getBestProvider(criteria, false);
               
                Location mylocation = this.locationManager.getLastKnownLocation(this.bestProvider);
               
                if(mylocation!=null)
                {
                    this.getLocation(mylocation);
                }
                else
                {
                    //this.afegir("Posición inicial vacía.");
                }
    }
   
 }
 private void getLocation(Location location)
 {
    if(location!=null)
        {
               
                boolean hasAltitude=false;
                boolean hasAccuracy=false;
                boolean hasBearing=false;
                lat=location.getLatitude();
                lon=location.getLongitude();
                alt=location.getAltitude();
               
                hasAltitude=location.hasAltitude();
                hasAccuracy=location.hasAccuracy();
                hasBearing=location.hasBearing();
               
                distance=location.distanceTo(coords);
                if(distance<5000)
                {
                    distanceState="near";
                }
                else
                {
                    distanceState="far";
                }
               
            }
    else
    {
        distanceState="Unknown";
   
    }
    //Toast.makeText(getApplicationContext(), "Distance is : " + distance, Toast.LENGTH_LONG).show();
    /*runOnUiThread(new Runnable() {
         public void run() {
                Toast.makeText(getApplicationContext(), "Distance is : " + distance, Toast.LENGTH_LONG).show();
                missatger.setText("Distance is : " + distance);
         }
     });*/
    escribir("Distance is : " + distance);
 }

private void createGpsDisabledAlert(){
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Your GPS is disabled! Would you like to enable it?")
         .setCancelable(false)
         .setPositiveButton("Enable GPS",
              new DialogInterface.OnClickListener(){
              public void onClick(DialogInterface dialog, int id){
                   showGpsOptions();
              }
         });
         builder.setNegativeButton("Do nothing",
              new DialogInterface.OnClickListener(){
              public void onClick(DialogInterface dialog, int id){
                   dialog.cancel();
              }
         });
    AlertDialog alert = builder.create();
    alert.show();
    }

    private void showGpsOptions(){
            Intent gpsOptionsIntent = new Intent(
                    android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivity(gpsOptionsIntent);
    }
}

En nuestro caso la luz la hemos activado a través de un botón externo a la escena , esta señal modifica la textura de la esfera que nos indica el estado de la bombilla , según sea la respuesta del servidor , ON , OFF o sin conexión , si la bombila está ON la esfera que emula la bombilla encendida , que está en la lámpara , se hace visible rodeando una esfera más pequeña que hace de núcleo de la bombilla.

Tutorial Arduino parte 3

image_pdf

En este tutorial veremos como conectar la placa Arduino a la red de 220V de nuestra casa , y poder utilizarlo para controlar nuestros aparatos eléctricos .

En este ejemplo mostraremos como encender una bombilla a 220V desde un lugar remoto .

Este tutorial está basado en un tutorial de la página de Arduino , ver referencias al final del post.

En el próximo tutorial explicaremos como utilizar una aplicación android en 3D para crear un interfaz para este tutorial , que podremos utilizar en nuestro smartphone Android.

Material necesario:

-Placa Arduino
-1 Relé de 5V ó 6V a 220V
-1 Diodo
-1 Transistor 5V
-1 Resistencia
-Cable
-1 Clavija
-1 Portalamparas
-1 Bombilla

Material necesario

Material necesario

Una vez tengamos el material necesario procedemos a realizar el cableado de los circuitos .

descripción circuitos

descripción circuitos

Una vez preparado el cableado , el código necesario para la placa Arduino es muy sencillo.
Utilizamos el pin 8 para activar el relé por medio del transistor.

Abrimos el puerto USB 115200 en modo lectura para recibir las notificaciones que nos enviará el servidor PHP.

Si por el puerto nos entra el caracter 2 , activa el relé , si es 1 lo desactiva.

Código Arduino:

int ledPin = 8;

    int number_in = 0;


    void setup() {

      pinMode(ledPin, OUTPUT);

      Serial.begin(115200);

    }


    void loop() {

      if (Serial.available() > 0) {

        number_in = Serial.read();

      }

 

      if (number_in > 0) {

          if(number_in==2)
          {
           digitalWrite(ledPin, HIGH);
          }
          else
          {
              if(number_in==1)
              {
                  digitalWrite(ledPin, LOW);
              }
          }

      }

      number_in = 0;

    }

Utilizaremos un simple servidor php para enviar la señal a la placa Arduino conectada a nuestro servidor GNU/linux , en este caso a través del cable USB.

En nuestro caso la ruta al dispositivo que vamos a utilizar es /dev/ttyUSB0.

El puerto de la conexión USB que utilizaremos para comunicarnos con la placa Arduino será el 115200 .

Para encender o apagar la bombilla enviaremos por get a la ruta de nuestro servidor la variable hight , para encender , y la variable low para apagar.

Finalmente el servidor responde con un mensaje si ha recibido una señal correcta.

Código PHP:

<?php
// Nonzero number to be sent to Arduino
$c = 0;
if(isset($_GET["hight"]))
{
    $c=2;
}
if(isset($_GET["low"]))
{
    $c=1;
}

if($c>0)
{
    // Include the PHP serial class
    require_once("phpSerial.php");


    // Start a new serial class

    $serial = new phpSerial;


    // Specify the device being used

    $serial->deviceSet("/dev/ttyUSB0");


    // Set baud rate

    $serial->confBaudRate(115200);

    $serial->confParity("none");

    $serial->confCharacterLength(8);

    $serial->confStopBits(1);

    $serial->confFlowControl("none");


    // Open the device

    $serial->deviceOpen();


    // Write to the device

    $serial->sendMessage(chr($c));


    // Close the port

    $serial->deviceClose();
    $message= "Signal ".$c." Received! .<br/>";

    die(json_encode(array('status' => 'success', 'data' => $message)));
}
else
{
    $message= "No Signal Received! .";
    die(json_encode(array('status' => 'failed', 'data' => $message)));
}
?>

Y ya lo tenemos , tenemos una página php que nos funciona como un servicio para poder encender o apagar una bombilla .

Podríamos crear en este punto una pequeña interfaz html , aprovechando el mismo fichero .php , comentando las líneas die(… , creando unos botones para encender y apagar la bombilla , pero nuestra intención es utilizarlo como servicio para una aplicación Android que os explicaremos en el próximo tutorial.

En este ejemplo hemos utilizado la librería phpSerial.php ,no recuerdo de donde la saqué así que os dejo el código , aunque en principio cualquier librería que os permita comunicar con el puerto serie debería valer.

este es el código:

<?php
define ("SERIAL_DEVICE_NOTSET", 0);
define ("SERIAL_DEVICE_SET", 1);
define ("SERIAL_DEVICE_OPENED", 2);

/**
 * Serial port control class
 *
 * THIS PROGRAM COMES WITH ABSOLUTELY NO WARANTIES !
 * USE IT AT YOUR OWN RISKS !
 *
 * @author Rémy Sanchez <thenux@gmail.com>
 * @thanks Aurélien Derouineau for finding how to open serial ports with windows
 * @thanks Alec Avedisyan for help and testing with reading
 * @copyright under GPL 2 licence
 */
class phpSerial
{
    var $_device = null;
    var $_windevice = null;
    var $_dHandle = null;
    var $_dState = SERIAL_DEVICE_NOTSET;
    var $_buffer = "";
    var $_os = "";

    /**
     * This var says if buffer should be flushed by sendMessage (true) or manualy (false)
     *
     * @var bool
     */
    var $autoflush = true;

    /**
     * Constructor. Perform some checks about the OS and setserial
     *
     * @return phpSerial
     */
    function phpSerial ()
    {
        setlocale(LC_ALL, "en_US");

        $sysname = php_uname();

        if (substr($sysname, 0, 5) === "Linux")
        {
            $this->_os = "linux";

            if($this->_exec("stty --version") === 0)
            {
                register_shutdown_function(array($this, "deviceClose"));
            }
            else
            {
                trigger_error("No stty availible, unable to run.", E_USER_ERROR);
            }
        }
        elseif(substr($sysname, 0, 7) === "Windows")
        {
            $this->_os = "windows";
            register_shutdown_function(array($this, "deviceClose"));
        }
        else
        {
            trigger_error("Host OS is neither linux nor windows, unable tu run.", E_USER_ERROR);
            exit();
        }
    }

    //
    // OPEN/CLOSE DEVICE SECTION -- {START}
    //

    /**
     * Device set function : used to set the device name/address.
     * -> linux : use the device address, like /dev/ttyS0
     * -> windows : use the COMxx device name, like COM1 (can also be used
     *     with linux)
     *
     * @param string $device the name of the device to be used
     * @return bool
     */
    function deviceSet ($device)
    {
        if ($this->_dState !== SERIAL_DEVICE_OPENED)
        {
            if ($this->_os === "linux")
            {
                if (preg_match("@^COM(\d+):?$@i", $device, $matches))
                {
                    $device = "/dev/ttyS" . ($matches[1] - 1);
                }

                if ($this->_exec("stty -F " . $device) === 0)
                {
                    $this->_device = $device;
                    $this->_dState = SERIAL_DEVICE_SET;
                    return true;
                }
            }
            elseif ($this->_os === "windows")
            {
                if (preg_match("@^COM(\d+):?$@i", $device, $matches) and $this->_exec(exec("mode " . $device)) === 0)
                {
                    $this->_windevice = "COM" . $matches[1];
                    $this->_device = "\\.\com" . $matches[1];
                    $this->_dState = SERIAL_DEVICE_SET;
                    return true;
                }
            }

            trigger_error("Specified serial port is not valid", E_USER_WARNING);
            return false;
        }
        else
        {
            trigger_error("You must close your device before to set an other one", E_USER_WARNING);
            return false;
        }
    }

    /**
     * Opens the device for reading and/or writing.
     *
     * @param string $mode Opening mode : same parameter as fopen()
     * @return bool
     */
    function deviceOpen ($mode = "r+b")
    {
        if ($this->_dState === SERIAL_DEVICE_OPENED)
        {
            trigger_error("The device is already opened", E_USER_NOTICE);
            return true;
        }

        if ($this->_dState === SERIAL_DEVICE_NOTSET)
        {
            trigger_error("The device must be set before to be open", E_USER_WARNING);
            return false;
        }

        if (!preg_match("@^[raw]\+?b?$@", $mode))
        {
            trigger_error("Invalid opening mode : ".$mode.". Use fopen() modes.", E_USER_WARNING);
            return false;
        }

        $this->_dHandle = @fopen($this->_device, $mode);

        if ($this->_dHandle !== false)
        {
            stream_set_blocking($this->_dHandle, 0);
            $this->_dState = SERIAL_DEVICE_OPENED;
            return true;
        }

        $this->_dHandle = null;
        trigger_error("Unable to open the device", E_USER_WARNING);
        return false;
    }

    /**
     * Closes the device
     *
     * @return bool
     */
    function deviceClose ()
    {
        if ($this->_dState !== SERIAL_DEVICE_OPENED)
        {
            return true;
        }

        if (fclose($this->_dHandle))
        {
            $this->_dHandle = null;
            $this->_dState = SERIAL_DEVICE_SET;
            return true;
        }

        trigger_error("Unable to close the device", E_USER_ERROR);
        return false;
    }

    //
    // OPEN/CLOSE DEVICE SECTION -- {STOP}
    //

    //
    // CONFIGURE SECTION -- {START}
    //

    /**
     * Configure the Baud Rate
     * Possible rates : 110, 150, 300, 600, 1200, 2400, 4800, 9600, 38400,
     * 57600 and 115200.
     *
     * @param int $rate the rate to set the port in
     * @return bool
     */
    function confBaudRate ($rate)
    {
        if ($this->_dState !== SERIAL_DEVICE_SET)
        {
            trigger_error("Unable to set the baud rate : the device is either not set or opened", E_USER_WARNING);
            return false;
        }

        $validBauds = array (
            110    => 11,
            150    => 15,
            300    => 30,
            600    => 60,
            1200   => 12,
            2400   => 24,
            4800   => 48,
            9600   => 96,
            19200  => 19,
            38400  => 38400,
            57600  => 57600,
            115200 => 115200
        );

        if (isset($validBauds[$rate]))
        {
            if ($this->_os === "linux")
            {
                $ret = $this->_exec("stty -F " . $this->_device . " " . (int) $rate, $out);
            }
            elseif ($this->_os === "windows")
            {
                $ret = $this->_exec("mode " . $this->_windevice . " BAUD=" . $validBauds[$rate], $out);
            }
            else return false;

            if ($ret !== 0)
            {
                trigger_error ("Unable to set baud rate: " . $out[1], E_USER_WARNING);
                return false;
            }
        }
    }

    /**
     * Configure parity.
     * Modes : odd, even, none
     *
     * @param string $parity one of the modes
     * @return bool
     */
    function confParity ($parity)
    {
        if ($this->_dState !== SERIAL_DEVICE_SET)
        {
            trigger_error("Unable to set parity : the device is either not set or opened", E_USER_WARNING);
            return false;
        }

        $args = array(
            "none" => "-parenb",
            "odd"  => "parenb parodd",
            "even" => "parenb -parodd",
        );

        if (!isset($args[$parity]))
        {
            trigger_error("Parity mode not supported", E_USER_WARNING);
            return false;
        }

        if ($this->_os === "linux")
        {
            $ret = $this->_exec("stty -F " . $this->_device . " " . $args[$parity], $out);
        }
        else
        {
            $ret = $this->_exec("mode " . $this->_windevice . " PARITY=" . $parity{0}, $out);
        }

        if ($ret === 0)
        {
            return true;
        }

        trigger_error("Unable to set parity : " . $out[1], E_USER_WARNING);
        return false;
    }

    /**
     * Sets the length of a character.
     *
     * @param int $int length of a character (5 <= length <= 8)
     * @return bool
     */
    function confCharacterLength ($int)
    {
        if ($this->_dState !== SERIAL_DEVICE_SET)
        {
            trigger_error("Unable to set length of a character : the device is either not set or opened", E_USER_WARNING);
            return false;
        }

        $int = (int) $int;
        if ($int < 5) $int = 5;
        elseif ($int > 8) $int = 8;

        if ($this->_os === "linux")
        {
            $ret = $this->_exec("stty -F " . $this->_device . " cs" . $int, $out);
        }
        else
        {
            $ret = $this->_exec("mode " . $this->_windevice . " DATA=" . $int, $out);
        }

        if ($ret === 0)
        {
            return true;
        }

        trigger_error("Unable to set character length : " .$out[1], E_USER_WARNING);
        return false;
    }

    /**
     * Sets the length of stop bits.
     *
     * @param float $length the length of a stop bit. It must be either 1,
     * 1.5 or 2. 1.5 is not supported under linux and on some computers.
     * @return bool
     */
    function confStopBits ($length)
    {
        if ($this->_dState !== SERIAL_DEVICE_SET)
        {
            trigger_error("Unable to set the length of a stop bit : the device is either not set or opened", E_USER_WARNING);
            return false;
        }

        if ($length != 1 and $length != 2 and $length != 1.5 and !($length == 1.5 and $this->_os === "linux"))
        {
            trigger_error("Specified stop bit length is invalid", E_USER_WARNING);
            return false;
        }

        if ($this->_os === "linux")
        {
            $ret = $this->_exec("stty -F " . $this->_device . " " . (($length == 1) ? "-" : "") . "cstopb", $out);
        }
        else
        {
            $ret = $this->_exec("mode " . $this->_windevice . " STOP=" . $length, $out);
        }

        if ($ret === 0)
        {
            return true;
        }

        trigger_error("Unable to set stop bit length : " . $out[1], E_USER_WARNING);
        return false;
    }

    /**
     * Configures the flow control
     *
     * @param string $mode Set the flow control mode. Availible modes :
     *  -> "none" : no flow control
     *  -> "rts/cts" : use RTS/CTS handshaking
     *  -> "xon/xoff" : use XON/XOFF protocol
     * @return bool
     */
    function confFlowControl ($mode)
    {
        if ($this->_dState !== SERIAL_DEVICE_SET)
        {
            trigger_error("Unable to set flow control mode : the device is either not set or opened", E_USER_WARNING);
            return false;
        }

        $linuxModes = array(
            "none"     => "clocal -crtscts -ixon -ixoff",
            "rts/cts"  => "-clocal crtscts -ixon -ixoff",
            "xon/xoff" => "-clocal -crtscts ixon ixoff"
        );
        $windowsModes = array(
            "none"     => "xon=off octs=off rts=on",
            "rts/cts"  => "xon=off octs=on rts=hs",
            "xon/xoff" => "xon=on octs=off rts=on",
        );

        if ($mode !== "none" and $mode !== "rts/cts" and $mode !== "xon/xoff") {
            trigger_error("Invalid flow control mode specified", E_USER_ERROR);
            return false;
        }

        if ($this->_os === "linux")
            $ret = $this->_exec("stty -F " . $this->_device . " " . $linuxModes[$mode], $out);
        else
            $ret = $this->_exec("mode " . $this->_windevice . " " . $windowsModes[$mode], $out);

        if ($ret === 0) return true;
        else {
            trigger_error("Unable to set flow control : " . $out[1], E_USER_ERROR);
            return false;
        }
    }

    /**
     * Sets a setserial parameter (cf man setserial)
     * NO MORE USEFUL !
     *  -> No longer supported
     *  -> Only use it if you need it
     *
     * @param string $param parameter name
     * @param string $arg parameter value
     * @return bool
     */
    function setSetserialFlag ($param, $arg = "")
    {
        if (!$this->_ckOpened()) return false;

        $return = exec ("setserial " . $this->_device . " " . $param . " " . $arg . " 2>&1");

        if ($return{0} === "I")
        {
            trigger_error("setserial: Invalid flag", E_USER_WARNING);
            return false;
        }
        elseif ($return{0} === "/")
        {
            trigger_error("setserial: Error with device file", E_USER_WARNING);
            return false;
        }
        else
        {
            return true;
        }
    }

    //
    // CONFIGURE SECTION -- {STOP}
    //

    //
    // I/O SECTION -- {START}
    //

    /**
     * Sends a string to the device
     *
     * @param string $str string to be sent to the device
     * @param float $waitForReply time to wait for the reply (in seconds)
     */
    function sendMessage ($str, $waitForReply = 0.1)
    {
        $this->_buffer .= $str;

        if ($this->autoflush === true) $this->flush();

        usleep((int) ($waitForReply * 1000000));
    }

    /**
     * Reads the port until no new datas are availible, then return the content.
     *
     * @pararm int $count number of characters to be read (will stop before
     *  if less characters are in the buffer)
     * @return string
     */
    function readPort ($count = 0)
    {
        if ($this->_dState !== SERIAL_DEVICE_OPENED)
        {
            trigger_error("Device must be opened to read it", E_USER_WARNING);
            return false;
        }

        if ($this->_os === "linux")
        {
            $content = ""; $i = 0;

            if ($count !== 0)
            {
                do {
                    if ($i > $count) $content .= fread($this->_dHandle, ($count - $i));
                    else $content .= fread($this->_dHandle, 128);
                } while (($i += 128) === strlen($content));
            }
            else
            {
                do {
                    $content .= fread($this->_dHandle, 128);
                } while (($i += 128) === strlen($content));
            }

            return $content;
        }
        elseif ($this->_os === "windows")
        {
            /* Do nohting : not implented yet */
        }

        trigger_error("Reading serial port is not implemented for Windows", E_USER_WARNING);
        return false;
    }

    /**
     * Flushes the output buffer
     *
     * @return bool
     */
    function flush ()
    {
        if (!$this->_ckOpened()) return false;

        if (fwrite($this->_dHandle, $this->_buffer) !== false)
        {
            $this->_buffer = "";
            return true;
        }
        else
        {
            $this->_buffer = "";
            trigger_error("Error while sending message", E_USER_WARNING);
            return false;
        }
    }

    //
    // I/O SECTION -- {STOP}
    //

    //
    // INTERNAL TOOLKIT -- {START}
    //

    function _ckOpened()
    {
        if ($this->_dState !== SERIAL_DEVICE_OPENED)
        {
            trigger_error("Device must be opened", E_USER_WARNING);
            return false;
        }

        return true;
    }

    function _ckClosed()
    {
        if ($this->_dState !== SERIAL_DEVICE_CLOSED)
        {
            trigger_error("Device must be closed", E_USER_WARNING);
            return false;
        }

        return true;
    }

    function _exec($cmd, &$out = null)
    {
        $desc = array(
            1 => array("pipe", "w"),
            2 => array("pipe", "w")
        );

        $proc = proc_open($cmd, $desc, $pipes);

        $ret = stream_get_contents($pipes[1]);
        $err = stream_get_contents($pipes[2]);

        fclose($pipes[1]);
        fclose($pipes[2]);

        $retVal = proc_close($proc);

        if (func_num_args() == 2) $out = array($ret, $err);
        return $retVal;
    }

    //
    // INTERNAL TOOLKIT -- {STOP}
    //
}
?>

Referencias:

Tutorial de la página de Arduino

Vídeo del turorial

Próximamente:

Tutorial Arduino parte 4

En el próximo tutorial explicaremos como utilizar una aplicación android en 3D para crear un interfaz para este tutorial , que podremos utilizar en nuestro celular Android.

Arduino Segunda Parte

image_pdf

Introducción 

En este segundo post vamos a realizar una pequeña aplicación que controla dos leds (uno rojo y uno verde) conectados a Arduino. Esta placa estará conectada a un pc con un servidor servidor web. En dicho servidor web alojaremos un archivo PHP que se encargará de enviar valores a través de USB al arduino. Con un pequeño programa en Android atacaremos mediante Post a ese fichero. De esta manera podremos controlar los leds desde nuestro terminal, siempre y cuando estemos en la misma red local que el servidor web.

 

  • GNU\Linux, venditos ficheros

GNU\Linux es un sistema operativo que utiliza el núcleo Linux junto con bibliotecas y herramientas del proyecto GNU y de muchos otros proyectos/grupos de software.
Bien, en GNU\Linux el hardware esta asignado a un fichero. Así pues, solo tendremos que esribir en el fichero que identifica al puerto USB donde tenemos conectado nuestro Arduino, ni drivers ni complicaciones. Abrir en modo escritura, escribir i cerrar el fichero, así de fácil.

 

  •  Android

Android es un sistema operativo basado en el núcleo Linux diseñado originalmente para dispositivos móviles, tales como teléfonos inteligentes, pero que posteriormente se expandió su desarrollo para soportar otros dispositivos tales como tablet, reproductores MP3, netbook, PC, televisores, lectores de e-book e incluso, se han llegado a ver en el CES, microondas y lavadoras. Crearemos una pequeña aplicación que enviará un post a un fichero php que se encargará de escribir en el puerto USB correspondiente. Por la simplicidad de la aplicación y no ser Android objetivo del post sólo pondremos el código relativo a la ejecución del post.

 

Instalación de paquetes necesarios

Deberemos instalar las librerías y el IDE. Para ello podeis consultar la primera parte de la serie Arduino Arduino Primera Parte

 

Diseño electrico del Arduino

 

Código Arduino

int ledPin = 9;
int ledPin2 = 6;
int number_in = 0;

void setup() {
     pinMode(ledPin, OUTPUT);
     pinMode(ledPin2, OUTPUT);

     Serial.begin(115200);
}

void loop() {
     if (Serial.available() &gt; 0) {
          number_in = Serial.read();
          Serial.print("He rebut: ");
          Serial.println(number_in, DEC);
     }

     while (number_in == 49) {
          digitalWrite(ledPin, HIGH);
          delay(800);
          digitalWrite(ledPin, LOW);
          delay(800);
          if (Serial.available() &gt; 0) {
               number_in = Serial.read();
               Serial.print("He rebut: ");
               Serial.println(number_in, DEC);
          }
     }

     while (number_in == 51) {
          digitalWrite(ledPin2, HIGH);
          delay(800);
          digitalWrite(ledPin2, LOW);
          delay(800);
          if (Serial.available() &gt; 0) {
               number_in = Serial.read();
               Serial.print("He rebut: ");
               Serial.println(number_in, DEC);
          }
     }
}

 

Servidor Web

  • Deberemos dar permisos al usuario www-data (usuario por defecto del servidor Apache) para escribir en el fichero que corresponde al puerto USB:
sudo adduser www-data dialout
  • En el servidor web alojaremos el fichero que se encargará de enviar las señales a Arduino:
if (!empty($_POST['green'])) {
     $return['msg'] = "green";
     // '/dev/ttyACM1' corresponde a al puerto USB deberemos cambiarlo por el que corresponda en nuestro PC
     $fp =fopen("/dev/ttyACM1", "w");
     fwrite($fp, chr('51'));
     fclose($fp);
}else if (!empty($_POST['red'])){
     $return['msg'] = "red";
     $fp =fopen("/dev/ttyACM1", "w");
     fwrite($fp, chr('49'));
     fclose($fp);
}else if (!empty($_POST['off'])){
     $return['msg'] = "off";
     $fp =fopen("/dev/ttyACM1", "w");
     fwrite($fp, chr('48'));
     fclose($fp);
}

 

Código Android

  • Encender led Verde
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://localhost/post.php");
     
List<NameValuePair> postValues = new ArrayList<NameValuePair>(2);
postValues.add(new BasicNameValuePair("green", "green"));
httppost.setEntity(new UrlEncodedFormEntity(postValues));
         
HttpResponse response = httpclient.execute(httppost);
  • Encender led Rojo
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://localhost/post.php");
     
List<NameValuePair> postValues = new ArrayList<NameValuePair>(2);
postValues.add(new BasicNameValuePair("red", "red"));  
httppost.setEntity(new UrlEncodedFormEntity(postValues));  
         
HttpResponse response = httpclient.execute(httppost);
  • Apagar leds
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://localhost/post.php");

ListpostValues = new ArrayList(2);
postValues.add(new BasicNameValuePair("off", "off"));
httppost.setEntity(new UrlEncodedFormEntity(postValues));

HttpResponse response = httpclient.execute(httppost);

 

Observaciones

Con esta segunda parte podemos ver una aproximación a las posibilidades de arduino. De esta manera podemos controlar cualquier cosa que connectemos a Arduino (las posibilidades son infinitas) y es que con este «juguete» se sabe cuando se empieza pero no cuando se acaba.

Fuentes

Ruben

Arduino – Primera Parte

image_pdf

Introducción
En este primer post mostraremos que es Arduino, como funciona y como cargar el programa Blink. Esto nos permitirá ver el funcionamiento básico y comprobar que nuestra placa funciona correctamente.

  • Arduino

 

Arduino es una plataforma de hardware libre, basada en una placa con un microcontrolador y un entorno de desarrollo, diseñada para facilitar el uso de la electrónica en proyectos multidisciplinares.
El hardware consiste en una placa con un microcontrolador Atmel AVR y puertos de entrada/salida. Los microcontroladores más usados son el Atmega168, Atmega328, Atmega1280, ATmega8 por su sencillez y bajo coste que permiten el desarrollo de múltiples diseños. Por otro lado el software consiste en un entorno de desarrollo que implementa el lenguaje de programación Processing/Wiring y el cargador de arranque (boot loader) que corre en la placa.
Arduino se puede utilizar para desarrollar objetos interactivos autónomos o puede ser conectado a software del ordenador (por ejemplo: Macromedia Flash, Processing, Max/MSP, Pure Data). Las placas se pueden montar a mano o adquirirse. El entorno de desarrollo integrado libre se puede descargar gratuitamente.
Al ser open-hardware, tanto su diseño como su distribución es libre. Es decir, puede utilizarse libremente para el desarrollo de cualquier tipo de proyecto sin haber adquirido ninguna licencia.

 

  • Processing

Processing es un lenguaje de programación y entorno de desarrollo integrado de código abierto basado en Java, de fácil utilización, y que sirve como medio para la enseñanza y producción de proyectos multimedia e interactivos de diseño digital. Fue iniciado por Ben Fry y Casey Reas a partir de reflexiones en el Aesthetics and Computation Group del MIT Media Lab dirigido por John Maeda.
Processing es desarrollado por artistas y diseñadores como una herramienta alternativa al software propietario. Puede ser utilizado tanto para aplicaciones locales así como para aplicaciones web (Applets).
Se distribuye bajo la licencia GNU GPL.

 

Instalando el software necesario

Deberemos instalar las librerías y el IDE con este simple comando:

sudo apt-get install arduino arduino-core

 

Diseño Arduino

Conectaremos el led teniendo en cuenta que la patilla corta es el negativo y la patilla larga el positivo. Necesitaríamos una resistencia para que no se queme el led, por suerte el pin 13 de la placa Arduino incluye una. Así pues, conectaremos la patilla larga(positivo) al conector 13 y la corta(negativo) a la entrada de corriente GND, como se puede comprobar los dos conectores y la resistencia están puestos estrategicamente.

 

Cargando el programa Blink

Este programa es el más básico, simplemente produce un parpadeo del led. Conectamos el Arduino por USB. Deberemos comprobar que hemos seleccionado correctamente el puerto USB, en mi caso es el /dev/ttyACM0 tal y como se ve en la imagen.

 

Cargaremos el programa Blink.

 

 

 

Haremos unas pequeñas modificaciones para poder obtener feedback de lo que esta ocurriendo. Processing nos dirá que el código es read-only, simplemente guardamos el código con un nuevo nombre y listo.

/*
Blink
Turns on an LED on for one second, then off for one second, repeatedly.

This example code is in the public domain.
*/


void setup() {
// initialize the digital pin as an output.
// Pin 13 has an LED connected on most Arduino boards:
pinMode(13, OUTPUT);
Serial.begin(115200); //Establecemos la velocidad de envio de datos
}

void loop() {
Serial.print("Led encendido");
digitalWrite(13, HIGH); // set the LED on
delay(1000); // wait for a second
Serial.print("Led apagado");
digitalWrite(13, LOW); // set the LED off
delay(1000); // wait for a second
}

 

Subir el programa a Arduino y arrancar el Serial Monitor

Subiremos el programa tal y como se ve en la imagen.

 

 

Una vez cargado el programa arrancamos el Serial Monitor y podremos ver el feedback que recibimos del Arduino al mismo tiempo que nuestro led empieza a parpadear. Debemos tener en cuenta que la velocidad que hemos indicado en el codigo

Serial.begin(115200)

sea la misma con la que escucha el Serial monitor(Desplegables inferior derecho).

 

 

 

 

Observaciones

Con este primer post podemos tener un primer contacto con este espectacular juguete. Las posibilidades son muchas y se pueden encontrar miles de proyectos en la red. Próximamente, mostraré un proyecto un poco más avanzado son Arduino y más adelante el compañero Scuraki continuará con la tercera parte.

Fuentes

Ruben

C/C++ en Linux

image_pdf

Introducción

En este post voy a comentar alguna librerías y otros útiles para la programación de c/c++ en GNU\Linux. Cuando trabajamos con GNU\Linux todo programa debe tener un adecuado archivo de configuración, debe aceptar parámetros, debe poder recibir señales y actuar en función de ellas, así mismo también debería implementar un sistema de logs. También puede ser interesante acceder a MySql o tener un pequeño servidor web para mostrar información en una simple web html sin necesidad de instalar un Apache entero.

Trataremos

  • Señales -> Mostraremos un pequeño codigo con el que podemos captar señales y de esta manera actuar en consecuencia.
  • Dotconf -> Mostraremos un ejemplo de esta librería que biene a ser un parser para archivos de configuración estandar.
  • Log4cxx -> Esta libería nos permite trabajar con logs comodamente, se bas en un xml de configuración donde podemos especificar como será formatación de las cadenas de loggin por pantalla hasta la configuración de logs rotativos escritos a disco.
  • MySql – libmysql++ -> Con esta librería podremos realizar operaciones sobre bases de datos MySql.
  • Swill Server -> Esta librería nos permitirá levantar un pequeño servidor web.
  • Jansson -> Esta librería nos permitirá parsear estructuras fácilmente.

 

Cabe decir que no se va profundizar, esto pretende ser una aproximación a buenas «maneras» de trabajar de programar con GNU\Linux.

Señales
En esencia una señal es una notificación asíncrona enviada a un a un programa. En caso de que no se haya programado un handle el programa será el que trate las señal, sinó se ejecutará la accción por defecto para esa señal. En este ejemplo veremos como programar el handle para poder manejar las señales que recibamos.

Bien para compilarlo:

g++ main.cpp -o signal

Codigo:

*
* main.cpp
* Author: ruben
*/

#include
#include
#include
#include

void kctrlc(int signum){
    printf("He recibido un ctrl + c (%d). Deberia abortar lo que este haciendo ahora.\n", signum);
}

void ksigusr(int signum){
    printf("He recibido un sigusr 1 o 2 (%d)\n", signum);
}

void ksigt(int signum){
    printf("He recibido un sigterm (%d). Deberia acabar lo que este haciendo...\n", signum);
}

void ksigalrm(int signum){
    printf("He recibido un sigalrm (%d).\n", signum);
}
void ksighup(int signum){
    printf("He recibido un sighup (%d). Deberia releer la conmfiguracion de sete programa.\n", signum);
}

void kgeneric(int signum){
    printf("He recibido otra senal (%d)\n", signum);
}

void ksigsegv(int signum){
    printf("Segmentation fault (%d).\n", signum);
    exit(1);
}

void ksigbus(int signum){
    printf("bus error (%d).\n", signum);
    exit(2);
}

/* Esta funcion es un distribuidor, capta las senales y en funcion de eso
* llama a una u otra funcion.
*/

void ksighandler(int signum){
    switch (signum){
        case SIGINT:
            kctrlc(signum);
            break;
        case SIGUSR1:
        case SIGUSR2:
            ksigusr(signum);
            break;
        case SIGTERM:
            ksigt(signum);
            break;
        case SIGHUP:
            ksighup(signum);
            break;
        case SIGALRM:
            ksigalrm(signum);
            break;
        case SIGSEGV:
            ksigsegv(signum);
            break;
        case SIGBUS:
            ksigbus(signum);
            break;
        default:
            kgeneric(signum);
            break;
    }
    /* reprogramamos la senal que ha llegado para que vuelva ha hacer lo mismo
    */

    signal(signum, ksighandler);
}

int main(){
    int i;
    /* haciendo 'kill -l' veremos que hay 64 senales... les reprogramaremos
    * para que cuando llegue una se ejecute la funcion la funcio ksighandler.
    */

    for (i = 1; i <= 64; i++){
        signal(i, ksighandler);
    }

    /* programamos una alarma para que en 30 segundons envie un SIGALRM (14)
    * al proceso
    */

    alarm(30);

    /* con este bucle infinito veremos el pid del proceso, para
    * poder enviarle las senales que queramos con 'kill -num $PID' o
    */

    while (1){
        printf("Soy el pid %d y espero senales\n", getpid());
    sleep(2);
    }
}

Dotconf
Esta librería nos permitirá manejar fácilmente archivos standar de configuración.

Para compilar:

g++ conf.cpp -o conf -ldotconf

Archvo configuración

# the default behaviour for dot.conf is to stop parsing as
# soon as the first unquoted, unescaped #-sign is found
# you can override it by giving the flag NO_INLINE_COMMENTS to dotconf_create()

var1 'upper case' #inline comment 1
var2 '1' # inline comment 2
var3 '2' # inline comment 3
var4 '3' #inline comment 4

Archivo fuente

/*
* main.cpp
* Author: ruben
*/


#include
#include
#include

/*
tabsize: 4
shiftwidth: 4
*/


DOTCONF_CB(cb_noinline){
    int i;
    int j=0;
    char sport[200];
    char sport2[200];
    char sport3[200];
    char sport4[200];

    printf("[test.conf] Have %d args\n", cmd->arg_count);

    for (i = 0; i < cmd->arg_count; i++){

        if(j==0){
            strcpy (sport,cmd->data.list[i]);
            printf("Arg: %s\n", sport);
            j=1;
        }else if (j== 1){
            strcpy (sport2,cmd->data.list[i]);
            printf("Arg: %s\n", sport2);
            j=2;
        }else if(j==2){
            strcpy (sport3,cmd->data.list[i]);
            printf("Arg: %s\n", sport3);
            j=3;
        }else if(j==3){
            strcpy (sport4,cmd->data.list[i]);
            printf("Arg: %s\n", sport4);
            j=0;
        }
    }

    return NULL;
}

static configoption_t options[] = {
    {"var1", ARG_LIST, cb_noinline, NULL, 0},
    {"var2", ARG_LIST, cb_noinline, NULL, 0},
    {"var3", ARG_LIST, cb_noinline, NULL, 0},
    {"var4", ARG_LIST, cb_noinline, NULL, 0},
    LAST_OPTION
};

void readit(int flags){
    configfile_t *configfile;

    configfile = dotconf_create("test.conf", options, 0, flags);
    if (!dotconf_command_loop(configfile))
    fprintf(stderr, "Error reading config file\n");
    dotconf_cleanup(configfile);
}

int main(int argc, char **argv){
    //printf("Reading the configuration with NO_INLINE_COMMENTS enabled\n");
    //readit(NO_INLINE_COMMENTS);

    //printf("\n\n");
    printf("Reading the configuration\n");
    readit(0);

    //printf("%s\n",cmd->data.list[0]);

    return 0;
}

Log4cxx

Esta librería nos permitirá gestionar los log’s de nuestra aplicación adecuadamente.

Para compilar:

g++ log.cpp -I/opt/include /usr/lib/liblog4cxx.a -lapr-1 -laprutil-1

Archvo configuración

<?xml version="1.0" encoding="UTF-8" ?>
 <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
  <!-- Output the log message to system console.
   -->
  <appender name="appxConsoleAppender" class="org.apache.log4j.ConsoleAppender">    
    <param name="Target" value="System.out"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
        </layout>
  </appender>

  <!-- Output the log message to log file
   -->
  <appender name="appxNormalAppender" class="org.apache.log4j.FileAppender">
    <param name="file" value="/var/log/custom.log" />
    <param name="append" value="true" />
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d %-5p %C{2} (%F:%L) - %m%n" />
    </layout>
  </appender>

  <root>
        <priority value="all" />
        <appender-ref ref="appxNormalAppender"/>
        <appender-ref ref="appxConsoleAppender"/>
  </root>

  <!-- Specify the level for some specific categories -->
  <category name="functionA" >
        <priority value ="info" />
        <appender-ref ref="appxNormalAppender"/>
        <appender-ref ref="appxConsoleAppender"/>
  </category>

 </log4j:configuration>
#include <log4cxx/logger.h>
#include <log4cxx/xml/domconfigurator.h>

using namespace log4cxx;
using namespace log4cxx::xml;
using namespace log4cxx::helpers;

// Define static logger variable
LoggerPtr loggerMyMain(Logger::getLogger( "main"));
LoggerPtr logtest(Logger::getLogger( "Function A"));

void functionA(){
    LOG4CXX_INFO(logtest, "Executing functionA.");
    LOG4CXX_INFO(logtest, "exiting functionA.");
}

int main(){
    // Load configuration file
    DOMConfigurator::configure("conf.xml");

    LOG4CXX_TRACE(loggerMyMain, "this is a debug message for detailed code discovery.");
    LOG4CXX_DEBUG(loggerMyMain, "this is a debug message.");
    LOG4CXX_INFO (loggerMyMain, "this is a info message, ignore.");
    LOG4CXX_WARN (loggerMyMain, "this is a warn message, not too bad.");
    LOG4CXX_ERROR(loggerMyMain, "this is a error message, something serious is happening.");
    LOG4CXX_FATAL(loggerMyMain, "this is a fatal message!!!");
    functionA();

    return 0;
}

 

MySql

Esta librería nos permitirá acceder y utilizar bases de datos Mysql comodamente.

Archvo configuración sql

-- phpMyAdmin SQL Dump
-- version 3.4.10.1deb1
-- http://www.phpmyadmin.net
--
-- Servidor: localhost
-- Temps de generació: 31-08-2012 a les 15:27:03
-- Versió del servidor: 5.5.24
-- Versió de PHP : 5.3.10-1ubuntu3.2

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Base de dades: `emp`
--

-- --------------------------------------------------------

--
-- Estructura de la taula `emp`
--

CREATE TABLE IF NOT EXISTS `emp` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` text NOT NULL,
  `surname` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

--
-- Bolcant dades de la taula `emp`
--

INSERT INTO `emp` (`id`, `name`, `surname`) VALUES
(1, 'test', 'test1'),
(2, 'test2', 'test3');

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

Para compilar:

 gcc conexion.cpp main.cpp -o conexion2 -Wno-deprecated -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient -lstdc++ -lz
/*
* main.cpp
* Author: ruben
*/


#include <sys/time.h>
#include <stdio.h>
#include <mysql.h>

int main(){

    MYSQL_RES *result;
    MYSQL_ROW row;
    MYSQL *connection, mysql;

    int state;

    mysql_init(&mysql);

    connection = mysql_real_connect(&mysql,"localhost","user","pass","emp",0,0,0);

    if (connection == NULL){
        printf("Error: %s\n",mysql_error(&;mysql));
        return 1;
    }

    state = mysql_query(connection, "SELECT * FROM emp");

    if (state !=0){
        printf("Error: %s\n",mysql_error(connection));
        return 1;
    }

    result = mysql_store_result(connection);
    printf("Rows: %d\n",mysql_num_rows(result));

    while ( ( row=mysql_fetch_row(result)) != NULL ){
        printf("id -> %s, name -> %s, surname -> %s\n", (row[0] ? row[0] : "NULL"), (row[1] ? row[1] : "NULL"),(row[2] ? row[2] : "NULL"));
    }

    mysql_free_result(result);
    mysql_close(connection);

    return 0;
};

Sqlite3

No siempre enecesitamos guardar datos en una gestor como pueda ser MySql, aveces no requerimos de todo lo que nos puede ofrecer y con SqLite podemos tener una compensación entre recursos consumidos y funcionalidad muy buena

Archvo configuración sql

BEGIN TRANSACTION;
CREATE TABLE emp (id TEXT, name TEXT, surname TEXT);
INSERT INTO emp VALUES(1000,'test','test2');
COMMIT;

Para compilar:

g++ main.cpp -o sqlite -lsqlite3
/*
* main.cpp
* Author: ruben
*/


#include "sqlite3.h"
#include <stdio.h>
#include <string.h>
#include <string>
#include <sstream>

#include <iostream>
#include <cstdlib>
#include <string>

#include <stdio.h>
#include <stdlib.h>

char missatge[1000];
char sentence[1000];
sqlite3 *db;
char *zErrMsg = 0;
int rc;

char **result;

int nrow;
int ncol;
int i;

void insertar(){

    rc = sqlite3_open("emp", &db);

    if( rc ){
        sprintf(missatge, "Test: Can't open database %s to insert row for DB persistence\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        exit(1);
    }

    i++;

    sprintf(sentence, "insert into emp ('id', 'name', 'surname') values ('%d', 'test', 'test2')", i);

    rc = sqlite3_get_table(
        db,
        sentence,
        &result,
        &nrow,
        &ncol,
        &zErrMsg
    );

    sqlite3_free_table(result);
    sqlite3_close(db);

    if (zErrMsg != NULL){
        printf("Error:%s\n",zErrMsg);
        std::cin.ignore(); // ignores the newline
        std::cin.get(); //waits for character
    }else{
        printf("Insertado correctamente\n");
        std::cin.ignore(); // ignores the newline
        std::cin.get(); //waits for character
    }
}

void borrar(){

    rc = sqlite3_open("emp", &db);

    if( rc ){
        sprintf(missatge, "SpoolAndScheduler: Can't open database %s to delete row for DB persistence\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        exit(1);
    }

    std::string cons="delete from emp where id='1'";

    rc = sqlite3_get_table(
        db,
        cons.c_str(),
        &result,
        &nrow,
        &ncol,
        &zErrMsg
    );

    sqlite3_free_table(result);
    sqlite3_close(db);

    if (zErrMsg != NULL){
        printf("Error:%s\n",zErrMsg);
        std::cin.ignore(); // ignores the newline
        std::cin.get(); //waits for character
    }else{
        printf("Borrado correctamente\n");
        std::cin.ignore(); // ignores the newline
        std::cin.get(); //waits for character
    }

}

void listar(){

    rc = sqlite3_open("emp", &db);

    if( rc ){
        sprintf(missatge, "SpoolAndScheduler: Can't open database %s to select rows for DB persistence\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        exit(1);
    }

    std::string cons="select * from emp";//where ds='as'";

    rc = sqlite3_get_table(
        db,
        cons.c_str(),
        &result,
        &nrow,
        &ncol,
        &zErrMsg
    );

    printf("\n --------RESULT-------- \n");

    //printf("Voltes->%d\n",(nrow*ncol)+ncol);
    int j=(nrow*ncol)+ncol;

    for(i=0 ; i < j; i=i+3){
        if(i>=3){
            printf("i->%d - ",i);
            printf("id: %s - ",result[i]);
            printf("name: %s - ",result[i+1]);
            printf("surname: %s\n",result[i+2]);
        }
    }

    sqlite3_free_table(result);

    sqlite3_close(db);

    if (zErrMsg != NULL){
        printf("Error:%s\n",zErrMsg);
        std::cin.ignore(); // ignores the newline
        std::cin.get(); //waits for character
    }else{
        std::cin.ignore(); // ignores the newline
        std::cin.get(); //waits for character
    }
}

int main(){

    int fin = 0;
    int opcion;

    while (fin == 0){
        system("clear");
        printf("Menú simple\n\n");

        printf("\t1] Insertar.\n");
        printf("\t2] Borrar.\n");
        printf("\t3] Listar.\n");
        printf("\t4] Sortir.\n");

        printf("\n\nOpción: ");
        scanf("%i", &opcion);

        switch(opcion){
            case 1:
                insertar();
                break;
            case 2:
                borrar();
                break;
            case 3:
                listar();
                break;
            case 4:
                fin = 1;
                break;
            default:
                fin = 0;
                break;
        }

    }

    return 0;
}

Swill Server

SWILL (Simple Web Interface Link Library) es una librería que nos permite de manera fácil añadir una interfaz web a un programa en C/C++. Deberemos bajarnos la librería y ejecutar los siguientes comandos para descomprimirla desde Swill e instalarla:

tar xvzf swill-0.3.tgz
cd SWILL-0.3
./configure
make
make install

Para compilar:

 g++ main.cpp -o swill_server -I/usr/local/include/swill/ -lswill
/*
* main.cpp
* Author: ruben
*/


#include

void count_to_ten(FILE *f) {
    int i;
    for (i = 0; i < 10; i++) {
        fprintf(f,"%d\n", i);
    }
}

int main() {
    swill_init(8181);
    swill_handle("ten.txt", count_to_ten, 0);
    swill_file("index.html",0);
    while (1) {
    swill_serve();
    }
    swill_shutdown();
}

 

Jansson
Esta librería nos permitirá manejar fácilmente archivos json.

Para compilar:

gcc main.c -o json -ljansson

Archvo json

{
    "errors": [
        {
            "id": "1",
            "message": "string not found"
        },
        {
            "id": "2",
            "message": "system error"
        }

    ]
}
Archivo fuente

/*
*  Author: Ruben
*/


#include <stdlib.h>
#include <string.h>

#include <jansson.h>


#define BUFFER_SIZE  (256 * 1024)  /* 256 KB */

#define URL_FORMAT   "http://github.com/api/v2/json/commits/list/%s/%s/master"
#define URL_SIZE     256

/* Return the offset of the first newline in text or the length of
text if there's no newline */

static int newline_offset(const char *text){
    const char *newline = strchr(text, '\n');
    if(!newline)
    return strlen(text);
    else
    return (int)(newline - text);
}

struct write_result{
    char *data;
    int pos;
};


int main(int argc, char *argv[]){
    size_t i;


    json_t *root;
    json_error_t error;
    json_t *errors;


    root = json_load_file("file.json", 0, &amp;error);


    if(!root){
        fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
        return 1;
    }

    errors = json_object_get(root, "errors");
    if(!json_is_array(errors)){
        fprintf(stderr, "error: errors is not an array\n");
        return 1;
    }

    for(i = 0; i < json_array_size(errors); i++){
        json_t *error, *id, *message;
        const char *message_text;

        error = json_array_get(errors, i);
        if(!json_is_object(error)){
            fprintf(stderr, "error: error %d is not an object\n", i + 1);
            return 1;
        }

        id = json_object_get(error, "id");
        if(!json_is_string(id)){
            fprintf(stderr, "error: error %d: id is not a string\n", i + 1);
            return 1;
        }

        message = json_object_get(error, "message");
        if(!json_is_string(message))    {
            fprintf(stderr, "error: error %d: message is not a string\n", i + 1);
            return 1;
        }

        message_text = json_string_value(message);
        printf("%.8s %.*s\n",
        json_string_value(id),
        newline_offset(message_text),
        message_text);
    }

    json_decref(root);
    return 0;
}

 

Observaciones
Bien, espero que esto pueda ser de ayuda. No es más que un poco de cada. Pero al fin y al cabo estas utilidades siempre puede ir bien.

Ruben

Python XMPP Client (Twisted)

image_pdf

Introducción

En este post vamos a realizar un cliente de xmpp en python. Es de obligada mención Twisted Matrix, una increíble framework para python el cual facilita muchíssimo la programación enfocada a redes. En cuanto a protocolos podemos trabajar con HTTP, XMPP, NNTP, IMAP, SSH, IRC, FTP y muchos más, también podemos trabajar con varias arquitecturas (TCP, UDP, SSL/TLS, IP Multicast, Unix domain sockets).

Características

  • Separación de los protocolos y transportes

El diseño de Twisted se basa en la separación completa entre los protocolos lógicos (que por lo general dependen de la conexión semántica basada en streams –flujos–, como el HTTP o POP3) y el transporte en capas físicas soportado como la semántica basada en streams (como archivos, bibliotecas sockets o SSL). La conexión entre un protocolo lógico y una capa de transporte que ocurre en el último momento posible, justo antes de la información se pase a la instancia de protocolo lógico. El protocolo lógico es informado de la instancia de capa de transporte, y puede utilizarlo para enviar mensajes de un lado para comprobar la identidad del otro extremo. Tenga en cuenta que todavía es posible, en el código de protocolo, para consultar profundamente la capa de transporte en cuestiones de transporte (como la comprobación de un certificado SSL del lado del cliente). Naturalmente, el código de dicho protocolo, se producirá un error (lanzar una excepción) si la capa de transporte no es compatible con tales semánticas.

  • Deferreds

El modelo central de aplicación para Twisted es el concepto de un deferred (predefinir algo que se usara como valor futuro). Un deferred es un valor que no se ha calculado todavía, por ejemplo, porque las necesidades de datos desde un equipo remoto. Los deferreds se pueden transferir, al igual que los objetos normales, pero no se puede pedir por su valor. Cada deferred es compatible con una cadena de devolución de llamada. Cuando el deferred toma el valor, es transferido a través de la cadena de devolución de llamada, con el resultado de cada de callback (devolución) siendo la entrada (input) para la siguiente. Esto permite que operen en los valores de un deferred sin saber lo que son. Por ejemplo, si un deferred devuelve una cadena desde un equipo remoto con una dirección IP en formato quad, un callback se puede adjuntar para traducirla a un número de 32 bits. Cualquier usuario del deferred puede ahora tratarlo como deferred de retorno de un número de 32 bits. Esto, y la capacidad de relación para definir «errbacks» (callbacks que son llamados como controladores de errores), permite que el código que se ve como si fuera de serie, mientras que todavía mantiene la abstracción por eventos.

  • Soporte de Thread (hilos o subprocesos)

Twisted soporta una abstracción sobre threads en crudo usando un thread como una fuente deferred. Por lo tanto, un deferred que es retornado inmediatamente, recibirá un valor cuando finalice el thread. Los callbacks se pueden adjuntar cuando corran en el thread principal, a fin de aliviar la necesidad de soluciones complejas de bloqueo. Un buen ejemplo de tal uso, que viene de las bibliotecas de soporte de Twisted, es usar este modelo para llamadas en bases de datos. La llamada de la base de datos misma pasa de un thread exterior, pero el análisis del resultado que sucede en el thread principal.

  • Soporte de bucle de externos

Twisted se puede integrar con bucles de eventos externos, tales como los de GTK+, Qt y Cocoa (a través de PyObjC). Esto le permite el uso de Twisted como la capa de soporte de red en aplicaciones GUI, usando todas sus colecciones sin tener que añadir una sobrecarga de thread-por-socket, como lo haria cualquier biblioteca nativa de Python. Se pude integrar en proceso un completo web server con una aplicación interfaz gráfica utilizando este modelo, por ejemplo.

Cabe decir que no es objetivo de este post profundizar en twisted matrix, pues se necesitarían sería muy extenso (de echo harían falta muchos :p). También hace falta añadir, que hay una muy buena documentación en la página oficial.

Instalación

Podemos descargar el framework des de la página oficial:
# Twisted Matrix Downloads
O bien odemos instalarlo fácilmente en Debian y derivados, puesto que esta en los repositorios (sino en el link de la página oficial antes citada te facilitan la PPA):

$>sudo apt-get install python-twisted python-twisted-words

El modulo twisted-words contiene las librerías de jabber.

Codigo del Cliente

#!/usr/bin/python

# Twisted Imports
from twisted.words.protocols.jabber import client, jid , xmlstream
from twisted.words.xish import domish
from twisted.internet import reactor

name = None
server = None
resource = None
password = None
me = None

thexmlstream = None
tryandregister = 1

def initOnline(xmlstream):
    # creamos los observadores hacia las respuestas xml message y una general (podemos incluir presence, iq...)
    global factory
    print 'Initializing...'
    xmlstream.addObserver('/message', gotMessage)
    xmlstream.addObserver('/*', gotSomething)

def authd(xmlstream):
    # Autentificacion
    global thexmlstream
    thexmlstream = xmlstream
    print "we've authd!"
    print repr(xmlstream)

    # se envia la presencia a los demas clientes
    presence = domish.Element(('jabber:client', 'presence'))
    presence.addElement('status').addContent('Online')
    xmlstream.send(presence)

    initOnline(xmlstream)

def send(author, to, msg):
    # esta funcion envia los mensajes
    global thexmlstream
    message = domish.Element(('jabber:client','message'))
    message["to"] = jid.JID(to).full()
    message["from"] = jid.JID(author).full()
    message["type"] = "chat"
    message.addElement("body", "jabber:client", msg+ "- ya lo sabia adicotalainformatica1")

    thexmlstream.send(message)

def gotMessage(el):
    # esta funcion parsea los mensajes recibidos
    global me
    # print 'Got message: %s' % str(el.attributes)
    from_id = el["from"]

    body = "empty"
    for e in el.elements():
        if e.name == "body":
            body = unicode(e.__str__())
        break

    send(me, from_id, body)

def gotSomething(el):
    # Observador general
    print 'Got something: %s -> %s' % (el.name, str(el.attributes))

def authfailedEvent(xmlstream):
    global reactor
    print 'Auth failed!'
    reactor.stop()

def invaliduserEvent(self,xmlstream):
    print "Invalid User"

def registerfailedEvent(self,xmlstream):
    print 'Register failed!'

if __name__ == '__main__':
    #Parametrizamos la conexion
    PASSWORD = '123456'
    myJid = jid.JID('adictoalainformatica2@antitot-linux')
    me = 'adictoalainformatica2@antitot-linux'
    factory = client.XMPPClientFactory(myJid, PASSWORD)

    # Registramos las callbacks de autentificacion
    print 'register callbacks'
    factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, authd)
    factory.addBootstrap(client.BasicAuthenticator.INVALID_USER_EVENT, invaliduserEvent)
    factory.addBootstrap(client.BasicAuthenticator.AUTH_FAILED_EVENT, authfailedEvent)
    factory.addBootstrap(client.BasicAuthenticator.REGISTER_FAILED_EVENT, registerfailedEvent)

    # Paarametrizamos y arrancamos el reactor (encargado de mantener y gestionar las callbacks
    # producidas por las acciones de la conexion)
    reactor.connectTCP('localhost', 5222, factory)

Test

Para realizar el test haremos referencia al post anteriror sobre xmpp donde configuramos y creamos dos usuarios (adictosalainformatica1, adictosalainformatica2) con el servidor  openfire. Aprovecharemos los usuarios
para configurar el script e indicaremos al reactor donde esta el servidor xmpp:

#Parametrizamos la conexion
PASSWORD = '123456'
myJid = jid.JID('adictoalainformatica2@antitot-linux')
me = 'adictoalainformatica2@antitot-linux'
factory = client.XMPPClientFactory(myJid, PASSWORD)
reactor.connectTCP('antitot-linux', 5222, factory)

y cualquier cliente como por ejemplo Kopete. Abriremos Kopete e hiremos a configuraciones -> configura. Se abrirá una nueva ventana en esta pincharemos en añadir nuevo elemento.
Seguidamente deberemos escoger el protocolo:

Configuramos la cuenta:

Y ya esta, cuando des del usuario adictosalainformatica enviemos un mensaje a nuestro script éste le responderá el mismo mensaje con la coletilla » – ya lo sabia adicotalainformatica2″.

Código del cliente Xmpp

Puedes descargar el código de este post desde la cuenta de GitHub

Observaciones

Y con este post cierro el tema de redes xmpp dando una vista superficial pero intuitiva de lo que puede ofrecernos este nuevo protocolo tanto a nivel de mensajería como a nivel de distribuidor de comandos. espero que haya sido de ayuda.

Fuentes

Ruben

Top

Desplazarse y navegar por este sitio confirman que aceptas el uso de cookies. + info

Mostramos este incómodo mensaje porque alguien hizo una ley sin sentido que perjudica la usabilidad en internet, el navegador ya incorpora herramientas para bloquear este tipo de contenidor, pero nos vemos obligados a mostrar este mensaje solicitando su consentimiento: Esta web utiliza cookies para ofrecerte la mejor experiencia de navegación posible, como la mayoría. Si sigues utilizando esta web estarás dando tu consentimiento.

Cerrar

magbo system