Jon Garrido Martin GIS Developer

GIS Developer Freelance

Emitiendo mi posicion con node.js

By jongarrido | September 4, 2015 | 0 Comment

Node.js es un entorno de programación en la capa del servidor basado en el lenguaje de programación JavaScript  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ón que vamos a explicar se pretende que cada vez que un usuario se conecte a la aplicación se envie su posición al servidor y este a su vez comunique esta posición al resto de usuarios conectados.

Cuando la posición del usuario es actualizada esta es nuevamente emitida desde el servidor a los usuarios conectados. En el ejemplo cada usuario podrá ver su posicion en un mapa así como la de las personas que se vayan conectando durante su sesión.

El resultado final en …. http://demos.jongarrido.es/nodetest

Ingredientes:

Vamos a detallar a continuación como se ha desarrolado la parte html, el código de servidor (node.js) y el código de cliente.

CÓDIGO HTML

La composición html es muy sencilla… un encabezado y un div para nuestro mapa…

Ahora sí, importante tener en cuenta que hay que incluir un enlace a nuestro modulo socket.io de node.js.El encabezado también lo utilizaremos para mostrar mensajes.

<!DOCTYPE html>
<html lang=”es”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>
<meta http-equiv=”X-UA-Compatible” content=”IE=7,IE=9″>
<meta name=”viewport” content=”initial-scale=1, maximum-scale=1, user-scalable=no”>
<title>Geolocation and node</title>
<script src=”http://www.jongarrido.es:1003/socket.io/socket.io.js”></script>
<script src=”http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js”></script>
<link rel=”stylesheet” href=”http://js.arcgis.com/3.6/js/esri/css/esri.css”/>
<script src=”http://code.jquery.com/jquery-1.9.1.js”></script>
<script src=”http://js.arcgis.com/3.6/”></script>
<link rel=”stylesheet” href=”css/estilos.css”/>
<link rel=”stylesheet” href=”http://js.arcgis.com/3.6/js/dojo/dijit/themes/claro/claro.css”/>
<script type=”text/javascript” src=”js/nodeclient.js”></script>

<!– Script para obtener la ip–>
<script language=”JavaScript” src=”http://only-ip4.wimip.fr/ip.php”></script>

</head>

<body>
<div id=”encabezado”>
<p id=”texto”>Geolocation API, node.js and socket.io testing page</p>
</div>
<div id=”mapDiv”></div>
</body>
</html>

 PARTE SERVIDORA

El código de la parte servidora es también bastante sencillo. Como decíamos anteriormente es código basado en eventos. En primer lugar referenciamos a una variable nuestra conexión a socket.io para después conectar dos eventos: uno controlará la conexión de usuarios y el otro la desconexión.  En la función de launch, cuando un usuario es conectado, se controla el evento nuevaPosicion (que se lanzará desde cliente)  y que desde el servidor ejecutará la emisión de la posición recibida como parámetro.

var miSocket = require(‘socket.io’).listen(1003);
miSocket.sockets.on(“connection”, launch);
miSocket.on(‘disconnect’, desconectar);
function launch(posicion){
posicion.on(“nuevaPosicion”, emitirPosicion);
}

function emitirPosicion(posicion){
miSocket.sockets.emit(“posicionDesdeServidor”, posicion);
}

function desconectar(posicion){
console.log(“Usuario desconectado”);
}
console.log(‘Server running at jongarrido.es:1003’);

PARTE CLIENTE

 La parte de código en cliente, es un poco más extensa. A grandes rasgos lo que queremos es que la posicion de cada usuario (su propia posición) aparezca representada con un símbolo verde y la posición del resto de usuarios que vayan conectándose aparezan e rojo. Para ello vamos a identificar cada usuario con su Ip pública.

Lo primero que realiza el codigo por tanto es, una vez cargado el elemento mapa, obtener la ip del usuario local y su posición mediente el método getCurrentPosition de la API de gelocalización.  Con estos datos se crea un esri.Graphic que es representado en el mapa.

La siguente línea de codigo es la que conecta el evento para recibir nuevas posiciones:

websocket.on(“posicionDesdeServidor”, recibirPosicion);

A continuación se crea un elemento para el seguimiento de la posición mediante el método watchPosition y  cada vez que esta esta posición es modificada se envia la información al servidor node.js a través del evento declarado en la parte servidora:

websocket.emit(“nuevaPosicion”, position);

En el codigo de nuestro ejemplo cada vez que una nueva posición es recibida se comprueba si es la nuestra (nuestra ip),  si es una posicion de un usuario ya conectado o si es la posición de un nuevo usuario. En cada caso se actualizará la posición o se añadirá un nuevo punto al mapa. El código  de la parte cliente viene a continuación.

Podeis visatar el ejemplo en…

http://www.jongarrido.es/nodetest

Espero que os guste. Cualquier aportación será bien recibida.

/// variables globales

var miIp;
var myPoint;
var pos = {Lat:””,Long:””, personalIp:””};
var mensaje = “”

var map;

require([“esri/map”, “dojo/domReady!”,”dojo/on”], function(Map) {
map = new Map(“mapDiv”, {
center: [-1.049, 42.485],
zoom: 7,
basemap: “streets”
});
map.on(“load”, inicio);
});

