La semana pasada estuve hablando en WebCamp Zagrebuna gran conferencia para desarrolladores y diseñadores. Hice una presentación titulada "Deja que tus dispositivos hablen entre sí". Para la parte de demostración hice una aplicación de mensajes muy simple que se sincroniza automáticamente con cualquier otra persona que la esté ejecutando en la misma red. Las diapositivas y el código de la demo están en github. La presentación se ha filmado y estará en línea en breve.
El tema de esta presentación es IoT (Internet de las cosas), M2M (De máquina a máquina) y la descentralización. Todas estas cosas de Internet suelen enviar sus datos (la mayoría de las veces datos muy privados, sí, te estoy mirando a ti, movimiento del yo cuantificado) a un servidor en algún lugar de la nube. Eso básicamente significa que ya no son tus datos (privados). Esto es muy triste. Esta es la idea principal que me llevó a hacer esta charla. Pero hay muchas otras buenas razones para dejar que tus dispositivos se comuniquen entre sí. Y esto no es algo nuevo. Lo que ahora llamamos M2M es muy común en la industria desde hace años.
Pero volvamos al tema original. Una forma de evitar esta centralización sería que tus cosas de Internet dejaran de ser cosas de Internet y empezaran a ser cosas de tu red doméstica. Deberían empezar a comunicarse entre sí y enviar sus datos donde tú decidas, como una instancia de Couchbase Lite corriendo en una RaspberryPI o cualquier otro pequeño dispositivo que soporte la JVM.
Y, por supuesto, una forma de hacer que los dispositivos se comuniquen entre sí puede ser instalar Couchbase Lite en ellos y utilizar la sincronización P2P. Ya tenemos varios entrada del blog sobre el asunto. Así que para aportar algo nuevo a esto te diré cómo hacer que esa sincronización sea automática.
La sincronización se basa en enlaces de replicación. Normalmente requieren una dirección y credenciales. Como quiero la menor fricción posible, me he saltado la parte de credenciales/seguridad. Lo cual es malo, pero hizo mi demo de presentación mucho más fácil. Entonces, si todo lo que necesitas es una dirección, ¿cómo la obtienes automáticamente?
Para que la sincronización P2P funcione, los dispositivos que se sincronizan tienen que estar en la misma red. Y la buena noticia es que existen varios protocolos de red para realizar el descubrimiento automático de servicios. Puede que hayas oído hablar de conceptos como Bonjour, RendezVous, ZeroConf, Android NSD, mDNS, DLNA, UPnP y muchos más. La mayoría de ellas se basan en el registro de servicios DNS. Porque sí, el DNS puede hacer algo más que asignar IPs a hosts. También puede almacenar una lista de servicios con su dirección, nombre y descripción.
Esto es lo que he utilizado en mi demostración. He elegido una implementación Java sencilla basada en el método Biblioteca JmDNS. De esta manera tengo casi el mismo impl en mi aplicación nativa Java y en Android. Funciona haciendo broadcasting UDP. Envía paquetes a otras cosas conectadas en la red.
He aquí un breve vistazo a los fragmentos de código más relevantes.
Iniciando Couchbase Lite Listener en el dispositivo para que pueda recibir conexiones.
1 2 3 4 5 6 7 8 9 |
público int startCBLiteListener(int puerto) { LiteListener ls = nuevo LiteListener(base de datos.getManager(), puerto, null); Hilo hilo = nuevo Hilo(ls); hilo.iniciar(); devolver ls.getListenPort(); } |
Exposición de un nuevo servicio mediante JmDNS
1 2 3 4 5 6 |
público void exponerServicio(int puerto) lanza IOException { ServiceInfo sInfos = ServiceInfo.crear(TIPO DE SERVICIO, serviceName, puerto, DESCRIPCIÓN_DEL_SERVICIO); jmdns.registerService(sInfos); } |
Escuchar un servicio en particular usando JmDNS. El oyente DiscoveryListener es importante porque es donde realmente se puede configurar la sincronización.
1 2 3 4 5 |
público void listenForService(){ jmdns.addServiceListener(TIPO DE SERVICIO, nuevo DiscoveryListener(base de datos, jmdns, serviceName)); } |
No es la implementación más limpia que existe, pero te harás una idea. Fíjate especialmente en el método serviceResolved. Es el que se llama cuando se ha descubierto un nuevo Servicio en la red. Nos da la URL del servicio permitiéndonos así configurar el enlace de replicación clásico.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
paquete org.couchbase.desvelar; importar com.couchbase.lite.Base de datos; importar com.couchbase.lite.oyente.LiteListener; importar com.couchbase.lite.replicador.Replicación; importar javax.jmdns.JmDNS; importar javax.jmdns.ServicioEvento; importar javax.jmdns.ServiceListener; importar java.io.IOException; importar java.red.URL; /** * Creado por ldoguin el 13/02/15. */ público clase DiscoveryListener implementa ServiceListener { privado Base de datos base de datos; privado JmDNS jmdns; privado Cadena serviceName; público DiscoveryListener(Base de datos base de datos, JmDNS jmdns, Cadena serviceName) { este.base de datos = base de datos; este.jmdns = jmdns; este.serviceName = serviceName; } @Anular público void servicioAñadir(ServicioEvento evento) { si (! serviceName.es igual a(evento.getName())){ jmdns.requestServiceInfo(evento.getType(), evento.getName(), 10); } } @Anular público void servicioRetirado(ServicioEvento evento) { Sistema.fuera.println(evento.getName() + "retirado"); } @Anular público void servicioResuelto(ServicioEvento evento) { Sistema.fuera.println("RESUELTO"); Cadena[] servicioUrls = evento.getInfo().getURLs(); para (Cadena url : servicioUrls) { Sistema.fuera.println(url); setupSync(base de datos, url + "/mensajes"); } } público void setupSync(Base de datos base de datos, Cadena syncUrl) { pruebe { URL url = nuevo URL(syncUrl); Replicación pullReplication = base de datos.createPullReplication(url); pullReplication.setContinuous(verdadero); pullReplication.iniciar(); Replicación pushReplication = base de datos.createPushReplication(url); pushReplication.setContinuous(verdadero); pushReplication.iniciar(); } captura (IOException e){ tirar nuevo RuntimeException(e); } } } |
Y ese es un divertido proyecto experimental, fácil de implementar, para asegurarte de que todos tus dispositivos Couchbase Lite pueden sincronizarse fácilmente. Hay por supuesto mucho más que se puede hacer. Como añadir la parte de seguridad. Podrías imaginar tener una primera sincronización manual que intercambie credenciales una vez y luego hacer todo lo demás automáticamente. Espero que encuentres esto útil. No dudes en comentar y darnos tu opinión.