Compartiendo Datos Con Gestos Thump Matching

Bienvenido a la parte III de la serie Compartir datos con gestos. En la parte II, creamos nuestro proceso de servidor intermediario en Ruby on Rails. Este proceso del servidor actuará como un conducto entre dos dispositivos que intentan comunicarse con un gesto al que llamamos un "golpe". Cuando dos dispositivos se "juntan", el servidor los igualará calculando su proximidad entre ellos a través de las coordenadas del GPS y una marca de tiempo casi idéntica a la de cuando abrieron la comunicación con el servidor. Una vez realizada esta coincidencia, el servidor intercambiará los mensajes escritos en la aplicación móvil, simulando la comunicación de dispositivo a dispositivo..

En la parte III, implementaremos nuestra aplicación de servidor en la plataforma heroku y luego actualizaremos nuestra aplicación móvil para comunicarnos con ella.

Para empezar, modificaremos nuestro archivo de migración de la tabla de golpes para que sea compatible con Postgres. Puede encontrar este archivo en el directorio "db / migrate" y se llamará algo así como: TIMESTAMP_create_thumps.rb. La forma más fácil de implementar una aplicación heroku es usar su servicio de base de datos compartida, que resulta ser Postgres en lugar de MySQL. Vamos a reemplazar las siguientes líneas:

 t.decimal: lat,: precision => 8,: scale => 8 t.decimal: lng,: precision => 8,: scale => 8

Con estas nuevas líneas:

 t.decimal: lat,: scale => 8 t.decimal: lng,: scale => 8

Postgres maneja los grandes campos decimales de manera diferente a como lo hace MySQL, por lo que este es un cambio necesario para garantizar que obtengamos la precisión del punto de datos que necesitamos en nuestros campos de latitud y longitud.

Ya que esta es una aplicación Rails 2.3.5, utilizaremos el antiguo método heroku para instalar gemas creando un archivo .gems en la raíz de nuestro proyecto Rails. La mayoría de ustedes probablemente estarán acostumbrados a usar Bundler para este tipo de tareas, sin embargo, dado que el complemento geokit no se ha actualizado para que sea compatible con Rails 3.0, debemos hacer cosas con las convenciones más antiguas de Rails 2.

Simplemente agregamos lo siguiente a nuestro archivo .gems:

 rieles -v 2.3.5 pg geokit --version '= 1.5.0'

Aquí especificamos la gema de rieles y la versión que estamos usando para este proyecto, así como la gema de postgres y la versión 1.5.0 de la gema geokit..

¡Ahora podemos comenzar nuestro despliegue! Comencemos creando un repositorio local de git dentro de nuestro proyecto. Todo lo que tenemos que hacer es ejecutar el siguiente comando en el directorio raíz de nuestro proyecto Rails:

 $ git init

Antes de comprometernos con este repositorio, necesitamos crear nuestra aplicación en la plataforma heroku. Si aún no se ha registrado en una cuenta gratuita de heroku, hágalo simplemente registrándose en https://api.heroku.com/signup. Si aún no tiene la gema heroku instalada en su sistema, puede hacerlo ejecutando el siguiente comando:

 $ sudo gema instalar heroku

Una vez que la gema está instalada, ejecute el siguiente comando desde el directorio raíz del proyecto:

 $ heroku crea --stack bamboo-ree-1.8.7

Aquí estamos especificando la pila de bamboom-ree debido a que esta es una aplicación Rails 2. En el caso de que haya creado una nueva cuenta, es posible que se le soliciten las credenciales de su cuenta de heroku. Una vez ingresadas, estas credenciales se almacenarán para futuras interacciones con los servidores de heroku. Si todo va bien, heroku debería responder con algo como lo siguiente:

 Creado http://APPNAME.heroku.com/ | [email protected]: APPNAME.git Git remoto heroku añadido

Aquí he reemplazado el nombre de la aplicación real y el subdominio con un marcador de posición llamado APPNAME Tome nota de este APPNAME ya que lo usaremos más adelante. Ahora vamos a enviar nuestros archivos de proyecto al repositorio de git local que creamos anteriormente. Es tan simple como ejecutar estos dos comandos:

 $ git añadir. $ git commit -m "mi primer commit"

Una vez que el proyecto se haya comprometido completamente con el repositorio local de git, debemos enviarlo al repositorio remoto que se creó cuando ejecutamos el comando heroku create.

 $ git push heroku master

La gema heroku le permite ejecutar comandos de rake remotos en el servidor con el comando "rake heroku". Para completar el despliegue, debemos ejecutar las migraciones de nuestra base de datos que generarán nuestra tabla de golpes en la base de datos de heroku.

 $ heroku rastrillo db: migrar

Felicidades Ha implementado con éxito nuestra aplicación de servidor thump en la plataforma heroku. Ahora volvemos a la aplicación móvil.!

Abramos nuestro archivo main.lua en nuestra aplicación Corona y agreguemos las siguientes líneas en la parte superior:

 http = require ("socket.http") ltn12 = require ("ltn12") url = require ("socket.url") require ("Json")

Necesitamos requerir algunas bibliotecas que nos permitan crear una conexión de socket a nuestra aplicación de servidor. También incluiremos la biblioteca de análisis JSON para que podamos entender los objetos de respuesta que el servidor enviará.

¿Recuerdas el APNAME que se dio cuando creamos la aplicación heroku? Es hora de usar eso ahora:

 local appname = "APPNAMEHERE"

Esta variable se combinará con otras más adelante para generar nuestra URL de servidor para comunicación externa.

En la Parte I, tuvimos la aplicación mostrando un cuadro de alerta con nuestro mensaje cuando detectó un "golpe" o un gesto de sacudida. Ya que necesitamos comunicar este mensaje al servidor, eliminaremos la siguiente línea de nuestra función getThump:

 local alert = native.showAlert ("Thump!", "Location:"? latitudeText? ","? longitudeText? "\ r \ nMessage:"? textField.text, "OK")

Ahora vamos a agregar alguna funcionalidad a este método getThump para enviar nuestro mensaje al servidor. Vamos a desglosar esto:

 local message = textField.text local post = "thump [deviceid] ="? ¿ID del dispositivo? "& thump [lat] ="? latitudeText? "& thump [lng] ="? longitudetext? "& thump [mensaje] ="? respuesta local del mensaje = 

Aquí estamos generando nuestras variables para enviar al servidor. La variable "post" se configura en el formato de cadena de consulta y nuestra "respuesta" se declara como un objeto de tabla vacío por ahora.

 local r, c, h = http.request url = "http: //"? ¿nombre de la aplicación? ".heroku.com / thumps", method = "POST", headers = ["content-length"] = #post, ["Content-Type"] = "application / x-www-form-urlencoded", source = ltn12.source.string (post), sink = ltn12.sink.table (response) local jsonpost = Json.Decode (table.concat (response, "))

Aquí estamos ejecutando una solicitud HTTP de tipo POST a nuestro servidor. Estamos sustituyendo nuestra variable appname como el subdominio de la url. Los encabezados son estándar para una llamada posterior típica. En el campo "longitud de contenido", la sintaxis lua de poner un # delante de la variable dará salida a la longitud en caracteres de esa cadena. Ya que queremos almacenar la respuesta de nuestro servidor en una variable llamada "respuesta", nuestra última línea decodificará esa variable como un objeto JSON y creará un objeto de tabla lua para que podamos acceder a los campos que contiene..

En el caso de un error de comunicación, debemos alertar al usuario de que algo salió mal. Crearemos un método genérico showError () para mostrar un cuadro de alerta al usuario si esto ocurre:

 función local showError () alerta local = native.showAlert ("¡Error!", "¡Inténtalo de nuevo!", "OK") fin

Debido al hecho de que Rails es de un solo hilo por naturaleza y de que las cuentas gratuitas de heroku le permiten ejecutar un solo proceso de servidor; Una vez que la aplicación móvil complete la llamada POST para enviar datos, vamos a sondear nuestro servidor, solicitando un objeto de respuesta. Si bien esta puede no ser la forma más ideal de diseñar esto, nos permite ejecutar este tipo de aplicaciones con recursos de servidor heroku mínimos..

