{"id":73,"date":"2015-09-04T21:12:23","date_gmt":"2015-09-04T21:12:23","guid":{"rendered":"https:\/\/jongarrido.es\/?p=73"},"modified":"2015-09-04T21:12:23","modified_gmt":"2015-09-04T21:12:23","slug":"emitiendo-mi-posicion-con-node-js","status":"publish","type":"post","link":"https:\/\/jongarrido.es\/?p=73","title":{"rendered":"Emitiendo mi posicion con node.js"},"content":{"rendered":"<p style=\"text-align: justify;\"><a title=\"Node.js\" href=\"http:\/\/nodejs.org\">Node.js<\/a> es un entorno de programaci\u00f3n en la capa del servidor basado en el lenguaje de programaci\u00f3n JavaScript\u00a0 con arquitectura orientada al evento. En resumen: una estupenda herramienta que ejecuta codigo javascript en el servidor cuando determinados eventos son disparados desde el cliente.<\/p>\n<p style=\"text-align: justify;\">En el ejemplo de utilizaci\u00f3n que vamos a explicar se pretende que cada vez que un usuario se conecte a la aplicaci\u00f3n se envie su posici\u00f3n al servidor y este a su vez comunique esta posici\u00f3n al resto de usuarios conectados.<\/p>\n<p style=\"text-align: justify;\"><!--more--><\/p>\n<p style=\"text-align: justify;\">Cuando la posici\u00f3n del usuario es actualizada esta es nuevamente emitida desde el servidor a los usuarios conectados. En el ejemplo cada usuario podr\u00e1 ver su posicion en un mapa as\u00ed como la de las personas que se vayan conectando durante su sesi\u00f3n.<\/p>\n<p style=\"text-align: justify;\">El resultado final en &#8230;. <a title=\"Nodetest\" href=\"http:\/\/demos.jongarrido.es\/nodetest\">http:\/\/demos.jongarrido.es\/nodetest<\/a><\/p>\n<p style=\"text-align: justify;\">Ingredientes:<\/p>\n<ul style=\"text-align: justify;\">\n<li>Para la\u00a0 obtenci\u00f3n de la localizaci\u00f3n utilizaremos la <a title=\"HTML5 geolocation API\" href=\"http:\/\/dev.w3.org\/geo\/api\/spec-source.html\">API de geolocalizaci\u00f3n HTML5<\/a>.<\/li>\n<li>Para la envio de datos al servidor node.js y emisi\u00f3n desde el mismo se ha empleado el m\u00f3dulo<a title=\"Socket.io\" href=\"http:\/\/socket.io\/\"> socket.io<\/a> de node.js.<\/li>\n<li>Para el mapa base y elementos gr\u00e1ficos se ha utilizado la <a title=\"ESRI JavaSrcipt API\" href=\"https:\/\/developers.arcgis.com\/en\/javascript\/\">API para javascript de ESRI.<\/a><\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Vamos a detallar a continuaci\u00f3n como se ha desarrolado la parte html, el c\u00f3digo de servidor (node.js) y el c\u00f3digo de cliente.<\/p>\n<p style=\"text-align: justify;\"><strong>C\u00d3DIGO HTML<\/strong><\/p>\n<p style=\"text-align: justify;\">La composici\u00f3n html es muy sencilla&#8230; un encabezado y un div para nuestro mapa&#8230;<\/p>\n<p style=\"text-align: justify;\">Ahora s\u00ed, importante tener en cuenta que hay que incluir un enlace a nuestro modulo socket.io de node.js.El encabezado tambi\u00e9n lo utilizaremos para mostrar mensajes.<\/p>\n<p style=\"text-align: justify;\">&lt;!DOCTYPE html&gt;<br \/>\n&lt;html lang=\u00bbes\u00bb&gt;<br \/>\n&lt;head&gt;<br \/>\n&lt;meta http-equiv=\u00bbContent-Type\u00bb content=\u00bbtext\/html; charset=utf-8&#8243;&gt;<br \/>\n&lt;meta http-equiv=\u00bbX-UA-Compatible\u00bb content=\u00bbIE=7,IE=9&#8243;&gt;<br \/>\n&lt;meta name=\u00bbviewport\u00bb content=\u00bbinitial-scale=1, maximum-scale=1, user-scalable=no\u00bb&gt;<br \/>\n&lt;title&gt;Geolocation and node&lt;\/title&gt;<br \/>\n<span style=\"color: #ff0000;\">&lt;script src=\u00bbhttp:\/\/www.jongarrido.es:1003\/socket.io\/socket.io.js\u00bb&gt;&lt;\/script&gt;<\/span><br \/>\n&lt;script src=\u00bbhttp:\/\/ajax.googleapis.com\/ajax\/libs\/jquery\/1.10.1\/jquery.min.js\u00bb&gt;&lt;\/script&gt;<br \/>\n&lt;link rel=\u00bbstylesheet\u00bb href=\u00bbhttp:\/\/js.arcgis.com\/3.6\/js\/esri\/css\/esri.css\u00bb\/&gt;<br \/>\n&lt;script src=\u00bbhttp:\/\/code.jquery.com\/jquery-1.9.1.js\u00bb&gt;&lt;\/script&gt;<br \/>\n&lt;script src=\u00bbhttp:\/\/js.arcgis.com\/3.6\/\u00bb&gt;&lt;\/script&gt;<br \/>\n&lt;link rel=\u00bbstylesheet\u00bb href=\u00bbcss\/estilos.css\u00bb\/&gt;<br \/>\n&lt;link rel=\u00bbstylesheet\u00bb href=\u00bbhttp:\/\/js.arcgis.com\/3.6\/js\/dojo\/dijit\/themes\/claro\/claro.css\u00bb\/&gt;<br \/>\n&lt;script type=\u00bbtext\/javascript\u00bb src=\u00bbjs\/nodeclient.js\u00bb&gt;&lt;\/script&gt;<\/p>\n<p style=\"text-align: justify;\">&lt;!&#8211; Script para obtener la ip&#8211;&gt;<br \/>\n&lt;script language=\u00bbJavaScript\u00bb src=\u00bbhttp:\/\/only-ip4.wimip.fr\/ip.php\u00bb&gt;&lt;\/script&gt;<\/p>\n<p style=\"text-align: justify;\">&lt;\/head&gt;<\/p>\n<p style=\"text-align: justify;\">&lt;body&gt;<br \/>\n&lt;div id=\u00bbencabezado\u00bb&gt;<br \/>\n&lt;p id=\u00bbtexto\u00bb&gt;Geolocation API, node.js and socket.io testing page&lt;\/p&gt;<br \/>\n&lt;\/div&gt;<br \/>\n&lt;div id=\u00bbmapDiv\u00bb&gt;&lt;\/div&gt;<br \/>\n&lt;\/body&gt;<br \/>\n&lt;\/html&gt;<\/p>\n<p style=\"text-align: justify;\"><strong>\u00a0PARTE SERVIDORA<\/strong><\/p>\n<p style=\"text-align: justify;\">El c\u00f3digo de la parte servidora es tambi\u00e9n bastante sencillo. Como dec\u00edamos anteriormente es c\u00f3digo basado en eventos. En primer lugar referenciamos a una variable nuestra conexi\u00f3n a socket.io para despu\u00e9s conectar dos eventos: uno controlar\u00e1 la conexi\u00f3n de usuarios y el otro la desconexi\u00f3n.\u00a0 En la funci\u00f3n de launch, cuando un usuario es conectado, se controla el evento nuevaPosicion (que se lanzar\u00e1 desde cliente)\u00a0 y que desde el servidor ejecutar\u00e1 la emisi\u00f3n de la posici\u00f3n recibida como par\u00e1metro.<\/p>\n<p style=\"text-align: justify;\">var miSocket = require(&#8216;socket.io&#8217;).listen(1003);<br \/>\nmiSocket.sockets.on(\u00abconnection\u00bb, launch);<br \/>\nmiSocket.on(&#8216;disconnect&#8217;, desconectar);<br \/>\nfunction launch(posicion){<br \/>\nposicion.on(\u00abnuevaPosicion\u00bb, emitirPosicion);<br \/>\n}<\/p>\n<p style=\"text-align: justify;\">function emitirPosicion(posicion){<br \/>\nmiSocket.sockets.emit(\u00abposicionDesdeServidor\u00bb, posicion);<br \/>\n}<\/p>\n<p style=\"text-align: justify;\">function desconectar(posicion){<br \/>\nconsole.log(\u00abUsuario desconectado\u00bb);<br \/>\n}<br \/>\nconsole.log(&#8216;Server running at jongarrido.es:1003&#8217;);<\/p>\n<p style=\"text-align: justify;\"><strong>PARTE CLIENTE<\/strong><\/p>\n<p style=\"text-align: justify;\">\u00a0La parte de c\u00f3digo en cliente, es un poco m\u00e1s extensa. A grandes rasgos lo que queremos es que la posicion de cada usuario (su propia posici\u00f3n) aparezca representada con un s\u00edmbolo verde y la posici\u00f3n del resto de usuarios que vayan conect\u00e1ndose aparezan e rojo. Para ello vamos a identificar cada usuario con su Ip p\u00fablica.<\/p>\n<p style=\"text-align: justify;\">Lo primero que realiza el codigo por tanto es, una vez cargado el elemento mapa, obtener la ip del usuario local y su posici\u00f3n mediente el m\u00e9todo getCurrentPosition de la API de gelocalizaci\u00f3n.\u00a0 Con estos datos se crea un esri.Graphic que es representado en el mapa.<\/p>\n<p style=\"text-align: justify;\">La siguente l\u00ednea de codigo es la que conecta el evento para recibir nuevas posiciones:<\/p>\n<p style=\"text-align: justify;\">websocket.on(\u00abposicionDesdeServidor\u00bb, recibirPosicion);<\/p>\n<p style=\"text-align: justify;\">A continuaci\u00f3n se crea un elemento para el seguimiento de la posici\u00f3n mediante el m\u00e9todo watchPosition y\u00a0 cada vez que esta esta posici\u00f3n es modificada se envia la informaci\u00f3n al servidor node.js a trav\u00e9s del evento declarado en la parte servidora:<\/p>\n<p style=\"text-align: justify;\">websocket.emit(\u00abnuevaPosicion\u00bb, position);<\/p>\n<p style=\"text-align: justify;\">En el codigo de nuestro ejemplo cada vez que una nueva posici\u00f3n es recibida se comprueba si es la nuestra (nuestra ip),\u00a0 si es una posicion de un usuario ya conectado o si es la posici\u00f3n de un nuevo usuario. En cada caso se actualizar\u00e1 la posici\u00f3n o se a\u00f1adir\u00e1 un nuevo punto al mapa. El c\u00f3digo\u00a0 de la parte cliente viene a continuaci\u00f3n.<\/p>\n<p style=\"text-align: justify;\">Podeis visatar el ejemplo en&#8230;<\/p>\n<p style=\"text-align: justify;\">http:\/\/www.jongarrido.es\/nodetest<\/p>\n<p style=\"text-align: justify;\">Espero que os guste. Cualquier aportaci\u00f3n ser\u00e1 bien recibida.<\/p>\n<p style=\"text-align: justify;\">\/\/\/ variables globales<\/p>\n<p>var miIp;<br \/>\nvar myPoint;<br \/>\nvar pos = {Lat:\u00bb\u00bb,Long:\u00bb\u00bb, personalIp:\u00bb\u00bb};<br \/>\nvar mensaje = \u00ab\u00bb<\/p>\n<p>var map;<\/p>\n<p>require([\u00abesri\/map\u00bb, \u00abdojo\/domReady!\u00bb,\u00bbdojo\/on\u00bb], function(Map) {<br \/>\nmap = new Map(\u00abmapDiv\u00bb, {<br \/>\ncenter: [-1.049, 42.485],<br \/>\nzoom: 7,<br \/>\nbasemap: \u00abstreets\u00bb<br \/>\n});<br \/>\nmap.on(\u00abload\u00bb, inicio);<br \/>\n});<\/p>\n<p>var websocket = io.connect(\u00abhttp:\/\/www.jongarrido.es:1003\u00bb);<\/p>\n<p>\/\/ esto es para obtener la ip del usuario<\/p>\n<p>var ip_list = {};<br \/>\nfunction FoundIp(ip, type) {<br \/>\n\/\/ type: 4=ipv4 6=ipv6 0=unknown (autodetect)<br \/>\nif (type == 0) {<br \/>\ntype = 4;<br \/>\nif (ip.indexOf(&#8216;:&#8217;) != -1) type = 6;<br \/>\n}<br \/>\nip_list[ip] = type;<br \/>\n}<\/p>\n<p>function obtenerIp() {<br \/>\nfor(ip in ip_list) {<br \/>\npos.personalIp = ip;<br \/>\nmiIp = ip;<br \/>\n}<br \/>\n}<\/p>\n<p>function inicio()<br \/>\n{<br \/>\nmensaje = document.getElementById(\u00abtexto\u00bb);<br \/>\nobtenerIp();<br \/>\nobtenerMiPosicionYmostrarla();<br \/>\nwebsocket.on(\u00abposicionDesdeServidor\u00bb, recibirPosicion);<\/p>\n<p>\/\/inicio el control de posicion de mi dispositivo<br \/>\nif (navigator.geolocation) {<br \/>\nvar watchId = navigator.geolocation.watchPosition(scrollMap, handleError, {enableHighAccuracy:true});<br \/>\n}<br \/>\n}<\/p>\n<p>function obtenerMiPosicionYmostrarla(){<\/p>\n<p>if (navigator.geolocation) {<br \/>\nvar miPosicion = navigator.geolocation.getCurrentPosition(function (position){<br \/>\nmostarMiposicion(position);<br \/>\nmensaje.innerHTML=\u00bbYour initial position showed in the map. Invite somebody to connect&#8230;\u00bb;<br \/>\n},handleError, {maximumAge:Infinity,enableHighAccuracy:true});<br \/>\n}<br \/>\nelse{<br \/>\nalert(\u00abGeolocation is not supported by this browser\u00bb);<br \/>\n}<br \/>\n}<br \/>\nfunction enviarPosicion(position){<br \/>\nwebsocket.emit(\u00abnuevaPosicion\u00bb, position);<\/p>\n<p>}<\/p>\n<p>function recibirPosicion(datosDesdeSrv){<br \/>\nif(esMiIp(datosDesdeSrv.personalIp)){<br \/>\nactualizarPosicion({Long:datosDesdeSrv.Long,Lat:datosDesdeSrv.Lat,personalIp:\u00bbYou\u00bb});<br \/>\nmensaje.innerHTML=\u00bbYour position has been updated\u00bb;<br \/>\n}<br \/>\nelse{<br \/>\nif(existeElUsuarioEnMiMapa(datosDesdeSrv)){<br \/>\nactualizarPosicion(datosDesdeSrv);<br \/>\nmensaje.innerHTML=\u00bbOther user&#8217;s position has been updated\u00bb;<br \/>\n}<br \/>\nelse{<br \/>\nmostrarPosicion(datosDesdeSrv);<br \/>\nmensaje.innerHTML=\u00bbNew user has connected\u00bb;<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>function scrollMap(position) {<br \/>\npos.Lat=position.coords.latitude;<br \/>\npos.Long=position.coords.longitude;<br \/>\nenviarPosicion(pos);<\/p>\n<p>}<\/p>\n<p>function handleError(error) {<br \/>\nswitch(error.code)<br \/>\n{<br \/>\ncase error.PERMISSION_DENIED:<br \/>\nmensaje.innerHTML=\u00bbUser denied the request for Geolocation.\u00bb;<br \/>\nbreak;<br \/>\ncase error.POSITION_UNAVAILABLE:<br \/>\nmensaje.innerHTML=\u00bbLocation information is unavailable.\u00bb;<br \/>\nbreak;<br \/>\ncase error.TIMEOUT:<br \/>\nmensaje.innerHTML=\u00bbThe request to get user location timed out.\u00bb;<br \/>\nbreak;<br \/>\ncase error.UNKNOWN_ERROR:<br \/>\nmensaje.innerHTML=\u00bbAn unknown error occurred.\u00bb;<br \/>\nbreak;<br \/>\n}<br \/>\n}<\/p>\n<p>function esMiIp(recivedIp){<br \/>\nif (recivedIp == miIp) {<br \/>\nreturn true;<br \/>\n}<br \/>\nelse{<br \/>\nreturn false;<br \/>\n}<br \/>\n}<\/p>\n<p>function existeElUsuarioEnMiMapa(datosDesdeSrv){<\/p>\n<p>var usuario = datosDesdeSrv.personalIp;<br \/>\nfor (g in map.graphics.graphics){<\/p>\n<p>var graf = map.graphics.graphics[g];<\/p>\n<p>if(graf.attributes) {<br \/>\nif(usuario == graf.attributes.UserIp)<br \/>\n{<br \/>\nreturn true;<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\nreturn false;<br \/>\n}<\/p>\n<p>function mostarMiposicion(nuevaPosicion) {<\/p>\n<p>var miPos = {<br \/>\n\u00abgeometry\u00bb:{<br \/>\n\u00abx\u00bb:nuevaPosicion.coords.longitude,<br \/>\n\u00aby\u00bb:nuevaPosicion.coords.latitude,<br \/>\n\u00abspatialReference\u00bb:{\u00abwkid\u00bb:4326}<br \/>\n},<br \/>\n\u00abattributes\u00bb:{<br \/>\n\u00abXCoord\u00bb:nuevaPosicion.coords.longitude,<br \/>\n\u00abYCoord\u00bb:nuevaPosicion.coords.latitude,<br \/>\n\u00abUserIp\u00bb:\u00bbYou\u00bb<br \/>\n},<br \/>\n\u00absymbol\u00bb:{<br \/>\n\u00abcolor\u00bb:[0,255,0,128],<br \/>\n\u00absize\u00bb:12,<br \/>\n\u00abangle\u00bb:0,<br \/>\n\u00abxoffset\u00bb:0,<br \/>\n\u00abyoffset\u00bb:0,<br \/>\n\u00abtype\u00bb:\u00bbesriSMS\u00bb,<br \/>\n\u00abstyle\u00bb:\u00bbesriSMSSquare\u00bb,<br \/>\n\u00aboutline\u00bb:{<br \/>\n\u00abcolor\u00bb:[0,0,0,255],<br \/>\n\u00abwidth\u00bb:1,<br \/>\n\u00abtype\u00bb:\u00bbesriSLS\u00bb,<br \/>\n\u00abstyle\u00bb:\u00bbesriSLSSolid\u00bb<br \/>\n}<br \/>\n},<br \/>\n\u00abinfoTemplate\u00bb:{<br \/>\n\u00abtitle\u00bb:\u00bbConnected people\u00bb,<br \/>\n\u00abcontent\u00bb:\u00bbLatitude: ${YCoord}&lt;br\/&gt;Longitude: ${XCoord}&lt;br\/&gt;Who: ${UserIp}\u00bb<br \/>\n}<br \/>\n};<\/p>\n<p>var gra = new esri.Graphic(miPos);<br \/>\nmap.graphics.add(gra);<br \/>\nalert(\u00abAlone in the map? Tell somebody to connect to http:\/\/www.jongarrido.es\/nodetest\u00bb)<br \/>\n}<\/p>\n<p>function mostrarPosicion(nuevaPosicion) {<\/p>\n<p>myPoint = {<br \/>\n\u00abgeometry\u00bb:{<br \/>\n\u00abx\u00bb:nuevaPosicion.Long,<br \/>\n\u00aby\u00bb:nuevaPosicion.Lat,<br \/>\n\u00abspatialReference\u00bb:{\u00abwkid\u00bb:4326}<br \/>\n},<br \/>\n\u00abattributes\u00bb:{<br \/>\n\u00abXCoord\u00bb:nuevaPosicion.Long,<br \/>\n\u00abYCoord\u00bb:nuevaPosicion.Lat,<br \/>\n\u00abUserIp\u00bb: nuevaPosicion.personalIp<br \/>\n},<br \/>\n\u00absymbol\u00bb:{<br \/>\n\u00abcolor\u00bb:[255,0,0,128],<br \/>\n\u00absize\u00bb:12,<br \/>\n\u00abangle\u00bb:0,<br \/>\n\u00abxoffset\u00bb:0,<br \/>\n\u00abyoffset\u00bb:0,<br \/>\n\u00abtype\u00bb:\u00bbesriSMS\u00bb,<br \/>\n\u00abstyle\u00bb:\u00bbesriSMSSquare\u00bb,<br \/>\n\u00aboutline\u00bb:{<br \/>\n\u00abcolor\u00bb:[0,0,0,255],<br \/>\n\u00abwidth\u00bb:1,<br \/>\n\u00abtype\u00bb:\u00bbesriSLS\u00bb,<br \/>\n\u00abstyle\u00bb:\u00bbesriSLSSolid\u00bb<br \/>\n}<br \/>\n},<br \/>\n\u00abinfoTemplate\u00bb:{<br \/>\n\u00abtitle\u00bb:\u00bbConnected people\u00bb,<br \/>\n\u00abcontent\u00bb:\u00bbLatitude: ${YCoord}&lt;br\/&gt;Longitude: ${XCoord}&lt;br\/&gt;Who: ${UserIp}\u00bb<br \/>\n}<br \/>\n};<\/p>\n<p>var gra = new esri.Graphic(myPoint);<br \/>\nmap.graphics.add(gra);<br \/>\n}<\/p>\n<p>function graphicConIp(ipbuscada){<br \/>\nfor(g in map.graphics.graphics){<br \/>\nvar graf = map.graphics.graphics[g];<\/p>\n<p>if(graf.attributes) {<br \/>\nif (graf.attributes.UserIp === ipbuscada){<br \/>\nreturn graf;<br \/>\n}<\/p>\n<p>}<br \/>\n}<br \/>\nreturn \u00abGrafico no encontrado..\u00bb;<br \/>\n}<br \/>\nfunction actualizarPosicion(posicion){<br \/>\nvar graficoParaActualizar = graphicConIp(posicion.personalIp);<br \/>\ngraficoParaActualizar.geometry.x = posicion.Long;<br \/>\ngraficoParaActualizar.geometry.y = posicion.Lat;<\/p>\n<p>var capaGrafica = map.getLayer(\u00abmapDiv_graphics\u00bb);<br \/>\ncapaGrafica.refresh();<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Node.js es un entorno de programaci\u00f3n en la capa del servidor basado en el lenguaje de programaci\u00f3n JavaScript\u00a0 con arquitectura orientada al evento. En resumen: una estupenda herramienta que ejecuta codigo javascript en el servidor cuando determinados eventos son disparados desde el cliente. En el ejemplo de utilizaci\u00f3n que vamos a explicar se pretende que [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[9,16,25],"class_list":["post-73","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-geolocation","tag-node-js","tag-socket-io"],"_links":{"self":[{"href":"https:\/\/jongarrido.es\/index.php?rest_route=\/wp\/v2\/posts\/73","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jongarrido.es\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jongarrido.es\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jongarrido.es\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/jongarrido.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=73"}],"version-history":[{"count":0,"href":"https:\/\/jongarrido.es\/index.php?rest_route=\/wp\/v2\/posts\/73\/revisions"}],"wp:attachment":[{"href":"https:\/\/jongarrido.es\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=73"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jongarrido.es\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=73"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jongarrido.es\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=73"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}