var websocket = io.connect(“http://www.jongarrido.es:1003”);

// esto es para obtener la ip del usuario

var ip_list = {};
function FoundIp(ip, type) {
// type: 4=ipv4 6=ipv6 0=unknown (autodetect)
if (type == 0) {
type = 4;
if (ip.indexOf(‘:’) != -1) type = 6;
}
ip_list[ip] = type;
}

function obtenerIp() {
for(ip in ip_list) {
pos.personalIp = ip;
miIp = ip;
}
}

function inicio()
{
mensaje = document.getElementById(“texto”);
obtenerIp();
obtenerMiPosicionYmostrarla();
websocket.on(“posicionDesdeServidor”, recibirPosicion);

//inicio el control de posicion de mi dispositivo
if (navigator.geolocation) {
var watchId = navigator.geolocation.watchPosition(scrollMap, handleError, {enableHighAccuracy:true});
}
}

function obtenerMiPosicionYmostrarla(){

if (navigator.geolocation) {
var miPosicion = navigator.geolocation.getCurrentPosition(function (position){
mostarMiposicion(position);
mensaje.innerHTML=”Your initial position showed in the map. Invite somebody to connect…”;
},handleError, {maximumAge:Infinity,enableHighAccuracy:true});
}
else{
alert(“Geolocation is not supported by this browser”);
}
}
function enviarPosicion(position){
websocket.emit(“nuevaPosicion”, position);

}

function recibirPosicion(datosDesdeSrv){
if(esMiIp(datosDesdeSrv.personalIp)){
actualizarPosicion({Long:datosDesdeSrv.Long,Lat:datosDesdeSrv.Lat,personalIp:”You”});
mensaje.innerHTML=”Your position has been updated”;
}
else{
if(existeElUsuarioEnMiMapa(datosDesdeSrv)){
actualizarPosicion(datosDesdeSrv);
mensaje.innerHTML=”Other user’s position has been updated”;
}
else{
mostrarPosicion(datosDesdeSrv);
mensaje.innerHTML=”New user has connected”;
}
}
}

function scrollMap(position) {
pos.Lat=position.coords.latitude;
pos.Long=position.coords.longitude;
enviarPosicion(pos);

}

function handleError(error) {
switch(error.code)
{
case error.PERMISSION_DENIED:
mensaje.innerHTML=”User denied the request for Geolocation.”;
break;
case error.POSITION_UNAVAILABLE:
mensaje.innerHTML=”Location information is unavailable.”;
break;
case error.TIMEOUT:
mensaje.innerHTML=”The request to get user location timed out.”;
break;
case error.UNKNOWN_ERROR:
mensaje.innerHTML=”An unknown error occurred.”;
break;
}
}

function esMiIp(recivedIp){
if (recivedIp == miIp) {
return true;
}
else{
return false;
}
}

function existeElUsuarioEnMiMapa(datosDesdeSrv){

var usuario = datosDesdeSrv.personalIp;
for (g in map.graphics.graphics){

var graf = map.graphics.graphics[g];

if(graf.attributes) {
if(usuario == graf.attributes.UserIp)
{
return true;
}
}
}
return false;
}

function mostarMiposicion(nuevaPosicion) {

var miPos = {
“geometry”:{
“x”:nuevaPosicion.coords.longitude,
“y”:nuevaPosicion.coords.latitude,
“spatialReference”:{“wkid”:4326}
},
“attributes”:{
“XCoord”:nuevaPosicion.coords.longitude,
“YCoord”:nuevaPosicion.coords.latitude,
“UserIp”:”You”
},
“symbol”:{
“color”:[0,255,0,128],
“size”:12,
“angle”:0,
“xoffset”:0,
“yoffset”:0,
“type”:”esriSMS”,
“style”:”esriSMSSquare”,
“outline”:{
“color”:[0,0,0,255],
“width”:1,
“type”:”esriSLS”,
“style”:”esriSLSSolid”
}
},
“infoTemplate”:{
“title”:”Connected people”,
“content”:”Latitude: ${YCoord}<br/>Longitude: ${XCoord}<br/>Who: ${UserIp}”
}
};

var gra = new esri.Graphic(miPos);
map.graphics.add(gra);
alert(“Alone in the map? Tell somebody to connect to http://www.jongarrido.es/nodetest”)
}

function mostrarPosicion(nuevaPosicion) {

myPoint = {
“geometry”:{
“x”:nuevaPosicion.Long,
“y”:nuevaPosicion.Lat,
“spatialReference”:{“wkid”:4326}
},
“attributes”:{
“XCoord”:nuevaPosicion.Long,
“YCoord”:nuevaPosicion.Lat,
“UserIp”: nuevaPosicion.personalIp
},
“symbol”:{
“color”:[255,0,0,128],
“size”:12,
“angle”:0,
“xoffset”:0,
“yoffset”:0,
“type”:”esriSMS”,
“style”:”esriSMSSquare”,
“outline”:{
“color”:[0,0,0,255],
“width”:1,
“type”:”esriSLS”,
“style”:”esriSLSSolid”
}
},
“infoTemplate”:{
“title”:”Connected people”,
“content”:”Latitude: ${YCoord}<br/>Longitude: ${XCoord}<br/>Who: ${UserIp}”
}
};

var gra = new esri.Graphic(myPoint);
map.graphics.add(gra);
}

function graphicConIp(ipbuscada){
for(g in map.graphics.graphics){
var graf = map.graphics.graphics[g];

if(graf.attributes) {
if (graf.attributes.UserIp === ipbuscada){
return graf;
}

}
}
return “Grafico no encontrado..”;
}
function actualizarPosicion(posicion){
var graficoParaActualizar = graphicConIp(posicion.personalIp);
graficoParaActualizar.geometry.x = posicion.Long;
graficoParaActualizar.geometry.y = posicion.Lat;

var capaGrafica = map.getLayer(“mapDiv_graphics”);
capaGrafica.refresh();

}

 

 

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *