ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA INGENIERÍA TÉCNICA EN INFORMÁTICA DE SISTEMAS CREADOR DE UN MAPA DE COBERTURA Realizado por Álvaro Chapresto Montesinos Tutor Dr. José Ramón Portillo Fernández Departamento Matemática Aplicada I Sevilla, Junio de 2009 Creador de un Mapa de Cobertura INDICE 1.-Definición de objetivos ................................................................................ 3 2.-Análisis de antecedentes y aportación realizada ....................................... 5 3.-Aportación Web ........................................................................................... 7 3.1.-Análisis de requisitos ...................................................................... 7 3.2.-Diseño ............................................................................................. 8 3.3.-Acceso web mediante PC ................................................................ 9 3.4.-Acceso web mediante Dispositivos Móviles ................................. 13 3.5.-API GoogleMaps............................................................................18 3.6.-Almacenamiento en Servidor Web ............................................... 25 4.-Implementación de la Aplicación en Symbian OS .................................. 30 4.1.-Análisis de requisitos .................................................................... 30 4.2.-Decisiones de diseño ..................................................................... 32 4.3.-Funcionamiento general de las Redes GSM, GPRS y WIFI. ........ 33 4.4.-API Symbian OS ........................................................................... 37 5.-Manual de la Aplicación a nivel de usuario ............................................. 78 6.-Pruebas ........................................................................................................ 84 7.-Herramientas .............................................................................................. 90 7.1.-Microsoft Expression Web ............................................................ 90 7.2.-MySQL y phpMyAdmin ............................................................... 91 7.3.-Herramientas necesarias para la programación en Symbian OS. .. 91 8.-Aplicaciones Futuras .................................................................................. 93 9.-Análisis Temporal ...................................................................................... 96 10.-Conclusiones ............................................................................................. 98 11.-Bibliografía ............................................................................................. 100 2 Creador de un Mapa de Cobertura Capítulo 1: Definición de objetivos El objetivo fundamental que tiene este proyecto fin de carrera es medir los niveles de cobertura de las redes GSM, GPRS y WIFI para poder visualizarlos en un mapa. Este proceso incluye dos fases: una primara fase dedicada a la obtención de dichos niveles de cobertura gracias a una aplicación Symbian OS y una segunda fase dedicada al almacenamiento de los datos en un servidor Web para poder generar un mapa sobre ellos a través de GoogleMap. No sólo se almacenarían en el servidor los niveles de cobertura, también era necesario almacenar las coordenadas, es decir, la longitud y la latitud de la posición en la cual obtuviéramos estos niveles. La necesidad de almacenar también la posición de donde realizáramos esta medida está relacionada con la segunda parte del proyecto. Esta segunda parte del proyecto trataba de generar un mapa haciendo uso de la API de GoogleMaps en el cual pudiéramos localizar estas redes y conocer los niveles de cobertura que nos ofrecen de una manera más visual. Para ello también fue necesario crear un sitio Web en el cual poder insertar el mapa con el fin de que todo aquel que quisiera pudiera conocer la cobertura que nos ofrecen las redes GSM, GPRS y WIFI en un lugar determinado. 3 Creador de un Mapa de Cobertura Mi intención en un primer instante fue implementar la aplicación en J2ME (plataforma de Java para desarrollar aplicaciones en dispositivos móviles) debido a la gran cantidad de documentación, herramientas, ayuda y ejemplos que se pueden encontrar acerca de este lenguaje. Sin embargo, desde la capa de Java no es posible acceder a cada una de las partes del dispositivo móvil que nos permiten acceder a los datos que necesitamos. Para poder obtener todos los datos necesarios era imprescindible tener acceso a las rutinas del sistema operativo de nuestro dispositivo móvil, por lo que la única alternativa era la utilización de Symbian C++ a la hora de implementar la aplicación. Symbian OS es el sistema operativo que utilizan la mayoría de dispositivos Nokia, y en concreto el modelo N95 que he utilizado en el proyecto como dispositivo móvil. A la hora de enviar los datos necesarios al servidor, mi idea en un principio fue la utilización de Java 2EE, haciendo uso de Servlets y JDBC para realizar la conexión a la base de datos e inserción de los mismos. Debido a la tremenda complejidad que supone encontrar alojamiento Web gratuito que soporte Java, decidí llevar a cabo esta parte del proyecto utilizando el lenguaje PHP, soportado por la inmensa mayoría de servidores. Finalmente comentar que en este proyecto la documentación relacionada con Symbian OS no ha sido un objetivo primordial, puesto que gracias a un proyecto de cursos anteriores que me ha servido de guía he podido resolver casi todas mis dudas en cuanto al comienzo de la programación en Symbian OS. 4 Creador de un Mapa de Cobertura Capítulo 2: Análisis de antecedentes y aportación realizada En este proyecto siempre he querido destacar que podemos diferenciar dos grandes partes: la primera de ellas relacionada con toda la aportación Web, es decir, servidor, base de datos, páginas Web, PHP etc… y la segunda y más importante relacionada con la programación en Symbian OS. Al ser la aplicación en Symbian OS el objetivo fundamental del proyecto, es sin duda la parte a la cual he dedicado más tiempo. Para comenzar a introducirme en la programación en Symbian OS utilicé como referencia un proyecto fin de carrera que fue expuesto en junio de 2007. Este proyecto incluía en la documentación una guía que indicaba a los futuros programadores como realizar su primera aplicación en Symbian OS utilizando como entorno de desarrollo integrado (IDE) Microsoft Visual .NET 2003 con un plug-in denominado Carbide.vs, el cual fue retirado por Nokia, necesario para poder realizar proyectos en Symbian OS. 5 Creador de un Mapa de Cobertura Debido a que han pasado dos años desde junio de 2007, todo el mundo relacionado con los dispositivos móviles, y más concretamente con Nokia y Symbian OS, ha experimentado una gran evolución. Es por este motivo por el que a la hora de elegir el entorno de desarrollo a través del cual iba a implementar mi aplicación en Symbian OS decidí decantarme por Carbide .c++ ya que es un software totalmente gratuito y actualizado que utilizan hoy en día casi la totalidad de los programadores en Symbian OS. Por tanto, creo que puede servir de ayuda a futuros programadores el hecho de que la aplicación en Symbian OS de este proyecto esté realizada con este entorno de desarrollo, ya que prácticamente toda información disponible sobre Symbian OS está relacionada con Carbide.c++. Al ir constantemente desarrollando Nokia nuevas funcionalidades para los dispositivos móviles, las versiones de Symbian OS están en continua actualización y por tanto la API y las SDK incluyen cada vez más información. La versión 9.2 de Symbian OS es la que yo he utilizado junto con la SDK s60 3erd edition FP1 para poder llevar a cabo este proyecto. Esta versión es en estos momentos una de las más actualizadas junto a la serie s60 5th edition. Una de las innovaciones que añade esta API de Symbian OS es el acceso a redes WIFI y a dispositivos GPS. Esta API también incluye nuevas clases para poder acceder con más detalle aún si cabe a los niveles de cobertura de las redes GSM y GPRS. Hace algún tiempo, para poder acceder al nivel de cobertura GSM había que utilizar una librería y una serie de métodos de la SDK apara desarrolladores de Nokia 9200 Comunicator, la cual fue retirada. En la aplicación Symbian OS de este proyecto se ofrecen las clases y los métodos necesarios para acceder a los niveles de cobertura GSM, GPRS y WIFI así como a las coordenadas GPS de los dispositivos móviles más actuales de la serie s60 de Nokia, es decir, la serie más extendida. Englobando un poco las dos grandes partes en las cuales puede dividirse este proyecto, creo que puede ser interesante disponer de una aplicación que relacione dos grandes conceptos como son Symbian OS y GoogleMap, haciendo posible obtener los niveles de cobertura GSM, GPRS y sobre todo WIFI que es una tecnología más actual, de un determinado lugar para poder almacenar dichos valores en un servidor Web con el fin de visualizar los datos a través de un mapa. Es una manera de acceder a dichos niveles de cobertura completa y sencilla para cualquier tipo de usuario. 6 Creador de un Mapa de Cobertura Capítulo 3: Aportación Web En este apartado trataré de detallar toda la parte del proyecto que está relacionada con la Web, comenzando por el diseño de la páginas Web donde queremos visualizar los niveles de cobertura obtenidos tanto en un PC como en un dispositivo móvil, enumerando y comentando cada una de las clases y métodos de la API de GoogleMaps que hacen posible generar el mapa, los marcadores y las ventanas de información necesarias y finalizando por la base de datos instalada en el servidor cuya función es la de almacenar los valores de las coordenadas y niveles de cobertura enviados desde el dispositivo móvil. 3.1.-Análisis de Requisitos Toda la aportación Web existente en el proyecto también está pensada para que sirva de ayuda al usuario, mostrando los niveles de cobertura GSM, GPRS y WIFI obtenidos de una manera más visual situándolos en un mapa. A la hora de realizar cualquier tipo de aplicación Web es fundamental realizar un 7 Creador de un Mapa de Cobertura estudio que nos permita obtener toda la información necesaria. El mundo relacionado con las aplicaciones Web es bastante extenso, existiendo mucha información acerca de todas las funcionalidades que pueden añadirse a una aplicación Web, pero la parte principal de este proyecto es la relacionada con la aplicación Symbian OS. Por este motivo he creído oportuno realizar una aplicación Web simple, haciendo uso únicamente de hojas de estilo y capas de posicionamiento. Los requisitos que debe cumplir la aplicación Web de este proyecto son los siguientes: Facilidad de Uso La aplicación Web debe ser lo más sencilla y clara posible ya su única función es la de mostrar en un mapa una serie de valores, para que pueda servir de ayuda a cualquier tipo de persona. Transparencia al Usuario Lo único que debe mostrar la aplicación al usuario es la información acerca de los niveles de cobertura obtenidos y el mapa mostrando la ubicación de estos. Todo lo relacionado a como se almacenan los niveles y las coordenadas en la base de datos debe quedar oculto para el usuario. 3.2.-Diseño El diseño empleado para realizar ambas páginas Web es muy sencillo y claro ya que esta basado únicamente en el uso de hojas de estilo y capas de posicionamiento. La única función que tienen ambas Web es la de mostrar información en un mapa acerca de cada uno de los niveles de cobertura obtenidos mediante la aplicación Symbian OS instalada en el dispositivo móvil por lo que no es necesario añadir ningún otro tipo de funcionalidad a cada una de las Web. El código para cada una de las páginas Web es casi idéntico con la excepción de que la página Web la cual es accedida desde un PC está centrada y posee un determinado margen tanto a izquierda como a derecha y la página Web la cual es accedida desde un dispositivo móvil no posee ningún tipo de margen ocupando todo el ancho de página disponible. 8 Creador de un Mapa de Cobertura La idea de realizar una Web para poder acceder desde un PC y una Web dedicada al acceso desde un dispositivo móvil esta relacionada con la posibilidad que están añadiendo hoy día los dispositivos móviles de conectarse a Internet a través de un dispositivo WIFI sin coste alguno y con el tamaño de la pantalla de cada tipo de dispositivo. Esta idea la detallaré más adelante en su respectivo apartado. 3.3.-Acceso Web mediante PC El código de la página Web donde queremos visualizar a través de un PC los niveles de cobertura obtenidos es el siguiente: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>Mapa de Cobertura</title> <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAYXgE2 vAAc2qhHiKrZMlnUxSY91aDXaiJPM7k4bLxEmyoVJ0ZIRRJ56TazbJMGN-CkuDkFwVd5A8uA&hl=es " type="text/javascript"></script> <script type="text/javascript"> //<![CDATA[ function load() { if (GBrowserIsCompatible()) { var map = new GMap2(document.getElementById("googleMap")); map.setCenter(new GLatLng(37.388163, -5.996475), 15); map.addControl(new GSmallMapControl()); map.addControl(new GMapTypeControl()); <?php $link=mysql_connect("mysql8.000webhost.com","a1285122_alvaro","merequet engue1") or die ("Error conexión"); mysql_select_db("a1285122_proyect", $link) or die ("Error selección BD"); $sql = "SELECT * FROM datos;"; $result = mysql_query($sql) or die ("La consulta <b>$sql</b> tiene algún error"); while ($row = mysql_fetch_array($result)){ $aux3 = $row['coberturagsm']; 9 Creador de un Mapa de Cobertura if(strpos($row['coberturagsm'], ",")!=false){ $ind3 = strpos($row['coberturagsm'], ","); $aux3 = $row['coberturagsm']; $aux3[$ind3] = "."; } $aux4 = $row['coberturagprs']; if(strpos($row['coberturagprs'], ",")!=false){ $ind4 = strpos($row['coberturagprs'], ","); $aux4 = $row['coberturagprs']; $aux4[$ind4] = "."; } $aux5 = $row['coberturawlan']; if(strpos($row['coberturawlan'], ",")!=false){ $ind5 = strpos($row['coberturawlan'], ","); $aux5 = $row['coberturawlan']; $aux5[$ind5] = "."; } $ind1 = strpos($row['latitud'], ","); $ind2 = strpos($row['longitud'], ","); $aux1 = $row['latitud']; $aux2 = $row['longitud']; $aux1[$ind1] = "."; $aux2[$ind2] = "."; echo "var latlng = new GLatLng(";echo $aux1;echo ",";echo $aux2; echo");"; echo "var opciones = { title: \"Niveles de Cobertura\", draggable: false, bouncy: false};"; echo "var opcionesven = { noCloseOnClick: false};"; echo "var marcador";echo $row['id'];echo " = new GMarker(latlng, opciones);"; echo "GEvent.addListener(marcador";echo $row['id'];echo ", \"click\", function() {"; echo "marcador";echo $row['id'];echo ".openInfoWindow(\"Cobertura GSM: ";echo $row['coberturagsm'];echo " %<br/> Cobertura GPRS: "; echo $row['coberturagprs'];echo " %<br/>Cobertura WIFI: ";echo $row['coberturawlan'];echo " %\", opcionesven); });"; echo "map.addOverlay(marcador";echo $row['id'];echo ");"; } mysql_close($link); ?> } } //]]> </script> <style type="text/css"> #envolvente { width: 650px; 10 Creador de un Mapa de Cobertura padding: 0px; margin-top: 10px; margin-right: auto; margin-left: auto; } #encabezado { color: #FFFFFF; background-color: #00A4CC; } #bienvenida { border-width: medium; border-color: #00A4CC; background-color: #D9E6FF; padding: 0px; width: 171px; float: left; border-right-style: solid; } #mapadecobertura { border-width: medium; border-color: #00A4CC; padding: 0px; width: 171px; float: right; background-color: #99CCFF; border-left-style: solid; } #piedepagina { color: #FFFFFF; background-color: #FF9D5B; } p, h1 { margin: 0px 10px 10px 10px; } h1 { font-size: 1.5em; padding-top: 10px; } h2 { font-size: 1.2em; padding-top: 10px; padding-left: 10px; } .style1 { font-family: "Comic Sans MS"; font-size: 2em; } .style2 { color: #0000CE; font-family: Candara; } .style4 { 11 Creador de un Mapa de Cobertura color: #0000FF; font-family: Candara; } .style5 { margin-right: 0px; } </style> <link rel="shortcut icon" href="http://alumno.us.es/a/alvchamon/favicon1.ico" type="image/x-icon" /> </head> <body onload="load()" onunload="GUnload()"> <div id="envolvente"> <div id="encabezado"> <h1 class="style1">Mapa de Cobertura</h1> </div> <div id="bienvenida"> <h2 class="style4">Bienvenido a mi Pagina Web</h2> <p><strong>Este es el Sitio Web de mi Proyecto Fin de Carrera. En este espacio quiero daros a todos la Bienvenida y agradecer de antemano que lo visiteis.</strong></p></div> <div id="mapadecobertura"> <h2 class="style2">Aplicacion</h2> <p><strong>La principal funcion que tiene la Web es ofrecer la posibilidad a todos los que la visiten de conocer los niveles de cobertura WIFI, GSM y GPRS de las distintas zonas que se pueden observar en el mapa gracias a la API de GoogleMap y a la aplicacion Symbian que hace posible obtener dichos niveles. </strong></p></div> <div id="googleMap" style="width:300px; height:366px; float:left" class="style5"></div> <br clear="all"/> <div id="piedepagina">Proyecto Fin de carrera. Alvaro Chapresto Montesinos</div> </div> </body> </html> En el código se puede observar lo que he comentado anteriormente acerca del uso de hojas de estilo y capas de posicionamiento para realizar la página Web. Para poder acceder a esta Web tenemos que introducir en el explorador la siguiente dirección: http://alvaro.netne.net. Una vez introducida dicha dirección accedemos a la Web que tendría la siguiente forma: 12 Creador de un Mapa de Cobertura 3.4.-Acceso Web mediante Dispositivos Móviles Como ya he comentado anteriormente, era necesaria la realización de una página Web para poder visualizar los niveles de cobertura obtenidos la cual fuera accedida desde un dispositivo móvil. El código de dicha página Web es el siguiente: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>Mapa de Cobertura Móviles</title> <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAYXgE2 13 Creador de un Mapa de Cobertura vAAc2qhHiKrZMlnUxSY91aDXaiJPM7k4bLxEmyoVJ0ZIRRJ56TazbJMGN-CkuDkFwVd5A8uA&hl=es " type="text/javascript"></script> <script type="text/javascript"> //<![CDATA[ function load() { if (GBrowserIsCompatible()) { var map = new GMap2(document.getElementById("googleMap")); map.setCenter(new GLatLng(37.388163, -5.996475), 15); map.addControl(new GSmallMapControl()); map.addControl(new GMapTypeControl()); <?php $link=mysql_connect("mysql8.000webhost.com","a1285122_alvaro","merequet engue1") or die ("Error conexión"); mysql_select_db("a1285122_proyect", $link) or die ("Error selección BD"); $sql = "SELECT * FROM datos;"; $result = mysql_query($sql) or die ("La consulta <b>$sql</b> tiene algún error"); while ($row = mysql_fetch_array($result)){ $aux3 = $row['coberturagsm']; if(strpos($row['coberturagsm'], ",")!=false){ $ind3 = strpos($row['coberturagsm'], ","); $aux3 = $row['coberturagsm']; $aux3[$ind3] = "."; } $aux4 = $row['coberturagprs']; if(strpos($row['coberturagprs'], ",")!=false){ $ind4 = strpos($row['coberturagprs'], ","); $aux4 = $row['coberturagprs']; $aux4[$ind4] = "."; } $aux5 = $row['coberturawlan']; if(strpos($row['coberturawlan'], ",")!=false){ $ind5 = strpos($row['coberturawlan'], ","); $aux5 = $row['coberturawlan']; $aux5[$ind5] = "."; } $ind1 = strpos($row['latitud'], ","); $ind2 = strpos($row['longitud'], ","); $aux1 = $row['latitud']; $aux2 = $row['longitud']; $aux1[$ind1] = "."; $aux2[$ind2] = "."; 14 Creador de un Mapa de Cobertura echo "var latlng = new GLatLng(";echo $aux1;echo ",";echo $aux2; echo");"; echo "var opciones = { title: \"Niveles de Cobertura\", draggable: false, bouncy: false};"; echo "var opcionesven = { noCloseOnClick: false};"; echo "var marcador";echo $row['id'];echo " = new GMarker(latlng, opciones);"; echo "GEvent.addListener(marcador";echo $row['id'];echo ", \"click\", function() {"; echo "marcador";echo $row['id'];echo ".openInfoWindow(\"Cobertura GSM: ";echo $row['coberturagsm'];echo " %<br/> Cobertura GPRS: "; echo $row['coberturagprs'];echo " %<br/>Cobertura WIFI: ";echo $row['coberturawlan'];echo " %\", opcionesven); });"; echo "map.addOverlay(marcador";echo $row['id'];echo ");"; } mysql_close($link); ?> } } </script> <style type="text/css"> #envolvente { width: 100%; padding: 0px; margin-top: 0px; float: left; } #encabezado { color: #FFFFFF; background-color: #00A4CC; width: 100%; } #bienvenida { border-width: medium; border-color: #00A4CC; background-color: #D9E6FF; padding: 0px; width: 50%; float: left; border-right-style: solid; border-left-style: none; } #mapadecobertura { border-width: medium; border-color: #00A4CC; padding: 0px; width: 49%; float: left; 15 Creador de un Mapa de Cobertura background-color: #99CCFF; border-left-style: solid; border-right-style: none; } #piedepagina { color: #FFFFFF; background-color: #FF9D5B; width: 100%; } p, h1 { margin: 0px 10px 10px 10px; } h1 { font-size: 1.5em; padding-top: 10px; } h2 { font-size: 1.2em; padding-top: 10px; padding-left: 10px; } .style1 { font-family: "Comic Sans MS"; font-size: 2em; } .style2 { color: #0000CE; font-family: Candara; } .style4 { color: #0000FF; font-family: Candara; } .style5 { margin-right: 0px; } </style> <link rel="shortcut icon" href="../favicon1.ico" type="image/xicon" /> </head> <body onload="load()" onunload="GUnload()"> <div id="envolvente"> <div id="encabezado"> <h1 class="style1">Mapa de Cobertura</h1> </div> <div id="mapadecobertura"> <h2 class="style2">Aplicacion</h2> <p><strong>La principal funcion que tiene la Web es ofrecer la posibilidada todos los que la visiten de conocer los niveles de cobertura WIFI, GSM y GPRS de las distintas zonas que se pueden observar en el mapa gracias a la API de GoogleMap y a la aplicacion Symbian que hace posible obtener dichos niveles. </strong></p></div> <div id="bienvenida"> 16 Creador de un Mapa de Cobertura <h2 class="style4">Bienvenido a mi Pagina Web</h2> <p><strong>Este es el Sitio Web de mi Proyecto Fin de Carrera. En este espacio quiero daros a todos la Bienvenida y agradecer de antemano que lo visiteis.</strong></p></div> <div id="googleMap" style="width:100%; height:348px; float:left" class="style5" ></div> </div> </body> </html> En el código se puede observar como se hace uso de hojas de estilo y capas de posicionamiento para realizar la Web pero con la salvedad de que esta página Web utiliza todo el ancho de la pantalla. Esta idea esta aplicada debido a que el tamaño de pantalla de un dispositivo móvil es mucho menor que el de cualquier pantalla de un PC. Al estar utilizando la página Web el 100% del ancho de la pantalla, se adapta perfectamente al tamaño de pantalla de cada dispositivo móvil de forma que en caso de que dispongamos de un ancho de pantalla muy pequeño, los bloques de información de la Web se irían apilando para evitar que se produzca scroll horizontal, que en un dispositivo móvil es más molesto que en un PC. También surgía la necesidad de realizar esta Web para que todo el que tenga la posibilidad de acceder a Internet desde su dispositivo móvil pueda consultar los niveles de cobertura obtenidos en un determinado punto. Para acceder a dicha página Web desde un dispositivo móvil tenemos que colocar en el navegar la siguiente dirección: http://alvaro.netne.net/moviles.htm. Una vez introducida la dirección nos aparecerá dicha página Web que posee la siguiente apariencia: 17 Creador de un Mapa de Cobertura Como se puede observar en la imagen, la página Web aprovecha todo el ancho de pantalla disponible que puede parecer exagerado a la hora de acceder a dicha Web desde un PC, pero que sin embargo a la hora de acceder a través de un dispositivo móvil se adapta perfectamente debido al reducido tamaño de su pantalla. 3.5.-API GoogleMaps Debido a que la idea fundamental del proyecto es la obtención de una serie de niveles de cobertura y plasmarlos en un mapa para que puedan ser de utilidad de una manera visual, es necesaria la utilización de la API de GoogleMaps. Para poder hacer uso de la API de GoogleMaps es necesario registrarte así como indicar el directoria Web donde se van a almacenar la páginas que van a mostrar mapas y demás contenidos relacionados con Google. Una vez hecho esto, obtendremos la clave necesaria para, haciendo uso de JavaScript, utilizar la API de GoogleMaps en nuestra Web. 18 Creador de un Mapa de Cobertura La API de GoogleMaps esta compuesta por infinidad de clases, métodos, atributos, constantes, estructuras de datos… etc. Es por este motivo por lo que yo en este apartado sólo quiero hacer referencia a la parte de la API de GoogleMaps que he utilizado a la hora de desarrollar este proyecto. Esta parte sería la siguiente: - Clase GMap2(container, opts?): Crea un mapa nuevo dentro del contenedor HTML en cuestión, que generalmente suele ser un elemento DIV. En el atributo container es donde tenemos que colocar el id de nuestra etiqueta DIV contenedora. El atributo opts? Se puede obviar puesto que hace referencia a las diferentes opciones que podemos elegir como el tipo del mapa, tamaño etc. Esta clase contiene los siguientes métodos: 1.- addControl(control, position?): Añade un objeto que implemente la interfaz GControl al mapa. El atributo position? Se puede obviar, en este caso se aplicará una posición predeterminada al control. 2.- setCenter(center, zoom?, type?): Define la vista del mapa de acuerdo al centro especificado en el atributo center. El atributo zoom hace referencia al zoom que tendrá el mapa al cargarse en la Web y el atributo type haría referencia al tipo de mapa. Ambos atributos se pueden obviar. 3.- addOverlay(overlay): Este método añade una superposición al mapa y activa el evento addoverlay. Las superposiciones son necesarias a la hora de añadir por ejemplo un marcador, como es nuestro caso. 4.- openInfoWindowHtml(latlong, html, opts?): Abre una ventana de información en el punto especificado del mapa a través del atributo latlong que es un objeto de la clase GLatLng. El atributo html hace referencia al texto HTML que vamos a mostrar. El atributo opts? se puede obviar, aunque hace referencia a las diferentes opciones que podemos agregar a dicha ventana. Esta opciones se establecen a través de un objeto de la clase GInfoWindowsOptions. - Clase GInfoWindowsOptions: las instancias de esta clase se utilizan como ya he comentado anteriormente en el atributo opts? de las 19 Creador de un Mapa de Cobertura clases GMap2 en el método openInfoWindowHtml. Las instancias de esta clase se crean como un objeto literal de JavaScript. Esta clase presenta las siguientes propiedades: 1.- MaxWidth: Representa la anchura máxima de la ventana de información en píxeles. 2.- noCloseOnClick: Esta propiedad es de tipo boolean e indica si la ventana debe cerrarse al hacer click en un lugar diferente a un marcador. “True” indicaría que la ventana no se cerrase. - Clase GMarker(latlong, icon?, inert?): esta clase establece un marcador en el mapa. El marcador utilizado se establece en la posición indicada a través del atributo latlong de la clase GLatLng. El atributo icon? hace referencia al icono que queremos mostrar como marcador y es un objeto de la clase icon que se puede obviar, en tal caso se utilizará como marcador un icono por defecto. El atributo inert? es de tipo boolean y hace referencia a la posibilidad de que se pueda hacer clic en el marcador y activar un evento. Esta clase contiene los siguientes métodos: 1.- openInfoWindowHtml(content, opts?): Abre una ventana de información sobre el icono el marcador al hacer clic en el marcador. El atributo content hace referencia al texto HTML que aparecerá en la ventana de información mientras el atributo opts?, que se puede obviar, está relacionado con la propiedad GInfoWindowOptions.maxWidth, que es la única que en este caso se puede añadir. 2.- blindInfowindowHtml(content, opts?): Enlaza en texto HTML indicado a través del atributo content. Este texto HTML se mostará automáticamente en la venatana de información al hacer clic sobre el marcador. El atributo opts? sigue haciendo referencia a las opciones que se pueden añadir, pudiendo ser obviado. 3.- setLatLng(latlng): Este método define las coordenadas geográficas del punto en el cual está anclado el marcador a través del atributo latlng, que es de la clase GLatLng. - Clase GMarkerOptions: Se usan instancias de esta clase en el 20 Creador de un Mapa de Cobertura atributo opts? para el constructor de la clase GMarker. No existe constructor para esta clase, por sus instancias se crean como un objeto literal de JavaScript. Como indica el nombre del propio atributo, las priedades se pueden obviar. Las propiedades que admite esta clase son las siguientes: 1.- icon: Elige el icono para el marcador. Esta propiedad es un objeto de la clase GIcon. 2.- tittle: Esta propiedad aparecerá como información de herramienta en el marcador, es decir, aparecerá cuando situemos el puntero del ratón sobre el marcador en cuestión. 3.- draggable: Esta propiedad habilita o deshabilita la posibilidad de arrastrar el marcador. Es un valor de tipo boolean, en caso de valer true posibilita que el marcador sea arrastrado. 4.- bouncy: Consiste en habilitar o deshabilitar que el marcador rebote hacia arriba o hacia abajo cuando termine de ser arrastrado. - Clase GIcon(copy?, image?): Se utiliza para crear el icono que queremos que aparezca como marcador en el mapa. Ambos atributos son opcionales y por tanto se pueden obviar. El atributo copy? Indica si sus propiedades se copiaran y el atributo image? define el valor de la propiedad image que se detalla a continuación. Esta clase contiene las siguientes propiedades: 1.- image: Indica la URL de la imagen en primer plano del icono que aparecerá como marcador. 2.- iconsize: Indica el tamaño en px de la imagen del icono. - Clase GLatLng(lat, long, unbouned?): Esta clase genera un punto de acuerdo a una latitud y una longitud de coordenadas geográficas pasadas como argumento. El atributo unbouned? Es opcional y es de tipo boolen. En caso de valer true las coordenadas se usan tal como se pasan mientras que en caso contrario la laitud está obligada a valer entre -90 grados y 90 grados mientras que la longitud deberá valer entre -180 grados y 180 grados. Esta clase posee los siguientes métodos: 21 Creador de un Mapa de Cobertura 1.- lat(): Devuelve la coordenada de latitud. 2.- lng(): Devuelve la coordenada de longitud. 3.- Equals(other): Devuelve true si el tamaño other pasado como argumento tiene componentes iguales. Por lo que other debe ser un objeto de la clase GLatLng. - Interfaz GControl(printable?, selectable?): Esta interfaz implementa todos los controles. Puedes implementarla para indicar un control personalizado para el mapa. El atributo printable? Es opcional e indica que el control deber estar visible en el mapa impreso. El atributo selectable? también se puede obviar e indica que el control contendrá texto seleccionable. Esta interfaz contiene los siguientes métodos: 1.- GSmallMapControl(): Este método crea un control con botones para hacer desplazamiento en cuatro direcciones y acercar o alejar el mapa. 2.- GLargeMapControl(): Es un método similar al anterior pero incluye barra de desplazamiento. 3.- GSmallZoomControl(): Añade al mapa un control con botones para acercar o alejar la imagen. - Función GBrowserIsCompatible(): Esta función de vuelve un valor de tipo boolean que indica si el navegador utilizado es compatible con la biblioteca de la API de GoogleMaps. - Función GUnload(): Esta función hace que la API de googleMaps limpie estructuras de datos internas para liberar memoria. Es el gestor de eventos “unload” de la página Web el encargado de llamar a esta función. - Namespace GEvent: Este espacio de nombres contiene funciones que se utilizan para registrar gestores de eventos personaliados. Posee el siguiente método: 1.- addListener(source, event, handler): registra un gestor de 22 Creador de un Mapa de Cobertura eventos para un evento personalizado en el objeto origen. El atributo source hace referencia al objeto de la clase GMarker, mientras que el atributo event indica el evento a realizar y el atributo handler es una función que realiza una tarea al producirse dicho evento sobre el marcador. La parte del código HTML que está relacionada con la API de GoogleMaps es la siguiente: <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAYXgE2 vAAc2qhHiKrZMlnUxSY91aDXaiJPM7k4bLxEmyoVJ0ZIRRJ56TazbJMGN-CkuDkFwVd5A8uA&hl=es "type="text/javascript"></script> En esta primera parte del código es donde se indica cual es nuestra API Key para que aparezcan correctamente todos mapas en las páginas del servidor indicado al registrarnos. <script type="text/javascript"> //<![CDATA[ function load() { Esta es la funcion que comprueba si el navegador es compatible con la API de GoogleMaps, en ese caso se ejecuta cada una de las sentencias. if (GBrowserIsCompatible()) { var map=new GMap2(document.getElementById("googleMap")); Almacenamos en la variable map un mapa que creamos mediante la clase GMap2 estableciendo dicho mapa en la capa div cuyo id es “googleMap”. map.setCenter(new GLatLng(37.388163, -5.996475), 15); A través del método setCenter y el parámetro que indica las coordenadas centramos nuestro mapa. map.addControl(new GSmallMapControl()); map.addControl(new GMapTypeControl()); Utilizando el método addControl y los constructores de controles GsmallMapControl() y GMapTypeControl() añadimos ambos controles al mapa. 23 Creador de un Mapa de Cobertura var latlng = new GLatLng(37.388163, -5.996475); var opciones = { title: "Niveles de Cobertura", draggable: false, bouncy: false}; Creamos ahora dos variables donde vamos a almacenar las coordenadas de nuestro marcador a través de la clase GLatLng y las opciones de dicho marcador. Estas opciones se declaran como un objeto literal de JavaScript. var opcionesven = { noCloseOnClick: false}; Almacenamos en una variable las opciones que va a tener nuestra ventana de información asociada al marcador. Estas opciones deben declararse como un objeto literal de JavaScript. var marcador = new GMarker(latlng, opciones); Creamos una variable marcador donde almacenaremos el objeto de la clase GMarker pasando como argumento sus coordenadas y sus propiedades. GEvent.addListener(marcador, "click", function() { marcador.openInfoWindow("Esto es una prueba,<br/> aqui es donde vamos a colocar<br/> los niveles de cobertura", opcionesven); }); Ahora a través de GEvent y el método addListener asociamos un evento al marcador, hacer click con el ratón, especificamos que al cumplirse el evento se abra una ventana de información y asociamos a dicha ventana de información las propiedades anteriormente declaradas. map.addOverlay(marcador); Añadimos el marcador al mapa. } } //]]> </script> Finalmente colocamos la marca que cierra el código JavaScript. 24 Creador de un Mapa de Cobertura 3.6.-Almacenamiento en Servidor Web Uno de los objetivos de este proyecto, como se ha comentado anteriormente, es poder establecer una serie de marcadores en un mapa haciendo uso de la API de GoogleMap de manera que al pulsar con el ratón en cada uno de ellos se abra una ventana de información en el que se muestren los niveles de cobertura GSM, GPRS y WIFI. Para poder llevar a cabo esta parte del proyecto, surgía la necesidad de disponer de alojamiento Web gratuito para poder subir las páginas Web. Otra necesidad fundamental era que el servidor soportase PHP, ya que dentro del código JavaScript de ambas páginas Web se ejecuta una función PHP que se detalla más adelante. El último y más importante de los requisitos que debía cumplir el alojamiento Web era que me permitiese acceder a las herramientas MySQL y phpMyAdmin para poder crear una base de datos en el servidor donde poder almacenar cada uno de los niveles de cobertura GSM, GPRS y WIFI así como la latitud y la longitud del punto en el que se realizase la media de dichos niveles. A través de http://www.0000webhost.com se puede solicitar alojamiento Web de manera totalmente gratuita cumpliendo dicho alojamiento con todos los requisitos que he comentado anteriormente. El directorio Web que me concedieron fue http://alvaro.netne.net. La base de datos es muy simple puesto que dispone de una única tabla, denominada “datos”, con seis campos en los cuales almaceno un valor de tipo entero que representa el id de cada fila siendo los cinco restantes de tipo varchar para almacenar los niveles de cobertura y las coordenadas del punto. La estructura de la tabla se puede observar en la siguiente figura: 25 Creador de un Mapa de Cobertura Una vez creada la base de datos en la cual podemos insertar cada uno de los valores necesarios, el siguiente paso sería averiguar como enviar los datos sin que el usuario tuviera que rellenar algún tipo de formulario, es decir, conectándose directamente a una url. Para ello fue necesario implementar una función en PHP que realizara la conexión a la base de datos, seleccionara la tabla e insertase cada uno de los valores indicados por la url en el campo correspondiente, siempre que no se encuentren ya insertados. La función PHP que realiza el tratamiento de los datos es la siguiente: <?php //1. Crear conexión a la Base de Datos $conexion= mysql_connect("mysql8.000webhost.com","a1285122_alvaro","merequetengue1 "); if (!$conexion) { die("Fallo la conexión a la Base de Datos: " . mysql_error()); } //2. Seleccionar la Base de Datos a utilizar $seleccionar_bd = mysql_select_db("a1285122_proyect", $conexion); if (!$seleccionar_bd) { die("Fallo la selección de la Base de Datos: " . mysql_error()); } 26 Creador de un Mapa de Cobertura //3. Tomar los campos provenientes del Formulario $coberturagsm = $_GET['coberturagsm']; $coberturagprs = $_GET['coberturagprs']; $coberturawlan = $_GET['coberturawlan']; $latitud = $_GET['latitud']; $longitud = $_GET['longitud']; if(strpos($longitud, "#oP9")!=false){ $cadena = str_replace( "#oP9", "", $longitud ); $longitud = $cadena; } //comprobar si ya estan los datos insertados $sql = "SELECT * FROM datos;"; $result = mysql_query($sql) or die ("La consulta <b>$sql</b> tiene algún error"); $enc = false; while ($row = mysql_fetch_array($result) and $enc == false){ if( $coberturagsm == $row['coberturagsm'] and $coberturagprs == $row['coberturagprs'] and $coberturawlan == $row['coberturawlan'] and $latitud == $row['latitud'] and $longitud == $row['longitud'] ) $enc = true; } if($enc == false){ //4. Insertar campos en la Base de Datos, ya que no están ya almacenados los valores $insertar = mysql_query("INSERT INTO datos (id, coberturagsm, coberturagprs, coberturawlan, latitud, longitud) VALUES (NULL, '$coberturagsm', '$coberturagprs', '$coberturawlan', '$latitud', '$longitud')", $conexion); if (!$insertar) { die("Fallo en la insercion de registro en la Base de Datos: " . mysql_error()); } } else{ $actualizar = mysql_query("UPDATE datos SET coberturagsm='$coberturagsm', coberturagprs='$coberturagprs', coberturawlan='$coberturawlan' WHERE id='$id'", $conexion); if (!$actualizar) { die("Fallo en la actualización de registro en la Base de Datos: " . mysql_error()); } } //5. Cerrar conexión a la Base de Datos mysql_close($conexion); ?> 27 Creador de un Mapa de Cobertura De esta forma, la url a la cual hay que conectarse para enviar los datos tiene el siguiente aspecto: http://alvaro.netne.net/ProcesaDatos.php?coberturagsm=valorgsm&coberturagp rs=valorgprs&coberturawlan=valorwlan&latitud=valorlat&longitud=valorlon Para finalizar, partiendo de la base de que todos los datos se encuentran perfectamente almacenados en la base de datos, el único paso que queda por dar es conectarse dicha base de datos e ir recorriendo cada una de las tuplas de la tabla generando el código JavaScript correspondiente para crear cada uno de los marcadores con los datos correspondientes. Para poder llevar a cabo todo se necesita utilizar de nuevo una función en PHP que esté contenida dentro de las etiquetas <script></script> de ambas páginas Web y que realice todo lo comentado anteriormente. El código de dicha función PHP sería el siguiente: <?php $link=mysql_connect("mysql8.000webhost.com","a1285122_alvaro","merequet engue1") or die ("Error conexión"); mysql_select_db("a1285122_proyect", $link) or die ("Error selección BD"); $sql = "SELECT * FROM datos;"; $result = mysql_query($sql) or die ("La consulta <b>$sql</b> tiene algún error"); while ($row = mysql_fetch_array($result)){ $aux3 = $row['coberturagsm']; if(strpos($row['coberturagsm'], ",")!=false){ $ind3 = strpos($row['coberturagsm'], ","); $aux3 = $row['coberturagsm']; $aux3[$ind3] = "."; } $aux4 = $row['coberturagprs']; if(strpos($row['coberturagprs'], ",")!=false){ $ind4 = strpos($row['coberturagprs'], ","); $aux4 = $row['coberturagprs']; $aux4[$ind4] = "."; } $aux5 = $row['coberturawlan']; if(strpos($row['coberturawlan'], ",")!=false){ $ind5 = strpos($row['coberturawlan'], ","); $aux5 = $row['coberturawlan']; $aux5[$ind5] = "."; 28 Creador de un Mapa de Cobertura } $ind1 = strpos($row['latitud'], ","); $ind2 = strpos($row['longitud'], ","); $aux1 = $row['latitud']; $aux2 = $row['longitud']; $aux1[$ind1] = "."; $aux2[$ind2] = "."; echo "var latlng = new GLatLng(";echo $aux1;echo ",";echo $aux2; echo");"; echo "var opciones = { title: \"Niveles de Cobertura\", draggable: true, bouncy: false};"; echo "var opcionesven = { noCloseOnClick: false};"; echo "var marcador";echo $row['id'];echo " = new GMarker(latlng, opciones);"; echo "GEvent.addListener(marcador";echo $row['id'];echo ", \"click\", function() {"; echo "marcador";echo $row['id'];echo ".openInfoWindow(\"Cobertura GSM: ";echo $row['coberturagsm'];echo " %<br/> Cobertura GPRS: "; echo $row['coberturagprs'];echo " %<br/>Cobertura WIFI: ";echo $row['coberturawlan'];echo " %\", opcionesven); });"; echo "map.addOverlay(marcador";echo $row['id'];echo ");"; } mysql_close($link); ?> 29 Creador de un Mapa de Cobertura Capítulo 4: Implementación de la Aplicación en Symbian OS 4.1.- Análisis de requisitos El objetivo principal que tiene la aplicación Symbian OS es ayudar a cualquier persona que necesite conocer los niveles de cobertura GSM, GPRS y WIFI en un determinado lugar. A la hora de realizar cualquier aplicación en Symbian OS es necesario realizar un estudio previo que nos permita obtener 30 Creador de un Mapa de Cobertura toda la información necesaria para poder comenzar a trabajar de forma adecuada y optimizando el rendimiento. El objetivo del análisis es recoger toda la información posible sobre el sistema a desarrollar y analizar los requisitos de usuario que la aplicación deberá satisfacer. Estos requisitos son los siguientes: Nociones básicas de Symbian Para comenzar deberíamos adquirir una nociones básicas de las plataformas de desarrollo para Symbian OS, en concreto de la serie s60, que es la que me incumbe en esta aplicación. Elección del entorno de desarrollo Otro aspecto interesante a estudiar antes de comenzar a desarrollar una aplicación en Symbian OS es la elección del entorno de desarrollo. Se debe elegir el entorno que más nos favorezca, intentando que sea lo más actual posible y que nos permita encontrar todo tipo de ayuda y documentación. Elección del SDK Otro punto muy interesante es la elección del SDK ya que cada terminal lleva una versión del sistema operativo Symbian OS. Dependiendo de la versión de Symbian OS que lleve nuestro dispositivo elegiremos un SDK u otro. Conocimientos de C++ Es muy importante poseer conocimientos de C++ ya que la programación en Symbian OS no es estrictamente idéntica a C++, pero utiliza una estructura muy similar. Modularidad del Código El código ha de estar lo más claro posible de forma que permita añadir nuevas funciones y complementar la aplicación lo más fácil posible. Coste Computacional 31 Creador de un Mapa de Cobertura El coste computacional no ha de ser elevado puesto que los recursos en los dispositivos móviles están muy limitados sobre todo en lo que a memoria RAM se refiere, por lo que hay que hacer hincapié en la óptima gestión de la memoria. Portabilidad La aplicación podrá ser utilizada en cualquier dispositivo móvil cuya versión de Symbian OS sea compatible con la SDK s60 3erd FP1. Para poder utilizar la aplicación en una versión distinta habrá que compilar de nuevo la aplicación con la correspondiente SDK. Fácil Mantenimiento Hay que intentar estructurar el código en funciones de forma que sean fáciles de utilizar para personas ajenas al proyecto, así como comentar el código lo máximo posible. Facilidad de Uso Esta aplicación está pensada para que pueda ser utilizada por cualquier tipo de persona, por lo que hay que procurar realizar un menú lo más sencillo y claro posible a la vez que completo. Transparencia al Usuario Cada uno de los cálculos y los procesos realizados en la aplicación deben producirse de manera oculta de forma que lo único que observe el usuario sea el resultado final. Requisito Hardware Es importante disponer de un dispositivo móvil que te permita realizar cualquier prueba de la aplicación, es decir, que tenga acceso a las redes GSM, GPRS y WIFI así como a las coordenadas GPS. 4.2.- Decisiones de Diseño 32 Creador de un Mapa de Cobertura En este apartado trataré de explicar la fase de diseño de la aplicación Symbian OS, que es el objetivo fundamental del proyecto. Esta fase de diseño no pretende entrar en detalles de implementación de software sino que pretende proponer una idea de la funcionalidad que será capaz de encapsular. La idea de implementar la aplicación en Symbian C/C++ parte de la base de que es el único lenguaje de programación que nos permite acceder a cada uno de los datos que la aplicación tiene como objetivo proporcionar. Como dispositivo móvil para utilizar de prueba he elegido el modelo N95 de Nokia por su facilidad en cuanto a la disponibilidad se refiere, ya que era el dispositivo móvil que utilizaba antes de decidir embarcarme en este proyecto, a su vez porque es un dispositivo capaz de acceder a redes GSM, GPRS y WIFI, y porque te permite obtener la posición exacta a través de GPS, es decir, latitud y longitud en un determinado instante. La elección de este dispositivo móvil a condicionado la posterior elección de la SDK correspondiente para realizar la aplicación. El menú realizado para ejecutar la aplicación también he intendado que fuera lo más sencillo posible dado que la aplicación Symbian OS de este proyecto tiene como objetivo servir de ayuda a cualquier tipo de usuario. En el menu se pueden observar, entre otras, dos funciones principales: la obtención de los niveles de cobertura GSM, GPRS y WIFI así como la opción de enviar dichos niveles y las coordenadas GPS latitud y longitud a la base de datos instalada en el servidor para poder generar el correspondiente marcador con la información necesaria en el punto exacto del mapa. 4.3.- Funcionamiento general de las Redes GSM, GPRS y WIFI La red GSM está estructurada de manera jerárquica. En una red GSM hay al menos una región administrativa, Mobile Switching Center (MSC). Cada región administrativa consiste al menos en una Área de Localización (LA). Cada Área de Localización está formada por varios grupos de Células. Cada grupo de células está asignado a un Estación Controladora Base ( Base Station Controler, BSC). Esta estructura se muestra en el siguiente gráfico : 33 Creador de un Mapa de Cobertura Jerarquía en la red GSM El sistema GSM tiene limitado en el rango de frecuencias de 25 Mhz a 900Mhz. En este rango hay un máximo de 125 canales cada canal de un ancho de 200 Khz. Un mismo canal se asigna a una sola célula , de esta manera se forman los clusters de células que agrupan a las células que contiguas que no comparten canal. Como el número de canales está limitado, la asignación de un canal se hace a más de una célula. Para evitar interferencias entre células que usen el mismo canal, las células que usen un mismo canal deben de estar lo mas alejado posible dentro de la red GSM. La siguiente figura muestra como las frecuencias pueden ser reutilizadas en tres casos diferentes, en cada caso el operador GSM tiene asignado un determinado numero K de canales. Podemos ver también la formación de Clusters. Reutilización de frecuencias y formación de clusters 34 Creador de un Mapa de Cobertura Cada teléfono móvil debe de comprobar periódicamente la intensidad de la señal emitida por la estaciones base cercanas. El dispositivo móvil selecciona la célula que dispone la mejor recepción. Una vez que el dispositivo esta conectado a una Célula la comunicación móvil es posible. Cuando el dispositivo esta en movimiento la intensidad de la señal recibida va variando de manera que deberá de elegir otra Célula para garantizar el servicio. Este proceso es el de reselección de célula es muy común dado a que cada célula dispone de un área limitada. Cuando el dispositivo está en movimiento el dispositivo elige la célula que le aporta mayor intensidad de señal para, de esta manera, asegurar el servicio. Cuando el dispositivo móvil cambia de célula recibe la señal de una célula con diferente CI. La tecnología GPRS (General Packet Radio Services) permite a las redes celulares una mayor velocidad y ancho de banda sobre el GSM, mejorando las capacidades de acceso móvil a Internet. El principal problema de esta tecnología resulta de su incompatibilidad con los aparatos GSM existentes, inclusive con los que ya soportan el protocolo WAP para acceso a la Internet. Asimismo, pocos son los modelos con tecnología GPRS. La red GPRS es una extensión del Sistema Global para Comunicaciones Móviles (Global System for Mobile Communications o GSM) para la transmisión de datos no conmutada (o por paquetes). Existe un servicio similar para los teléfonos móviles que del sistema IS-136. Permite velocidades de transferencia de 56 a 114 kbps. GPRS se puede utilizar para servicios tales como Wireless Application Protocol (WAP) , servicio de mensajes cortos (SMS), servicio de mensajería multimedia (MMS), Internet y para los servicios de comunicación, como el correo electrónico y la World Wide Web (WWW). La transferencia de datos de GPRS se cobra por volumen de información transmitida (en kilo o megabytes), mientras que la comunicación de datos a través de conmutación de circuitos tradicionales se factura por minuto de tiempo de conexión, independientemente de si el usuario utiliza toda la capacidad del canal o está en un estado de inactividad. GPRS da mejor rendimiento a la conmutación de paquetes de servicios, en contraposición a la conmutación de circuitos, donde una cierta calidad de servicio (QoS) está garantizada durante la conexión. Por este motivo, se considera más adecuada la conexión conmutada para servicios como la voz que requieren un ancho de banda constante durante la transmisión, mientras que los servicios de paquetes como GPRS se orientan al tráfico de datos. 35 Creador de un Mapa de Cobertura Cuando hablamos de WIFI nos referimos a una de las tecnologías de comunicación inalámbrica mediante ondas más utilizada hoy en día. WIFI, también llamada WLAN (wireless lan, red inalámbrica) o estándar IEEE 802.11. WIFI no es una abreviatura de Wireless Fidelity, simplemente es un nombre comercial. En la actualidad podemos encontrarnos con dos tipos de comunicación WIFI: 802.11b, que emite a 11 Mb/seg, y 802.11g, más rapida, a 54 MB/seg. De hecho, son su velocidad y alcance (unos 100-150 metros en hardware asequible) lo convierten en una fórmula perfecta para el acceso a internet sin cables. Para tener una red inalámbrica en casa sólo necesitaremos un punto de acceso, que se conectaría al módem, y un dispositivo WIFI que se conectaría en nuestro aparato. Existen terminales WIFI que se conectan al PC por USB, pero son las tarjetas PCI (que se insertan directamente en la placa base) las recomendables, nos permite ahorrar espacio físico de trabajo y mayor rapidez. Para portátiles podemos encontrar tarjetas PCMI externas, aunque muchos de los aparatos ya se venden con tarjeta integrada. Uno de los problemas más graves a los cuales se enfrenta actualmente la tecnología Wi-Fi es la progresiva saturación del espectro radioeléctrico, debida a la masificación de usuarios, esto afecta especialmente en la conexiones de larga distancia (mayor de 100 metros), en realidad WIFI esta diseñado para conectar ordenadores a la red a distancias reducidas, cualquier uso de mayor alcance esta expuesto a un excesivo riesgo de interferencias. Un muy elevado porcentaje de redes son instaladas sin tener en consideración la seguridad convirtiendo así sus redes en redes abiertas (o muy vulnerables a los crackers), sin proteger la información que por ellas circulan. Existen varias alternativas para garantizar la seguridad de estas redes. Las más comunes son: WEP, cifra los datos en su red de forma que sólo el destinatario deseado pueda acceder a ellos. Los cifrados de 64 y 128 bits son dos niveles de seguridad WEP. WEP codifica los datos mediante una “clave” de cifrado antes de enviarlo al aire. WPA: presenta mejoras como generación dinámica de la clave de acceso. Las claves se insertan como de dígitos alfanuméricos, sin restricción de longitud. 36 Creador de un Mapa de Cobertura 4.4.- API Symbian OS Para poder obtener los niveles de cobertura WIFI, GPRS y GSM así como las coordenadas latitud y longitud que es el objetivo fundamental del proyecto y poder enviarlas mediante protocolo HTTP a la base de datos alojada en el servidor hay que hacer uso de la API del sistema operativo Symbian OS v9.2. La API del sistema operativo Symbian OS v9.2 es muy extensa y está compuesta por infinidad de clases, métodos, atributos, constantes, estructuras de datos… etc. Es por este motivo por lo que yo en este apartado sólo quiero hacer referencia a la parte de la API de Symbian OS que he utilizado a la hora de desarrollar el proyecto. En primer lugar trataré de exponer la parte de la API de Symbian OS correspondiente a la obtención del nivel de cobertura WIFI. Para poder acceder a dicho nivel no es necesario implementar una clase auxiliar ya que realizo la petición al sistema operativo de manera asíncrona sin hacer uso de un recurso muy propio de Symbian OS como es Active Object. El código correspondiente al método que hace posible obtener dicho nivel es el siguiente: TPckgBuf<TConnMonNetworkNames> networks; RConnectionMonitor monitor; monitor.ConnectL(); CleanupClosePushL(monitor); TRequestStatus status; monitor.GetPckgAttribute(EBearerIdWLAN, 0, KNetworkNames , networks, status); User::WaitForRequest(status ) ; User::LeaveIfError(status.Int()); TBuf<20> ibuff; TInt count = networks().iCount; ibuff.Zero(); ibuff.AppendNum(count); CEikonEnv::InfoWinL(_L("Total de redes LAN encontradas: "), ibuff); if(count==0){ iSignalWLAN = 0.0;//para enviar luego al servidor. ibuff.Zero(); TRealFormat iFormat; 37 Creador de un Mapa de Cobertura ibuff.AppendNum(iSignalWLAN, iFormat); CEikonEnv::InfoWinL(_L("Cobertura WLAN media en %: "),ibuff); ibuff.Zero(); CEikonEnv::InfoWinL(_L("Cobertura WLAN media en dB: 0 "),ibuff); } else{ TInt iNivelTotal = 0; for(TInt i=0;i<count;i++) { TBuf8<32> ssid; ssid.Copy( networks().iNetwork[i].iName ); ibuff.Zero(); ibuff.Copy(ssid); CEikonEnv::InfoWinL(_L("Nombre de la Red:"),ibuff); TUint8 iSignal = networks().iNetwork[i].iSignalStrength; iNivelTotal = iNivelTotal + iSignal; ibuff.Zero(); ibuff.AppendNum(iSignal); CEikonEnv::InfoWinL(_L("Nivel de Cobertura WLAN en dB:"),ibuff); } iSignalWLAN = (iNivelTotal/count); TReal dec = iSignalWLAN; TInt decibelios = iSignalWLAN; TReal por; if(dec>0 && iSignalWLAN } // rango de else if(dec dec <= 50){ = 100; 80% a 100% >= 51 && dec <= 60){ dec = dec - 51; por = dec * 2.22; iSignalWLAN = 100 - por; } //rango de 60% a 80% else if(dec >= 61 && dec <= 70){ dec = dec - 61; por = dec * 2.22; iSignalWLAN = 80 - por; } //rango de 40% a 60% else if(dec >= 71 && dec <= 80){ dec = dec - 71; 38 Creador de un Mapa de Cobertura por = dec * 2.22; iSignalWLAN = 60 - por; } //rango de 20% a 40% else if(dec >= 81 && dec <= 90){ dec = dec - 81; por = dec * 2.22; iSignalWLAN = 40 - por; } //rango de 0% a 20% else if(dec >= 91 && dec <= 100){ dec = dec - 91; por = dec * 2.22; iSignalWLAN = 20 - por; } if(iSignalWLAN>100) iSignalWLAN = 100; TRealFormat iFormat; ibuff.Zero(); ibuff.AppendNum(iSignalWLAN, iFormat); CEikonEnv::InfoWinL(_L("Cobertura WLAN media en %: "),ibuff); ibuff.Zero(); ibuff.AppendNum(decibelios); CEikonEnv::InfoWinL(_L("Cobertura WLAN media en dB: "), ibuff); } CleanupStack::PopAndDestroy(); -Clase RConnectionMonior: Esta clase nos permite acceder y utilizar los servicios relacionados con redes que la plataforma s60 proporciona. La clase contiene los siguientes métodos: 1.- TInt ConnectL(): Este método es utilizado con el fin de establecer una conexión con el Connection Monitor Server. El método no recibe ningún tipo de argumento y devuelve un valor de tipo entero. Si el método se ha ejecutado de manera correcta y se ha podido realizar la conexión entonces devuelve KErrNone, en caso contrario devolvería el código de error producido. 39 Creador de un Mapa de Cobertura 2.- GetPckgAttribute(TUint aConnectionId, TUint aSubconnectionId, TUint attribute, TDes8 aValue, TrequesStatus aStatus): Este método se utiliza para buscar estructuras de datos representadas en un descriptor. El método no devuelve ningún parámetro y recibe como argumentos el identificador de conexión, el identificador de subconexión, el identificador del atributo que quiere ser buscado, un descriptor para almacenar el valor de dicho atributo y por último una variable para almacenar el código de error si se produjese o KErrNone si no hubiera ningún problema al realizar la llamada. En nuestro caso el método recibe como primer argumento EBearerWLAN que es una constante que forma parte del tipo enumerado TConnMonBearerType, como segundo argumento recibe 0 y como tercer argumento recibe KNetworkNames que es una constante de tipo entero. 3.- Close(): es el método necesario para cerrar la conexión previamente establecida con el Connection Monitor Server. - Clase TPckgBuf<TConnMonNetworkNames>: Esta clase es necesaria para almacenar los datos necesarios en la llamada al método GetPckgAttribute. Esta clase cuenta con dos atributos que son los siguientes: 1.- TUint iCount: Es un atributo de tipo entero utilizado a modo de contador ya que almacena en él el número de redes detectadas. 2.- iNetwork[KConnMonMaxNetworkCount]: Es un array con una dimensión máxima igual al número de redes detectadas que contiene elementos de la clase TConnMonNetwork. Esta clase contiene los siguientes atributos: TBuf8<32> iName, TInt iType, y TUint32 iSignalStrength, que es el que nos interesa para almacenar el nivel de cobertura de la red WLAN. La siguiente parte de la API de Symbian OS que he utilizado para poder realizar la aplicación es la relacionada con la obtención del nivel de cobertura GSM. Para poder realizar esta medida, no he aplicado directamente sobre el método AppUi::HandleCommandL las clases y métodos necesarios, sino que he 40 Creador de un Mapa de Cobertura tenido que implementar una clase auxiliar, la clase CGSM, ya que para poder obtener el nivel de cobertura GSM hay que utilizar una serie de métodos que realizan una petición asíncrona al sistema operativo y por tanto he realizado dicha petición a través de Active Objects, que es un concepto de porgramación basada en hilos. Una vez implementada la clase CGSM sólo tenemos que introducir las modificaciones necesarias en nuestra clase AppUi y en el método AppUi::HandleCommandL realizar la llamada al método de nuestra clase que se encarga de obtener dicho nivel de cobertura. El código de la clase CGSM es el siguiente: #ifndef CGSM_H_ #define CGSM_H_ #include <e32std.h> #include <e32base.h> #include <Etel3rdParty.h> class MNwSignalObserver { public: virtual void SignalStatus(TInt32 aStrength, TInt8 aBars ) = 0; }; class CGSM : public CActive { public: static CGSM* NewL(MNwSignalObserver& aObserver); static CGSM* NewLC(MNwSignalObserver& aObserver); ~CGSM(); private: CGSM(MNwSignalObserver& aObserver); void ConstructL(void); private: void RunL(); void DoCancel(); public: void GetSignalInfo(); private: MNwSignalObserver& iObserver; CTelephony* iTelephony; 41 Creador de un Mapa de Cobertura CTelephony::TSignalStrengthV1 iSigStrengthV1; CTelephony::TSignalStrengthV1Pckg iSigStrengthV1Pckg; TBool iGettingSignal; }; #endif /* CGSM_H_ */ La implementación de cada uno de los métodos de la clase CGSM es la siguiente: CGSM* CGSM::NewL(MNwSignalObserver& aObserver) { CGSM* self = CGSM::NewLC(aObserver); CleanupStack::Pop(self); return self; } CGSM* CGSM::NewLC(MNwSignalObserver& aObserver) { CGSM* self = new (ELeave) CGSM(aObserver); CleanupStack::PushL(self); self->ConstructL(); return self; } CGSM::~CGSM() { Cancel(); delete iTelephony; } void CGSM::ConstructL(void) { iTelephony = CTelephony::NewL(); } CGSM::CGSM(MNwSignalObserver& aObserver) : CActive(EPriorityStandard), iObserver(aObserver), iSigStrengthV1Pckg( iSigStrengthV1) 42 Creador de un Mapa de Cobertura { CActiveScheduler::Add(this); } void CGSM::GetSignalInfo() { if (iTelephony && !IsActive()) { iGettingSignal = ETrue; iTelephony->GetSignalStrength(iStatus, iSigStrengthV1Pckg); SetActive(); } } void CGSM::RunL() { iObserver.SignalStatus(iSigStrengthV1.iSignalStrength, iSigStrengthV1.iBar); if (iStatus != KErrCancel) { iTelephony->NotifyChange(iStatus, CTelephony::ESignalStrengthChange, iSigStrengthV1Pckg); SetActive(); } iGettingSignal = EFalse; } void CGSM::DoCancel() { if (iGettingSignal) iTelephony->CancelAsync(CTelephony::EGetSignalStrengthCancel); else iTelephony->CancelAsync(CTelephony:: ESignalStrengthChangeCancel); } Como ya comenté anteriormente, el método SignalStatus hay que redefinirlo en nuestra clase AppUi: 43 Creador de un Mapa de Cobertura void CprobandoWLANExampleAppUi::SignalStatus(TInt32 aStrength, TInt8 aBars) { switch(aBars){ case case case case case case case case 0: 1: 2: 3: 4: 5: 6: 7: iSignalGSM iSignalGSM iSignalGSM iSignalGSM iSignalGSM iSignalGSM iSignalGSM iSignalGSM = = = = = = = = 0;break; 14.2;break; 28.4;break; 42.6;break; 56.8;break; 71;break; 85.2;break; 99.4;break; } TBuf<50> ibuff; TRealFormat iFormat; ibuff.Zero(); ibuff.AppendNum(iSignalGSM, iFormat); CEikonEnv::InfoWinL(_L("Cobertura GSM en % aproximadamente: "), ibuff); ibuff.Zero(); ibuff.AppendNum(aBars); CEikonEnv::InfoWinL(_L("Barras de Cobertura GPRS mostradas en pantalla: "), ibuff); ibuff.Zero(); ibuff.AppendNum(aStrength); CEikonEnv::InfoWinL(_L("Cobertura GSM en dB: "), ibuff); } -Clase CTelephony: Esta clase nos provee de una interfaz para poder acceder al sistema del telefónico del dispositivo móvil. Los métodos que he utilizado de esta clase son los siguientes: 1.- static CTelephony* NewL(): El método construye un nuevo objeto de la clase CTelephony devolviendo la referencia a dicho objeto. Utilizando este método no colocamos la referencia al nuevo objeto en la pila CleanupStack. 2.SignalStrength(TRequestStatus aStatus, TDes8 aSignalStrength): Este es el método más interesante que utilizamos de la clase CTelephony ya que nos devuelve la intensidad de señal del dispositivo móvil, es decir, el nivel de cobertura a través de 44 Creador de un Mapa de Cobertura aSignalStrength que utilizamos como parámetro. El primer parámetro que toma este método es aStatus, que se utiliza para comprobar que la llamada al método se realiza de forma correcta. En mi caso utilizo como primer argumento la variable iStatus propia de CActive. Como segundo argumento utilizo una variable del tipo TSignalStrengthV1Pckg que necesita un objeto de la clase TSignalStrengthV1 para ser inicializada. 3.NotifyChange(TRequestStatus aStatus, const TNotificationEvent aEvent, TDes8 aDes ): Gracias a este método se registra nuestro interés en recibir notificaciones sobre el cambio de un evento. Como primer parámetro vuelvo a utilizar la variable iStatus propia de CActive y como segundo parámetro utilizo la constante ESignalStrengthChange que es una constante del tipo enumerado TNotificantionEvent propicia para registrar todos los cambios que se produzcan en cuanto al nivel de cobertura GSM. Como tercer parámetro vuelvo a utilizar una variable del tipo TSignalStrengthPckgV1 para almacenar el nuevo valor del nivel de cobertura. 4.- TInt CancelAsync(TCancellationrequest aRequest): El método se utiliza para cancelar cualquier petición asíncrona que está siendo realizada. Este método se utiliza cuando redefinimos el método DoCancel propio de CActive. Como parámetro toma una variable del tipo enumerado TCancellationRequest. En mi caso utilizamos como parámetro las constante ESignalStrengthCancel, que cancela una petición pendiente para obtener el nivel de cobertura, y la constante ESignalStrengthChangeCancel, que cancela una petición pendiente sobre cambio en el valor del nivel de cobertura. - Clase TSignalStrengthV1: A través de un objeto de esta clase podemos almacenar el nivel de cobertura GSM en la llamada al método GetSignalStrength de la clase CTelephony. Esta clase posee los siguientes atributos: 1.- iBar: Es de tipo TInt8 y almacena el número de barras de cobertura GSM que el dispositivo móvil debe mostrar. 2.- iSignalStrength: Es de tipo TInt32 y almacena el valor del nivel de cobertura GSM expresado en dB. 45 Creador de un Mapa de Cobertura A continuación trataré de explicar toda la parte de la API de Symbian OS relacionada con la obtención de las coordenadas GPS, es decir, las clases y métodos necesarios para poder obtener a través del GPS (interno o externo) del dispositivo móvil la latitud y la longitud del punto exacto en el cual realizamos la medida de los niveles de cobertura. Estas coordenadas son necesarias para poder colocar luego en el mapa de la página Web la información correspondiente. Al igual que en el caso de la obtención del nivel de cobertura GSM, a la hora de obtener las coordenadas GPS no aplico directamente el código necesario en el método AppUi::HandleCommandL sino que tengo que implementar una clase auxiliar, la clase CLBSInfo, ya que realizo una petición al sistema operativo a través de Active Objects, utilizando hilos, y por tanto tengo que implementar una serie de métodos heredados de la clase CActive. Una vez implementada la clase CLBSInfo sólo hay que añadir a la clase AppUi las modificaciones necesarias y en el método AppUi::HandleCommandL realizar la llamada al método que nos devuelve las coordenadas. El código correspondiente a la clase CLBSInfo es el siguiente: #include <lbs.h> #include <LbsSatellite.h> class MPositionObserver { public: virtual void LBSPositionUpdatedL(TPositionInfoBase& aPosInfo) = 0; virtual void LBSErrorL(const TDesC& aErrorString) = 0; virtual void LBSMessageL(const TDesC& aMessage) = 0; virtual void LBSMessageL(TInt aCode, const TDesC& aMessage) = 0; }; class CLBSInfo : public CActive 46 Creador de un Mapa de Cobertura { public: static CLBSInfo* NewL(MPositionObserver& aPositionListener ) ; virtual ~CLBSInfo(); protected: void DoCancel(); void RunL(); TInt RunError(TInt aError); private: // New Functions void ConstructL( ); CLBSInfo(MPositionObserver& aPositionListener ); void DoInitialiseL(); void PositionUpdatedL(); public: void Pause(); void Continue(); TPositionInfoBase* CurrentPosition(); private: TPositionModuleId UsedPsy; RpositionServer iPosServer; RPositioner iPositioner; TPositionInfo iPositionInfo; TPositionSatelliteInfo iSatelliteInfo; MPositionObserver& iPositionListener; 47 Creador de un Mapa de Cobertura TPositionInfoBase* iPosInfoBase; TBool iGettingLastknownPosition; }; La implementación correspondiente a cada uno de los métodos de la clase es la siguiente: #include <Lbs.h> #include <eikenv.h> #include "LBSInfo.h" const TInt KSecond = 1000000; const TInt KMaxAge = KSecond; const TInt KErrBuffer = 100; _LIT(KRequestor,"LocationExample"); _LIT(KLbsErrLocRequest,"Error Solicitud Localizacion: %d."); _LIT(KLbsErrAccess,"No Acceso Localizacion. Error: %d."); _LIT(KLbsErrPosServConn,"Error Servidor Localizacion: %d."); _LIT(KLbsErrOpenPos,"Error servidor Localizacion: %d."); _LIT(KLbsErrSetRequestor,"Error Solicitud Localizacion: %d."); _LIT(KLbsErrSetUpOpt,"Error Actualizacion Localizacion: %d."); _LIT(KLbsErrCanceled,"Localizacion Cancelada."); _LIT(KLbsErrQuality,"Calidad Localizacion Error"); _LIT(KLbsErrPosUnknown, "Posicion Localizacion Desconocida"); CLBSInfo::CLBSInfo(MPositionObserver& aPositionListener) : CActive(CActive::EPriorityStandard), iPositionListener( aPositionListener ), iPosInfoBase( &iPositionInfo ), iGettingLastknownPosition( ETrue ) { } 48 Creador de un Mapa de Cobertura void CLBSInfo::ConstructL() { CActiveScheduler::Add( this ); DoInitialiseL(); } CLBSInfo* CLBSInfo::NewL(MPositionObserver& aPositionListener) { CLBSInfo* self = new( ELeave ) CLBSInfo(aPositionListener); CleanupStack::PushL( self ); self->ConstructL(); CleanupStack::Pop( self ); return self; } CLBSInfo::~CLBSInfo() { Cancel(); iPositioner.Close(); iPosServer.Close(); } void CLBSInfo::DoCancel() { if ( iGettingLastknownPosition ) { iPositioner.CancelRequest(EPositionerGetLastKnownPosition); } else { iPositioner.CancelRequest(EPositionerNotifyPositionUpdate); } } void CLBSInfo::RunL() { TBuf<KPositionMaxModuleName> buffer; 49 Creador de un Mapa de Cobertura switch ( iStatus.Int() ) { case KErrNone: case KPositionPartialUpdate: { PositionUpdatedL(); break; } case KErrArgument: { iPosInfoBase = &iPositionInfo; iPositioner.NotifyPositionUpdate( *iPosInfoBase, iStatus ); SetActive(); break; } case KPositionQualityLoss: { iPositionListener.LBSErrorL(KLbsErrQuality); if ( iGettingLastknownPosition ) { iPosInfoBase = &iSatelliteInfo; } iPositioner.NotifyPositionUpdate( *iPosInfoBase, iStatus ); SetActive(); break; } case KErrAccessDenied: { buffer.Format(KLbsErrAccess, iStatus.Int()); iPositionListener.LBSErrorL(buffer); break; } 50 Creador de un Mapa de Cobertura case KErrTimedOut: { iPositionListener.LBSErrorL(KLbsErrPosUnknown); if ( iGettingLastknownPosition ) { iPosInfoBase = &iSatelliteInfo; } iPositioner.NotifyPositionUpdate( *iPosInfoBase, iStatus ); SetActive(); break; } case KErrCancel: { iPositionListener.LBSErrorL( KLbsErrCanceled ); break; } case KErrUnknown: { iPositionListener.LBSMessageL(KLbsErrPosUnknown); if ( iGettingLastknownPosition ) { iPosInfoBase = &iSatelliteInfo; iGettingLastknownPosition = EFalse; } iPositioner.NotifyPositionUpdate( *iPosInfoBase, iStatus ); SetActive(); break; } default: { buffer.Format(KLbsErrLocRequest, iStatus.Int()); iPositionListener.LBSErrorL( buffer ); break; } 51 Creador de un Mapa de Cobertura } if ( iGettingLastknownPosition ) { iGettingLastknownPosition = EFalse; } } void CLBSInfo::DoInitialiseL() { . TInt error = iPosServer.Connect( ); TBuf<KErrBuffer> buffer; if ( KErrNone != error ) { buffer.Format(KLbsErrPosServConn, error); iPositionListener.LBSErrorL( buffer ); return; } TUint numModules; TPositionModuleId modId; TPositionModuleInfo modInfo; TPositionModuleStatus modStatus; TBool foundModule = EFalse; User::LeaveIfError(iPosServer.GetNumModules(numModules)); for (TUint I=0 ; I < numModules ; I++) { User::LeaveIfError(iPosServer.GetModuleInfoByIndex(I, modInfo)); if ( modInfo.IsAvailable() && (modInfo.TechnologyType() == TPositionModuleInfo::ETechnologyAssisted) ) { TPositionModuleInfo::TCapabilities caps = modInfo.Capabilities(); if ((caps & TPositionModuleInfo::ECapabilitySpeed) && (caps & TPositionModuleInfo::ECapabilityHorizontal) && (caps & TPositionModuleInfo::ECapabilityVertical)) { modId = modInfo.ModuleId(); foundModule = ETrue; iPositionListener.LBSMessageL(_L("Assisted Technology chosen")); break;. } } 52 Creador de un Mapa de Cobertura } if(!foundModule) { for (TUint I=0 ; I < numModules ; I++) { User::LeaveIfError(iPosServer.GetModuleInfoByIndex(I, modInfo)); if ( modInfo.IsAvailable() && (modInfo.TechnologyType() == TPositionModuleInfo::ETechnologyTerminal) ) { modId = modInfo.ModuleId(); foundModule = ETrue; iPositionListener.LBSMessageL(_L("Terminal Technology chosen")); break; } } } if(!foundModule) { iPositionListener.LBSErrorL(KLbsErrPosUnknown); return; } error = iPositioner.Open(iPosServer, modId); iPositionListener.LBSMessageL(modId.iUid, _L("Hasta este modIDul")); if ( KErrNone != error ) { buffer.Format(KLbsErrOpenPos, error); iPositionListener.LBSErrorL( buffer ); iPosServer.Close(); return; } error = iPositioner.SetRequestor( CRequestor::ERequestorService , CRequestor::EFormatApplication , KRequestor ); if ( KErrNone != error ) { buffer.Format(KLbsErrSetRequestor, error); iPositionListener.LBSErrorL( buffer ); iPositioner.Close(); 53 Creador de un Mapa de Cobertura iPosServer.Close(); return; } TPositionUpdateOptions options; const TTimeIntervalMicroSeconds KUpdateInterval(2000000); const TTimeIntervalMicroSeconds KTimeOut(30000000); const TTimeIntervalMicroSeconds KMaxUpdateAge(1000000); options.SetUpdateInterval(KUpdateInterval); options.SetUpdateTimeOut(KTimeOut); options.SetMaxUpdateAge(KMaxUpdateAge); options.SetAcceptPartialUpdates(EFalse); error = iPositioner.SetUpdateOptions( options ); if ( KErrNone != error ) { buffer.Format(KLbsErrSetUpOpt, error); iPositionListener.LBSErrorL( buffer ); iPositioner.Close(); iPosServer.Close(); return; } iPositioner.GetLastKnownPosition(*iPosInfoBase,iStatus); SetActive(); } TInt CLBSInfo::RunError(TInt aError) { Cancel(); TBuf<32> err; err.Format(KLbsErrLocRequest, aError); iPositionListener.LBSMessageL(err); if ( iGettingLastknownPosition ) { iPosInfoBase = &iSatelliteInfo; iGettingLastknownPosition = EFalse; } if(!IsActive()) { 54 Creador de un Mapa de Cobertura iPositioner.NotifyPositionUpdate( *iPosInfoBase, iStatus ); SetActive(); } return KErrNone; } void CLBSInfo::Pause() { if (IsActive()) { Cancel(); } } void CLBSInfo::Continue() { if (!IsActive()) { iPositioner.GetLastKnownPosition(*iPosInfoBase,iStatus); SetActive(); } } TPositionInfoBase* CLBSInfo::CurrentPosition() { return iPosInfoBase; } void CLBSInfo::PositionUpdatedL() { iPositionListener.LBSPositionUpdatedL(*iPosInfoBase); if ( iGettingLastknownPosition ) { iPositionListener.LBSPositionUpdatedL(*iPosInfoBase); iPosInfoBase = &iSatelliteInfo; iPositioner.NotifyPositionUpdate( *iPosInfoBase, iStatus ); SetActive(); } else { if ( 0 == iUsedPsy.iUid) { 55 Creador de un Mapa de Cobertura iUsedPsy = iPosInfoBase->ModuleId(); } else if ( iPosInfoBase->ModuleId() != iUsedPsy ) { iUsedPsy = iPosInfoBase->ModuleId(); TPositionModuleInfo moduleInfo; iPosServer.GetModuleInfoById(iUsedPsy,moduleInfo); TInt32 moduleInfoFamily = moduleInfo.ClassesSupported(EPositionInfoFamily); iPosInfoBase = &iSatelliteInfo; if ( EPositionSatelliteInfoClass & moduleInfoFamily ) { iPosInfoBase = &iSatelliteInfo; } else { iPosInfoBase = &iPositionInfo; } } iPositionListener.LBSPositionUpdatedL(*iPosInfoBase); iPositioner.NotifyPositionUpdate( *iPosInfoBase, iStatus ); SetActive(); } } Los métodos propios de la clase observadora que hay que implementar en la clase AppUi son los siguientes: void CprobandoWLANExampleAppUi::LBSPositionUpdatedL( TPositionInfoBase& aPosInfo) { TReal rLatitude, rLongitude; TRealFormat rFormat(20, 10); TBuf<32> latitude, longitude; 56 Creador de un Mapa de Cobertura TPositionInfo* posInfo = static_cast<TPositionInfo*>(&aPosInfo); TPosition position; posInfo->GetPosition(position); rLatitude = position.Latitude(); rLongitude = position.Longitude(); latitude.Num(rLatitude, rFormat); longitude.Num(rLongitude, rFormat); iLastPosition = position; iLatitud = rLatitude; iLongitud = rLongitude; CEikonEnv::InfoWinL(_L("Latitud: "), latitude); CEikonEnv::InfoWinL(_L("Longitud: "), longitude); } void CprobandoWLANExampleAppUi::LBSErrorL(const TDesC& aErrorString) { CEikonEnv::InfoWinL(_L(""), aErrorString); } void CprobandoWLANExampleAppUi::LBSMessageL(const TDesC& aMessage) { if(iNetworkEngineObserver) iNetworkEngineObserver->HandleErrorL(KErrNone, aMessage); } void CprobandoWLANExampleAppUi::LBSMessageL(TInt aCode, const TDesC& aMessage) { if(iNetworkEngineObserver) iNetworkEngineObserver->HandleErrorL(aCode, aMessage); } -Clase RPositionServer: Esta es la clase que nos permite interactuar con el servidor de posicionamiento, se utiliza para realizar la conexión con dicho servidor. Los métodos que utilizo son los siguientes: 1.- TInt Connect(): Crea una sesión con el Servidor de Posicionamiento. Devuelve una variable de tipo entero que representa el código de error de Symbian OS. 57 Creador de un Mapa de Cobertura 2.- TInt GetNumModules(TUint aNumModules): El método devuelve el número de módulos de posicionamiento que están disponibles. Recibe un parámetro de entrada, anumModules, en donde almacenamos dicho número. Devuelve una variable de tipo que representa el código de error de Symbian OS. 3.- TInt GetModuleInfoByIndex(TInt aModuleIndex, TPositionModuleInfoBase aModuleInfo): Se utiliza para obtener sobre el módulo especificado. Recibe dos parámetros de entrada, el primero para indicar el índice (de 0 a n) del módulo acerca del cual queremos obtener información y el segundo para almacenar dicha información. Devuelve una variable de tipo entero que re presenta el código de error de Symbian OS. 4.- TInt GetModuleInfoById(TPositionmoduleId aModuleId, TPositionModuleInfoBase aModuleInfo): Este método es similar al anterior con la única salvedad que recibe como primer parámetro el identificador único (UID) del módulo sobre el que queremos obtener información. El resto de parámetros funcionan igual que el anterior. 5.- void Close(): El método se utiliza para finalizar una sesión con el Servidor de Posicionamiento. -Clase RPositioner: Esta clase es usada para crear una subsesión con el servidor de Posicionamiento con el propósito de obtener la posición actual. Los métodos que ha sido necesario utilizar de esta clase son los siguientes: 1.- TInt Open(RPositionserver aPosServer): Se utiliza para establecer una subsesión con el Servidor de Posicionamiento. El método recibe como parámetro de entrada un objeto de la clase RPositionServer que representa al Servidor de Posicionamiento al cual hay que conectarse previamente. Devuelve una variable de tipo TInt que representa el código de error de Symbian OS. 2.- TInt SetRequestor(TRequestorType aType, TRequestorFormat aFormat, TdesC aData): A través de este método podemos establecer una serie de requisitos que la información acerca de la localización debe cumplir. El método recibe como primer parámetro una variable del tipo definido TRequestorType que en mi caso es 58 Creador de un Mapa de Cobertura ERequestorService. En segundo lugar recibe como parámetro una variable del tipo definido TRequestorFormat, yo he utilizado EFormatApplication y por último recibe como parámetro un descriptor con el nombre de la petición. El método devuelve una variable de tipo TInt que representa el código de error de Symbian OS. 3.- TInt SetUpdateOptions( TPositionUpdateOptions aPosOpt): El método es utilizado para modificar el comportamiento del notificador de actualización de la posición, permitiendo establecer una serie de opciones a la hora de ir actualizando la posición. Recibe como parámetro de entrada un objeto de la clase TPositionUpdateOptions que se detalla más adelante. Devuelve una variable de tipo TInt que representa el código de error de Symbian OS. 4.- void GetLastKnowPosition( TPositionInfoBase pos, TRequestStatus aStatus): Se utiliza para almacenar en el objeto parado como primer parámetro la información de la última posición obtenida, si está disponible. El primer parámetro es un objeto de la clase TPositionInfoBase, clase que se detalla más adelante mientras que el segundo parámetro es un objeto de la clase TRequestStatus que almacena el resultado de la llamada asíncrona que necesita realizar el método al ser llamado. 5.- void NotifyPositionUpdate(TPositionInfo pos, TRequestStatus aStatus): Es un método asíncrono que se utiliza para ir actualizando la información acerca de la posición. Recibe como primer parámetro de entrada un objeto de la clase TPositionInfo, clase que se detalla más adelante, y como segundo parámetro de entrada un objeto de la clase TRequestStatus que contiene el resultado de la llamada asíncrona que el método realiza cuando se utiliza. 6.- TInt CancelRequest(TInt aRequestId): El método cancela una petición asíncrona para obtener la posición previamente realizada. Recibe como parámetro de entrada una variable del tipo enumerado TPositionIpcld, en mi caso utilizo las variables EPositionerGetLastKnowPosition y EPositionerNotifyPositionUpdate. En el objeto de la clase TRequestStaus se almacenará el valor 59 Creador de un Mapa de Cobertura KErrCancel si la petición de cancelación de ha realizado correctamente o el código de error de Symbian OS en caso contrario. 7.- void Close(): Para poder cerrar la subsesión creada con el servidor de Posicionamiento. - Clase TPosititonInfoBase: Esta clase contiene información sobre el tipo de actualización y el ID del módulo que dio la información de localización. El método que utilizo de esta clase es el siguiente: 1.- TPositionModuleId ModuleId(): El método devuelve el ID del módulo utilizado para obtener la información de localización en una variable del tipo definido TPositionModuleId. - Clase TPositionModuleInfo: Es la clase estándar utilizada para almacenar información acerca del módulo de posicionamiento utilizado. Los métodos utilizados de esta clase son los siguientes: 1.- TBool IsAvailable(): Devuelve en una variable de tipo TBool si el módulo está o no disponible. 2.- TTechnologyType TechnologyType(): El método devuelve en una variable del tipo definido TTecnologyType el tipo de tecnología que utiliza el módulo. La variable utilizada en mi caso es ETechNologyTerminal. 3.- TCapabilities Capabilities(): Devuelve en una variable de tipo enumerado TCapabilities las capacidades del módulo. En mi caso he utilizado las siguientes variables: ECapabilitySpeed, ECapabilityHorizontal y ECapabilityVertical. 4.-TUint32 CassesSupported( TpositionClass Family classType): Devuelve las clases soportadas. Recibe como parámetro una variable del tipo enumerado TPositionFamily, en mi caso EPositionFamily. - Clase TPositionUpdateOptions: Esta clase es la que se utiliza para almacenar las diferentes opciones que podemos especificar a la hora de recibir las actualizaciones sobre la información de posicionamiento. Los métodos utilizados son los siguientes: 60 Creador de un Mapa de Cobertura 1.-void SetUpdateInterval( TTimeInterval MicroSeconds aInter): Utilizado para establecer el intervalo de actualización. Recibe como parámetro un objeto de la clase TTImeIntervalMicroseconds que indica en microsegundos el tiempo del intervalo. 2.-void SetUpdateTimeOut( TTimeinterval Microseconds aTime): A través de este método se puede establecer el timeout, es decir, el tiempo máximo en el que se intentará actualizar la información acerca de la posición. Recibe como parámetro un objeto de la clase TTimeIntervalMicroseconds que representa ese timeout en microsegundos. La siguiente parte de la API de Symbian OS que desarrollo a continuación es la correspondiente al envío de todos los parámetros necesarios para generar el punto de información en el mapa de la página Web, estos parámetros son: niveles de cobertura GSM, GPRS, WIFI así como latitud y longitud del punto en el que se realiza la obtención de dichos niveles. Al igual que ocurre con la obtención del nivel de cobertura GSM y la obtención de las coordenadas GPS, a la hora de enviar los datos necesarios a la base del servidor no aplico directamente el código correspondiente en el método AppUi::HandleCommandL sino que implemento una clase auxiliar, la clase CHTTPClient, ya que la petición de envío de datos realizada al sistema operativo se realiza a través de Active Objects, es decir utilizando hilos como ya he comentado anteriormente, y redefinir una serie de métodos heredados de la clase CActive. Una vez implementada la clase CHTTPClient sólo hay que añadir a la clase AppUi las modificaciones necesarias y en el método AppUi::HandleCommandL realizar la llamada al método que realiza la conexión HTTP y envía los datos al servidor. El código correspondiente a la clase CHTTPClient es el siguiente: 61 Creador de un Mapa de Cobertura class CHTTPClient : public CBase, public MHTTPTransactionCallback, public MHTTPDataSupplier, public MHTTPAuthenticationCallback { public: static CHTTPClient* NewL(MClientObserver& iObserver); static CHTTPClient* NewLC(MClientObserver& iObserver); ~ CHTTPClient (); void IssueHTTPGetL(const TDesC8& aUri); void CancelTransaction(); inline TBool IsRunning() { return iRunning; }; private: void ConstructL(); CHTTPClient (MClientObserver& iObserver); void SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue); private: void MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent); TInt MHFRunError( TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent); private: void ReleaseData(); TBool GetNextDataPart(TPtrC8& aDataPart); TInt Reset(); TInt OverallDataSize(); 62 Creador de un Mapa de Cobertura void SetupConnectionL(); private: TBool GetCredentialsL( const TUriC8& aURI, RString aRealm, RStringF aAuthenticationType, RString& aUsername, RString& aPassword); private: RSocketServ iSocketServ; RConnection iConnection; RHTTPSession iSession; RHTTPTransaction iTransaction; MClientObserver& iObserver; HBufC8* iPostData; TBool iRunning; TBool iConnectionSetupDone; }; La implementación correspondiente a cada uno de los métodos de la clase es la siguiente: CHTTPClient* CClientEngine::NewL(MClientObserver& aObserver) { CClientEngine* self = CClientEngine::NewLC(aObserver); CleanupStack::Pop(self); return self; } CHTTPClient* CClientEngine::NewLC(MClientObserver& aObserver) { CClientEngine* self = new (ELeave) CClientEngine(aObserver); CleanupStack::PushL(self); self->ConstructL(); return self; 63 Creador de un Mapa de Cobertura } CHTTPClient::CHTTPClient(MClientObserver& aObserver) : iObserver(aObserver), iPostData(NULL), iRunning(EFalse) { } CHTTPClient::~CCHTTPClient() { iSession.Close(); // and finally close handles iConnection.Close(); iSocketServ.Close(); delete iPostData; } void CHTTPClient::ConstructL() { TRAPD(err, iSession.OpenL()); if(err != KErrNone) { _LIT(KErrMsg, "Cannot create session. Is internet access point configured?"); _LIT(KExitingApp, "Exiting app."); CEikonEnv::Static()->InfoWinL(KErrMsg, KExitingApp); User::Leave(err); } InstallAuthenticationL(iSession); } void CHTTPClient::SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue) { RStringF valStr = iSession.StringPool().OpenFStringL(aHdrValue); CleanupClosePushL(valStr); THTTPHdrVal val(valStr); aHeaders.SetFieldL(iSession.StringPool().StringF(aHdrField, 64 Creador de un Mapa de Cobertura RHTTPSession::GetTable()), val); CleanupStack::PopAndDestroy(); } void CHTTPClient::IssueHTTPGetL(const TDesC8& aUri) { SetupConnectionL(); TUriParser8 uri; uri.Parse(aUri); RStringF method = iSession.StringPool().StringF(HTTP::EGET, RHTTPSession::GetTable()); iTransaction = iSession.OpenTransactionL(uri, *this, method); RHTTPHeaders hdr = iTransaction.Request().GetHeaderCollection(); SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent); SetHeaderL(hdr, HTTP::EAccept, KAccept); iTransaction.SubmitL(); iRunning = ETrue; } void CHTTPClient::IssueHTTPPostL(const TDesC8& aUri, const TDesC8& aContentType, const TDesC8& aBody) { SetupConnectionL(); TUriParser8 uri; uri.Parse(aUri); delete iPostData; iPostData = aBody.AllocL(); RStringF method = iSession.StringPool().StringF(HTTP::EPOST, RHTTPSession::GetTable()); iTransaction = iSession.OpenTransactionL(uri, *this, method); RHTTPHeaders hdr = iTransaction.Request().GetHeaderCollection(); SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent); SetHeaderL(hdr, HTTP::EAccept, KAccept); SetHeaderL(hdr, HTTP::EContentType, aContentType); 65 Creador de un Mapa de Cobertura MHTTPDataSupplier* dataSupplier = this; iTransaction.Request().SetBody(*dataSupplier); iTransaction.SubmitL(); iRunning = ETrue; } void CHTTPClient::CancelTransaction() { if(!iRunning) return; iTransaction.Close(); iRunning = EFalse; TBuf<20> ibuff; ibuff.Copy(_L("Transaccion Cancelada")); CEikonEnv::InfoWinL(_L(""), ibuff); } void CHTTPClient::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent) { switch (aEvent.iStatus) { case THTTPEvent::EGotResponseHeaders: { RHTTPResponse resp = aTransaction.Response(); TInt status = resp.StatusCode(); TBuf<KStatustextBufferSize> statusText; statusText.Copy(resp.StatusText().DesC()); TBuf<KDefaultBufferSize> text; } break; case THTTPEvent::EGotResponseBodyData: { MHTTPDataSupplier* body = aTransaction.Response().Body(); TPtrC8 dataChunk; TBool isLast = body->GetNextDataPart(dataChunk); iObserver.ClientBodyReceived(dataChunk); 66 Creador de un Mapa de Cobertura TBuf<KInfotextBufferSize> text; body->ReleaseData(); } break; case THTTPEvent::EResponseComplete: { } break; case THTTPEvent::ESucceeded: { aTransaction.Close(); iRunning = EFalse; User:: Exit(KErrNone); } break; case THTTPEvent::EFailed: { aTransaction.Close(); iRunning = EFalse; } break; default: { TBuf<KInfotextBufferSize> text; if (aEvent.iStatus < 0) { aTransaction.Close(); iRunning = EFalse; } else { } iObserver.ClientEvent(text); } break; } } TInt CHTTPClient::MHFRunError(TInt aError, RHTTPTransaction /*aTransaction*/, const THTTPEvent& /*aEvent*/) { 67 Creador de un Mapa de Cobertura TBuf<KInfotextBufferSize> text; text.AppendNum(aError); CEikonEnv::InfoWinL(_L("MHFRunError: "), text); iObserver.ClientEvent(text); return KErrNone; } TBool CHTTPClient::GetNextDataPart(TPtrC8& aDataPart) { if(iPostData) { aDataPart.Set(iPostData->Des()); } return ETrue; } void CHTTPClient::ReleaseData() { // It's safe to delete iPostData now. delete iPostData; iPostData = NULL; } TInt CHTTPClient::Reset() { return KErrNone; } TInt CHTTPClient::OverallDataSize() { if(iPostData) return iPostData->Length(); else return KErrNotFound ; } TBool CHTTPClient::GetCredentialsL(const TUriC8& aURI, RString aRealm, RStringF aAuthenticationType, RString& aUsername, RString& aPassword) { TBuf<KDefaultBufferSize> userName; TBuf<KDefaultBufferSize> password; CAknMultiLineDataQueryDialog* dlg = CAknMultiLineDataQueryDialog::NewL(userName, password); 68 Creador de un Mapa de Cobertura TBuf8<KDefaultBufferSize> temp; temp.Copy(userName); TRAPD(err, aUsername = aRealm.Pool().OpenStringL(temp)); if (!err) { temp.Copy(password); TRAP(err, aPassword = aRealm.Pool().OpenStringL(temp)); if (!err) return ETrue; } return EFalse; } void CHTTPClient::SetupConnectionL() { if( iConnectionSetupDone ) return; iConnectionSetupDone = ETrue; User::LeaveIfError(iSocketServ.Connect()); User::LeaveIfError(iConnection.Open(iSocketServ)); CCommsDatabase* commDB = CCommsDatabase::NewL(EDatabaseTypeIAP); CleanupStack::PushL(commDB); // initialize a view CCommsDbConnectionPrefTableView* commDBView = commDB>OpenConnectionPrefTableInRankOrderLC(ECommDbConnectionDirection Unknown); User::LeaveIfError(commDBView->GotoFirstRecord()); CCommsDbConnectionPrefTableView::TCommDbIapConnectionPref pref; commDBView->ReadConnectionPreferenceL(pref); TUint32 iapID = pref.iBearer.iIapId; CleanupStack::PopAndDestroy(commDBView); CleanupStack::PopAndDestroy(commDB); TCommDbConnPref connectPref; connectPref.SetDialogPreference(ECommDbDialogPrefPrompt); connectPref.SetDirection(ECommDbConnectionDirectionOutgoing); User::LeaveIfError(iConnection.Start(connectPref)); 69 Creador de un Mapa de Cobertura RStringPool strPool = iSession.StringPool(); RHTTPConnectionInfo connInfo = iSession.ConnectionInfo(); connInfo.SetPropertyL ( strPool.StringF(HTTP::EHttpSocketServ, RHTTPSession::GetTable() ), THTTPHdrVal (iSocketServ.Handle()) ); connInfo.SetPropertyL ( strPool.StringF(HTTP::EHttpSocketConnection, RHTTPSession::GetTable() ), THTTPHdrVal (REINTERPRET_CAST(TInt, &(iConnection))) ); } - Clase RSocketServ: Esta clase tiene como principal objetivo proporcionar la conexión para crear una comunicación a través del canal IPC mediate con el servidor Socket. Los métodos utilizados de esta clase son los siguentes: 1.- TInt Connect(): Abre una sesión con el servidor Socket. Devuelve una variable de tipo TInt que representa el código de error de Symbian OS o KErrNone en caso de que no haya habido ningún problema. 2.- void Close(): Se encarga de cerrar la sesión previamente establecida con el servidor Socket. - Clase RConnection: Esta clase representa la principal interfaz para administrar una conexión o subconexión a la red. Proporciona al cliente la apertura y cierre de sesión, comenzar o detener la conexión, obtener información acerca del progreso durante la conexión leer campos pertenecientes a la base de datos CommDB, y un largo etc. Los métodos que ha sido necesario utilizar son los siguientes: 1.- TInt Open(RSocketServ aServ): El método consiste en abrir una nueva instancia de la clase RConnection. Recibe como único argumento un objeto de la clase RSocketServ que representa la sesión con el servidor Socket previamente establecida. Devuelve una variable 70 Creador de un Mapa de Cobertura del tipo TInt que representa el código de error de Symbian OS y KErrNone si no ocurre ningún tipo de problema. 2.- TInt Start(TConnPref aPref): Comienza una conexión sobrescribiendo las preferencias que se indican en el parámetro que recibe de entrada en la base de datos CommDB. Las preferencias que permite sobrescribir son las siguientes: IAP id, Network id, Dialog preferente, Direction y Bearer Set. Devuelve una variable de tipo TInt que representa el código de error de Symbian OS en caso de que ocurra algún tipo de fallo o KErrNone si no hay problema. 3.- void Close(): Cierra la conexión. -Clase RHTTPSession: Esta clase representa el manejador de sesión, entendiendo por sesión un conjunto de transacciones http que utilizan la misma configuración a la hora de realizar una conexión. De esta clase se utilizan los siguientes métodos: 1.- void OpenL(): Para utilizar este método hay que cumplir la precondición de que la sesión esté cerrada. El método abre una sesión utilizando por defecto el protocolo HTTP/TCP. 2.- RStringPool StrigPool(): El método permite acceso para el “string pool” propio de HTTP. Devuelve un objeto de la clase RStringPool, que se detalla más adelante. 3.- RHTTPConnectionInfo ConnectionInfo(): Permite acceso a la información de conexión de la sesión. Esta información de conexión debe ser establecida antes de que la primera transacción sea realizada. Devuelve un objeto de la clase RHTTPConnectionInfo, que se detalla más adelante, que permite estabelecer dicha información de conexión. 4.RHTTPTransaction OpenTransactionL(TUriC8 aUri, MHTTPTransactionCallBack aCallBack, RStrinF amethod): Este es el método utilizado para crear una transacción. Recibe como argumento un objeto de la clase TUriC8 que indica la url a la cual vamos a realizar la petición, un objeto de la clase MHTTPTransactionCallback que comprueba el estado de los eventos relacionados con las transacciones, y 71 Creador de un Mapa de Cobertura por último un objeto de la clase RStringF que indica el método con el que se quiere realizar dicha petición, por defecto GET. - Clase RHTTPTransaction: representa una transacción http. Esta clase encapsula a una petición http y a una respuesta http. Una transacción es asociada con una sesión por lo que debe ser creada utilizando el método CreateTransactionL. Los métodos utilizados pripios de esta clase son los sigientes: 1.- RHTTPRequest Request(): Método a través del cual obtenemos la petición en un objeto de la clase RHTTPRequest. 2.- void SubmitL(): A través de este método se solicita una transacción. El método provoca que la transacción sea hecha. 3.- void Close(): El método se utiliza para cerrar la transacción y liberar todos los recursos. 4.- RHTTPResponse Response(): Método a través del cual obtenemos la respuesta en un objeto de la clase RHTTPResponse, que se detalla más adelante. - Clase MHTTPAuthemticationCallBack: Surge la necesidad de implementar esta clase si es soportada la autentificación. Es utilizada para sustituir nombre y contraseña cuando son necesarios para autentificar. El método que se utiliza de esta clase es el siguiente: 1.- void InstallAuthenticationL(RHTTPSession aSession): Gracias a la llamada a este método la sesión que recibe como parámetro a través de un objeto de la clase RHTTPSession soporta autentificación. - Clase RHTTPHeaders: esta clase representa la colección de cabeceras asociadas con un mensaje. Estas cabeceras pueden ser creadas, leídas y modificadas. El método utilizado de esta clase es el siguiente: 1.- void SetFieldL(RString aFieldName, THTTPHdrVal aFieldvalue): El método es utilizado para establecer el campo nombre en la cabecera. Recibe como parámetros un objeto de la clase RString que 72 Creador de un Mapa de Cobertura representa el nombre del campo y un objeto de la clase THTTPHdrVal que indica el valor de dicho campo. - Clase TUriParser8: Esta clase es utilizada ya que proporciona funcionalidad a la hora de transformar un descriptor en una url. El método que se utiliza de esta clase es el siguiente: 1.- TInt Parse(TDesC8 aUri): Pasa el objeto de la clase TDesC8 a componente url. Devuelve una variable de tipo TInt que representa el código de error de Symbian OS en caso de que se produzca un problema o KErrNone si el método se ejecuta de manera correcta. - Clase RHTTPResponse: Representa una respuesta http. El método que se utiliza de esta clase es el siguiente: 1.- TInt StatusCode(): Devuelve en una variable de tipo TInt el código de estado. - Clase CCommDataBase: Esta clase permite acceder a la base de datos de las comunicaciones. Los métodos propios de esta clase que su utilizan son los siguientes: 1.- CCommDataBase* NewL(TCommDbDataBaseType type): Este método se utiliza para crear una nueva instancia de un objeto de esta clase. Al realizar la llamada a este método se acumula en la pila la referencia que devuelve el método. Recibe como parámetro una variable del tipo definido TCommDatabaseType, en mi caso utilizo EDatabaseTypeIAP. 2.-CCommsDbConnectionPrefTableView* OpenConnectionPrefTableInRankOrderLC(TCommDbConnectionDire ction dir): Se utiliza para abrir una vista de la tabla que contiene las preferencias de conexión. Devuelve la referencia a un objeto de la clase CCommsDbConnectionPrefTable que se detalla más adelante, y recibe como parámetro una variable del tipo enumerado TCommDbConnectionDirection, que en mi caso es ECommDbConnectionDirectionUnknown. 73 Creador de un Mapa de Cobertura - Clase CCommsDbConnectionprefTableView: Esta clase es utilizada para implementar cualquier tipo de acción en la tabla de preferencias de conexión. Permite al cliente establecer el orden en el que las conexiones serán atendidas. Los métodos utilizados de esta clase son los siguientes: 1.- TInt GoToFirstRecord(): Este método permite establecer la primera preferencia de conexión existente en la vista como preferencia de la conexión actual. Devuelve una variable de tipo TInt que contendrá KErrNotFound en el caso de que la tabla no tenga almacenada ninguna preferencia para la conexión o el código de error de la base de datos de conexiones en el caso de que haya ocurrido algún problema. 2.-void ReadConnectionPreferenceL (TCommDbIap ConnectionPref aPref): El método se utiliza para obtener en un objeto de la TCommDbConnectionPref, que se detalla a continuación, el IAP (punto de acceso a internet) de la preferencia de conexión actualmente seleccionada en la tabla. Este método puede provocar una salida en el código en caso de que no esté almacenada ninguna preferencia de conexión actual en la vista devolviendo KErrNotFound o en caso de que la tabla de preferencias de conexión esté vacía, devolviendo KErrUnknown. -Clase TCommDbIapConnectionPref: Esta clase encapsula la dirección y las opciones que aparecen en el cuadro de dialogo para seleccionar el IAP (punto de acceso a internet). De esta clase solo se utiliza el atributo iBearer, que es de la clase TCommDbIapBearer, que a su vez posee el atributo iIapId de tipo TUint32 que es el que interesa. - Clase TCommDbConnPref: Esta clase permite establecer una serie de preferencias a la hora de realizar una conexión. Los métodos utilizados propios de esta clase son los siguientes: 1.- void SetDialogPreference(TCommDbDialogPref aDialogPr): Este método se utiliza para establecer las preferencias de dialogo que se utilizan en la conexión. Recibe como parámetro una variable del tipo enumerado TCommDbDialogPref que en mi caso es EcommDbDialogPrefPromt, para que podamos elegir a través del 74 Creador de un Mapa de Cobertura cuadro de dialogo la forma en la que queremos establecer el punto de acceso a internet. 2.- void SetDirection(TCommDbConnectionDirection aDir): Se utiliza para establecer la dirección de la conexión. Recibe como parámetro de entrada una variable del tipo enumerado TcommDbConnectionDirection que en mi caso es ECommDbConnectionDirectionOutgoing. - Clase RHTTPConnectionInfo: A través de esta clase podemos establecer u obtener los valores utilizados de la conexión en relación con el protocolo. El método utilizado de esta clase es el siguiente: 1.- void SetPropertyL(RstringF propertyName, THTTPHdrVal, aValue): Gracias a este método podemos crear o modificar el valor de una propiedad. Recibe como parámetros un objeto de la clase RstringF que representa el nombre de la propiedad y un objeto de la clase THTTPHdrVal que indica el valor de dicha propiedad. - Clase RHTTPResponse: Esta clase representa una respuesta http. Elmétodo utilizado de esta clase es el siguiente: 1.- MHTTPDataSupplier* Body(): El método devuelve una referencia a un objeto de la clase MHTTPDataSupplier que representa el cuerpo de la transacción. Para finalizar con este apartado, la siguiente parte de la API de Symbian OS que se desarrollará a continuación es la relacionada con la obtención del nivel de cobertura GPRS. Para poder obtener este nivel, no he tenido que implementar una clase auxiliar para realizar la petición al sistema operativo, sino que aplico directamente el código necesario en la clase AppUi al igual que sucede como se comentó anteriormente con la obtención del nivel de cobertura WIFI. El código que hace posible acceder al nivel de cobertura GPRS es el siguiente: 75 Creador de un Mapa de Cobertura RConnectionMonitor monitor; monitor.ConnectL(); CleanupClosePushL(monitor); TRequestStatus status; TInt iSignalStrength; monitor.GetIntAttribute( EBearerIdGPRS, 0, KSignalStrength, iSignalStrength, status ); User::WaitForRequest(status); User::LeaveIfError(status.Int()); TInt decibelios = iSignalStrength; if(decibelios<94){ iSignalGPRS = 100; } else{ decibelios = decibelios - 94; TReal porcentaje = decibelios*4.14; iSignalGPRS = 100-porcentaje; }//cierre del else if(iSignalGPRS>100) iSignalGPRS = 100; TRealFormat iformat; TBuf<20> ibuff; ibuff.Zero(); ibuff.AppendNum(iSignalGPRS, iformat); CEikonEnv::InfoWinL(_L("Cobertura GPRS en %: "), ibuff); ibuff.Zero(); ibuff.AppendNum(iSignalStrength); CEikonEnv::InfoWinL(_L("Cobertura GPRS en dB: "), ibuff); CleanupStack::PopAndDestroy(); -Clase RConnectionMonior: Es la única clase que se utiliza en esta parte de la API de Symbian OS, permitiéndonos acceder y utilizar los servicios relacionados con redes que la plataforma s60 proporciona. La clase contiene los siguientes métodos: 76 Creador de un Mapa de Cobertura 1.- TInt ConnectL(): Este método nos permite conectar el cliente que desea realizar la petición con el servidor Connection Monitor. Devuelve una variable de tipo TInt que representa el código de error de Symbian OS en caso de que se haya producido algún fallo en la llamada o KErrNone si todo se realiza de manera satisfactoria. 2.- void GetIntAttribute(TUint aConnId, TUint aSubConnId, TUint aAttribute, TInt aValue, TRequestStatus status): Se utiliza para obtener el atributo de tipo TInt que indiquemos. Recibe como primer parámetro una variable de tipo TUint que representa el Id de la conexión, pero en mi caso utilizo la constante EBearerIdGPRS del tipo enumerado TConnMonBearerId. Como segundo parámetro recibe una variable de tipo TUint que indica el Id de la sebconexión pero en mi caso es 0. Como tercer parámetro recibe una variable de tipo TUint que representa el atributo el cual queremos obtener su valor, yo utilizo la constante KSignalStrength para indicar que quiero obtener el valor de intensidad de señal, es decir, el nivel de cobertura. Como cuarto parámetro tenemos una variable de tipo TInt donde almacenamos el valor del nivel de cobertura y por último recibe una variable de tipo TRequestStatus que almacena KErrNone si todo se realiza correctamente o el código de error de Symbian OS si se produce algún fallo. 77 Creador de un Mapa de Cobertura Capítulo 5: Manual de la Aplicación a nivel de usuario En este capítulo de la memoria me gustaría explicar el funcionamiento de la aplicación Symbian OS de este proyecto fin de carrera desde el punto del usuario final. Como he comentado en anteriores ocasiones, siempre he intentado que la aplicación fuera lo más sencillo posible de entender de forma y manera que pudiera ser utilizada por cualquier tipo de usuario sin que éste tuviera que poseer algún tipo de conocimiento adicional. A continuación se muestran a modo de guía cada uno de los pasos que debemos seguir para utilizar la aplicación de forma correcta: Al abrir la aplicación y pulsando sobre el menú “options” nos encontramos con las siguientes opciones: 78 Creador de un Mapa de Cobertura En primer lugar seleccionamos “Cobertura WLAN” para obtener el nivel de cobertura WIFI existente. El dispositivo móvil nos irá mostrando por cada red encontrada el nombre de dicha red así como su nivel de cobertura en dB, para finalmente mostrarnos el nivel medio de cobertura WLAN en % y en dB. Una vez que ejecutemos esta opción se almacena en una variable interna dicho valor. No incluyo aquí ninguna imagen de este paso puesto que he realizado esta guía con el emulador que la SDK pone a nuestra disposición y no soporta acceso a WIFI. En segundo lugar seleccionamos la opción “Cobertura GPRS” con el fin de obtener el nivel de cobertura GPRS que existe en el punto en el cual realizamos la medida. El dispositivo móvil nos mostrará el nivel de cobertura GPRS existente tanto en dB como en %, como se puede observar en las siguientes imágenes: 79 Creador de un Mapa de Cobertura Una vez realizado este paso almacenamos dicho valor de cobertura GPRS en una variable interna. El siguiente paso es seleccionar la opción “Cobertura GSM” a través de la cual obtenemos el nivel de cobertura GSM y el número de barras de cobertura que muestra el dispositivo móvil. 80 Creador de un Mapa de Cobertura Al igual que sucediera con los niveles de cobertura WIFI y GPRS, al obtener el nivel de cobertura GSM, dicho valor queda almacenado en una variable interna. Después de seleccionar esta opción en el menú, en el momento en que se produzca una variación en el nivel de cobertura GSM obtendremos una notificación indicándonos los nuevos valores actualizados. A continuación, una vez obtenidos los niveles de cobertura GSM, GPRS y WIFI, el siguiente paso es obtener las coordenadas, es decir, latitud y longitud del punto en el cual realizamos la medida de dichos niveles. Para ellos seleccionamos la opción “Obtener Latitud y Longitud” obteniendo el siguiente resultado: 81 Creador de un Mapa de Cobertura Es importante destacar que a la hora de seleccionar la opción “Obtener latitud y Longitud” esta aplicación devuelve en primer lugar la última posición que quedó almacenada en el servidor, por lo que para obtener las coordenadas de la posición actual habría que estar en movimiento y en el instante en que se encontrara un satélite irían apareciendo en pantalla cada una de las coordenadas, de forma que a medida que fuéramos avanzando estas coordenadas se irían actualizando constantemente. Una vez hecho esto, los últimos valores obtenidos son los que quedarían almacenados en variables internas. Una vez obtenidos todos los valores necesarios, el último paso de nuestra aplicación sería enviar dichos valores a la base de datos del servidor. Para llevar a cabo este paso tendríamos que seleccionar la opción “Enviar datos al Servidor”. Al ejecutar esta opción se ejecuta un método que recibe como parámetros las variables internas que almacenan cada uno de los valores necesarios y establece una conexión http con una url, mostrando el correspondiente mensaje de error en caso de que la transacción no se haya realizado correctamente o cerrándose la aplicación en caso de que todo haya ocurrido con normalidad. 82 Creador de un Mapa de Cobertura Para finalizar, desde el propio dispositivo móvil a través de http://alvaro.netne.net/moviles.htm podríamos comprobar de manera visual que se ha insertado el correspondiente marcador con su información en el mapa. 83 Creador de un Mapa de Cobertura Capítulo 6: Pruebas Con el objetivo de comprobar el correcto funcionamiento de la aplicación, he decidido realizar una serie de pruebas obteniendo los niveles de cobertura GSM, GPRS y WIFI, enviando dichos datos junto con las coordenadas GPS del punto en el que realizo la medida a la base de datos del servidor, comprobando en el mapa de la página Web que se genera el correspondiente marcador y que la información mostrada es correcta. La aplicación muestra los niveles de cobertura GSM, GPRS y WIFI así como las coordenadas GPS de cualquier punto en el que deseemos ejecutarla, pero a la hora de enviar los datos al servidor, para que las pruebas no supongan ningún coste, siempre quise realizar las medidas en una serie de puntos en los que dispusiera de una red WIFI a la cual pudiera acceder, ya que he realizado todas las pruebas utilizando como dispositivo móvil el modelo N95 de Nokia. 84 Creador de un Mapa de Cobertura La primera de las pruebas la realicé en mi casa, en la calle c/Jiménez Aranda, donde las coordenadas son: latitud 37,3868211363 y longitud 5,9808381089, obteniendo los siguientes niveles de cobertura: 71.0% de la red GSM, 66.88% de red GPRS y 69.0% de red WIFI. En la siguiente imagen se puede observar como se genera el marcador en el lugar adecuado con la correspondiente información: La segunda de las pruebas decidí llevarla a cabo en el centro de formación Diasoft, en donde actualmente estoy realizando un Máster. Este centro se encuentra en la calle c/Samuel Morse, cuyas coordenadas son: latitud 37,375816 y longitud -6,0085702, obteniendo una cobertura GSM del 85.2%, una cobertura GPRS del 83.44 y una cobertura WIFI del 100%. En la siguiente imagen se puede observar el marcador y la información asociada a él: 85 Creador de un Mapa de Cobertura La siguiente de las pruebas está realizada en la Facultad de Ciencias Económicas y Empresariales, situada en la avenida Av. Ramón y Cajal cuyas coordenadas son las siguientes: latitud 37,377740000 y longitud 5,9765466667. A la hora de medir los niveles de cobertura obtuve el siguiente resultado: para la red GSM un 99.4%, para la red GPRS un 100% y para la red WIFI un 28.9%. A continuación en la imagen se puede observar el marcador mostrando los correspondientes datos: 86 Creador de un Mapa de Cobertura En siguiente lugar, quise realizar una prueba en la escuela E.T.S. Ingeniería Informática, en la misma puerta, en la avenida Av. Reina Mercedes donde las coordenadas de dicho punto tienen el siguiente valor: latitud 37,3578916667 y longitud 7 -5,9865650000, y donde el dispositivo móvil mostraba los siguientes valores: para la red GSM el 99.4%, para la red GPRS el 100%, y en el caso de la red WIFI el 51.12%. Aquí en la siguiente imagen puede comprobarse como el marcador del mapa muestra los datos correctamente: Una vez me desplacé hasta reina Mercedes para realizar la prueba anterior, creí oportuno realizar más pruebas en algunos puntos del campus, aprovechando por supuesto la red WIFI que la universidad pone a disposición de los alumnos para enviar los datos al servidor. La siguiente prueba realiza en esta zona fue en la Facultad de Biología, en el edificio rojo. En dicho punto se obtienen las siguientes coordenadas: latitud 37,3599850000 y longitud 5,9879366667. En dicho punto los niveles de cobertura detectados por la aplicación fueron: 99.4% para la red GSM, 100% para la red GPRS y 60.0 para la red WIFI. En la imagen puede apreciarse como se genera el marcador en el lugar exacto del mapa mostrando los niveles de cobertura: 87 Creador de un Mapa de Cobertura A continuación, la siguiente prueba fue realizada también en la Facultad de Biología pero en este caso en el edificio verde. Dicho punto posee las siguientes coordenadas: latitud 37,3597700000 y longitud -5,9870100000. Una vez ejecutada la aplicación, pude obtener los siguientes niveles de cobertura: 85.2% de red GSM, 83.44% de red GPRS y 71.12% de red WIFI. A continuación se muestra en la imagen el marcador en el mapa mostrando los niveles obtenidos: 88 Creador de un Mapa de Cobertura En último lugar, para finalizar con este apartado, la E.T.S. Arquitectura fue el punto en el que decidí realizar la última de las pruebas. En dicho punto pueden obtenerse las siguientes coordenadas: latitud 37,362518333 y longitud 5,9865600000. El dispositivo móvil mostraba los siguientes niveles al ejecutar la aplicación: 99.4% para la red GSM, 100% para la red GPRS y 86.68% para la red WIFI. En la correspondiente imagen se observa en el mapa el marcador en el mapa mostrando la información relativa a dichos niveles: 89 Creador de un Mapa de Cobertura Capítulo 7: Herramientas 7.1.- Microsoft Expression Web A la hora de plantearnos el desarrollo de una aplicación Web debemos decantarnos por utilizar el software que más se adapte a nuestras necesidades. En mi caso, la página Web que realizo forma parte del proyecto al igual que la aplicación Symbian pero en ningún momento es el objetivo fundamental por lo que decidí utilizar un software fácil y rápido de entender y a la vez completo en el sentido de que me permitiera implementar todos los requisitos que debe cumplir la Web. En la actualidad existen infinitas herramientas para el diseño de páginas Web utilizando todas y cada una de las tecnologías más actuales. Para la realización de la página Web a través de la cual accedemos de una manera más visual a los niveles de cobertura obtenidos he utilizado Microsoft Expression Web. Esta herramienta se puede utilizar de forma sencilla e intuitiva, dispone de un servidor local para comprobar el resultado y funcionamiento de la Web, validando nuestro contenido contra el estándar que deseemos seguir o 90 Creador de un Mapa de Cobertura navegador sobre el que vayamos a montar nuestra aplicación. A la vez se puede obtener de forma gratuita a través de Suscripción MSDN-AA en la web de la escuela como cualquier software de Microsoft. La versión que instalé fue la v12.0.04518 con todas las opciones por defecto. 7.2.- MySQL y phpMyAdmin Debido a la necesidad de disponer de una base de datos en la que poder almacenar los niveles de cobertura GSM, GPRS y WIFI así como las coordenadas del punto en el que se obtienen dichos niveles, es necesario que el servidor del alojamiento web utilizado nos permita acceder y hacer uso de estas dos herramientas, imprescindibles para poder conectarse a la base de datos, insertar valores y recorrer dichos datos para ir generando los marcadores y la información asociada a cada marcador de manera correcta. 7.3.- Herramientas necesarias para la programación en Symbian OS En este apartado intentaré explicar cuales han sido las herramientas necesarias para conseguir programar mi aplicación en Symbian OS, así como su orden de instalación. 1. En primer lugar es necesaria la instalacion de Perl, debido a su utilización en la ejecución de algunos comandos, necesarios para la creación de algunos archivos, construir proyectos (build project) etc. Este software se puede obtener de forma totalmente gratuita a través de http://www.activestate.com/ y es conveniente siempre descargarse la versión más actual posible e instalarla con las opciones por defecto. La versión que yo he utilizado es la v5.10.0. 2. En segundo lugar tenemos que instalar Java Runtime Environment para el correcto funcionamiento de la SDK. Este software también lo podemos descargar de forma gratuita a través de http://www.sun.com/ descargándonos como siempre la versión más actual posible. En mi caso estoy utilizando la versión v1.6.0.13 es decir, version 6 update 13. 91 Creador de un Mapa de Cobertura 3. El siguiente paso es instalar el entorno de desarrollo (IDE) que vamos a utilizar para implementar la aplicación Symbian. En mi caso, elegí Carbide.c++ Express Edition como entorno de desarrollo debido a que la única manera de implementar mi aplicación es utilizando Symbian C/C++, es una versión totalmente gratuita, es el entorno más actual que existe para desarrollar aplicaciones Symbian y a la vez el más usado por la mayoría de desarrolladores de este tipo de aplicaciones. La versión que he utilizado es la v2.0.2. Este IDE puede ser descargado a través de http://www.forum.nokia.com/. 4. Una vez instalado el IDE, el siguiente paso será la instalación de la correspondiente SDK que como ya he comentado anteriormente está relacionada con la versión del sistema operativo Symbian que utiliza el dispositivo móvil en el que ejecutaremos la aplicación. A través de http://www.forum.nokia.com/devices/matrix_all_1.html podemos seleccionar el dispositivo móvil que utilizaremos y descargarnos de forma gratuita la SDK que se nos aconseja. En mi caso, al utilizar como dispositivo móvil el modelo N95 de Nokia que utiliza un sistema operativo Symbian Os v9.2 he instalado la SDK s60 3erd FP1. Una vez instaladas todas estas herramientas ya podemos comenzar a desarrollar cualquier tipo de aplicacion Symbian para nuestro dispositivo móvil. 92 Creador de un Mapa de Cobertura Capítulo 8: Aplicaciones Futuras La funcionalidad que pueden aportar las dos partes de este proyecto, es decir, tanto la aplicación Symbian como la aplicación Web está ampliamente relacionada con la necesidad del usuario de conocer los niveles de cobertura GSM, GPRS y WIFI de un punto determinado. Uno de los posibles usos de la aplicación y posiblemente el principal es obtener los niveles exactos de cobertura GSM, GPRS y WIFI que nos ofrece el operador de telefonía que estamos utilizando, para poder comprobar si realmente disponemos de la cobertura que nos garantiza. Otra posible utilidad que nos puede proporcionar la aplicación es la relacionada con un cliente que quiera contratar uno de lo servicios de internet a través de USB que actualmente ofertan los operadores de telefonía. Si el cliente quiere utilizar este servicio únicamente en un punto determinado, puede comprobar de antemano el nivel de cobertura WIFI que realmente existe en ese 93 Creador de un Mapa de Cobertura punto y en el caso de que no sea suficiente comprobar si le merece la pena o no contratar dicho servicio. También puede ser útil la aplicación para cualquier usuario que quiera comprobar la posibilidad de trabajar a distancia. Por ejemplo, una persona que trabaja realizando cualquier tarea en el campo, puede comprobar los niveles de cobertura existentes, y tantear la posibilidad de colocar un autómata que sea capaz de realizar dichas tareas comunicándose con él a través de WIFI. Otro usuario al que puede interesarle la aplicación es aquel que quiera instalar una fábrica en un determinado punto lejos de la ciudad. Antes de desplazarse a ese punto para realizar cualquier tipo de comprobación acera del nivel de cobertura existente puede acceder a través de la página Web de manera visual a dichos niveles, determinando si la zona cumple o no los requisitos deseados en cuanto a cobertura. También se pueden encontrar más utilidades a la aplicación utilizando siempre como referente la posición, para poder utilizar la aplicación a modo de localizador y los niveles de cobertura disponibles para tener siempre la opción de elegir que red queremos utilizar para enviar dicha posición. En este sentido la aplicación puede ser utilizada por una flota de camiones u otro tipo de vehículos que sean utilizados para la entrega y recogida de mercancía. A la hora de tener que especificar la localización exacta del vehículo, para tener siempre localizada la mercancía, como gracias a esta aplicación conocemos las coordenadas y los niveles de cobertura GSM, GPRS y WIFI el sistema siempre puede intentar enviar dichas coordenadas de localización a través de WIFI para ahorrar costes siempre y cuando fuera posible. En caso contrario tendría que hacer uso de la red GPRS con los costes que conlleva. Otra funcionalidad que se puede añadir a la aplicación siguiendo esta idea de poder elegir la red a la hora de mandar información relacionada con la localización es en caso de robo del dispositivo móvil. En este caso podemos enviar un sms al dispositivo móvil en cuestión para que nos envíe las coordenadas exactas de su posición actual siempre teniendo la opción de elegir la red debido a que se conocen los niveles de cobertura gracias a la aplicación. Esta idea no sólo puede ser aplicada en caso de robo del dispositivo móvil ya que puede ser utilizada para recibir información acerca de la localización de un dispositivo móvil, por ejemplo de un menor de edad por cualquier motivo, sin 94 Creador de un Mapa de Cobertura que suponga ningún coste dado que el dispositivo móvil conoce el nivel de cobertura WIFI gracias a la aplicación y por tanto puede hacer uso de este recurso. Es posible también que haya casos en los que la opción de poder elegir la red a utilizar no esté relacionada únicamente con el ahorro de costes sino que también esté relacionada con la calidad de cada red. Esta idea puede ser aplicada para aquellas empresas o personas que tengan una elevada necesidad de enviar una serie de datos y por tanto deban disponer siempre de la mejor de las redes disponibles, es decir, la red que más nivel de cobertura posea. Para llevar a cabo esta idea se podría añadir algún tipo de implementación a esta aplicación que permita al dispositivo móvil cambiar automáticamente de red en cuestión del nivel de cobertura, que tanto para GSM, GPRS y WIFI sería conocido. Por último, y para finalizar este apartado, una funcionalidad que se podría añadir en un futuro a la Web es la de poder establecer una serie de opciones a la hora de mostrar los marcadores en el mapa. Esto se podría realizar a través de una serie de campos en un formulario que nos permitiera introducir opciones para que se nos mostraran en el mapa sólo aquellos marcadores que sean de nuestro interés como por ejemplo los de una ciudad concreta, los que representen zonas donde la cobertura supera un nivel mínimo introducido, etc. 95 Creador de un Mapa de Cobertura Capítulo 9: Análisis Temporal En este capítulo intentaré mostrar un resumen aproximado del tiempo empleado en realizar este proyecto. Cuantificando este tiempo en horas se obtienen un total de 336 horas dedicadas al proyecto, las cuales se agrupan en cuatro tareas principales que son las siguientes: Investigación Dentro de este grupo podemos englobar todas las tareas previas a la implementación, desde la elección y el estudio de la tecnología a utilizar, investigación acerca del sistema operativo Symbian, entornos y lenguajes de programación adecuados, etc. En mi caso, el lenguaje de programación Symbian C++ no es de los más conocidos por lo que he necesitado un estudio en profundidad para familiarizarme con él y con el entorno de trabajo que he utilizado. Durante el desarrollo de la aplicación Symbian también se ha requerido tiempo de investigación para solventar cada una de las dudas y problemas que iban surgiendo. El tiempo empleado para esta tarea ha sido un total de 67 horas. 96 Creador de un Mapa de Cobertura Desarrollo Esta es la parte que requiere mayor inversión temporal puesto que engloba toda la fase de diseño e implementación tanto de la aplicación Symbian como de la aplicación Web. El tiempo empleado ha sido de 160 horas. Pruebas Este grupo de tareas está íntimamente relacionado con el desarrollo, ya que tras la implementación o modificación de cualquier aplicación Symbian es necesario realizar una prueba en el dispositivo móvil para comprobar que su resultado es el esperado. También se engloba aquí el tiempo empleado en probar la aplicación Symbian una vez finalizada su implementación y comprobar su resultado a través de la aplicación Web. El tiempo empleado en esta fase del proyecto ha sido de 23 horas. Documentación Aquí incluyo todo el tiempo empleado en realizar la documentación del proyecto, empleando un total de 86 horas. En el siguiente gráfico se pueden observar los porcentajes que emplean cada una de las tareas principales sobre el tiempo total del proyecto. 7% 20% 47% Investigación Documentación Desarrollo Pruebas 26% 97 Creador de un Mapa de Cobertura Capítulo 10: Conclusiones Una de las cosas que tenía bastante claras antes de elegir el proyecto fin de carrera es que debería estar basado en una idea que realmente me gustase, ya que la tarea de implementar una aplicación que no despierte demasiado interés en el desarrollador puede llegar a ser muy tediosa. Otro de los factores que influyó en mi decisión fue el lenguaje de programación. Como ya he comentado en algún apartado anterior, Java y C++ eran las dos alternativas que manejaba a la hora de elegir el lenguaje de programación en el que implementar la aplicación del proyecto fin de carrera. La idea de implementar una aplicación en Symbian C++ para dispositivos móviles que estuviera relacionada con GoogleMap, y el hecho de disponer de un dispositivo móvil adecuado para realizar las pruebas, fueron las causas que hicieron que me decantara finalmente por este proyecto fin de carrera. A través de la realización de este proyecto fin de carrera he conseguido enfrentarme por primera vez al desarrollo de una aplicación por completo desde sus inicios, tanto en la parte relacionada con Symbian OS, que era un sistema y lenguaje totalmente desconocido para mí, como en la parte 98 Creador de un Mapa de Cobertura relacionada con la aportación Web ya que aunque no era desconocida nunca antes había desarrollado una aplicación Web relacionada con GoogleMap de similares características a la de este proyecto fin de carrera. Al ser la primera vez que implementaba un proyecto de esta magnitud partiendo de cero he podido comprobar las dificultades con las que tienen que enfrentarse los desarrolladores. Este hecho hace valorar de otra forma cualquier aplicación que normalmente podemos considerar que no es muy buena, apreciando realmente todo el trabajo que hay detrás. Este proyecto tenía como objetivo inicial realizar una aplicación que funcionase sobre la mayoría de los dispositivos móviles y que mediante acceso a un GPS interno, externo o de modo manual almacenase los índices de cobertura GSM, GPRS, y WIFI en un servidor y generase un mapa de estos. Creo que es importante destacar la total consecución de este objetivo inicial sin tener que variar o eliminar algún detalle de la idea inicial y realizando la aplicación en Symbian OS de forma y manera que podamos añadir nuevas funcionalidades sin ningún tipo de problema. Otro aspecto a tener en cuenta de este proyecto es el desarrollo de una aplicación en una plataforma como es Symbian OS, que aunque se basa en C++, es un lenguaje de programación muy poco utilizado en nuestra escuela. 99 Creador de un Mapa de Cobertura Capítulo 11: Bibliografía En este apartado quiero exponer toda la documentación que he utilizado para poder desarrollar por completo este proyecto. Destacar que toda la bibliografía utilizada ha sido información electrónica, es decir, a través de internet. Para llevar a cabo la aplicación en Symbian OS y resolver cualquier tipo de duda he recurrido a los siguientes enlaces: 1.- Documentación existente en la SDK s60 3erd edition FP1 correspondiente a la versión 9.2 de Symbian OS. En esta documentación se encuentran toda la API de dicha versión de Symbian OS e infinidad de artículos, respuestas a dudas frecuentes, ejemplos de código, etc… 2.- http://www.forum.nokia.com. Esta es la página oficial en la que Nokia pone a disposición de los desarrolladores cualquier tipo de información y herramientas necesarias de manera totalmente gratuita para implementar cualquier tipo de aplicación relacionada con los dispositivos móviles. Gracias a 100 Creador de un Mapa de Cobertura este enlace he podido encontrar documentación acerca de numerosos aspectos relacionados con Symbian OS. También he podido compartir y exponer todas las dudas que me iban surgiendo a lo largo del desarrollo de este proyecto mediante sus foros. Por último este enlace también me ha permitido acceder a una sección denominada “Wiki” en la que hay multitud de ejemplos sobre código ya implementado. 3.- http://developer.symbian.com. Esta es una de las páginas oficiales de Symbian OS. A través de este enlace he podido encontrar todo tipo de documentación, artículos y tutoriales relacionados con la programación en este lenguaje. También me ha sido de utilidad para postear todas mis dudas utilizando sus foros y para encontrar una gran cantidad de códigos de ejemplo. 4.- http://www.newlc.com. Gracias a este enlace, a través de sus foros, he podido encontrar información relacionada con los problemas que iba obteniendo a lo largo del desarrollo de la aplicación en Symbian OS. A la hora de realizar el apartado de la memoria correspondiente al funcionamiento general de las redes GSM, GPRS y WIFI he recurrido al siguiente enlace: - http://es.wikipedia.org. Para poder llevar a cabo la parte de este proyecto relacionada con el acceso a la base de datos, inserción de datos en la tabla y recorrido de dichos datos, he tenido que implementar una serie de funciones utilizando PHP como lenguaje de programación. Estos enlaces me han servido de utilidad: 1.- http://www.webtaller.com. 2.- http://www.forosdelweb.com. Todo lo relacionado con GoogleMap y JavaScript, es decir, mapa, controles, marcadores y ventanas de información ha sido implementado utilizando la API de GoogleMap, a la cual podemos acceder a través de este enlace: http://code.google.com/intl/es/apis/maps/documentacion/reference.html. 101 Creador de un Mapa de Cobertura En cuanto a las páginas Web, para el uso de capas de posicionamiento y hojas de estilo de utilizado los siguientes manuales: 1.- http://www.librosweb.es/xhtml. 2.- http://www.librosweb.es/css. 102