Aquí está nuestra lógica de sondeo a continuación:

 if (jsonpost.success == true) entonces native.setActivityIndicator (true); intentos locales = 0 función retrieveThump (evento) si 10 == intentos entonces native.setActivityIndicator (falso); timer.cancel (event.source) showError () else local response =  local r, c, h = http.request url = "http: //"? ¿nombre de la aplicación? ".heroku.com / thumps / search? thump [deviceid] ="? ¿ID del dispositivo? "& thump [lat] ="? latitudeText? "& thump [lng] ="? longitudeText, method = "GET", sink = ltn12.sink.table (response) local jsonget = Json.Decode (table.concat (response, ")) if (jsonget.success == true) luego native.setActivityIndicator (false ); timer.cancel (event.source) local alert = native.showAlert ("Thump!", jsonget.message, "OK") final intenta = intenta + 1 timer.performWithDelay (3000, retrieveThump) final del temporizador final. performWithDelay (1000, retrieveThump) else showError () end

Vamos a descomponerlo:

 if (jsonpost.success == true) entonces native.setActivityIndicator (true) ;? else showError () end

En el caso de que nuestra variable "jsonpost" devuelva "success = true" del servidor, estableceremos nuestro ActivityIndicator en el dispositivo como verdadero. Esto lanza un componente de chupete nativo que le indica al usuario que la aplicación está funcionando en algo. Si no recibimos un "success = true" del servidor, llamaremos a nuestra función de error genérico y mostraremos el cuadro de alerta de error.

 intentos locales = 0 función retrieveThump (evento)? end timer.performWithDelay (1000, retrieveThump)

En este caso, estamos configurando una variable de intentos fuera del alcance de nuestra función en 0. Usaremos esto más adelante para establecer un límite en el número de solicitudes que puede realizar nuestra función de sondeo "retrieveThump". Corona tiene una clase de temporizador integrada que nos permite llamar a una función en un intervalo de tiempo. La función timer.performWithDelay toma una cantidad de milisegundos y una función como parámetros.

 si 10 == intentos entonces native.setActivityIndicator (falso); timer.cancel (event.source) showError ()

Primero, verificaremos si hemos ejecutado esta función 10 veces. Si este es el caso, vamos a detener nuestro ActivityIndicator configurándolo en falso, cancelar nuestra función de temporizador y luego llamar a nuestra función de error para decirle al usuario que algo salió mal.

 else local response =  local r, c, h = http.request url = "http: //"? ¿nombre de la aplicación? ".heroku.com / thumps / search? thump [deviceid] ="? ¿ID del dispositivo? "& thump [lat] ="? latitudeText? "& thump [lng] ="? longitudeText, method = "GET", sink = ltn12.sink.table (response) local jsonget = Json.Decode (table.concat (response, ")) if (jsonget.success == true) luego native.setActivityIndicator (false ); timer.cancel (event.source) local alert = native.showAlert ("Thump!", jsonget.message, "OK") end intenta = intentos + 1 timer.performWithDelay (3000, retrieveThump) end

Si aún no hemos alcanzado 10 intentos, vamos a ejecutar una solicitud HTTP a nuestro servidor para buscar nuestro "golpe" coincidente. La función es similar a la llamada POST que hicimos anteriormente, solo pasamos el método GET en este caso porque estamos intentando leer y no escribir en el servidor.

Si recuerda de la Parte II, creamos una acción de búsqueda en nuestro servidor Rails que busca en nuestra base de datos un golpe que coincida con nuestras coordenadas GPS y una marca de tiempo similar. Pasamos esta información al servidor a través de la cadena de consulta en la URL. Similar a la llamada POST, estamos analizando el retorno del servidor como un objeto JSON y almacenándolo en una variable de tabla lua local llamada "jsonget". Si recibimos una copia de Success = true desde el servidor, vamos a detener nuestro ActivityIndicator, detener nuestra ejecución del temporizador y mostrar nuestro mensaje en un cuadro de alerta. Si este proceso falla, simplemente sondearemos el servidor de la misma manera para un máximo de 10 intentos.

¡Y ahí lo tienes! Este tutorial debería proporcionarle una buena base para crear diferentes tipos de aplicaciones que compartan datos a través de gestos. Algunas adiciones interesantes podrían ser compartir a través de un toque de pantalla simultáneo, o extender la aplicación para intercambiar imágenes tomadas de la cámara o la biblioteca local de fotos del dispositivo. Feliz golpeteo!