UNIVERSIDAD DE CONCEPCIÓN Facultad de Ingeniería Departamento de Ingeniería Eléctrica Profesor Patrocinante: Dr. Mario R. Medina C. Sistema de Lectura Remota, Almacenamiento y Despliegue de Parámetros de Línea del Abonado ADSL Andrés Hernán Carrasco Sternsdorff Informe de Memoria de Título para optar al Título de Ingeniero Civil Electrónico Enero 2006 i Resumen En el presente trabajo se desarrolla una herramienta de diagnóstico de bucles de abonados ADSL, basada en la adquisición remota desde los módems, el almacenamiento y el despliegue de las SNRs de los subcanales DMT. El trabajo está compuesto por una introducción teórica al tema, donde se exponen algunos conceptos y paradigmas relacionados con la tecnología ADSL, tales como las bases de su funcionamiento, los factores que influyen en las transmisiones y la administración de los equipos involucrados, entre otros. Luego, se desarrolla un marco para la implementación y puesta a prueba de un software que tiene como propósito solucionar uno de los problemas existentes en el contexto de la prestación del servicio ADSL. El problema aludido consiste en las complicaciones y dificultades que se presentan a los proveedores a la hora de determinar las causas del deterioro del servicio, relacionadas con las condiciones del bucle del abonado. El software es seguidamente implementado y descrito en detalle. La plataforma de programación utilizada es el ambiente integrado de desarrollo (IDE) de Borland C++ Builder 6 para MS Windows de 32 bits. Posteriormente, se muestran y comentan algunos de los resultados de lecturas experimentales de las SNRs de los subcanales de transmisión, realizadas con la ayuda de la herramienta. Finalmente, se exponen conclusiones y comentarios sobre diversos aspectos relacionados con la elaboración del trabajo, los resultados obtenidos y la aplicabilidad de la herramenta desarrollada; así como también, se proponen soluciones a algunos problemas encontrados y se sugieren algunas líneas de desarrollo futuro. ii Agradecimientos Al profesor Mario R. Medina C., por su invaluable ayuda y orientación durante todo el proceso de elaboración de esta memoria de título. Al profesor Jorge E. Pezoa N., por su guía decisiva en la definición y especificación del tema desarrollado en el presente trabajo. A mis padres, por su apoyo incondicional durante mis estudios y la elaboración de esta memoria. A mi esposa, por su apoyo, paciencia y solidaridad en todo momento. iii Tabla de Contenidos Lista de Figuras................................................................................................................................. vi Lista de Listados .............................................................................................................................viii Lista de Tablas .................................................................................................................................. xi Glosario............................................................................................................................................. xii 1. Introducción ............................................................................................................................... 1 2. Marco Teórico ............................................................................................................................ 4 2.1. El concepto ADSL.............................................................................................................. 4 2.2. Arquitectura del sistema .................................................................................................. 5 2.3. Utilización del espectro de frecuencias .......................................................................... 6 2.4. Factores que influyen en las transmisiones ADSL ....................................................... 7 2.4.1. Capacidad del enlace ................................................................................................ 9 2.4.2. Atenuación ................................................................................................................. 9 2.4.3. Diámetro y longitud del cable ............................................................................... 11 2.4.4. Tomas en puente ..................................................................................................... 12 2.4.5. Ruido Blanco Gaussiano Aditivo (AWGN)......................................................... 13 2.4.6. Interferencia de Frecuencia de Radio (RFI) ......................................................... 14 2.4.7. Ruido Impulsivo...................................................................................................... 14 2.4.8. Dispersión de pulsos............................................................................................... 15 2.4.9. Diafonía..................................................................................................................... 16 2.5. Técnicas de transmisión y modulación ........................................................................ 17 2.5.1. Modulación CAP ..................................................................................................... 17 2.5.2. Modulación DMT .................................................................................................... 18 2.6. Códigos de corrección de errores y entrelazado......................................................... 22 2.7. Protocolos ......................................................................................................................... 22 2.8. Nociones sobre el funcionamiento de los módems ADSL y los DSLAMs.............. 24 iv 2.8.1. Inicialización de la conexión.................................................................................. 24 2.8.2. Monitoreo de las SNRs y bit swapping................................................................ 27 2.8.3. Administración de la ATU-R................................................................................. 29 2.8.3.1. HTTP ................................................................................................................. 30 2.8.3.2. Telnet................................................................................................................. 30 2.8.3.3. Puerto Serial (RS-232) ..................................................................................... 31 2.8.3.4. SNMP ................................................................................................................ 31 2.8.3.5. TFTP y FTP ....................................................................................................... 32 2.8.4. 3. Desarrollo ................................................................................................................................. 35 3.1. Planteamiento del problema.......................................................................................... 35 3.2. Marco de desarrollo ........................................................................................................ 37 3.3. Metodología ..................................................................................................................... 40 3.4. Elección de un módem ADSL para lecturas experimentales .................................... 41 3.5. El módem SpeedTouch Pro............................................................................................ 43 3.5.1. 4. Administración del DSLAM .................................................................................. 33 Procedimiento para la lectura de la SNR ............................................................. 44 3.6. Configuración del sistema para la realización de lecturas experimentales ............ 46 3.7. Plataforma de programación ......................................................................................... 48 Implementación ....................................................................................................................... 50 4.1. Datos generales sobre la aplicación .............................................................................. 50 4.2. Archivos utilizados ......................................................................................................... 51 4.3. Interfaz gráfica ................................................................................................................. 56 4.3.1. Ventana Principal .................................................................................................... 56 4.3.1.1. Lista de IPs de los módems (sección A) ....................................................... 57 4.3.1.2. Gráficos de las características de las SNRs (sección B) .............................. 58 4.3.1.3. Barra de menús (sección C)............................................................................ 64 4.3.1.4. Barra de herramientas (sección D) ................................................................ 66 v 4.3.1.5. Barra de información (sección E) .................................................................. 67 4.3.2. Ventana para agregar una entrada ....................................................................... 68 4.3.3. Ventana para reconfigurar una entrada............................................................... 70 4.3.4. Ventana de estado ................................................................................................... 71 4.3.5. Ventana “Acerca de Cu Line Analyzer” .............................................................. 73 4.4. Proceso de iniciación de la aplicación .......................................................................... 74 4.5. Proceso de lectura remota .............................................................................................. 78 4.5.1. 4.6. La hebra de lectura remota .................................................................................... 82 Procesos de despliegue de la información................................................................... 95 4.6.1. Lista de IPs ............................................................................................................... 95 4.6.2. Gráficos ................................................................................................................... 101 4.6.2.1. Página “Última lectura” ............................................................................... 102 4.6.2.2. Página “Archivo de lecturas en 3D”........................................................... 105 4.6.2.3. Página “Archivo de lecturas en 2D”........................................................... 113 4.6.3. Barra de información ............................................................................................ 118 4.6.4. Ventana de estado ................................................................................................. 119 4.7. Otros procesos................................................................................................................ 127 4.7.1. Adición de una entrada a la base de módems .................................................. 127 4.7.2. Eliminación de una entrada de la base de módems ......................................... 132 4.7.3. Reconfiguración de una entrada de la base de módems ................................. 135 5. Resultados de lecturas experimentales .............................................................................. 139 6. Conclusiones y comentarios ................................................................................................ 150 Bibliografía ..................................................................................................................................... 155 Anexo A. Declaraciones y funciones no incluidas en el capítulo 4..................................... 159 vi Lista de Figuras Fig. 2.1. Arquitectura de una red ADSL típica ........................................................................ 6 Fig. 2.2. Utilización del espectro de frecuencias por las técnicas EC y FDM ...................... 7 Fig. 2.3. Variación de la atenuación en función de la frecuencia de la señal..................... 11 Fig. 2.4. Toma en puente ........................................................................................................... 13 Fig. 2.5. Dispersión de pulsos ................................................................................................... 15 Fig. 2.6. Paradiafonía (NEXT) y Telediafonía (FEXT). .......................................................... 16 Fig. 2.7. Adaptación del número de bits/símbolo a las SNRs de los subcanales............... 21 Fig. 2.8. Proceso de inicialización de la conexión ADSL. ..................................................... 26 Fig. 3.1. Conjunto de archivos que debe utilizarse en el sistema ........................................ 39 Fig. 3.2. Configuración del sistema para la realización de lecturas remotas..................... 48 Fig. 4.1. Ventana principal de la aplicación............................................................................ 57 Fig. 4.2. Lista de IPs ................................................................................................................... 58 Fig. 4.3. Gráfico de la última lectura de la característica de la SNR.................................... 60 Fig. 4.4. Gráfico de la variación en el tiempo de la característica de la SNR ..................... 62 Fig. 4.5. Ventana de opciones del gráfico ............................................................................... 62 Fig. 4.6. Gráfico de la característica de la SNR leída en el instante seleccionado en la lista de fechas y horas. ................................................................................................ 64 Fig. 4.7. Barra de menús de la aplicación................................................................................ 65 Fig. 4.8. Barra de herramientas de la aplicación. ................................................................... 67 Fig. 4.9. Barra de información .................................................................................................. 68 Fig. 4.10. Ventana de diálogo para agregar una entrada a la base de módems .................. 70 Fig. 4.11. Ventana de diálogo para reconfigurar una entrada de la base de módems ....... 71 Fig. 4.12. Ventana de estado. ...................................................................................................... 73 Fig. 4.13. Ventana “Acerca de Cu Line Analyzer” .................................................................. 74 Fig. 5.1. Características de la SNR de dos conexiones ADSL ............................................ 141 vii Fig. 5.2. Cambio fuerte y repentino de las SNRs ................................................................. 143 Fig. 5.3. Variación en el tiempo de características de la SNR de dos conexiones ADSL ........................................................................................................................... 145 Fig. 5.4. Cambio en el patrón de la variación en el tiempo de la característica de la SNR de una conexión ADSL .................................................................................... 147 Fig. 5.5. Variación en el tiempo de características de la SNR de dos conexiones ADSL ........................................................................................................................... 149 viii Lista de Listados Listado 3.1. Sesión Telnet con lectura de la SNR de una línea real .................................... 46 Listado 4.1. Ejemplo de registro de un módem dentro del archivo ModemDB.txt........ 52 Listado 4.2. Contenido del archivo SpeedTouchProCmd.txt ........................................ 54 Listado 4.3. Contenido del archivo SpeedTouchProSNRKey.txt ................................. 56 Listado 4.4. Función FormCreate. ........................................................................................ 76 Listado 4.5. Función AddTimers............................................................................................ 77 Listado 4.6. Función ATimerOnTimer .................................................................................. 80 Listado 4.7. Función ReadoutSBtnClick ........................................................................... 81 Listado 4.8. Método Execute de la hebra ReadoutThread ............................................ 84 Listado 4.9. Continuación del método Execute de la hebra ReadoutThread ............. 86 Listado 4.10. Continuación del método Execute de la hebra ReadoutThread ............. 87 Listado 4.11. Funciones ATelnetClientDataAvailable y ATelnetClientSessionClosed .................................................................. 91 Listado 4.12. Función TimeoutTimerOnTimer.................................................................... 92 Listado 4.13. Función DecodeSNR............................................................................................ 94 Listado 4.14. Función FillStringsWithIPs ...................................................................... 97 Listado 4.15. Función IPListBoxClick.............................................................................. 100 Listado 4.16. Función DrawLastReadChart....................................................................... 104 Listado 4.17. Función FillCBs............................................................................................... 109 Listado 4.18. Función DrawHistoricChart....................................................................... 112 Listado 4.19. Función FillDateLB ....................................................................................... 115 Listado 4.20. Función DrawSpecChart ................................................................................ 118 Listado 4.21. Función FormCreate ....................................................................................... 120 Listado 4.22. Funciones FillGenStatusSG y FillStatusSG....................................... 122 Listado 4.23. Función StatusSGDrawCell ......................................................................... 125 ix Listado 4.24. Función AddModem ............................................................................................ 131 Listado 4.25. Función DeleteModem ..................................................................................... 134 Listado 4.26. Función SaveBtnClick................................................................................... 138 Listado A.1. Declaración de la clase TCuLAMainForm...................................................... 162 Listado A.2. Función FormDestroy del formulario TCuLAMainForm .......................... 162 Listado A.3. Función ReadingModem................................................................................... 163 Listado A.4. Función NewReadoutThreadTerminate ................................................... 163 Listado A.5. Función FromDateCBSelect ......................................................................... 164 Listado A.6. Función ToDateCBSelect.............................................................................. 165 Listado A.7. Función AddModemSBtnClick....................................................................... 165 Listado A.8. Función DelModemSBtnClick....................................................................... 166 Listado A.9. Función ReprogSBtnClick ........................................................................... 167 Listado A.10. Funciones ShowChartOptsSBClick, RightSBtnClick, LeftSBtnClick, UpSBtnClick, DownSBtnClick y CenterSBtnClick........................................................................................... 168 Listado A.11. Función DateLBClick ..................................................................................... 168 Listado A.12. Función ShowStatusSBClick....................................................................... 169 Listado A.13. Funciones ExitClick, AddClick, DeleteClick, ReconfigureClick, ReadClick, StatusClick y AboutClick ........ 170 Listado A.14. Declaración de la clase ReadoutThread .......................................................... 171 Listado A.15. Constructor de la clase ReadoutThread .......................................................... 171 Listado A.16. Función ATelnetClientSessionConnected.......................................... 172 Listado A.17. Función UpdateLabels................................................................................... 172 Listado A.18. Función UpdateLRChart ................................................................................ 172 Listado A.19. Función UpdateHistChart ........................................................................... 173 Listado A.20. Función UpdateCBs.......................................................................................... 174 Listado A.21. Función UpdateDateLB................................................................................... 175 x Listado A.22. Declaración de la clase TIPProgDlgForm ....................................................... 175 Listado A.23. Constructor de la clase TIPProgDlgForm ....................................................... 176 Listado A.24. Función SaveBtnClick del formulario TIPProgDlgForm ........................ 176 Listado A.25. Función CancelBtnClick del formulario TIPProgDlgForm.................... 177 Listado A.26. Declaración de la clase TIPReprogDlgForm................................................... 177 Listado A.27. Función CancelBtnClick del formulario TIPReprogDlgForm ............... 178 Listado A.28. Declaración de la clase TStatusForm ............................................................... 178 Listado A.29. Función FormClose del formulario TStatusForm ....................................... 178 Listado A.30. Función AddToStatusSG ................................................................................ 179 Listado A.31. Función DelFromStatusSG ........................................................................... 180 Listado A.32. Funciones GenStatusSGClick y StatusSGClick .................................. 180 Listado A.33. Función UncheckSG.......................................................................................... 180 xi Lista de Tablas Tabla 2.1. Relación entre velocidad de transferencia y diámetro y longitud del cable... 12 Tabla 2.2. Relación entre el número de bits/símbolo la SNR de un subcanal .................. 20 Tabla 4.1. Variables y objetos utilizados en el Listado 4.4. ................................................. 76 Tabla 4.2. Variables y objetos utilizados en el Listado 4.5. ................................................. 78 Tabla 4.3. Variables y objetos utilizados en el Listado 4.6. ................................................. 80 Tabla 4.4. Variables y objetos utilizados en el Listado 4.7. ................................................. 81 Tabla 4.5. Variables y objetos utilizados en los Listados 4.8, 4.9 y 4.10............................. 88 Tabla 4.6. Variables y objetos utilizados en el Listado 4.11. ............................................... 91 Tabla 4.7. Variables y objetos utilizados en el Listado 4.12. ............................................... 92 Tabla 4.8. Variables y objetos utilizados en el Listado 4.13. ............................................... 95 Tabla 4.9. Variables y objetos utilizados en el Listado 4.14. ............................................... 98 Tabla 4.10. Variables y objetos utilizados en el Listado 4.15. ............................................. 101 Tabla 4.11. Variables y objetos utilizados en el Listado 4.16. ............................................. 105 Tabla 4.12. Variables y objetos utilizados en el Listado 4.17. ............................................. 110 Tabla 4.13. Variables y objetos utilizados en el Listado 4.18. ............................................. 113 Tabla 4.14. Variables y objetos utilizados en el Listado 4.19. ............................................. 116 Tabla 4.15. Variables y objetos utilizados en el Listado 4.20. ............................................. 118 Tabla 4.16. Variables y objetos utilizados en el Listado 4.21. ............................................. 121 Tabla 4.17. Variables y objetos utilizados en el Listado 4.22. ............................................. 123 Tabla 4.18. Variables y objetos utilizados en el Listado 4.23. ............................................. 126 Tabla 4.19. Variables y objetos utilizados en el Listado 4.24. ............................................. 132 Tabla 4.20. Variables y objetos utilizados en el Listado 4.25. ............................................. 135 Tabla 4.21. Variables y objetos utilizados en el Listado 4.26. ............................................. 138 xii Glosario AAL Capa de Adaptación ATM (ATM Adaptive Layer) ADSL Línea Digital Asimétrica del Abonado (Asymmetrical Digital Subscriber Line) ATM Modo de Transmisión Asincrónica (Asynchronous Transfer Mode) ATU Unidad de Terminación ADSL (ADSL Termination Unit) ATU-C Unidad de Terminación ADSL en la Central (ADSL Termination Unit – Central Office) ATU-R Unidad Remota de Terminación ADSL (ADSL Termination Unit – Remote) AWGN Ruido Blanco Gaussiano Aditivo (Additive White Gaussian Noise) BER Tasa de Errores de Bits (Bit Error Rate) CAP Modulación Amplitud/Fase sin Portadora (Carrierless Amplitude/Phase Modulation) CLI Interfaz de Línea de Comandos (Command Line Interface) DMT Multitono Discreto (Discrete Multitone) DSL Línea Digital del Abonado (Digital Subscriber Line) DSLAM Multiplexor de Acceso DSL (DSL Access Multiplexer) EC Cancelación de Eco (Echo Cancellation) FDM Multiplexación por División de Frecuencia (Frequency Division Multiplexing) FEXT Telediafonía (Far-End Crosstalk) HDSL Línea Digital del Abonado de Alta Velocidad (High Bit-Rate Digital Subscriber Line) ISI Interferencia Intersímbolo (Intersymbol Interference) ISP Proveedor de Servicio de Internet (Internet Service Provider) LAN Red de Área Local (Local Area Network) MDF Tablero de Distribución Principal (Main Distribution Frame) xiii MIB Base de Información para la Gestión (Management Information Base) NEXT Paradiafonía (Near-End Crosstalk) POTS Telefonía Tradicional (Plain Old Telephone System) PPPoA Protocolo Punto a Punto sobre ATM (Point-to-Point Protocol over ATM) PPPoE Protocolo Punto a Punto sobre Ethernet (Point-to-Point Protocol over Ethernet) QAM Modulación de Amplitud en Cuadratura (Quadrature Amplitud Modulation) RADSL DSL con Velocidad Adaptable (Rate-Adaptive DSL) RFI Interferencia de Frecuencia de Radio (Radio Frequency Interference) SDH Jerarquía Digital Sincrónica (Synchronous Digital Hierarchy) SDSL DSL Simétrica (Symmetric DSL) SNMP Protocolo Simple de Gestión de Redes (Simple Network Management Protocol) SNR Razón Señal-Ruido (Signal-to-Noise Ratio) VDSL Línea Digital del Abonado de Muy Alta Velocidad (Very High Bit-Rate Digital Subscriber Line) WAN Red de Área Amplia (Wide Area Network) xDSL Cualquier tipo de DSL xTU-C Unidad de Terminación de xDSL en la Central (xDSL Termination Unit – Central Office) xTU-R Unidad Remota de Terminación de xDSL (xDSL Termination Unit – Remote) 1 1. Introducción 1. Inicio de numeración figuras, tablas y listados La tecnología ADSL constituye hoy en día el método más común de prestación de servicios de banda ancha a pequeñas empresas y usuarios individuales, principalmente en el ámbito de provisión de acceso a Internet. Su popularidad se debe principalmente al aprovechamiento de las plantas utilizadas por el sistema telefónico tradicional, a las cuales tienen acceso miles de millones de personas en todo el mundo, y a las velocidades de transferencia de datos relativamente altas que éstas permiten alcanzar. A medida que ésta y otras tecnologías xDSL se han ido popularizando y desarrollando, han surgido diversos desafíos a los que se han debido enfrentar las diferentes entidades involucradas en el proceso (fabricantes de equipos, organización responsables de la creación de estándares, proveedores de servicios, etc.). Uno de estos desafíos consiste en la frecuente necesidad por parte de los proveedores del servicio ADSL de realizar diagnósticos de las condiciones de los pares trenzados de cobre con el objetivo de determinar las causas de fallas en las conexiones o conocer las capacidades de los enlaces. Actualmente existen diversas técnicas para la realización de estos diagnósticos. Algunas involucran mediciones en la planta externa de algunas características de los bucles de los abonados. Otras consisten en la adquisición de información relevante a través de los sistemas de gestión de los DSLAMs o las interfaces administrativas de los módems. En este ámbito, las mediciones de los parámetros de las líneas son realizadas directamente sobre el par trenzado, el módem o el DSLAM por personal capacitado mediante el uso de instrumentos especializados. Estas mediciones pueden incluir la determinación del balance longitudinal, la característica de la atenuación, del ruido, de la razón señal-ruido (SNR), así como también pruebas de reflectometría y otras [17] [30] [31]. Basándose en los resultados, 2 los proveedores determinan las acciones que deben ser realizadas para solucionar los problemas con el servicio ADSL. Por otro lado, los sistemas de gestión de los módems ADSL y de los DSLAMs permiten obtener los resultados de las mediciones realizadas por estos equipos durante su inicialización y operación. Los parámetros disponibles desde las interfaces administrativas de los módems frecuentemente incluyen el nivel de ruido, la atenuación y la SNR [34] [35], pero éstos generalmente representan un valor promedio a lo ancho del espectro de frecuencias utilizado. Por su parte, los sistemas de gestión de los DSLAMs ponen a disposición del operador una amplia variedad de parámetros, que incluyen los mencionados y otros, tales como los bits asignados a cada subcanal, la potencia total transmitida por cada ATU-C y ATU-R [32] [33], etc. Los datos disponibles varían de un fabricante a otro, ya que no están estandarizados. Las técnicas existentes para el diagnóstico de bucles de abonados ADSL poseen algunas desventajas, dependiendo de cuál de ellas se utilice. Así, por ejemplo, pueden involucrar costos elevados, no suministrar información suficiente, requerir de una conexión activa y, en particular, no permitir el análisis del comportamiento histórico de los parámetros relevantes. En el presente trabajo se propone una técnica alternativa que elimina algunos de los inconvenientes presentes en otros métodos de realización de diagnósticos de los pares trenzados que transportan servicios ADSL. En ella se aprovechan los resultados de las mediciones de las SNRs de los subcanales de la técnica de modulación DMT, realizadas por los módems ADSL. Estos datos son adquiridos desde los módems remotamente, almacenados y desplegados a solicitud del operador, el cual los utiliza para realizar diagnósticos de los bucles de los abonados. 3 El trabajo comienza con una introducción teórica, donde se analizan las bases sobre las que se sustenta la tecnología ADSL, así como también algunas de sus características más importantes y los factores que influyen en su desempeño. En este marco teórico se hace hincapié en los aspectos relacionados con las mediciones de las SNRs realizadas por los módems ADSL y los DSLAMs y las posibilidades que ofrecen estos equipos para la lectura de los resultados. Luego, en la etapa de desarrollo, se escoge un modelo de módem que permita la lectura remota, a través de Internet, de los resultados de las mediciones de las SNRs y se escoge una plataforma de programación que cumpla con las exigencias propias del sistema desarrollado, principalmente con la necesidad de posibilitar la programación multi hebra, las conexiones Telnet y el despliegue de gráficos tridimensionales. Posteriormente, se describe detalladamente el sistema creado. Esto incluye el programa con sus funciones, los archivos utilizados por la aplicación y su interfaz gráfica. Luego, se muestran y analizan algunos resultados de lecturas remotas de las SNRs realizadas desde varios módems ADSL. Allí se despliegan diferentes características en frecuencia de las SNRs y sus variaciones en el tiempo, y el análisis hace énfasis en cómo éstas se relacionan con el desempeño de las conexiones ADSL. Finalmente, se presentan conclusiones y comentarios acerca de diversos aspectos del trabajo desarrollado, así como también se plantean recomendaciones sobre cómo pudieran ser superados algunos de los obstáculos encontrados. Igualmente, se hacen sugerencias sobre los tópicos considerados de interés a desarrollar en un trabajo futuro. 4 2. Marco Teórico 2. Inicio de numeración figuras, tablas y listados 2.1. El concepto ADSL La idea central sobre la que se basan ésta y otras tecnologías xDSL (HDSL, SDSL, VDSL, etc.) es el aprovechamiento del par trenzado de cobre, tradicionalmente utilizado por las redes telefónicas o POTS, para la transmisión de datos entre la central y los abonados. La tecnología ADSL hace uso de un rango del espectro de frecuencias que se encuentra en la parte superior del rango ocupado por el sistema telefónico, lográndose así la coexistencia, sin interferencias mutuas, de ambos servicios. Los rangos de frecuencias utilizados en ADSL para la transmisión desde la central al abonado (canal descendente) y en sentido contrario (canal ascendente) no son iguales entre sí: el primero es mucho más amplio que el segundo. Esto da como resultado una capacidad de transferencia mayor hacia el abonado que hacia la central, lo que le otorga al sistema su asimetría. A pesar de que fue concebido teniendo en cuenta una variedad de posibles aplicaciones, el objetivo principal del sistema ADSL, hoy en día, es brindar acceso a Internet a usuarios residenciales y a pequeñas empresas. Este tipo de abonados generalmente no requiere de un enlace de alta velocidad en sentido ascendente, ya que el carácter de los servicios a los que acceden habitualmente es tal que la cantidad de información que es necesario transmitir desde los servidores hacia los equipos de los usuarios es significativamente mayor que aquella en dirección contraria. 5 Dependiendo de diversos factores externos y de las características de la implementación, la tecnología ADSL permite tasas de transferencia de datos de hasta aproximadamente 640 kbps (640·103 bps) en sentido ascendente y 8 mbps (8·106 bps) en sentido descendente [27]. 2.2. Arquitectura del sistema Del lado del abonado, el par trenzado de cobre está conectado a un filtro – conocido como “splitter” – cuya función es separar la señal telefónica de la señal ADSL. La primera es enviada a los equipos telefónicos tradicionales (teléfono, fax, módem POTS, etc.) y la segunda se transmite al módem ADSL (ATU-R). Este último, a su vez, está conectado a algún equipo de red, como un enrutador (router), un conmutador (switch) o la tarjeta de un computador, siendo la tercera la alternativa la más común. En la Fig. 2.1 se muestra el esquema de conexión para un abonado con dos computadores. Existe también una variación de ADSL llamada “ADSL Lite” (o “Splitterless ADSL”) que no utiliza el filtro mencionado. No se entrará en detalles sobre esta alternativa ya que está fuera de los alcances del trabajo. En la central, existe también un splitter que divide las señales telefónica y ADSL. La primera es enviada a la red POTS y la segunda a uno de los módems (ATU-C) en un DSLAM, que es un equipo cuya función principal es concentrar las señales DSL de un grupo de abonados y enviarlas a una red digital de alta velocidad – generalmente ATM. A esta red pueden conectarse los proveedores de diversos servicios, así como también las estaciones de gestión (Fig. 2.1). 6 Fig. 2.1. Arquitectura de una red ADSL típica. 2.3. Utilización del espectro de frecuencias El sistema ADSL puede trabajar en dos modos diferentes en lo que concierne a los rangos de frecuencia utilizados por el canal descendente y el ascendente: la cancelación de eco o EC y la multiplexación por división de frecuencia o FDM [1]. En la cancelación de eco, el rango de frecuencias utilizado por el canal descendente, en su parte inferior se solapa con el del canal ascendente (Fig. 2.2). Como consecuencia, esta solución permite alcanzar velocidades de transferencia de datos desde la central al abonado mayores que con FDM, pero se caracteriza también por ser altamente sensible a la paradiafonía o NEXT (ver 2.4.9) y por la necesidad de implementar canceladores de eco. La recomendación ITU-T G.992.1 (o G.dmt) [1] sugiere utilizar el rango de frecuencias entre 25,875 y 138 kHz para el canal de subida y entre 25,875 y 1104 kHz para el canal de bajada. La multiplexación por división de frecuencia difiere de la técnica anterior en que los rangos de frecuencia utilizados para cada una de las direcciones de la transmisión no se solapan (Fig. 2.2). Gracias a esto, la conexión es prácticamente inmune a la paradiafonía y, además, 7 no se requieren canceladores de eco. Sin embargo, su principal desventaja es la limitación impuesta al canal de bajada, lo cual se traduce en velocidades menores de transferencia de datos. En este caso, el rango de frecuencias ocupado por la transmisión descendente se encuentra entre 138 y 1104 kHz, aunque, en la práctica, para evitar interferencias, se deja un segmento de frecuencias sin utilizar entre ambos canales. Debido a que generalmente hay más de un par de cobre con servicio ADSL dentro de un mismo grupo de cables, el efecto de paradiafonía es importante y por esta razón, la FDM es el método más utilizado [17]. Fig. 2.2. Utilización del espectro de frecuencias por las técnicas EC y FDM. 2.4. Factores que influyen en las transmisiones ADSL El sistema ADSL se caracteriza por poder adaptarse a las condiciones del medio de transmisión y conservar un nivel de calidad mínimo impuesto. Este nivel de calidad es definido como la máxima tasa permisible de ocurrencia de errores de bits (llamada BER), la cual, según las normas vigentes, no debe ser mayor a 10-7. De este modo, las condiciones del enlace no afectan la calidad de la transmisión, sino la velocidad de transferencia 8 máxima alcanzable o, en algunos casos, la viabilidad misma de la instalación de ADSL sobre un bucle determinado. Los factores determinantes de las condiciones del medio a las que deben adaptarse las transmisiones ADSL son de muy diversa índole. Con el objetivo de lograr una mayor claridad en su descripción, es útil dividirlos en dos categorías: Características físicas del bucle del abonado. Son factores relacionados con las características de la planta externa. Normalmente no varían en el tiempo y sus parámetros sólo cambian si se modifica físicamente la planta. Los más importantes son: la capacidad del enlace, la atenuación, el diámetro del cable, su longitud y las tomas en puente. Interferencias y distorsiones. Son elementos que afectan negativamente la señal y su ingerencia en las transmisiones generalmente varía en el tiempo. Sus fuentes son muy diversas y pueden ser externas a la planta o relacionadas con la forma en que es utilizado el medio de transmisión por la tecnología ADSL. Entre los más importantes se encuentran: el ruido blanco gaussiano aditivo (AWGN), la interferencia de frecuencia de radio (RFI), el ruido impulsivo, la dispersión de pulsos y la diafonía. A continuación se describen resumidamente los factores mencionados. Los primeros cuatro puntos, del 2.4.1 al 2.4.4, corresponden a la categoría de características físicas del bucle y los siguientes, del 2.4.5 al 2.4.9, a la categoría de interferencias y distorsiones. 9 2.4.1. Capacidad del enlace La base para el cálculo de la velocidad máxima teórica de transferencia de datos digitales a través de un medio de transmisión viene dada por el Teorema de Shannon-Hartley [17]: 1 C = BW ⋅ SNR 3 Donde: C – Capacidad, en bps. BW – Ancho de la banda de frecuencias utilizada, en Hz. SNR – Razón Señal-Ruido, en dB. Dado que el ancho de la banda de frecuencias es fijo, el parámetro que impone el límite teórico de velocidad de transferencia es la razón señal-ruido. Aún en condiciones ideales, es decir, en ausencia de interferencias y atenuación de la señal, la SNR puede sólo alcanzar valores limitados. Esto es así porque siempre existe un nivel de ruido blanco imposible de eliminar y porque existen límites para las potencias máximas de transmisión. 2.4.2. Atenuación Las señales transmitidas a través del par trenzado de cobre llegan al extremo opuesto de la línea con una amplitud mucho menor. Este efecto es conocido como atenuación o pérdidas de inserción. A medida que la potencia de la señal se aproxima a la del ruido, la SNR 10 disminuye y es, por lo tanto, menor la velocidad de transferencia de datos que puede ser alcanzada, como se deduce del Teorema de Shannon-Hartley (ver 2.4.1). La atenuación se mide en decibeles y corresponde a la relación entre la potencia de la señal recibida y la de la señal transmitida: P A = 10 log recibida Ptransmitida Nótese que A es siempre un número negativo, ya que la potencia recibida es siempre menor que la transmitida, y será cada vez más negativo mientras mayor sea la atenuación. Sin embargo, en muchas publicaciones se utilizan valores positivos de la atenuación, lo cual corresponde, en realidad, a su valor absoluto. Los principales factores que influyen en este parámetro son la longitud del cable, su diámetro y la frecuencia de la señal [21], lo cual se muestra en la Fig. 2.3. Debido a que la atenuación depende de la frecuencia, los módems pueden incrementar, dentro de ciertos límites, las potencias de transmisión de las señales en la parte alta del espectro, lo que permite alcanzar mayores velocidades de transmisión en sentido descendente. 11 Fig. 2.3. Variación de la atenuación en función de la frecuencia de la señal, para cables de diferentes longitudes y de 0,5 mm de diámetro [17]. Frecuencia en escala logarítmica. 2.4.3. Diámetro y longitud del cable En las plantas telefónicas, los cables más comunes en casi todo el mundo tienen un diámetro de 0,4 mm (26 AWG) ó 0,5 mm (24 AWG). Un cable más grueso produce una atenuación menor de la señal y, por lo tanto, un mejor desempeño del sistema ADSL, pero implica mayor costo. La longitud es igualmente un factor determinante en la atenuación que afectará la señal y, por ende, en las velocidades de transferencia que podrán ser alcanzadas, al menos teóricamente, para cada abonado. La longitud depende principalmente de la topología de la planta externa y de la distancia entre el abonado y la central. En general, se considera que, para que sea viable la instalación de ADSL, la longitud de un cable de 0,5 mm de diámetro no debería sobrepasar los 5,5 km y para uno de 0,4 mm, los 4,6 km [9] (ver Tabla 2.1). 12 Velocidad Diámetro Longitud [Mbps] [mm] [km] 1,5 ó 2 0,5 5,5 1,5 ó 2 0,4 4,6 6,1 0,5 3,7 6,1 0,4 2,7 Tabla 2.1. Estimación de la relación entre la velocidad de transferencia alcanzada y el diámetro y la longitud del cable [9]. 2.4.4. Tomas en puente Una toma en puente es un segmento abierto de par trenzado de cobre conectado en paralelo con el bucle de un abonado (Fig. 2.4). Las tomas en puente no representan un problema para las comunicaciones telefónicas y por ello, en el pasado no se realizaban esfuerzos para eliminarlas o prevenirlas y están presentes en muchas plantas externas. Generalmente son el resultado de dejar conectadas ramificaciones de los pares trenzados, que tenían como objetivo abarcar una mayor área de servicio, confiriéndole así a la planta una mayor adaptabilidad a la distribución geográfica de la demanda. Sin embargo, con el advenimiento de los sistemas modernos de comunicaciones digitales de datos que utilizan el par trenzado de cobre como medio de transmisión (como el ADSL y otros), las tomas en puente se han convertido en un factor que puede tener un impacto negativo en estos sistemas. Los principales problemas con ellas relacionados son las interferencias intersímbolo (ISI) e intrasímbolo [14], la generación de eco [16] y la atenuación de ciertas frecuencias [21]. Las primeras se deben a la generación de versiones retrasadas de símbolos que interfieren con 13 otros contiguos en el tiempo o consigo mismos. El eco, en cambio, es el resultado de una parte de la señal que regresa a la fuente. En los sistemas ADSL con FDM el eco no es una interferencia relevante, ya que los rangos de frecuencia utilizados para las transmisiones en sentido descendente y ascendente no se solapan (ver 2.3). La atenuación de ciertas frecuencias tiene lugar cuando la señal reflejada por la toma en puente retorna a la línea principal con una diferencia de fase cercana a los 180° con respecto a la señal principal. Esto sucede con las frecuencias de las señales cuya longitud de onda es cercana a 4 veces la longitud de la toma en puente [21]. Fig. 2.4. Representación de una toma en puente y el comportamiento de la señal. 2.4.5. Ruido Blanco Gaussiano Aditivo (AWGN) Este tipo de ruido se caracteriza por poseer una densidad espectral constante y una distribución gaussiana de la amplitud. Posee muy diversos orígenes; sin embargo, un factor importante que influye en el nivel de AWGN es la temperatura del par de cobre, la cual es un parámetro variante en el tiempo. 14 2.4.6. Interferencia de Frecuencia de Radio (RFI) Las transmisiones radiales AM de onda larga y media pueden interferir en las comunicaciones ADSL, afectando uno o varios segmentos relativamente angostos dentro del espectro de frecuencias utilizado por el sistema. Esto sucede principalmente cuando existen tendidos aéreos, imperfecciones en el enrollado o deficiencias en el balance longitudinal del par trenzado de cobre. Las transmisiones ADSL no son afectadas significativamente por este problema gracias a las técnicas de modulación utilizadas (ver 2.5) y a que esta forma de interferencia prácticamente no varía en el tiempo. Sin embargo, en casos particulares y en presencia de fuertes interferencias de radio, puede verse afectada la velocidad máxima de transmisión alcanzable en un servicio ADSL. Por otro lado, las comunicaciones ADSL pueden interferir en las transmisiones radiales; por esto existen normas que ponen límites a las potencias utilizadas [17]. 2.4.7. Ruido Impulsivo Corresponde a interferencias de corta duración, con densidad espectral relativamente constante en el rango de frecuencias utilizado en ADSL y, generalmente, de gran amplitud. Entre las fuentes de ruido impulsivo se encuentran: las unidades de conmutación eléctrica, las líneas de alta tensión, la caída de rayos, los pulsos transitorios en las centrales de conmutación, el discado telefónico por pulsos y las señales de timbre [17]. 15 Algunos elementos del equipamiento de la residencia del abonado pueden también generar ruido impulsivo; por ejemplo, los interruptores regulados de luz, los refrigeradores, un sistema de alarma no aislado de la red ADSL y otros. El ruido impulsivo puede degradar considerablemente la señal ADSL y son la principal causa de los llamados “errores de ráfaga”. Una técnica importante para la corrección de este tipo de errores es el entrelazado del mensaje transmitido [14] (ver 2.6). 2.4.8. Dispersión de pulsos Un símbolo que es transmitido desde un extremo del par de cobre, va sufriendo un efecto de dispersión o deformación a medida que avanza a lo largo del cable (Fig. 2.5). Esto se debe a que la función de transferencia del enlace depende de su longitud y de la frecuencia de la señal. La dispersión de pulsos conlleva a la interferencia entre símbolos contiguos en el tiempo, lo que es conocido como ISI [29]. Este problema es limitante en sistemas de alta velocidad, como el ADSL. Fig. 2.5. Representación de la dispersión de pulsos. 16 2.4.9. Diafonía La diafonía es la interferencia, por acoplamiento capacitivo, de una señal presente en un cable, en otra señal en otro cable del mismo grupo o de uno adyacente. Existen dos tipos de diafonía: la paradiafonía o NEXT y la telediafonía o FEXT. La primera ocurre cuando una señal transmitida interfiere en otra señal recibida en un mismo extremo de la línea. La segunda, en cambio, ocurre cuando una señal transmitida interfiere en otra recibida en el extremo opuesto (Fig. 2.6). De las dos, la NEXT del lado de la central es la más importante, pues allí se encuentra una mayor cantidad de cables adyacentes transportando diversos servicios [17]. La NEXT no es un factor importante de interferencia entre dos pares con ADSL con FDM, ya que los rangos de frecuencias utilizados para cada sentido de la transmisión son diferentes. Sin embargo, éste puede ser un factor limitante crucial, si dentro del mismo cable multipar, se encuentran otros tipos de servicios como ISDN, HDSL, etc. Fig. 2.6. Representación de la paradiafonía (NEXT) y la telediafonía (FEXT). 17 2.5. Técnicas de transmisión y modulación La tecnología ADSL utiliza el esquema de modulación QAM en el cual los datos son codificados mediante variaciones de la amplitud y la fase de una portadora. Asignándole a la portadora diferentes valores de amplitud y fase, es posible codificar varios bits en un solo “símbolo” que luego es transmitido a través del cable. Entonces, para que en un símbolo sean codificados n bits, son necesarios 2n pares de valores de amplitud y fase. Al conjunto de estos pares se le llama “constelación” y a la cantidad de ellos, “tamaño de la constelación”. A medida que crece el tamaño de la constelación, las variaciones de amplitud y fase entre los diferentes símbolos se hacen más pequeñas. De este modo, la cantidad de bits posibles de codificar en una portadora dependerá de la relación entre la potencia de la señal y el ruido (la SNR), cumpliendo con el requisito de que la tasa de errores de bits (BER) sea menor a 10-7 (ver 2.5.2). En un principio, existían dos tipos de técnicas de transmisión; ambas, variaciones del esquema QAM: la modulación amplitud/fase sin portadora (CAP) y la modulación multitono discreto (DMT). Sin embargo, hoy en día, la segunda es la técnica utilizada en todas las instalaciones, ya que el ANSI y la ITU la han adoptado como estándar en sus especificaciones T1.413 Issue 2 [5] y G.992.1 (G.dmt) [1], respectivamente. 2.5.1. Modulación CAP Esta técnica utiliza QAM para la modulación de la señal sobre una portadora, haciendo uso de toda la banda de frecuencias disponible. Como la portadora misma no transporta 18 información, ésta es suprimida antes de efectuarse la transmisión; de ahí el nombre de esta técnica. La modulación CAP requiere transceptores de menor grado de complejidad que la DMT, pero es menos robusta ante la presencia de algunas imperfecciones del medio, como es el caso de ruido impulsivo o interferencias de frecuencias de radio. Como se mencionó anteriormente, este tipo de modulación está hoy en día obsoleto. 2.5.2. Modulación DMT Antes de realizar la modulación propiamente dicha, el espectro hasta 1104 kHz es dividido en 256 subcanales, llamados también “subportadoras”, “bins” o “tonos”, equidistantes entre sí por 4312,5 Hz y numerados del 0 al 255. Luego, cada subcanal puede ser utilizado independientemente para la transmisión de datos mediante la modulación de su portadora central con el esquema QAM, disponiendo para ello de su respectivo ancho de banda. Según el anexo A de la recomendación ITU-T G.992.1 [1] para ADSL sobre POTS, la transmisión en sentido ascendente debe realizarse a través de los tonos comprendidos entre los números 6 y 31 (entre 25,875 y 138 kHz), y la descendente, a través de aquellos entre el 6 y el 255 (entre 25,875 y 1104 kHz), para sistemas EC, o entre el 32 y el 255 (entre 138 y 1104 kHz), para sistemas FDM. Los subcanales 16 y 64, según esta misma recomendación, están reservados para las señales de sincronización (“tonos piloto”). El rango de frecuencias ocupado por el canal 0 (entre 0 y 4312,5 Hz) es utilizado por la señal POTS y el rango entre 4312,5 Hz y 25,875 kHz, ocupado por los canales del 1 al 5, actúa como banda de transición y no es utilizado para la transmisión. 19 En la práctica, en los sistemas FDM, que son los más comunes, lo habitual es que los rangos de frecuencias utilizados no se acerquen demasiado a los extremos inferiores propuestos por la recomendación ITU, dejando así un margen mayor entre la señal telefónica y el comienzo del canal ADSL ascendente y entre éste y el canal descendente. A través de cada tono pueden ser transmitidos símbolos a una tasa de 4000 por segundo1 y cada símbolo puede transportar hasta 15 bits. La máxima cantidad de bits/símbolo que puede transportar un subcanal depende de su SNR, del margen SNR2 mínimo configurado para el sistema y de la ganancia introducida por los códigos de corrección de errores (ver 2.6). La expresión que relaciona estas cantidades es [19]: SNR − Γ b = log 2 1 + 10 10 , donde b es la capacidad del subcanal en bits/símbolo, SNR es la razón señal-ruido en dB y Γ es un valor que para una BER ≤ 10-7, es determinado por Γ[dB] = 9,8 + γ m − γ c , donde γ m es el márgen SNR mínimo (normalmente 6 dB en ADSL) y γ c es la ganancia de codificación, estimada en alrededor de 4 dB para ADSL con Reed-Solomon y codificación trellis [18] (ver 2.6). En la Tabla 2.2 se muestra la relación entre algunas cantidades de Si se cuentan los llamados “símbolos de sincronización”, que son transmitidos cada 68 símbolos que trasportan información, la tasa es de 4058,8 símbolos/segundo. 2 El margen SNR puede entenderse como la cantidad adicional de ruido que puede soportar el sistema sin que la BER supere 10-7. 1 20 bits/símbolo y la SNR del subcanal necesaria, determinada basándose en las expresiones y valores mencionados. Una de las principales ventajas de la técnica DMT es su capacidad de adaptación a las condiciones del medio y su casi óptima utilización del espectro. Esto se debe a que es posible asignar a cada subcanal una cantidad diferente de bits, adecuada a la capacidad determinada por su SNR (Fig. 2.7). Este proceso de adaptación es realizado durante la inicialización de los módems (ver 2.8.1), mediante la asignación de un número fijo de bits a cada tono, así como también durante su operación normal (“showtime”), mediante una técnica dinámica llamada “bit swapping” (ver 2.8.2). Para lograr este objetivo, los equipos efectúan mediciones de la SNR de cada subportadora en el proceso de encendido y continúan su monitoreo durante el funcionamiento. Nº de bits/símbolo SNR [dB] necesaria 2 16,6 4 23,6 6 29,8 8 35,9 10 41,9 12 47,9 14 54,0 Tabla 2.2. Relación entre el número de bits/símbolo soportado por un subcanal y su SNR, con un margen SNR mínimo de 6 dB, una ganancia de código estimada en 4 dB y una BER ≤ 10-7. 21 Fig. 2.7. Representación de la adaptación del número de bits/símbolo a la SNR de cada subcanal. 22 2.6. Códigos de corrección de errores y entrelazado El objetivo que se persigue con estas técnicas es brindarle al sistema la robustez necesaria para funcionar adecuadamente ante la presencia de imperfecciones en la transmisión, principalmente ante ruido impulsivo. Esto se logra mediante técnicas de prevención, detección y corrección de errores. Está fuera del alcance del presente trabajo analizar cada una de estas técnicas, por lo cual se presenta aquí sólo un pequeño resumen. ADSL usa tres niveles de codificación. El nivel más básico consiste en un código convolucional (codificación trellis) que es apropiado para corregir errores aleatorios pero, a la vez, puede producir errores de ráfaga durante el proceso de decodificación. En el siguiente nivel se utiliza el código de corrección de errores Reed-Solomon, el cual es muy eficiente en la detección y corrección de errores de ráfaga. El último nivel de codificación hace uso de un código de redundancia cíclica, el cual es capaz de detectar errores pero no de corregirlos [14]. Además de los códigos descritos, ADSL utiliza también la técnica de entrelazado que consiste en la reorganización del mensaje antes de la transmisión, de tal manera de que los datos normalmente contiguos son separados en el tiempo. Esto permite una mayor resistencia del sistema a errores de ráfaga. 2.7. Protocolos Prácticamente todas las implementaciones de ADSL utilizan ATM entre la ATU-R y el DSLAM. Este protocolo es también generalmente utilizado en la red de acceso de banda ancha (normalmente SDH) a la que están conectados el DSLAM, los ISP y los eventuales 23 proveedores de otros servicios. La capa de adaptación ATM (AAL) mayormente utilizada es la AAL5, orientada al tráfico de datos. Debido a los elevados costos de las interfaces ATM para el abonado individual, el protocolo imperante entre el módem ADSL y el PC (u otro equipo en la LAN) es Ethernet. Una alternativa que ha venido ganando popularidad es la conexión entre estos equipos a través del puerto USB, lo cual presenta la ventaja de prescindir del uso de tarjetas de red. Para establecer la conexión entre la ATU-R y el proveedor de servicios se ha optado generalmente por usar PPPoE o PPPoA. En el primer caso se realiza la encapsulación de PPP sobre una capa Ethernet alojada a su vez sobre la capa ATM. La segunda alternativa directamente encapsula PPP sobre la capa ATM. Independientemente del protocolo punto a punto que se utilice, es necesaria también la presencia de un servidor DHCP para la asignación de la dirección IP pública al equipo del abonado. Si el protocolo usado es el PPPoA, esta dirección es asignada al módem ADSL, el cual soporta igualmente otros protocolos de capas superiores y funciona como enrutador. En cambio, si se opta por PPPoE, lo habitual es que la IP pública sea asignada directamente a la interfaz de red del PC y el módem actúe meramente como puente en la conexión. En la actualidad, sin embargo, muchos módems tienen implementado PPPoE, lo cual permite su funcionamiento a manera de enrutador aún usando este protocolo. 24 2.8. Nociones sobre el funcionamiento de los módems ADSL y los DSLAMs 2.8.1. Inicialización de la conexión En el momento en que se establece la conexión entre la ATU-R y la ATU-C, un complejo proceso de inicialización es llevado a cabo entre ambos equipos. Este proceso, que aquí será descrito en forma resumida, consiste en cuatro etapas: “handshake”, acondicionamiento de los transceptores, análisis de canales e intercambio (Fig. 2.8). La primera etapa se rige por las recomendaciones ITU-T G.994.1 [3] y G.992.1 [1] y su objetivo es determinar el modo de operación de las ATUs (por ejemplo, ADSL sobre POTS o ADSL sobre ISDN) e intercambiar información sobre sus capacidades básicas (por ejemplo, si utilizan ATM o STM, qué rangos de frecuencia y subcanales DMT soportan, etc.). La segunda fase cumple principalmente con la función de ajustar las ganancias de los receptores y las potencias de transmisión de los transmisores para cada subcanal DMT utilizado. La base para este acondicionamiento de los transceptores es la estimación de la atenuación del bucle del abonado que es también llevada a cabo en este punto. Esta y las dos siguientes etapas de la inicialización de la conexión se rigen por la recomendación ITU–T G.992.1. En la siguiente fase (análisis de canales) la ATU-C propone a la ATU-R cuatro posibles velocidades de transmisión en orden de prioridad con el fin de aportar alternativas en caso de que ciertas velocidades no puedan ser alcanzadas. Además, las ATUs intercambian 25 información sobre algunas de sus características como el máximo número de bits por subcanal que soportan, la capacidad de utilizar cancelación de eco (EC) o codificación trellis, etc. También en esta etapa las ATUs estiman las SNRs de los subcanales DMT basándose en la generación y recepción de señales seudoaleatorias de banda ancha. La última etapa de la inicialización comprende un intercambio de una amplia variedad de información entre las ATUs y la adopción de los parámetros de configuración finales de la conexión ADSL. Es aquí donde se fijan definitivamente las velocidades de transmisión. Aparte de la velocidad, otros parámetros importantes que se establecen durante esta fase son: el número de bits por símbolo de cada subcanal, el margen SNR, los códigos de corrección de errores a utilizar, etc. Muchos de estos parámetros son fijados basándose en las mediciones de las condiciones del enlace realizadas en la fase anterior. 26 Fig. 2.8. Esquema simplificado del proceso de inicialización de la conexión ADSL. 27 Uno de los problemas que pueden surgir en el transcurso del proceso de inicialización es que la planta externa resulte no ser capaz de soportar las velocidades de transmisión requeridas, en cuyo caso la conexión final no será establecida. Cuando no existen problemas, los módems “sincronizan” y entran al estado de funcionamiento normal, llamado “showtime”. Aún cuando en un principio las ATUs sincronicen, es posible que se pierda posteriormente la conexión debido a una disminución de la calidad de la transmisión (ocasionada, por ejemplo, por alguna interferencia). Esto sucede cuando la BER sobrepasa 10-7. En ese caso, una alternativa es repetir el proceso de inicialización para así determinar nuevamente las características del medio y ajustar a ellas los parámetros de la transmisión. Sin embargo, no obstante lo anterior, en la actualidad todos los equipos ADSL están capacitados para hacer uso del bit swapping (ver 2.8.2), que en la mayor parte de los casos, elimina la necesidad de reacondicionamiento de los módems. 2.8.2. Monitoreo de las SNRs y bit swapping Durante el showtime, tanto la ATU-R como la ATU-C tienen la capacidad de monitorear constantemente el valor de la SNR de cada subportadora del canal a través del cual transmite la ATU del extremo opuesto. Este proceso es realizado con el fin de detectar situaciones en que la SNR de uno o más subcanales disminuya a un nivel por debajo del necesario para seguir transmitiendo la misma cantidad de bits/símbolo (ver 2.5.2). Cuando tiene lugar un problema como el mencionado, los módems ADSL pueden hacer uso de una técnica llamada “bit swapping”. Esta técnica consiste en la disminución del 28 número de bits/símbolo transmitidos por un subcanal y el incremento simultáneo del número de bits/símbolo de otro subcanal, en la misma cantidad en que fue disminuido el primero. De esta manera los sistemas ADSL son capaces de reaccionar activamente a las variaciones de las condiciones bajo las cuales se realiza la transmisión, sin que esto conlleve necesariamente a cambios en las velocidades o a interrupciones en el servicio. El protocolo de comunicación entre las ATUs relacionado con esta técnica se encuentra descrito en la recomendación ITU-T G.992.1 [1]. En la actualidad, prácticamente todas las ATUs pueden además ser configuradas para negociar durante el showtime, cambios dinámicos de las velocidades de transmisión en situaciones en las que las variaciones de las condiciones de la línea así lo ameriten. Estos cambios pueden tener lugar cuando ya no sea factible, mediante bit swapping, mantener las velocidades requeridas (todas las subportadoras estarían siendo utilizadas en su máxima capacidad), o cuando las condiciones del medio hayan mejorado y la conexión sea capaz de soportar velocidades mayores. Esta técnica es conocida como RADSL o DSL con velocidad adaptable. La continua medición de los valores de las SNR de los subcanales DMT por parte de los módems es crucial para lograr los objetivos del presente trabajo. Es a través del acceso remoto a estos valores que el sistema aquí desarrollado adquiere noción de las condiciones del bucle del abonado, que luego son presentadas gráficamente como una herramienta de diagnóstico. 29 2.8.3. Administración de la ATU-R El módem ADSL del lado del abonado permite configurar un abanico de parámetros necesarios para el funcionamiento del servicio. Así, por ejemplo, el tipo de encapsulación a usar (PPPoA, PPPoE, bridge u otro), los canales virtuales ATM, si se hará bit swapping, etc., son todos elementos que deben ser configurados antes de poder activar la conexión ADSL y esto es generalmente realizado por el proveedor del servicio. Existe también una serie de variables propias de la operación del servicio a las cuales es posible acceder en un módem ADSL. Algunas de ellas pueden ser, por ejemplo, las velocidades de transmisión, la cantidad de errores detectados, el número de bytes transmitidos y recibidos, las características físicas del canal como la SNR y la atenuación, etc. La cantidad y el tipo de variables de operación a las que un módem permite acceder depende en gran medida del firmware que tenga instalado (lo cual depende de su chipset y éste, a su vez, del fabricante) y de la interfaz a través de la cual se realice la gestión. Las interfaces para la administración de los módems ADSL son muy variadas; algunas de ellas son propietarias de los fabricantes, otras son herramientas estándar que hacen uso de protocolos universales. Seguidamente se analizarán las características y funcionalidades más relevantes de este segundo grupo, enfocando la atención sobre todo en lo que concierne al tema central del presente trabajo, es decir, en la capacidad que presentan de permitir el acceso remoto a los resultados de las mediciones de las SNRs de los subcanales en la línea entre el abonado y el DSLAM. 30 2.8.3.1. HTTP La mayoría de los módems ADSL del abonado permite la gestión y el monitoreo del servicio a través del protocolo HTTP, haciendo uso de algún navegador web estándar. En muchos casos es posible configurar el módem para que no permita la conexión desde la WAN a esta herramienta de administración, lo cual incrementa la seguridad pero también imposibilita su gestión remota por parte del proveedor del servicio. Además, el acceso desde la WAN al módem es sólo factible si éste no está configurado como puente, ya que en ese caso la IP pública le pertenece a la interfaz de red del PC o router del usuario. A través de este método es posible configurar diversos parámetros relacionados con la operación del servicio, así como también acceder a algunas variables dinámicas que caracterizan la transmisión en un momento determinado. Dentro de este último conjunto es habitual que se despliegue información sobre los valores promedio de la atenuación, la SNR y la potencia de transmisión, pero no sobre estos mismos valores en relación a cada subportadora por separado. 2.8.3.2. Telnet Al igual que en el caso del HTTP, casi todos los módems ADSL hoy en día ofrecen la posibilidad de acceder a su configuración y a algunas variables operacionales a través de una interfaz de línea de comandos (CLI) usando el protocolo Telnet. Es también necesario para esto que el módem tenga su propia IP del lado de la WAN y que este tipo de conexión no haya sido bloqueado, si se desea acceder a él remotamente. 31 Habitualmente este método de administración pone a disposición del usuario un rango mayor de parámetros posibles de modificar o leer que la interfaz web. Sin embargo, a cuántos y cuáles de éstos se tiene acceso, depende en gran medida del firmware. En algunas ocasiones es posible acceder a los datos sobre la atenuación, el ruido, la SNR y el número de bits de cada subcanal. Tal es el caso de los módems de Alcatel SpeedTouch Home y SpeedTouch Pro y del módem OPEN 501R de OPEN Networks, entre los estudiados en el presente trabajo. 2.8.3.3. Puerto Serial (RS-232) Unos pocos módems permiten el acceso desde el puerto serial del computador del usuario como método para realizar la configuración inicial del equipo. Cuando esta interfaz está presente, a través de ella se accede a la misma CLI que con Telnet y, por lo tanto, los parámetros y variables disponibles son los mismos que en el punto anterior. Lógicamente, este tipo de conexión no puede realizarse remotamente, de modo que no es compatible con los objetivos del trabajo. Uno de los módems que presentan esta funcionalidad es el OfficeConnect Remote 812 de 3Com. 2.8.3.4. SNMP La mayoría de los módems ADSL posee esta alternativa de gestión remota; sin embargo, existe mucha divergencia entre los distintos modelos en lo que respecta a las MIBs implementadas. 32 Todos los equipos administrados con SNMP deben manejar MIB-II, que es estándar y está descrita en RFC-1213 [11]. Por otro lado, RFC-2662 [12] define una MIB para ADSL basándose en el TR-027 [8] del DSL Forum; este estándar tiene estatus de “propuesto”. Además, cada fabricante puede implementar sus propias MIBs de acuerdo a su criterio. La MIB-II es genérica y no depende de la interfaz de transmisión del equipo gestionado, por lo tanto no posee objetos específicos de ADSL. La MIB para líneas ADSL (RFC-2662) no pone a disposición del gestor los parámetros de transmisión divididos por subcanal y su implementación en un módem en particular depende de si una de las interfaces definidas en la MIB-II es marcada como ADSL, lo cual no es siempre el caso. Por último, las MIBs propietarias dependen completamente de los fabricantes – los datos a los que se puede acceder son muy variados y no existe ningún patrón común. Como se observa, en la actualidad el acceso al módem del abonado a través de SNMP no permite, en la mayor parte de los casos, la lectura de la SNR de cada subportadora, que es el parámetro relevante en el presente trabajo, siendo la MIB del fabricante la única alternativa para la obtención de este tipo de datos. 2.8.3.5. TFTP y FTP Muchos módems tienen implementados estos protocolos (o uno de ellos) como una forma de permitir la actualización del firmware o realizar respaldos de la configuración. Sin embargo, para los efectos de este trabajo, el acceso a los archivos en el módem no posee utilidad, ya que los valores dinámicos de los parámetros que rigen la conexión ADSL no son almacenados de esta forma, sino en la memoria volátil. 33 2.8.4. Administración del DSLAM Los DSLAMs concentran datos de una gran cantidad de líneas independientes conectadas cada una de ellas a una ATU-C en módulos dentro de éstos. Generalmente son acompañados de algún tipo de plataforma de gestión propietaria del fabricante, que posee todas las funcionalidades básicas para la administración de la red digital en la central cuando ésta está compuesta por equipos de la misma firma. Otras alternativas que ofrecen habitualmente los DSLAMs son la gestión local, a través de un terminal conectado directamente al equipo, y varias formas de gestión remota, utilizando para ello protocolos como SNMP, TFTP y Telnet. Para la operación del SNMP los fabricantes implementan en el agente una amplia variedad de MIBs, algunas estándar, otras propietarias. El TFTP es generalmente usado para la manipulación de los archivos de configuración. Por último, tanto a través del terminal local como de Telnet, se accede a una interfaz de comandos que depende de la empresa creadora del equipo. No se encuentra entre los alcances del presente trabajo analizar en detalle el tipo de información que los DSLAMs ponen a disposición de los operadores para su lectura o configuración. Sin embargo, vale la pena hacer mención de algunos estándares existentes relacionados con este aspecto. La recomendación ITU-T G.997.1 [4] sugiere muchos de los elementos propios de la conexión ADSL que deben ser abarcados por un sistema de gestión en interfaz con la ATUC. Entre ellos se encuentran datos sobre errores, el desempeño y la configuración de las dos ATUs. Para ello, según esta recomendación, debe existir un intercambio de información entre ambas de tal manera que la del lado de la central tenga acceso en cada momento a los 34 parámetros de la del lado del abonado. Este intercambio se realiza por medio de mecanismos descritos en las recomendaciones ITU-T G.997.1 y G.992.1 [1]. Los estándares MIB-II (RFC-1213 [11]) y la MIB para líneas ADSL (RFC-2662 [12]) descritos en el punto 2.8.3.4 se aplican de igual manera a las ATU-Cs. Adicionalmente, el DSL Forum propone en su TR-024 [7] una MIB específica para líneas con modulación DMT a implementarse en un agente SNMP instalado en la ATU-C. Esta MIB contiene, entre otros, objetos con información sobre la atenuación, la SNR y el número de bits correspondientes a cada subcanal de la transmisión. Este estándar no posee carácter obligatorio y no todos los fabricantes lo implementan en sus productos. 35 3. Desarrollo 3. Inicio de numeración figuras, tablas y listados 3.1. Planteamiento del problema Como se mencionó en el punto 2.1, los sistemas xDSL utilizan como medio de transmisión el par trenzado de cobre que es empleado para las comunicaciones telefónicas, muchas veces con la coexistencia de ambos servicios. En el punto 2.4 se vio que el bucle del abonado está expuesto a diversas interferencias que afectan la calidad de las transmisiones ADSL. Uno de los problemas a los que se enfrentan este tipo de conexiones es que, aún cuando las unidades de terminación ADSL (ATUs) sean capaces de sincronizar en un momento dado, las condiciones variables del medio pueden repercutir en las velocidades posibles de alcanzar y, en casos más extremos, en el funcionamiento continuo del servicio. Es posible que, bajo ciertas circunstancias y en determinados momentos, no pueda ser alcanzada la velocidad que fue contratada por el abonado o que la conexión misma entre las ATUs se interrumpa por un período limitado. En estos casos, existen dos alternativas para hacer un diagnóstico del problema: La realización por parte del proveedor del servicio ADSL de mediciones en terreno de algunas de las características del medio de transmisión, como son la atenuación, el ruido y las razones señal-ruido (SNRs), a lo ancho del rango de frecuencias utilizado. La lectura de los parámetros mencionados en la primera alternativa, desde el sistema de gestión del DSLAM, si éste tiene la capacidad de desplegarlos a petición del operador. En este caso, es necesario que la conexión esté activa en el momento de la 36 lectura o bien, que el sistema sea capaz de entregar las últimas mediciones realizadas antes de la interrupción del servicio. Los dos procedimientos mencionados poseen, sin embargo, una desventaja: los datos adquiridos reflejarán sólo una instantánea de las condiciones en el momento en que fueron realizadas las mediciones. Además, el primer procedimiento tiene el evidente inconveniente que representan los gastos y complicaciones con él relacionados (como la necesidad de contar con personal capacitado para la tarea, contar con los instrumentos adecuados, la dilatación del tiempo necesario para realizar el diagnóstico, etc.). El tipo de datos obtenido mediante cualquiera de estos métodos puede ser de gran utilidad en algunas circunstancias; especialmente cuando la interferencia es fácilmente identificable3 y relativamente constante en el tiempo. Sin embargo, es posible, por ejemplo, que a determinadas horas del día, la calidad de la señal disminuya debido a cambios en la temperatura de los cables, en la frecuencia de llamadas telefónicas realizadas a través de la misma planta utilizada por el servicio ADSL, etc. Esto, sumado a algún otro tipo de interferencia (constante o variable en el tiempo), puede manifestarse como reducciones de la velocidad de transmisión y/o como interrupciones cortas del servicio. En estos casos, la información suministrada por una medición instantánea de las condiciones del medio puede no ser suficiente para la determinación de las causas del problema, y poseer información sobre la variación de éstas en el tiempo puede ser de gran ayuda para acercarse a un diagnóstico definitivo. 3 Una interferencia es fácilmente identificable si la característica de la SNR (o del ruido o de la atenuación) en el espectro de frecuencias posee un patrón que la diferencie de otros tipos de interferencia. Tal es el caso, por ejemplo, de las interferencias de frecuencia de radio (ver 2.4.6). 37 Es por estas razones que en el presente trabajo se propone un sistema para la lectura y almacenamiento, continuados en el tiempo, del parámetro más relevante en las transmisiones ADSL – la SNR de cada subportadora de la modulación DMT (ver 2.5.2). El objetivo es permitir el despliegue de esta información, a solicitud de un operador capacitado en la interpretación de este tipo de datos, para así poder realizar un diagnóstico informado de los problemas que puedan presentarse con las conexiones. 3.2. Marco de desarrollo Las lecturas de los datos mencionados en el punto anterior pueden ser realizadas desde el módem del abonado o desde el DSLAM. En el presente trabajo se opta por la primera alternativa, debido a las dificultades técnicas que representa la segunda – la lectura desde el DSLAM requeriría tener acceso irrestricto a él, lo cual conlleva severos riesgos si el equipo está siendo explotado comercialmente y en funcionamiento. La elección de esta opción impone como requisito que las lecturas sean realizadas remotamente, ya que el sistema debe monitorear constantemente las SNRs de las líneas de una gran cantidad de abonados. La aplicación realiza las lecturas remotas a través de la red Internet. Esto le otorga gran flexibilidad, pero demanda que el módem del abonado no esté configurado como puente y que posea una IP fija (o que sea posible conocer la nueva IP, cada vez que ésta cambia). Además de las lecturas remotas periódicas y su almacenamiento, es necesario que el sistema ofrezca la posibilidad de realizar lecturas de las SNRs de una determinada línea, a solicitud del operador, en cualquier instante (siempre y cuando esté activa la conexión 38 ADSL). Esta característica es de utilidad en situaciones en las que se requiere conocer las condiciones del enlace en un momento dado, independientemente de los períodos de tiempo programados. El protocolo a utilizar para la lectura desde los módems de los abonados debe ser estándar, ya que es deseable que el sistema sea fácilmente configurable para trabajar con cualquiera de estos equipos. Los protocolos disponibles que cumplen con los requisitos son HTTP, Telnet y SNMP (ver 2.8.3). Es necesario que el sistema ofrezca la posibilidad de ser fácilmente configurado para trabajar con distintos modelos de módem y protocolos de comunicación (HTTP, Telnet y SNMP). Con este fin se debe utilizar un conjunto de archivos externos a la aplicación, en los cuales estén contenidos los datos específicos de cada módem o modelo de módem, como se muestra en la Fig. 3.1. Se considera suficiente que, en la etapa de desarrollo actual, el sistema trabaje con un único modelo de módem, a través del protocolo de comunicación adecuado para éste. Esto no contradice los objetivos asumidos de lectura, almacenamiento y despliegue de las SNRs; en cambio, se evitan las complicaciones relacionadas con la necesidad de tener acceso a diversos modelos de módems. Como se verá en el punto 3.4, no son muchos los modelos que ponen a disposición del operador las SNRs de los subcanales (ver 2.8.3), lo cual limita considerablemente las alternativas de elección. 39 Fig. 3.1. Conjunto de archivos que debe utilizarse en el sistema. 40 Es importante señalar que se encuentra fuera de los alcances del presente trabajo realizar un análisis detallado de las características en frecuencia – y su variación en el tiempo – de las SNRs de líneas reales y sus posibles causas. Un análisis de esta naturaleza requeriría de un extenso estudio que, si bien podría ser de gran utilidad, se alejaría del principal objetivo del trabajo, que es la lectura remota, almacenamiento y despliegue de estos datos. 3.3. Metodología El primer paso en el desarrollo del proyecto (puntos 3.4, 3.5 y 3.6) es la elección de un modelo de módem ADSL que cumpla con el requisito de poner a disposición del usuario las mediciones de las SNRs, divididas por subcanal, a través de alguno de los protocolos mencionados en el punto anterior; así como también la determinación de la configuración del sistema para la realización de las lecturas. Seguidamente, se escoge una plataforma de programación que permita la integración de las herramientas necesarias para crear el sistema (punto 3.7). El siguiente punto es la programación misma de la aplicación (capítulo 4), la cual aprovecha el monitoreo de la SNR por parte de los módems ADSL para la adquisición de los datos (ver 2.8.2). Por último, se realizan lecturas de las mediciones de las SNRs de algunas líneas ADSL durante un período de tiempo suficiente para la observación de las variaciones de éstas en el tiempo (capítulo 5). 41 3.4. Elección de un módem ADSL para lecturas experimentales Como se ha mencionado, existen algunos requisitos que debe cumplir un módem que permita realizar lecturas experimentales de la SNR a través del sistema aquí desarrollado. Éstos son: Debe poder accederse a los resultados de las mediciones de la SNR de cada subcanal a través de HTTP, Telnet o SNMP. La conexión ADSL de la cual el módem forma parte debe poder ser configurada para que éste posea una IP fija; o, alternativamente, se debe poder tener conocimiento de su nueva IP cada vez que ésta cambie. Es necesario tener libre acceso al módem desde Internet. En la primera etapa de investigación fueron analizadas las capacidades de algunos modelos de módems. Para ello se escanearon diversos rangos de IPs públicas donde existía una elevada probabilidad de encontrar módems ADSL, en busca de equipos que tuviesen abiertos los puertos TCP 80 (HTTP) y/o 23 (Telnet). La aplicación utilizada para este efecto fue Angry IP Scanner (versión 2.21), la cual es un software libre de código abierto para los sistemas operativos MS Windows de 32 bits. Generalmente las empresas asignan a sus abonados ADSL IPs comprendidas en ciertos rangos definidos. Además, frecuentemente se asignan a estas IPs dominios que contienen la palabra “adsl” o “dsl”. Esta situación y el hecho de que es poco común que existan en un solo rango de IPs numerosos equipos con los puertos mencionados abiertos, excepto cuando se trata de módems ADSL o cablemódems, constituyeron el factor discriminante que permitió limitar la cantidad de IPs que fue necesario analizar. 42 Utilizando este procedimiento, se encontraron en Internet numerosos modelos de módems ADSL. Cada modelo encontrado fue luego analizado desde el punto de vista de las posibilidades que presentaba de entregar a través de alguna de sus interfaces de gestión las SNRs de los subcanales de transmisión. Además de HTTP y Telnet, esto incluyó el estudio de la información entregada a través de SNMP. Los modelos estudiados y sus fabricantes se mencionan en la siguiente lista: A. 3Com: OfficeConnect Remote 812. B. Alcatel: SpeedTouch Home y SpeedTouch Pro. C. Arescom: NetDSL 1000. D. Billion: BiPAC 5100. E. D-Link: DSL-504 y DSL-500G. F. DrayTek: Vigor2600. G. OPEN Networks: OPEN 501R. H. TRENDnet: E300. I. ZyXEL: Prestige 650H. De los listados, todos, excepto los módems B, poseen agentes SNMP, pero sus MIBs no tienen implementados objetos con la SNR. Los módems B, F y G permiten la lectura de los datos necesarios a través de una conexión Telnet, pero el F sólo entrega la SNR de los subcanales que están siendo utilizados para la transferencia de datos. Por último, los módems F y G despliegan la SNR a través de la interfaz web, pero sólo el segundo lo hace en forma numérica. Todos estos modelos pueden ser configurados para trabajar como enrutadores (routers), con su propia IP pública, y para permitir conexiones a sus interfaces de configuración desde la WAN. 43 Por lo expuesto y por razones prácticas (ya que se tuvo acceso a numerosos módems de este modelo y fue posible conocer sus IPs en todo momento), el que fue utilizado para realizar las lecturas experimentales de las condiciones del bucle del abonado es el SpeedTouch Pro. El protocolo usado para acceder a estos datos fue Telnet, ya que las otras posibilidades quedaron descartadas para este modelo. 3.5. El módem SpeedTouch Pro Como se mencionó, para la realización del trabajo se tuvo acceso a unidades SpeedTouch Pro. Este modelo forma parte de la familia de módems SpeedTouch, originalmente fabricada por Alcatel y actualmente por Thomson. El módem SpeedTouch Home, perteneciente también a esta familia, utiliza el mismo firmware que la versión Pro y, por lo tanto, el procedimiento de lectura de las SNRs descrito más adelante es aplicable igualmente a éste. Es importante señalar, a modo de aclaración, que cada ATU tiene la capacidad de medir las SNRs sólo del canal a través del cual transmite la ATU del otro extremo de la línea (ver 2.8.2). Es decir, la ATU-R mide las SNRs de las subportadoras del canal descendente y la ATU-C, aquellas del canal ascendente. Como se mencionó en el punto 2.8.4, existen mecanismos de intercambio de información entre las ATUs que permiten conocer las SNRs medidas en los extremos opuestos, pero no es común que se haga uso de ellos para transmitir estos datos a la ATU-R, aunque sí en sentido contrario. Por esto, la mayor parte de las veces, los módems poseen información de las SNRs del canal descendente y no las del canal ascendente. Tal es el caso de los módems a los cuales se tiene acceso para el desarrollo del presente trabajo. Esto no es considerado un problema, ya que son justamente 44 las subportadoras del canal de bajada las más expuestas a problemas de transmisión (debido a que están en la parte superior del espectro). 3.5.1. Procedimiento para la lectura de la SNR La interfaz de línea de comandos (CLI) de este equipo cuenta con dos niveles de privilegios para el usuario. En el primero de ellos, llamado “Normal”, se tiene acceso a un número limitado de comandos que permiten realizar tareas básicas de configuración. El segundo modo es llamado “Expert” y las instrucciones en él implementadas permiten acceder a una amplia variedad de datos estadísticos, de configuración, de estado, etc. Entre otros, desde este nivel es posible leer los resultados de las mediciones de las SNRs, tanto de aquellas realizadas durante el encendido, como de las realizadas durante el showtime, en el proceso de monitoreo de la calidad del canal de bajada. El acceso a través de Telnet está protegido por contraseña. Una vez autentificado el usuario, es necesario entrar al modo “Expert” para poder leer las SNRs de los subcanales. Esto se realiza introduciendo el comando EXPERT y una contraseña específica, diferente para cada equipo. Luego, se debe entrar al grupo de comandos “golden”, introduciendo golden en la línea de comandos. Para obtener las mediciones showtime de las SNRs se utiliza la instrucción operational_channel. El Listado 3.1 muestra el procedimiento en una sesión Telnet real. La secuencia descrita es utilizada por la aplicación para leer automáticamente la SNR del bucle del abonado en períodos programados de tiempo o a petición del operador. 45 ... =>EXPERT 'SpeedTouch (00-90-D0-22-28-D7)' Password : Switch to expert mode. Return to Normal mode by typing <NORMAL> >golden golden>operational_channel Operational Channel report : near end (Downstream) -------------------------------------------------1) SNR (dB) Carrier 38 : 23.1 20.1 Carrier 40 : 23.3 25.7 27.0 27.4 30.8 27.1 32.4 30.0 32.9 32.9 Carrier 50 : 32.9 32.8 33.0 32.8 32.8 32.9 32.9 32.6 32.5 32.4 Carrier 60 : 32.3 32.0 31.9 31.8 31.6 31.5 31.4 31.3 31.1 31.0 Carrier 70 : 30.8 30.8 30.6 30.6 30.4 30.4 30.3 30.1 30.0 29.6 Carrier 80 : 29.5 29.4 29.5 29.1 29.1 28.9 28.8 28.7 28.4 28.3 Carrier 90 : 28.1 27.9 27.8 27.6 27.5 27.4 27.1 26.9 26.9 26.6 Carrier 100 : 26.4 26.3 26.3 26.0 25.9 25.8 25.6 25.4 25.3 25.2 Carrier 110 : 25.0 24.9 24.8 24.6 24.4 24.3 24.3 24.1 24.1 23.8 Carrier 120 : 23.8 23.8 23.5 23.5 23.3 23.4 23.2 23.1 23.0 22.8 Carrier 130 : 22.8 22.6 22.5 22.6 22.4 22.2 21.3 14.6 21.7 22.1 Carrier 140 : 21.8 21.6 21.4 21.1 0.0 20.8 21.1 21.1 21.1 21.0 Carrier 150 : 20.9 20.5 20.6 20.3 20.1 19.4 18.9 14.8 0.0 0.0 Carrier 160 : 19.6 20.1 19.9 20.2 20.0 20.1 19.8 19.8 19.9 19.9 Carrier 170 : 19.3 19.4 19.4 19.3 20.1 19.2 19.3 19.8 19.4 19.5 Carrier 180 : 19.4 19.3 19.4 19.1 18.8 19.3 19.1 19.1 18.9 18.5 Carrier 190 : 18.6 18.7 19.1 17.9 18.5 18.3 0.0 0.0 0.0 0.0 Carrier 200 : 11.9 0.0 0.0 17.5 17.8 17.8 17.6 17.1 17.3 17.8 Carrier 210 : 17.8 16.8 18.0 17.4 17.4 17.6 17.1 17.3 17.6 17.0 Carrier 220 : 17.6 17.1 17.3 17.0 16.9 16.9 17.0 16.8 17.3 16.7 Carrier 230 : 16.9 17.0 16.2 16.7 16.4 16.8 16.8 15.8 14.9 8.6 Carrier 240 : 15.5 16.4 16.8 16.4 17.6 17.4 17.7 17.0 18.0 17.0 46 Carrier 250 : 14.8 13.1 10.0 7.1 0.0 0.0 Operational Channel report : far end (Upstream) -----------------------------------------------Data is not available. Type 'help golden' for more information. golden> Listado 3.1. Sesión Telnet con lectura de la SNR de una línea real. 3.6. Configuración del sistema para la realización de lecturas experimentales Las lecturas experimentales de las características de las SNRs fueron realizadas desde módems SpeedTouch Pro pertenecientes a abonados ADSL de ENTEL Internet. Como estos abonados poseen IPs dinámicas, que cambian cada vez que sus conexiones son inicializadas, se determinaron los rangos de IPs utilizados por la empresa para el servicio ADSL. De esta manera, durante el proceso de realización de las lecturas experimentales, cada vez que la IP de un equipo monitoreado cambiaba, era posible recorrer estos rangos con el fin de determinar su nueva IP. Para ello se creó una aplicación simple que establece sesiones Telnet con equipos SpeedTouch Pro presentes en rangos de IPs determinados y lee desde ellos información específica para cada unidad. Esta información fue utilizada para rastrear los equipos, independientemente de su IP. Para la realización de las lecturas experimentales, se escogió aleatoriamente cierto número de estos módems, con IPs contenidas en diferentes rangos. Los bucles de estos abonados están expuestos a diversas condiciones ambientales y poseen variadas características 47 físicas, lo cual permitió obtener una amplia gama de resultados que muestran diferentes patrones y comportamientos de los parámetros adquiridos. La aplicación desarrollada en el presente trabajo (Cu Line Analyzer) fue configurada para leer remotamente las SNRs de los subcanales de transmisión desde estos equipos. Las lecturas fueron realizadas ininterrumpidamente por la aplicación, desde una estación de monitoreo consistente en un PC con MS Windows 2000 conectado a Internet. El espacio de tiempo durante el cual se realizaron lecturas fue de 30 días, aunque no todos los bucles estudiados fueron monitoreados durante la totalidad de ese período. En la Fig. 3.2 se muestra una representación del sistema utilizado para la adquisición remota de las SNRs de transmisión desde módems SpeedTouch Pro de abonados de ENTEL Internet. 48 Fig. 3.2. Configuración del sistema para la realización de lecturas remotas. 3.7. Plataforma de programación Entre los requisitos impuestos al lenguaje de programación utilizado, los más importantes son que permita la programación multihebra (multi-threading), ya que la aplicación debe realizar múltiples conexiones en forma asincrónica, y que permita la incorporación de 49 herramientas para realizar conexiones Telnet y para desplegar y configurar gráficos en 2D y 3D. Para la programación de la aplicación se ha escogido el ambiente integrado de desarrollo (IDE) de Borland C++ Builder 6 para MS Windows de 32 bits, que es una plataforma que cumple con los requisitos expuestos. Este ambiente de programación tiene originalmente instalados componentes para conexiones Telnet (parte de la colección de componentes Indy) y para gráficos en 2D (componentes TeeChart); sin embargo, éstos no presentan la funcionalidad suficiente para lo que se requiere. Por esto se utiliza el cliente Telnet de la colección Internet Component Suite (ICS) [13] y una versión actualizada de los componentes TeeChart que ofrece una mayor flexibilidad de configuración y la posibilidad de graficar en 3D con datos numéricos en las tres coordenadas. La colección ICS es un conjunto de varios componentes para Borland Delphi y C++ Builder, dedicados a las comunicaciones a través de Internet. Es distribuida como freeware con código fuente a través de la página web www.overbyte.be. Entre los componentes distribuidos en el paquete se destacan clientes y servidores FTP, HTTP, SMTP, POP3, Telnet y otros. 50 4. Implementación 4. Inicio de numeración figuras, tablas y listados 4.1. Datos generales sobre la aplicación El programa aquí descrito fue desarrollado en el ambiente integrado de desarrollo (IDE) de Borland C++ Builder 6 para MS Windows de 32 bits. Debido a las razones expuestas en el punto 3.7, a éste se le instaló el grupo de componentes Internet Component Suite [13], el cual posee, entre otros, un cliente Telnet adecuado a los requisitos. Además, fue necesario actualizar el grupo de componentes TeeChart a la versión 7.02 que permite realizar gráficos tridimensionales con valores numéricos arbitrarios en los tres ejes de coordenadas. En su forma actual, el programa no utiliza el registro de Windows, no hace uso de bibliotecas dinámicas especiales y no necesita cambiar de ningún modo la configuración del sistema, por lo que, una vez creado el archivo ejecutable, éste puede ser ejecutado inmediatamente. La aplicación utiliza un conjunto de varios archivos durante su ejecución que deben encontrarse en la misma carpeta que el ejecutable. Las características de éstos se describen en el punto 4.2. La aplicación es del tipo SDI (Single Document Interface). Por lo tanto, posee sólo ventanas de diálogo y todos sus formularios son creados en el momento de iniciación. Otro aspecto que merece mención es la utilización de múltiples hebras de ejecución por parte de la aplicación. Cada hebra es responsable de un proceso de lectura remota de las SNRs desde un módem y es iniciada automáticamente por un temporizador o 51 manualmente por el usuario. En un momento determinado puede haber varias hebras ejecutándose, lo cual requiere del uso de mecanismos de coordinación, los cuales son analizados en el punto 4.5. 4.2. Archivos utilizados Para su funcionamiento, la aplicación utiliza un conjunto de archivos externos a ella. Esto le confiere cierto grado de independencia de los modelos de módems con los cuales trabaja. De esta manera, no es necesario cambiar y recompilar el código del programa cada vez que se deba trabajar con un nuevo modelo de módem. La otra razón es la necesidad de almacenar datos específicos de cada módem desde el cual se realizan las lecturas remotas. Todos los archivos utilizados por la aplicación se encuentran en la misma carpeta que el ejecutable. A continuación se describen las características y propósitos de cada uno de ellos. ModemDB.txt Los datos básicos necesarios para realizar las lecturas de las SNRs de los módems se encuentran en este archivo, al cual, en adelante, se hará referencia como “base de módems”. En ella, a cada módem desde el cual se realizan lecturas, le corresponden 5 líneas en código ASCII (ver Listado 4.1), lo cual representa una “entrada” en la base de módems. La primera línea representa la IP del módem; la segunda, el modelo; la tercera, el nombre del usuario; la cuarta, la contraseña y la quinta, el intervalo entre las lecturas remotas en días, horas y minutos. Cada línea está precedida de un código de dos letras y el carácter “:”. 52 ... IP:201.18.105.101 MM:SpeedTouch Home o Pro UN:EXPERT PW:2036777042 RF:00.01.30 ... Listado 4.1. Ejemplo de registro de un módem dentro del archivo ModemDB.txt. SNR*.snr Existe uno de estos archivos por cada módem programado. En el nombre, el asterisco es ocupado por la IP del módem, sin sus puntos (por ejemplo, SNR20118105101.snr). En este archivo (al cual, en adelante, se hará referencia como “archivo de SNRs”) se registran todas las SNRs leídas desde un módem específico, así como también la fecha y hora en que se realizó cada lectura. El formato de los datos es binario y cada entrada consiste en una representación numérica de la fecha y la hora y 256 valores decimales de las SNRs de cada subcanal. *Cmd.txt El asterisco en este caso corresponde al nombre de un modelo de módem (por ejemplo, SpeedTouchProCmd.txt) y existe uno de estos archivos por cada tipo de módem con que la aplicación esté trabajando. En estos archivos se encuentran programadas las secuencias necesarias para la comunicación por Telnet con el módem, de acuerdo a un simple lenguaje script creado con ese fin. 53 Este lenguaje posee 4 instrucciones: <WaitFor:> - La hebra de lectura espera hasta recibir del servidor la cadena de caracteres de la línea siguiente a la instrucción antes de realizar cualquier otra acción. <Send:> - El cliente Telnet envía al servidor la cadena de caracteres de la línea siguiente a la instrucción o la contraseña programada para el módem, si la siguiente línea es “<SendPwd>”. <StoreSNRtil:> - La aplicación almacena en un búfer todo lo que recibe del servidor Telnet hasta que encuentra la cadena de caracteres de la línea siguiente a la instrucción. Aunque puede hacerlo con cualquier tipo de datos, este comando está pensado para almacenar aquellos que contengan las SNRs. <Disconnect> - El cliente Telnet se desconecta del servidor. Como el programa trabaja por el momento con un sólo modelo de módem, se tiene también sólo un archivo de este tipo – el SpeedTouchProCmd.txt (ver Listado 4.2). <WaitFor:> User : <Send:> EXPERT <WaitFor:> Password : <Send:> <SendPwd> <WaitFor:> => <Send:> 54 EXPERT <WaitFor:> Password : <Send:> <SendPwd> <WaitFor:> > <Send:> golden <WaitFor:> golden> <Send:> operational_channel <WaitFor:> Carrier 38 : <StoreSNRtil:> golden> <Disconnect> Listado 4.2. Contenido del archivo SpeedTouchProCmd.txt. Script utilizado para la lectura de la SNR desde un módem SpeedTouch Pro a través de Telnet. *SNRKey.txt Como respuesta a las comandos ya descritos, cada modelo de módem envía las SNRs de los subcanales con un formato propio, el cual está pensado en función de que éstas serán leídas por un usuario en una consola o terminal. Por esto es necesario extraerlas de los datos “en bruto” que son recibidos por el cliente en una sesión de Telnet y que son almacenados con la instrucción <StoreSNRtil:>, mencionada más arriba. La función de este archivo es constituir una pauta de cómo extraer la SNR de estos datos “en bruto”. Existe uno para cada modelo de módem con el cual la aplicación esté trabajando y el asterisco corresponde al nombre de ese modelo. A este archivo se hará referencia, en adelante, como “pauta” (para la extracción de las SNRs de los subcanales). 55 La estructura del archivo es tal que en él se encuentran, en el mismo orden, los mismos caracteres que se espera recibir desde el módem en la etapa del proceso de comunicación donde éste envía los valores de las SNRs de los subcanales, excepto en las posiciones en las que se espera recibir uno de estos valores. En esas posiciones, en el archivo figura una secuencia que empieza con el carácter “¤” y continúa con 3 valores alfanuméricos que representan el número del subcanal al cual corresponde la SNR; por ejemplo, “¤193”, corresponde a la cadena de caracteres en la pauta, donde se espera recibir la SNR del subcanal 193. Por las mismas razones discutidas anteriormente, en este caso existe sólo un archivo de este tipo – el SpeedTouchProSNRKey.txt –, el cual se muestra en el Listado 4.3. Carrier 38 : ¤038 ¤039 Carrier 40 : ¤040 ¤041 ¤042 ¤043 ¤044 ¤045 ¤046 ¤047 ¤048 ¤049 Carrier 50 : ¤050 ¤051 ¤052 ¤053 ¤054 ¤055 ¤056 ¤057 ¤058 ¤059 Carrier 60 : ¤060 ¤061 ¤062 ¤063 ¤064 ¤065 ¤066 ¤067 ¤068 ¤069 Carrier 70 : ¤070 ¤071 ¤072 ¤073 ¤074 ¤075 ¤076 ¤077 ¤078 ¤079 Carrier 80 : ¤080 ¤081 ¤082 ¤083 ¤084 ¤085 ¤086 ¤087 ¤088 ¤089 Carrier 90 : ¤090 ¤091 ¤092 ¤093 ¤094 ¤095 ¤096 ¤097 ¤098 ¤099 Carrier 100 : ¤100 ¤101 ¤102 ¤103 ¤104 ¤105 ¤106 ¤107 ¤108 ¤109 Carrier 110 : ¤110 ¤111 ¤112 ¤113 ¤114 ¤115 ¤116 ¤117 ¤118 ¤119 Carrier 120 : ¤120 ¤121 ¤122 ¤123 ¤124 ¤125 ¤126 ¤127 ¤128 ¤129 Carrier 130 : ¤130 ¤131 ¤132 ¤133 ¤134 ¤135 ¤136 ¤137 ¤138 ¤139 Carrier 140 : ¤140 ¤141 ¤142 ¤143 ¤144 ¤145 ¤146 ¤147 ¤148 ¤149 Carrier 150 : ¤150 ¤151 ¤152 ¤153 ¤154 ¤155 ¤156 ¤157 ¤158 ¤159 Carrier 160 : ¤160 ¤161 ¤162 ¤163 ¤164 ¤165 ¤166 ¤167 ¤168 ¤169 Carrier 170 : ¤170 ¤171 ¤172 ¤173 ¤174 ¤175 ¤176 ¤177 ¤178 ¤179 Carrier 180 : ¤180 ¤181 ¤182 ¤183 ¤184 ¤185 ¤186 ¤187 ¤188 ¤189 Carrier 190 : ¤190 ¤191 ¤192 ¤193 ¤194 ¤195 ¤196 ¤197 ¤198 ¤199 Carrier 200 : ¤200 ¤201 ¤202 ¤203 ¤204 ¤205 ¤206 ¤207 ¤208 ¤209 Carrier 210 : ¤210 ¤211 ¤212 ¤213 ¤214 ¤215 ¤216 ¤217 ¤218 ¤219 Carrier 220 : ¤220 ¤221 ¤222 ¤223 ¤224 ¤225 ¤226 ¤227 ¤228 ¤229 56 Carrier 230 : ¤230 ¤231 ¤232 ¤233 ¤234 ¤235 ¤236 ¤237 ¤238 ¤239 Carrier 240 : ¤240 ¤241 ¤242 ¤243 ¤244 ¤245 ¤246 ¤247 ¤248 ¤249 Carrier 250 : ¤250 ¤251 ¤252 ¤253 ¤254 ¤255 Listado 4.3. Contenido del archivo SpeedTouchProSNRKey.txt. Pauta para la extracción de las SNRs de los datos recibidos por la aplicación en una sesión Telnet (compárese con el Listado 3.1). 4.3. Interfaz gráfica 4.3.1. Ventana Principal La ventana principal de la aplicación consiste en un formulario (llamado CuLAMainForm en el código del programa) dividido en las secciones marcadas en la Fig. 4.1 con las letras de la A a la E y explicadas a continuación. 57 Fig. 4.1. Ventana principal de la aplicación con sus secciones marcadas. 4.3.1.1. Lista de IPs de los módems (sección A) Bajo el título “IP” se encuentra la lista de las IPs (Fig. 4.2) de todos los módems en la base de módems, cuyas características de la SNR son leídas y almacenadas periódicamente o a solicitud del operador. Las IPs se listan en orden ascendente y son seleccionables individualmente. Cuando una IP es seleccionada, se despliega en la sección B el gráfico apropiado (ver 4.3.1.2) de la característica de la SNR de la línea y se actualiza la información en la sección E (ver 4.3.1.5). La lista de las IPs está contenida en un componente TListBox, llamado IPListBox. 58 Fig. 4.2. Sección de la ventana principal con la lista de IPs de los módems desde los cuales son realizadas lecturas remotas. 4.3.1.2. Gráficos de las características de las SNRs (sección B) Aquí se despliegan los gráficos de las características de las SNRs leídas desde el módem cuya IP se encuentra seleccionada en la sección A (ver 4.3.1.1). La aplicación cuenta con 3 modos diferentes de desplegar esta información: el primero despliega sólo la característica 59 de la SNR correspondiente a la última lectura realizada desde el módem; el segundo, grafica las características de las SNRs correspondientes a lecturas sucesivas en un rango determinado de tiempo, en un gráfico tridimensional; y el tercero despliega cualquiera de las características archivadas de una línea determinada. La selección del modo utilizado para el despliegue de las características de la SNR se realiza presionando la pestaña correspondiente de un componente TPageControl, llamado OutputPageControl. El componente tiene 3 páginas – una para cada forma de presentar la información – que son descritas a continuación. Página “Última lectura” En esta página – mostrada en la Fig. 4.3 – se despliega el gráfico de la última lectura realizada de la característica de la SNR (en dB) en función de la frecuencia (en kHz). El gráfico corresponde a la característica del par tranzado conectado al módem seleccionado en la sección A (ver 4.3.1.1). El valor máximo en la escala del eje de las ordenadas se ajusta automáticamente al valor máximo adoptado por la característica de la SNR. En el título del gráfico – desplegado en su parte superior – se muestra la fecha y la hora en que esta lectura fue realizada. Esta es la página desplegada al iniciarse la aplicación. El gráfico utilizado es un componente TChart, llamado LastReadChart, con una serie de datos del tipo TLineSeries de nombre LastSNRSeries y se encuentra sobre una página del OutputPageControl, llamada LastReadTabSheet. El título es un componente TLabel con el nombre de LastReadInfoLbl. 60 Fig. 4.3. Sección de la ventana principal con el gráfico de la última lectura de la característica de la SNR leída desde el módem, cuya IP se encuentra seleccionada. Página “Archivo de lecturas en 3D” Aquí se despliega la característica de la SNR (en dB) en función de la frecuencia (en kHz) y del tiempo, en forma de un gráfico tridimensional (Fig. 4.4). En este gráfico se puede observar las variaciones en el tiempo de la característica de la SNR de una línea que haya sido monitoreada durante un cierto período. A través de una ventana de opciones (Fig. 4.5), es posible seleccionar – dentro del rango durante el cual hayan sido realizadas lecturas desde el módem – el espacio de tiempo desplegado. También desde allí es posible rotar arbitrariamente el gráfico. La ventana de 61 opciones puede ser mostrada u ocultada mediante un botón en la parte superior izquierda de la página. El gráfico tridimensional es un componente TChart, llamado HistoricChart, con una serie de datos del tipo TSurfaceSeries, de nombre HistoricSNRSeries. La ventana de las opciones del gráfico es un componente TPanel, llamado ChartOptsPanel, que contiene dos componentes TComboBox, llamados FromDateCB y ToDateCB, cuyos elementos seleccionados determinan los límites del período a graficar (el primero, el límite más antiguo y el segundo, el más reciente). Esta ventana contiene también 5 componentes TSpeedButton, 4 de ellos utilizados para rotar el gráfico y 1 para devolverlo a su posición original. Los nombres de estos componentes son: RightSBtn, LeftSBtn, UpSBtn, DownSBtn y CenterSBtn. El botón utilizado para mostrar u ocultar la ventana de opciones es también un componente TSpeedButton, de nombre ShowChartOptsSB, que puede adoptar el estado de presionado y de no presionado. Los elementos gráficos mencionados se encuentran sobre una página del OutputPageControl, llamada HistoricTabSheet. 62 Fig. 4.4. Sección de la ventana principal con el gráfico de la variación en el tiempo de la característica de la SNR, leída desde el módem, cuya IP se encuentra seleccionada. Fig. 4.5. Ventana de opciones del gráfico. A la izquierda, botón utilizado para mostrar u ocultar la ventana. A la derecha, ventana de opciones desplegada. 63 Página “Archivo de lecturas en 2D” Esta página está dividida en dos partes, como se observa en la Fig. 4.6. A la izquierda se encuentra una lista, ordenada en forma ascendente, de las fechas y horas en que fueron realizadas todas las lecturas archivadas de las características de las SNRs de la línea conectada al módem, cuya IP se encuentra seleccionada. Los elementos de esta lista pueden ser seleccionados individualmente con el fin de desplegar el gráfico de la característica de la SNR leída en ese momento. El gráfico se encuentra en la parte derecha de la página y es similar al de la página “Última lectura”. La diferencia con éste, además del instante en que fue leída la característica de la SNR, es que la escala del eje de las ordenadas no se ajusta automáticamente al valor máximo de esta característica. Esto facilita la observación de las diferencias entre diferentes lecturas al seleccionar alternadamente distintos elementos de la lista de fechas y horas. En el título del gráfico – desplegado en la parte superior de éste – se muestra la fecha y la hora en que fue realizada la lectura cuya característica de la SNR se encuentra desplegada. La lista de fechas y horas está contenida en un componente TListBox llamado DateLB. El gráfico es un componente TChart, con el nombre de SpecReadChart, con una serie de datos del tipo TLineSeries, llamada SpecSNRSeries. Tanto la lista de fechas y horas, como el gráfico, se encuentran sobre una página del OutputPageControl llamada SpecTabSheet. 64 Fig. 4.6. Sección de la ventana principal donde se despliega el gráfico de la característica de la SNR leída desde el módem, cuya IP se encuentra seleccionada, en el instante seleccionado en la lista de fechas y horas. 4.3.1.3. Barra de menús (sección C) La barra contiene 4 menús desplegables: “Archivo”, “Módem”, “Ver” y “Ayuda” (Fig. 4.7), los cuales son descritos a continuación. Los menús y sus ítems guardan relación con las características actuales de la aplicación, pero son fácilmente ampliables si ésta adopta nuevas funcionalidades. La barra y sus menús se encuentran encapsulados en un componente TMainMenu, llamado MainMenu. 65 Fig. 4.7. Barra de menús de la aplicación. Menú “Archivo” Ítem “Salir”: Finaliza la ejecución de la aplicación. Este comando es también accesible a través de la combinación de teclas Ctrl+Q o Alt+A+S. Menú “Módem” Desde este menú se accede a los comandos relacionados con la interacción de la aplicación con los módems ADSL. Ítem “Agregar...”: Abre una ventana de diálogo (ver 4.3.2) a través de la cual es posible añadir una entrada a la base de módems desde los cuales la aplicación realiza lecturas remotas. La misma acción es ejecutable a través de la combinación de teclas Ctrl+M o Alt+M+A. Ítem “Eliminar...”: Elimina de la base de módems la entrada correspondiente a aquel, cuya IP se encuentra seleccionada en la lista de la sección A (ver 4.3.1.1). La misma acción puede ser ejecutada mediante la tecla Del o la combinación Alt+M+E. Ítem “Reconfigurar...”: Abre una ventana de diálogo (ver 4.3.3) desde donde es posible reconfigurar la entrada de la base de módems correspondiente a aquel, cuya IP se encuentra seleccionada. A través de la combinación de teclas Ctrl+R o Alt+M+R es posible ejecutar esta misma acción. 66 Ítem “Realizar lectura”: Inicia un proceso de lectura remota para obtener la característica de la SNR desde el módem cuya IP se encuentra seleccionada. Lo mismo es realizable a través de la combinación de teclas Ctrl+L o Alt+M+L. Menú “Ver” Ítem “Ventana de estado”: Despliega u oculta la ventana de diálogo (ver 4.3.4) donde se muestra el estado de las conexiones con los módems y el número de entradas en la base de módems. A la izquierda de este ítem del menú se muestra una marca si la ventana de estado se encuentra desplegada. Las combinaciones de teclas Ctrl+E y Alt+V+S realizan la misma acción. Menú “Ayuda” Ítem “Acerca de Cu Line Analyzer...”: Despliega una ventana de diálogo con información sobre la aplicación (ver 4.3.5). 4.3.1.4. Barra de herramientas (sección D) La barra de herramientas contiene 5 botones (Fig. 4.8) que corresponden a algunos de los ítems de los menús descritos en el punto anterior. En orden de izquierda a derecha, las funciones de estos botones son: añadir una entrada a la base de módems (corresponde al ítem “Agregar...” del menú “Módem”); eliminar una entrada (corresponde al ítem “Eliminar” del menú “Módem”); reconfigurar una entrada (corresponde al ítem “Reconfigurar...” del menú “Módem”); realizar una lectura remota de la característica de la 67 SNR (corresponde al ítem “Realizar lectura” del menú “Módem”); y desplegar u ocultar la ventana de estado (corresponde al ítem “Ventana de estado” del menú “Ver”). Este último botón adopta las posiciones de presionado y no presionado, dependiendo de si la ventana de estado se encuentra desplegada u oculta, respectivamente. Cada botón despliega un comentario explicativo sobre su función cuando el usuario posiciona el cursor sobre él. La barra de herramientas es un componente TToolBar, llamado ToolBar, y contiene 5 componentes TSpeedButton, correspondientes a los 5 botones, llamados AddModemSBtn, DelModemSBtn, ReprogSBtn, ReadoutSBtn y ShowStatusSB, de acuerdo a sus posiciones de izquierda a derecha en la barra. Fig. 4.8. Barra de herramientas de la aplicación. 4.3.1.5. Barra de información (sección E) Aquí se despliega la información relevante relacionada con la entrada de la base de módems, correspondiente al módem cuya IP se encuentra seleccionada en la lista de la sección A (ver 4.3.1.1). La información incluye el modelo del módem, el nombre del usuario programado y el intervalo programado entre las lectura remotas automáticas de la característica de la SNR (Fig. 4.9). 68 Los datos sobre el modelo del módem, el usuario y el intervalo se despliegan en 3 componentes TEdit, no editables, llamados ModModelEdit, UserEdit y FreqEdit, respectivamente. Fig. 4.9. Barra de información. 4.3.2. Ventana para agregar una entrada Esta ventana de diálogo (Fig. 4.10) es desplegada ya sea seleccionando el ítem “Agregar...” del menú “Módem” (ver 4.3.1.3), presionando el botón correspondiente de la barra de herramientas (ver 4.3.1.4), o bien, utilizando la combinación de teclas Ctrl+M o Alt+M+A. Está dividida en dos secciones y su propósito es añadir una entrada a la base de módems desde los cuales se realizan lecturas remotas. En la parte superior, en la sección “Opciones del módem”, el usuario debe introducir la información correspondiente al módem desde el cual se realizarán las lectura. Para esto existen 5 espacios que deben ser rellenados con la información pertinente: el nombre del modelo del módem (el cual puede también ser seleccionado de una lista expandible), su IP, el nombre de un usuario que posea una cuenta de acceso al módem, su contraseña y, por último, el intervalo de tiempo programado entre las lecturas automáticas que serán realizadas por la aplicación (un intervalo igual a cero indica que la aplicación no debe realizar lecturas remotas automáticas desde ese módem). 69 En la sección inferior de la ventana, bajo el título “Opciones de archivo”, el usuario debe escoger entre crear un nuevo archivo para el registro de lecturas de las SNRs desde el módem o utilizar uno ya existente. Si esta última es la alternativa escogida, se le pide al usuario señalar el archivo a utilizar. El formulario posee, además, dos botones con las etiquetas “Guardar” y “Cancelar”. Presionando el primero de ellos, se crea una nueva entrada en la base de módems y se configura la aplicación para realizar lecturas desde el nuevo módem relacionado con esta entrada. Este botón no cierra la ventana de diálogo, sino que borra del formulario los datos introducidos, de manera que el usuario pueda agregar una nueva entrada. El botón “Cancelar” cierra la ventana de diálogo sin realizar ninguna operación adicional. La ventana es un formulario con el nombre de IPProgDlgForm. Su propiedad BorderStyle tiene el valor de bsToolWindow, por lo que posee un borde simple, no es redimensionable y sus íconos del sistema y su título son de tamaño pequeño. El espacio para introducir – o escoger de una lista – el nombre del modelo del módem es un componente TComboBox editable, llamado MModelCBox. Los espacios para introducir la IP, el nombre del usuario y la contraseña son componentes TLabeledEdit, llamados IPEdit, UserEdit y PWEdit, respectivamente. El espacio para introducir el intervalo de tiempo programado entre las lecturas automáticas es un componente TMaskEdit, con el nombre de freqEdit que permite introducir sólo 3 pares de cifras, separados por puntos y correspondientes al número de días, horas y minutos. Para permitir la elección entre crear un nuevo registro de SNRs o utilizar uno existente, se utiliza un componente TRadioGroup con dos ítems y el nombre de FileRGrp. Los botones son componentes TButton con los nombres de SaveBtn y CancelBtn. 70 Fig. 4.10. Ventana de diálogo para agregar una entrada a la base de módems desde los cuales la aplicación realiza lecturas remotas. 4.3.3. Ventana para reconfigurar una entrada Esta ventana de diálogo (Fig. 4.11) es desplegada, ya sea seleccionando el ítem “Reconfigurar...” del menú “Módem” (ver 4.3.1.3), presionando el botón correspondiente de la barra de herramientas (ver 4.3.1.4), o bien, utilizando la combinación de teclas Ctrl+R o Alt+M+R. La ventana es similar a aquella utilizada para agregar una entrada (ver 4.3.2). Existen, sin embargo, algunas diferencias con esta última: Al ser desplegada, los espacios son rellenados con los datos de la entrada correspondiente al módem cuya IP se encuentra seleccionada en la lista de la sección A (ver 4.3.1.1). Otra diferencia se encuentra en las alternativas de elección en las “Opciones de archivo”. En este caso las alternativas son crear un nuevo registro de SNRs para el módem o continuar almacenándolas en el mismo archivo. Por último, la acción del botón “Guardar” difiere con aquella de la ventana para agregar una entrada, en que, en este caso, es eliminada la entrada correspondiente al módem cuya IP se encuentra seleccionada, lo que, en la práctica, equivale a sustituir la 71 entrada existente con la nueva. Además, el botón “Guardar” produce el cierre de la ventana de diálogo. La ventana es un formulario con el nombre de IPReprogDlgForm. Su propiedad BorderStyle tiene el valor de bsToolWindow, por lo que posee un borde normal, no es redimensionable y sus íconos del sistema y su título son de tamaño pequeño. Los componentes sobre el formulario son idénticos a aquellos presentes en la ventana para agregar entradas (ver 4.3.2) y poseen los mismos nombres. Fig. 4.11. Ventana de diálogo para reconfigurar una entrada de la base de módems desde los cuales la aplicación realiza lecturas remotas. 4.3.4. Ventana de estado Esta ventana (Fig. 4.12) es desplegada u ocultada mediante la selección del ítem “Ventana de estado” del menú “Ver” (ver 4.3.1.3), la utilización del botón correspondiente de la barra de herramientas (ver 4.3.1.4), o bien, la combinación de teclas Ctrl+M o Alt+M+A. 72 Además, puede ser ocultada presionando el botón del sistema para cerrar una ventana o presionando la combinación de teclas Alt+F4. En ella se muestran 3 tipos de información: el número de entradas en la base de módems, el número de conexiones activas (es decir, el número de procesos de lectura remota ejecutándose) en un momento dado y el estado de cada conexión con los módem de la base. Los dos primeros datos se muestran bajo la etiqueta “Información general”; los datos sobre el estado de las conexiones se muestran en una lista bajo la etiqueta “Conexiones”. Una conexión puede asumir 5 estados: “Desconectado”, “Conectando...”, “Conectado”, “Error” e “Inactivo”. Cuando desde el inicio de la aplicación, no se ha realizado ninguna lectura desde uno de los módem o cuando la última lectura de la característica de la SNR desde ese módem finalizó con éxito, el estado de esta conexión es “Desconectado”. Mientras la aplicación intenta establecer una conexión con un módem, el estado de esa conexión es “Conectando...”. Una vez establecida la conexión con un módem, durante el período en que la característica de la SNR está siendo leída desde éste, el estado de su conexión es “Conectado”. Si el proceso de lectura de la característica de la SNR desde un módem no fue completado con éxito, el estado de su conexión es “Error”. Cuando en una entrada en la base de módems figura un intervalo entre lecturas remotas igual a cero, la aplicación no realiza lecturas automáticas desde el módem correspondiente y el estado de su conexión es “Inactivo” (mientras no se esté realizando un proceso de lectura iniciado por el usuario; en cuyo caso rigen las normas ya mencionadas). Cada estado es desplegado con un color diferente: “Desconectado”, en negro; “Conectando...”, en azul; “Conectado”, en verde; “Error”, en rojo; e “Inactivo”, en gris. Esta ventana es un formulario cuya propiedad BorderStyle tiene el valor de bsSizeToolWindow, por lo que posee un borde simple, es redimensionable y sus íconos del sistema y su título son de tamaño pequeño. El nombre del formulario es StatusForm. 73 Los datos son desplegados en dos componentes TStringGrid, de dos columnas cada uno, llamados GeneralStatusSG y StatusSG. El primero se encuentra bajo la etiqueta “Información general” y el segundo bajo la etiqueta “Conexiones”. Fig. 4.12. Ventana de estado. 4.3.5. Ventana “Acerca de Cu Line Analyzer” En esta ventana de diálogo (Fig. 4.13) se despliega información general sobre la aplicación: el nombre, el número de la versión, el autor y la institución y proyecto, en el marco de los cuales fue creada. 74 La ventana es un formulario llamado AboutForm cuya propiedad BorderStyle tiene el valor de bsToolWindow, por lo que posee un borde simple, no es redimensionable y sus íconos del sistema y su título son de tamaño pequeño. Fig. 4.13. Ventana “Acerca de Cu Line Analyzer” 4.4. Proceso de iniciación de la aplicación Cuando la aplicación es iniciada, todos sus formularios son creados, ya que ésta es de tipo SDI (ver 4.1). Esto implica que en ese momento ocurre el evento OnCreate de cada formulario. En el programa se implementan manejadores de ese evento para dos de sus formularios: el principal, llamado CuLAMainForm y el de la ventana de estado, llamado StatusForm. En ellos se realizan una serie de operaciones orientadas a inicializar algunos elementos necesarios para el correcto funcionamiento de la aplicación. El manejador CuLAMainFormCreate del formulario principal se analiza a continuación, mientras que el manejador StatusFormCreate se describe en el punto 4.6.4. En CuLAMainFormCreate (Listado 4.4) se especifican los formatos de fecha y de hora que deben ser utilizados por las funciones que operan con estos datos; también se crean una imagen en la memoria dinámica de la base de módems (ver 4.2), una lista de punteros a los 75 temporizadores que serán asociados a cada entrada de la base de módems y una lista de punteros a las hebras de lectura remota que hayan sido creadas (ver 4.5). Además, desde este manejador son invocadas tres funciones: FillStringsWithIPs, cuyo propósito es desplegar las IPs de los módems en la lista de IPs (ver 4.3.1.1) y cuya descripción es realizada en el punto 4.6.1; AddTimers, la cual es analizada más adelante, en este mismo punto; e IPListBoxClick – descrita también en el punto 4.6.1 – que es el manejador del evento OnClick del componente que contiene la lista de IPs y que es invocada para simular la selección de una IP por parte del usuario, resultando en la actualización de algunos elementos de la interfaz gráfica. void __fastcall TCuLAMainForm::FormCreate(TObject *Sender) { // Inicializa formatos de fecha y hora. DateSeparator = '/'; ShortDateFormat = "dd/mm/yy"; TimeSeparator = ':'; LongTimeFormat = "hh:nn:ss"; // Inicializa las listas de la base de módems, de punteros a los temporizadores y de // punteros a las hebras activas. UnsoModList = new TStringList; UnsoModList->Sorted = false; TimerList = new TList; ActiveThreads = new TList; // Despliega la página "Última lectura" del page control con los gráficos. OutputPageControl->ActivePageIndex = 0; // Controla que el archivo con los datos de los módems exista. Si no, // pide confirmar su creación. Ante respuesta negativa, termina la aplicación. if(!FileExists("ModemDB.txt")) { // Código omitido. } 76 // Si la aplicación no ha sido terminada (existe el archivo ModemDB.txt), carga los // datos de los módems a la base de módems, rellena la lista de IPs, crea los // temporizadores correspondientes y selecciona la primera IP en la lista de IPs. if(!Application->Terminated) { UnsoModList->LoadFromFile("ModemDB.txt"); if(UnsoModList->Count) { FillStringsWithIPs(IPListBox->Items,UnsoModList); AddTimers(TimerList, UnsoModList); IPListBox->ItemIndex = 0; IPListBoxClick(this); } } } Listado 4.4. Función FormCreate. Manejador del evento OnCreate del formulario TCuLAMainForm. Variable u objeto Tipo Explicación Formulario principal de la aplicación. Instancia de un CuLAMainForm TCuLAMainForm* descendiente de la clase TForm. Lista que contiene la base de módems en la memoria UnsoModList TStringList* dinámica, exactamente como en el archivo ModemDB.txt (ver 4.2). Lista de punteros a los temporizadores asociados a las TimerList TList* entradas en la base de módems (ver 4.2), en el mismo orden. Lista de punteros a las hebras activas en un momento dado, en ActiveThreads TList* el orden en que hayan sido activadas. “ModemDB.txt” AnsiString Nombre del archivo con la base de módems (ver 4.2). IPListBox TListBox* Ver Tabla 4.10. Tabla 4.1. Variables y objetos utilizados en el Listado 4.4. La función AddTimers (Listado 4.5), tiene como objetivo crear un temporizador para cada entrada de la base de módems. Los punteros a los temporizadores creados son 77 almacenados en una lista de punteros con el fin de poder direccionarlos posteriormente. En el programa, los temporizadores cumplen con la función de iniciar un proceso de lectura remota de las SNRs de los subcanales (ver 4.5) desde el módem al cual está asociado, cada cierto intervalo de tiempo. Un vez creado un temporizador, a éste le es asignado un intervalo de acuerdo a lo configurado en la entrada correspondiente de la base de módems. Como todos los temporizadores cumplen con el mismo propósito, en el código existe para ellos sólo un manejador de sus eventos OnTimer (Listado 4.6), el cual es aquí asignado a cada uno. Por último, el puntero al nuevo objeto es agregado a la lista punteros a los temporizadores. void __fastcall TCuLAMainForm::AddTimers(TList *Timers, TStringList *ModList) { int Days, Hrs, Mins; // Recorre toda la lista y crea un temporizador por cada módem. for(int i=0; i<=ModList->Count-1; i++) if(ModList->Strings[i].Pos("IP:") == 1) { // Transforma a enteros - separados en días, horas y minutos - el valor // alfanumérico del intervalo. Days = StrToInt(ModList->Strings[i+4].SubString(4,2)); Hrs = StrToInt(ModList->Strings[i+4].SubString(7,2)); Mins = StrToInt(ModList->Strings[i+4].SubString(10,2)); // Crea un nuevo objeto TTimer, le asigna el intervalo en milisegundos // y establece la función ATimerOnTimer como manejador de su evento OnTimer. ATimer = new TTimer(this); ATimer->Interval = (Days*24*3600+Hrs*3600+Mins*60)*1000; ATimer->OnTimer = &ATimerOnTimer; // Agrega el puntero del nuevo temporizador a la lista de punteros. Timers->Add(ATimer); } } Listado 4.5. Función AddTimers. 78 Variable u objeto Tipo Explicación ModList TstringList* Lista que contiene la base de módems (ver 4.2). Timers TList* Lista de punteros a los temporizadores asociados a cada módem, en el mismo orden que en la base de módems (ver 4.2). Intervalo entre lecturas automáticas desde un módem, dividido Days, Hrs, Mins int en días, horas y minutos. ATimer TTimer* Nuevo temporizador. Tabla 4.2. Variables y objetos utilizados en el Listado 4.5. 4.5. Proceso de lectura remota Las lecturas remotas de las SNRs de los subcanales almacenadas en los módems son llevadas a cabo, cada una, por un hebra diferente. Esta hebra es creada, inicializada y ejecutada desde la hebra principal cada vez que un temporizador asociado a una entrada en la base de módems cumple con el tiempo de espera programado (ver 4.4), o bien, el usuario inicia un proceso de lectura remota mediante alguna de las acciones descritas en el punto 4.3. Cuando ocurre lo primero, el programa ejecuta el manejador del evento OnTimer (ATimerOnTimer), el cual es igual para todos los temporizadores. El segundo caso es analizado más adelante, en este mismo punto. En ATimerOnTimer (Listado 4.6), después de comprobarse que no exista ya un proceso de lectura activo desde el mismo módem, se crea una hebra (una instancia de ReadoutThread – ver 4.5.1) en estado suspendido, se inicializan algunas de sus propiedades, y se le asigna el manejador del evento OnTerminate (Listado A.4), el cual se ejecutado cuando ésta finaliza. El puntero a la hebra es almacenado en una lista de 79 punteros con el fin de poder direccionarla posteriormente. Luego, la ventana de estado es actualizada (ver 4.6.4) y la hebra liberada. void __fastcall TCuLAMainForm::ATimerOnTimer(TObject *Sender) { // Determina cuál temporizador generó el evento. int Idx = TimerList->IndexOf(Sender); // Determina la IP, el modelo y la contraseña del usuario del módem al cual se // encuentra asociado el temporizador que generó el evento. AnsiString MyIP, MyMod, MyPwd; MyIP = UnsoModList->Strings[Idx*5]; MyIP.Delete(1,3); MyMod = UnsoModList->Strings[Idx*5+1]; MyMod.Delete(1,3); MyPwd = UnsoModList->Strings[Idx*5+3]; MyPwd.Delete(1,3); // Si ya existe una conexión con el módem, finaliza la función. if(ReadingModem(MyIP)) return; // Crea un hebra de lectura remota e inicializa algunas de sus propiedades. NewReadoutThread = new ReadoutThread(true); NewReadoutThread->IP = MyIP; NewReadoutThread->MMod = MyMod; NewReadoutThread->Pwd = MyPwd; // Establece NewReadoutThreadTerminate como manejador del evento OnTerminate. NewReadoutThread->OnTerminate = NewReadoutThreadTerminate; // Agrega el puntero a la lista de punteros a las hebras activas ActiveThreads->Add(NewReadoutThread); // Actualiza el número de conexiones activas en la ventana de estado. StatusForm->GenStatusSG->Cells[1][1] = IntToStr(ActiveThreads->Count); 80 // Libera la hebra. NewReadoutThread->Resume(); } Listado 4.6. Función ATimerOnTimer. Manejador del evento OnTimer de los temporizadores asociados a las entradas en la base de módems. Variable u objeto Tipo Explicación Posición en la lista TimerList (ver Tabla 4.1) del Idx int temporizador que generó el evento. IP, nombre del modelo y contraseña del usuario del módem MyIP, MyMod, MyPwd AnsiString al cual está asociado el temporizador que generó el evento. NewReadoutThread ReadoutThread* Instancia de una hebra de tipo ReadoutThread (ver 4.5.1). ActiveThreads TList* Ver Tabla 4.1. StatusForm TStatusForm* Ver Tabla 4.16. Tabla 4.3. Variables y objetos utilizados en el Listado 4.6. Como se mencionó, un proceso de lectura puede ser iniciado por el usuario a través de alguna de las acciones descritas en el punto 4.3. En cualquier caso, se ejecuta el manejador del evento OnClick del botón ReadoutSBtn (Listado 4.7). Este manejador comprueba que esté seleccionada una IP en la lista de IPs (ver 4.3.1.1) y que no exista ya una conexión activa con el módem con esa IP. Si se cumplen esas condiciones, invoca el manejador del evento OnTimer (Listado 4.6) – común para todos los temporizadores – el cual, como se vio, inicia un proceso de lectura remota. void __fastcall TCuLAMainForm::ReadoutSBtnClick(TObject *Sender) { // Si no hay ninguna IP seleccionada en la lista de IPs, despliega un mensaje de // error y finaliza la función. if(IPListBox->ItemIndex == -1) { // Código omitido. } 81 // Si ya existe una conexión con el módem, despliega un mensaje de error // y finaliza la función. if(ReadingModem(IPListBox->Items->Strings[IPListBox->ItemIndex])) { // Código omitido. } // Encuentra el puntero al temporizador asociado al módem cuya IP se encuentra // seleccionada en la lista de IPs e invoca el manejador de su evento OnTimer. int Idx = UnsoModList->IndexOf("IP:"+IPListBox->Items->Strings[IPListBox->ItemIndex]); ATimerOnTimer((TTimer *)TimerList->Items[Idx/5]); } Listado 4.7. Función ReadoutSBtnClick. Manejador del evento OnClick del botón ReadoutSBtn. Variable u objeto Tipo IPListBox TListBox* Idx int Explicación ver Tabla 4.10. Posición en la lista UnsoModList (Ver Tabla 4.1) de la IP seleccionada en la lista de IPs (ver 4.3.1.1). UnsoModList TStringList* Ver Tabla 4.1. TimerList TList* Ver Tabla 4.1. Tabla 4.4. Variables y objetos utilizados en el Listado 4.7. La función ReadingModem (Listado A.3), que es invocada desde las dos funciones que se acaba de analizar, comprueba si existe una conexión activa con un módem específico. La función requiere como argumento la IP del módem y devuelve un valor de tipo bool – true si hay una conexión activa y false, en caso contrario. 82 Cuando una hebra está por finalizar, se ejecuta el manejador de su evento OnTerminate, en este caso NewReadoutThreadTerminate (Listado A.4). Esta función elimina el puntero a la hebra de la lista de punteros a las hebras activas y actualiza la ventana de estado (ver 4.6.4). 4.5.1. La hebra de lectura remota Para trabajar con hebras, en Borland C++ Builder 6, es necesario, en primer lugar, crear uno o más descendientes de la clase TThread. Luego, cada instancia que se cree de uno de estos descendientes será una nueva hebra de ejecución. En el programa sólo es necesario un tipo de hebras, por lo tanto es creado sólo un descendiente – la clase ReadoutThread, cuya declaración se muestra en el Listado A.14. Las instancias de este descendiente son creadas cada vez que se va a ejecutar un proceso de lectura remota, como se vio más arriba. Un aspecto importante que se debe tener en cuenta cuando se trabaja con hebras es que no haya conflictos entre ellas cuando se ejecutan simultáneamente. Principalmente, esto se traduce a que deben adoptarse medidas preventivas cuando una hebra secundaria accede y modifica recursos que no le pertenecen sólo a ella. Existen diversos mecanismos para coordinar múltiples hebras: semáforos, mutex, secciones críticas, etc. La alternativa aquí utilizada es que la hebra secundaria entregue el control a la hebra principal sobre la ejecución de partes conflictivas del código. Esto se logra llamando a métodos de la hebra secundaria mediante Synchronize. Cuando una hebra secundaria es ejecutada, se ejecuta el código contenido en su método Execute y una vez que éste finaliza, la hebra principal ejecuta el manejador del evento OnTerminate. Luego, si la propiedad FreeOnTerminate de la hebra secundaria es igual 83 a true, ésta es destruida. De modo que es necesario modificar el método Execute, para que la hebra realice el proceso de lectura remota desde el módem. En la implementación del método Execute, (Listados 4.8, 4.9 y 4.10) se crea una instancia de un cliente Telnet, utilizando la clase TTnCnx que forma parte del conjunto de clases y componentes Internet Component Suite (ver 3.7). Se asignan las direcciones de los manejadores de tres de sus eventos: OnDataAvailable (Listado 4.11), OnSessionConnected (Listado A.16) y OnSessionClosed (Listado 4.11), y se inicializan algunas de sus propiedades. Seguidamente, se crea una instancia de un temporizador, al cual se le asigna un intervalo y un manejador del evento OnTimer (Listado 4.12), y se actualiza la ventana de estado (ver 4.6.4). El propósito del temporizador es forzar la finalización del proceso de lectura remota si éste no ha concluido con éxito dentro de un lapso de 30 segundos. void __fastcall ReadoutThread::Execute() { // Carga en CmdList el script a utilizar para leer la caract. de la SNR del módem. CmdList = new TStringList; CmdList->LoadFromFile("SpeedTouchProCmd.txt"); // Objeto utilizado para guardar temporalmente los datos originales que envíe // el módem conteniendo las SNRs de los subcanales. RawSNR = new AnsiString; // Indicador de recepción exitosa de los datos desde el módem. DataRcvdOK = false; // Indicador de superación del tiempo de espera máximo para la recepción de // los datos de las SNRs desde el módem. Timedout = false; // Crea una instancia de un cliente Telnet y le asigna las direcciones de los // manejadores de eventos implementados y los valores de las propiedades relevantes. 84 ATelnetClient = new TTnCnx((void *)NULL); ATelnetClient->OnDataAvailable = &ATelnetClientDataAvailable; ATelnetClient->OnSessionConnected = &ATelnetClientSessionConnected; ATelnetClient->OnSessionClosed = &ATelnetClientSessionClosed; ATelnetClient->Host = IP; // IP del servidor Telnet. ATelnetClient->TermType = "VT100"; // Tipo de terminal. ATelnetClient->Socket->MultiThreaded = true; // Debe ser true si el cliente es // usado en una hebra secundaria. // Crea el temporizador de superación de tiempo de espera y le asigna un intervalo y // la dirección de su evento OnTimer. TTimer *TimeoutTimer = new TTimer(NULL); TimeoutTimer->Interval = 30000; TimeoutTimer->OnTimer = &TimeoutTimerOnTimer; // Actualiza la ventana de estado. ConnStatus = "Conectando..."; Synchronize(UpdateLabels); ... Listado 4.8. Método Execute de la hebra ReadoutThread. Continúa en el Listado 4.9. En este punto, la hebra entra en un bucle while del cual sale sólo si se cumple una o más de las siguientes condiciones: los datos desde el módem fueron recibidos exitosamente, se superó el tiempo de espera para su recepción exitosa (30 s) y/o la hebra fue terminada. Esto último significa que su propiedad Terminated adopta el valor true (no que la hebra sea destruida), lo cual sucede, por ejemplo, si el usuario finaliza la aplicación cuando la hebra está siendo ejecutada. Dentro del bucle, a través del método Connect de la clase TTnCnx, se intenta conectar el cliente Telnet con el servidor en el módem ADSL. Esto inicia una hebra secundaria independiente, cuya ejecución es controlada por los métodos de la clase, mientras que la ejecución del método Execute de la hebra de lectura remota continúa paralelamente. 85 El procesamiento de mensajes no ocurre automáticamente dentro del método Execute de una hebra secundaria. Es entonces necesario crear un cola de mensajes y procesarla continuamente con el fin de que el control pueda ser transferido a los manejadores de eventos que sea necesario. Aquí se utiliza el método MessageLoop de la clase TWSocket, sobre la que está basada TTnCnx, el cual crea una cola de mensajes que es procesada ininterrumpidamente. Este método interrumpe la ejecución de la hebra hasta que la cola de mensajes reciba un mensaje WM_QUIT. Este mensaje es enviado cuando se supera el lapso para la finalización exitosa del proceso de lectura remota, o cuando el cliente Telnet se desconecta del servidor; situaciones que serán analizadas más adelante, en este mismo punto. Cuando la ejecución de la hebra sale del bucle while, al cumplirse una o más de las condiciones mencionadas arriba, se actualiza la ventana de estado (ver 4.6.4) y se destruyen los objetos que no serán ya utilizados. ... // Se repite hasta que los datos hayan sido recibidos exitosamente o se haya // superado el tiempo máximo de espera (30 s) o la hebra haya sido terminada. while(!DataRcvdOK && !Timedout && !Terminated) { // Apunta al primer comando del script. InstrIdx = 0; // Intenta conectar el cliente Telnet al módem. ATelnetClient->Connect(); // Crea una cola de mensajes para la hebra y entra en un bucle hasta // recibir el mensaje WM_QUIT. ATelnetClient->Socket->MessageLoop(); } // Actualiza la ventana de estado si se ha superado el tiempo de espera // o si la hebra ha sido terminada. if(Timedout || Terminated) 86 { ConnStatus = "Error"; Synchronize(UpdateLabels); } // Destruye los objetos. delete ATelnetClient; delete CmdList; delete TimeoutTimer; ... Listado 4.9. Continuación del método Execute de la hebra ReadoutThread. Continúa en el Listado 4.10. Si el proceso de lectura remota finalizó con éxito, se procede a extraer las SNRs de los subcanales de los datos enviados por el módem, utilizando para ello la función DecodeSNR (Listado 4.13), la cual será analizada más adelante, en este mismo punto. Luego, se almacenan en el archivo de SNRs del módem (ver 4.2), la fecha y hora actual (representada como un valor double) y las SNRs (representadas también como valores double). Al final se actualizan algunos elementos de la interfaz gráfica, lo cual será analizado en el punto 4.6. ... // Si la lectura finalizó con éxito, extrae las SNRs de los datos enviados por el // módem y las almacena en el archivo de SNRs correspondiente, junto con la fecha // y hora de la lectura. if(!Timedout && !Terminated) { // Extrae la SNR. DecodeSNR(SNR, RawSNR); // Determina el nombre del archivo de SNRs del módem basándose en su IP. AnsiString FileName = "SNR" + IP; while(FileName.Pos(".")) FileName.Delete(FileName.Pos("."),1); FileName += ".snr"; 87 // Abre el archivo de SNRs del módem para lectura y escritura y fija // su posición al final. TFileStream *SNRArchive; SNRArchive = new TFileStream(FileName, fmOpenReadWrite); SNRArchive->Seek(0,soFromEnd); // Lee la fecha y hora actuales en su representación double. ReadoutDateDouble = double(Now()); // Almacena la fecha y hora y las SNRs en el archivo de SNRs del módem. SNRArchive->Write(&ReadoutDateDouble,8); SNRArchive->Write(SNR,8*256); // Determina la cantidad de lecturas realizadas desde el módem. int ReadoutsCount = SNRArchive->Size/257/8; // Destruye el objeto. delete SNRArchive; // Actualiza los componentes TComboBox de la ventana de opciones del gráfico de // la variación en el tiempo de la característica de la SNR. Synchronize(UpdateCBs); // Actualiza el gráfico de la variación en el tiempo de la caract. de la SNR. if(ReadoutsCount >= 2) Synchronize(UpdateHistChart); // Actualiza el gráfico de la última característica leída de la SNR. Synchronize(UpdateLRChart); // Actualiza la lista de fechas y horas. Synchronize(UpdateDateLB); } // Destruye el objeto. delete RawSNR; } Listado 4.10. Continuación del método Execute de la hebra ReadoutThread. 88 Variable u objeto Tipo Explicación Lista con las instrucciones del script de comunicación entre CmdList TStringList* el cliente Telnet y el módem (ver 4.2). MMod AnsiString RawSNR AnsiString Nombre del modelo del módem. Bufor para el almacenamiento temporal de los datos que son enviados desde el módem. DataRcvdOK bool Timedout bool Indicador de recepción exitosa de los datos desde el módem. Indicador de superación del tiempo de espera máximo para la recepción de los datos con las SNRs desde el módem. ATelnetClient TTnCnx* TimeoutTimer TTimer* Instancia de un cliente Telnet. Temporizador de superación de tiempo de espera máximo para la recepción de los datos con las SNRs desde el módem. ConnStatus AnsiString Estado de la conexión con el módem. Índice que contiene el numero de la siguiente línea a InstrIdx int ejecutar del script de comunicación entre el cliente Telnet y el módem (ver 4.2). 0 es la primera línea. Puntero a un arreglo de 256 elementos que contiene los SNR double* valores de las SNRs de los subcanales, leídos desde el módem. FileName AnsiString SNRArchive TFileStream* Nombre del archivo de SNRs del módem (ver 4.2). Stream utilizado para las operaciones de lectura y escritura del archivo de SNRs del módem (ver 4.2). ReadoutDateDouble double ReadoutsCount int Fecha y hora de la lectura de las SNRs desde el módem. Cantidad de lecturas de las SNRs realizadas desde el módem. Tabla 4.5. Variables y objetos utilizados en los Listados 4.8, 4.9 y 4.10. Uno de los manejadores de eventos implementados para el cliente Telnet es el del evento OnDataAvailable (Listado 4.11), el cual ocurre cuando el cliente recibe datos desde el servidor del módem ADSL. Esto sucede como respuesta a la iniciación de la conexión, o 89 bien, como respuesta al envío de comandos por parte del cliente una vez que la comunicación ha sido establecida. En el programa, esta función maneja el intercambio entre la aplicación y el módem. Para ello se basa en el script de comandos programados para éste (ver 4.2) y en un índice que apunta a las líneas sucesivas del script, según vaya progresando el proceso de lectura. En un momento de la comunicación, cuando se alcanza el comando <StoreSNRtil:> del script, la función almacena en un objeto AnsiString los datos que envía el servidor, hasta recibir una cadena de caracteres igual a la contenida en la siguiente línea del script. Así, si todo sale de acuerdo a lo esperado, al finalizar el intecambio, este objeto contendrá los datos “en bruto” con los valores de las SNRs de los subcanales. De ser así, finalmente se alcanza el comando <Disconnect> del script de comunicación, el cual causa que la función marque el indicador que señala que la comunicación ha finalizado con éxito y desconecte el cliente. Cuando éste se desconecta del servidor, se ejecuta su manejador del evento OnSessionClosed (Listado 4.11), en cuya implementación se actualiza la ventana de estado (ver 4.6.4) y se envía a la hebra de lectura remota un mensaje WM_QUIT, con el fin de finalizar la ejecución del método MessageLoop del cliente (ver Listado 4.9). void __fastcall ReadoutThread::ATelnetClientDataAvailable (TTnCnx *Sender, Pointer Buffer, int Len) { // Convierte los datos recibidos desde el módem a AnsiString. AnsiString RxTxt = (char *)Buffer; // Si el comando actual del script de comunicación es "<WaitFor:>" y si en los // datos recibidos se encuentra el texto de la siguiente línea del script, // incrementa el índice de comandos. if(CmdList->Strings[InstrIdx] == "<WaitFor:>" && 90 RxTxt.Pos(CmdList->Strings[InstrIdx+1])) InstrIdx += 2; // Si el comando actual del script de comunicación es "<Send:>", envía el texto // de la siguiente línea o la contraseña, si ese texto es "<SendPwd>", // e incrementa el índice de comandos. if(CmdList->Strings[InstrIdx] == "<Send:>") { if(CmdList->Strings[InstrIdx+1] == "<SendPwd>") ATelnetClient->SendStr(Pwd+"\r"); else ATelnetClient->SendStr(CmdList->Strings[InstrIdx+1]+"\r"); InstrIdx += 2; } // Si el comando actual del script de comunicación es "<StoreSNRtil:>", almacena // los datos recibidos hasta que entre ellos se encuentre el texto de la // siguiente línea del script. Entonces, incrementa el índice de comandos. if(CmdList->Strings[InstrIdx] == "<StoreSNRtil:>") { *RawSNR = *RawSNR + RxTxt; if(RxTxt.Pos(CmdList->Strings[InstrIdx+1])) InstrIdx += 2; } // Si el comando actual del script de comunicación es "<Disconnect>", marca el // indicador de recepción exitosa de los datos y desconecta el cliente del módem. if(CmdList->Strings[InstrIdx] == "<Disconnect>") { DataRcvdOK = true; ATelnetClient->Close(); } } void __fastcall ReadoutThread::ATelnetClientSessionClosed (TTnCnx *Sender, WORD Error) { // Actualiza la ventana de estado. if(DataRcvdOK) ConnStatus = "Desconectado"; Synchronize(UpdateLabels); 91 // Envía a la hebra el mensaje WM_QUIT para finalizar MessageLoop. PostThreadMessage(ThreadID,WM_QUIT,0,0); } Listado 4.11. Funciones ATelnetClientDataAvailable y ATelnetClientSessionClosed. Manejadores de los eventos OnDataAvailable y OnSessionClosed del cliente Telnet. Variable u objeto Tipo Explicación Buffer Pointer Puntero genérico a los datos recibidos por el cliente Telnet. RxTxt AnsiString Datos recibidos por el cliente Telnet. CmdList TStringList* Ver Tabla 4.5. InstrIdx int Ver Tabla 4.5. Timedout bool Ver Tabla 4.5. ATelnetClient TTnCnx* Ver Tabla 4.5. DataRcvdOK bool Ver Tabla 4.5. ThreadID int Identificador de la hebra en el sistema. Tabla 4.6. Variables y objetos utilizados en el Listado 4.11. En algunos casos, es posible que la hebra no logre finalizar exitosamente el proceso de lectura desde el módem. Esto puede deberse a un error en la entrada de la base de módems (ver 4.2), a un módem desconectado de Internet, etc. Con el fin de que la hebra de lectura remota finalice su ejecución, aún cuando exista un problema de esta índole, en el método Execute de la hebra de lectura remota se crea un temporizador de superación de tiempo de espera, al cual se le asigna un intervalo de 30 segundos (ver Listado 4.8). Cuando este lapso se cumple, se ejecuta su manejador del evento OnTimer (Listado 4.12). Éste manejador desconecta el cliente Telnet del servidor (si está conectado), marca el indicador de superación de tiempo de espera y envía a la hebra 92 un mensaje WM_QUIT para que finalice el método MessageLoop del cliente (ver Listado 4.9). void __fastcall ReadoutThread::TimeoutTimerOnTimer(TObject *Sender) { // Si el cliente está conectado, lo desconecta. if(ATelnetClient->IsConnected()) ATelnetClient->Close(); // Marca el indicador de superación del tiempo de espera para la finalización // exitosa del proceso de lectura desde el módem. Timedout = true; // Envía a la hebra el mensaje WM_QUIT para finalizar MessageLoop. PostThreadMessage(ThreadID,WM_QUIT,0,0); } Listado 4.12. Función TimeoutTimerOnTimer. Manejador del evento OnTimer del temporizador de superación de tiempo de espera. Variable u objeto Tipo Explicación ATelnetClient TTnCnx* Ver Tabla 4.5. Timedout bool Ver Tabla 4.5. ThreadID int Ver Tabla 4.6. Tabla 4.7. Variables y objetos utilizados en el Listado 4.12. Si las SNRs de los subcanales fueron leídas con éxito por la hebra de lectura remota, se ejecuta la función DecodeSNR (Listado 4.13), como se observa en el Listado 4.10. Su propósito es extraer los valores de las SNRs de la cadena de datos alfanuméricos recibida por el cliente Telnet. La función requiere como argumentos un puntero a los datos recibidos por el cliente y un puntero a un arreglo tipo double de 256 elementos, donde ésta guarda los valores numéricos de las SNRs de los subcanales. 93 Para extraer estos valores, se realiza una comparación secuencial, carácter por carácter, de los datos alfanuméricos almacenados durante el intercambio entre el cliente y el módem (ver Listado 4.11), con la pauta para la extracción de las SNRs (ver 4.2). Los caracteres iniciales y finales de la cadena almacenada durante el intercambio, son descartados, si la pauta no los abarca. Cada vez que se encuentra el carácter “¤” en la cadena de la pauta, significa que en esa misma posición, en la cadena almacenada, comienza un valor de la SNR de un subcanal. En ese momento se procede a convertir ese valor a uno de tipo double y a almacenarlo en el arreglo double apuntado por el argumento de la función, en la posición correspondiente al número del subcanal. Este último dato viene dado por los tres caracteres subsiguientes a “¤” en la cadena de la pauta. void __fastcall ReadoutThread::DecodeSNR(double *SNR, AnsiString *RawSNR) { AnsiString SNRValue; char KeyChar, Channel[4]; int i, k; // Inicializa el arreglo entregado por el argumento. for(i=0; i<=255; i++) SNR[i]=0; // Carga en DecodeKey la pauta para la extracción de las SNRs. TMemoryStream *DecodeKey = new TMemoryStream(); DecodeKey->LoadFromFile("SpeedTouchProSNRKey.txt"); // Índexa el primer carácter de la cadena que contiene las SNRs de los subcanales. i = 0; // Se repite mientras no se haya leído completamente la pauta para la extracción // de las SNRs. while(DecodeKey->Position < DecodeKey->Size) { // Lee un carácter de la pauta. DecodeKey->Read(&KeyChar,1); // Incrementa el índice de caracteres de la cadena con las SNRs y compara el // carácter indexado con el leído de la pauta. Si son diferentes y no se espera 94 // en esa pos. el valor de una SNR, retorna el stream de la pauta a su inicio. i++; if((*RawSNR)[i] != KeyChar && KeyChar != '¤') DecodeKey->Seek(0,soFromBeginning); else { // Si se espera el valor de una SNR en la cadena con las SNRs, extrae ese // valor y lo almacena como double en el arreglo entregado por el argumento. if(KeyChar == '¤') { k=0; SNRValue = ""; // Extrae el valor alfanumérico de la SNR. while( ((*RawSNR)[i+k] >= '0' && (*RawSNR)[i+k] <= '9') || (*RawSNR)[i+k] == '.' ) { if((*RawSNR)[i+k] == '.') SNRValue = SNRValue + DecimalSeparator; else SNRValue = SNRValue + (*RawSNR)[i+k]; k++; } // Lee de la pauta el número del subcanal al que corresponde la SNR. DecodeKey->Read(Channel,3); Channel[3] = NULL; // Convierte la SNR a float y la almacena en la posición del arreglo // correspondiente al número del subcanal. SNR[ StrToInt((AnsiString)Channel) ] = StrToFloat(SNRValue); // Incrementa el índice de la cadena con las SNRs de manera que apunte // al último carácter del valor alfanumérico de la SNR. i += k-1; } } } delete DecodeKey; } Listado 4.13. Función DecodeSNR. Extrae las SNRs de los subcanales de los datos enviados por el módem. 95 Variable u objeto Tipo Explicación Puntero a un arreglo de 256 elementos donde se almacenan double* SNR los valores de las SNRs de los subcanales. RawSNR AnsiString * Puntero a los datos con las SNRs, recibidos desde el módem. SNRValue AnsiString SNR de un subcanal representada en forma alfanumérica. KeyChar char Un carácter leído de la pauta para la extracción de los valores de las SNRs de los datos recibidos desde el módem. Puntero a un arreglo de 4 elementos con la representación Channel char* alfanumérica del número de un subcanal. i, k int Índices y contadores. Stream utilizado para las operaciones de lectura de la pauta TMemoryStream* para la extracción de los valores de las SNRs de los datos DecodeKey recibidos desde el módem. Tabla 4.8. Variables y objetos utilizados en el Listado 4.13. 4.6. Procesos de despliegue de la información 4.6.1. Lista de IPs Como se vio en el punto 4.4, durante la iniciación de la aplicación, desde el manejador del evento OnCreate del formulario principal (Listado 4.4), se invoca la función FillStringsWithIPs (Listado 4.14). Ésta es también invocada desde AddModem (Listado 4.24), cuando el usuario añade o reconfigura una entrada de la base de módems (ver 4.7.1 y 4.7.3). La función rellena la lista de IPs (ver 4.3.1.1) con las IPs de los módems presentes en la base de módems (ver 4.2), ordenadas en forma ascendente. La función requiere como 96 argumento un puntero a un objeto TStrings y un puntero a un objeto TStringList. Para rellenar la lista de IPs, es necesario que el primero de ellos apunte a la propiedad Items de IPListBox (ver Tabla 4.10) y el segundo, a la lista que contiene la base de módems, es decir, a UnsoModList. El primer paso del procedimiento utilizado para rellenar la lista de IPs, consiste en almacenar en una lista TStringList, ordenada alfabéticamente en forma ascendente, la representación binaria, en forma alfanumérica (como sucesión de caracteres “1” y “0”), de las IPs de los módems presentes en la base de módems. Seguidamente, se copian estas IPs, en el mismo orden, a la lista de IPs, pero esta vez en su representación decimal, en forma alfanumérica (por ejemplo “219.100.100.100”). La razón por la cual es primero necesario ordenar ascendentemente las IPs representadas en su forma binaria, es que el orden alfabético de sus representaciones decimales no corresponde necesariamente al orden correcto. En cambio, el orden alfabético de las cadenas de caracteres que representan binariamente las IPs, es siempre correcto. Por ejemplo, alfabéticamente, la cadena de caracteres “29.100.100.100“ es posterior a “219.100.100.100“; pero “11101011001000110010001100100” (29.100.100.100) es anterior a “11011011011001000110010001100100” (219.100.100.100). Este método de ordenar las IPs en forma ascendente resulta sencillo gracias a la utilización de un objeto TIpProperty (del paquete de componentes “Indy”). Esta clase, entre otras funcionalidades, permite acceder a diferentes representaciones de una IP, a través de sus propiedades. 97 void __fastcall TCuLAMainForm::FillStringsWithIPs(TStrings *IPStrings, TStringList *ModList) { int i; // Crea un objeto TIpProperty y una lista TStringList ordenada ascendentemente, para // el almacenamiento de las IPs en su representación binaria alfanumérica. TIpProperty *AnIP = new TIpProperty; TStringList *TmpModList = new TStringList; TmpModList->Sorted = true; // Recorre las líneas de la base de módems. for(i=0; i<=ModList->Count-1; i++) // Cuando una línea de la base de módems corresponde a una IP, almacena su // representación binaria alfanumérica en la lista ordenada. if(ModList->Strings[i].Pos("IP:") == 1) { AnIP->AsString = ModList->Strings[i].SubString(4,ModList->Strings[i].Length()-3); TmpModList->Add(AnIP->AsBinaryString); } // Recorre en sentido ascendente la lista con las representaciones binaria de las // IPs y las copia en ese mismo orden, a la lista de IPs representadas decimalmente for(i=0; i<=TmpModList->Count-1; i++) { AnIP->AsBinaryString = TmpModList->Strings[i]; IPStrings->Add(AnIP->AsString); } delete TmpModList; delete AnIP; } Listado 4.14. Función FillStringsWithIPs. Rellena en orden ascendente, la lista de IPs con las IPs de los módems presentes en la base. 98 Variable u objeto Tipo IPStrings TStrings* ModList TStringList* Explicación Lista de IPs en su representación decimal alfanumérica. Puntero a un objeto que contenga la base de módems (ver 4.2). i int Contador. AnIP TIpProperty* Objeto utilizado para la manipulación de IPs. Lista ordenada en forma ascendente, que contiene la TmpModList TStringList* representación binaria alfanumérica de las IPs de los módems presentes en la base de módems (ver 4.2) Tabla 4.9. Variables y objetos utilizados en el Listado 4.14. Otra función relacionada con la lista de IPs es el manejador del evento OnClick de IPListBox (Listado 4.15). Éste es ejecutado cada vez que el usuario selecciona una IP de la lista y su propósito es actualizar todos los elementos de la interfaz gráfica del usuario que guardan relación con el módem cuya IP ha sido seleccionada. El manejador es ejecutado, además, desde el manejador del evento OnCreate del formulario principal (Listado 4.4), cuando la aplicación es iniciada, simulando la selección por parte del usuario del primer elemento de la lista de IPs; desde la función AddModem (Listado 4.24), cuando una nueva entrada es añadida a la base de módems, simulando la selección por parte del usuario de la IP correspondiente a esa entrada; y desde DeleteModem (Listado 4.25), cuando una entrada es eliminada de la base de módems, simulando la selección de un ítem contiguo al eliminado, de acuerdo a lo descrito en el punto 4.7.2. En la implementación de este manejador, primero se determina la IP que ha sido seleccionada en la lista y el número de la línea en la base de módems que esta IP ocupa (esta línea es la primera de la entrada correspondiente al módem cuya IP ha sido 99 seleccionada). La función lee algunos de los datos de la entrada correspondiente en la base de módems y con ellos actualiza la barra de información (ver 4.6.3). Luego, son actualizados los siguientes elementos: el gráfico de la última característica de la SNR (ver 4.6.2), a través de la función DrawLastReadChart (Listado 4.16); los componentes TComboBox de la ventana de opciones del gráfico de la variación en el tiempo de la característica de la SNR (ver 4.6.2), a través de la función FillCBs (Listado 4.17); el estado de rotación de este gráfico; el gráfico mismo, a través de la función DrawHistoricChart (Listado 4.18); y la lista de fechas y horas (ver 4.6.2), a través de la función FillDateLB (Listado 4.19). Si se ha realizado por lo menos una lectura desde el módem cuya IP ha sido seleccionada, la función simula la selección por parte del usuario del más reciente elemento de la lista de fechas y horas, invocando el manejador de su evento OnClick (DateLBClick, Listado A.11). Desde ese manejador se invoca la función DrawSpecChart (Listado 4.20) que actualiza el gráfico de la característica de la SNR leída en la fecha y hora seleccionada. void __fastcall TCuLAMainForm::IPListBoxClick(TObject *Sender) { // Determina la IP seleccionada. AnsiString IP = IPListBox->Items->Strings[IPListBox->ItemIndex]; // Determina el número de la línea de la base de módems desde el que comienza la // entrada correspondiente al módem cuya IP ha sido seleccionada. int Idx = UnsoModList->IndexOf("IP:"+IP); // Actualiza los datos de la barra de información. ModModelEdit->Text = UnsoModList->Strings[Idx+1].SubString (4,UnsoModList->Strings[Idx+1].Length()-3); UserEdit->Text = UnsoModList->Strings[Idx+2].SubString (4,UnsoModList->Strings[Idx+2].Length()-3); FrecEdit->Text = UnsoModList->Strings[Idx+4].SubString (4,UnsoModList->Strings[Idx+4].Length()-3); 100 // Actualiza el gráfico de la última característica de la SNR leída desde el módem. DrawLastReadChart(IP); // Rellena los componentes TComboBox de la ventana de opciones del gráfico de la // variación en el tiempo de la característica de la SNR. FillCBs(IP); // Fija la rotación del gráfico de la variación de la característica de la SNR // en el tiempo. HistoricChart->View3DOptions->Rotation = 310; HistoricChart->View3DOptions->Elevation = 340; // Actualiza el gráfico de la variación de la característica de la SNR en el tiempo. DrawHistoricChart(IP); // Rellena la lista de fechas y horas en que fueron realizadas lecturas de la // característica de la SNR. FillDateLB(IP); // Comprueba si se han realizado lecturas desde el módem. if(DateLB->Count) { // Simula la selección por parte del usuario del valor más reciente de // la lista de fechas y horas DateLB->ItemIndex = DateLB->Count-1; DateLBClick(this); } else { // Borra los datos del gráfico y le asigna un título sin fecha ni hora. SpecReadChart->Series[0]->Clear(); SpecReadChart->Title->Text->Strings[0] = "Razón Señal-Ruido"; } } Listado 4.15. Función IPListBoxClick. Manejador del evento OnClick de la lista de IPs. Variable u objeto Tipo Explicación IP AnsiString IP seleccionada en la lista de IPs. IPListBox TListBox* Componente con la lista de IPs (ver 4.3.1.1). 101 Número de la primera línea en la base de módems de la Idx int entrada del módem cuya IP se encuentra seleccionada. UnsoModList TStringList* ModModelEdit TEdit* Ver Tabla 4.1. Componente con el nombre del modelo del módem cuya IP se encuentra seleccionada. Componente con el nombre del usuario con acceso al UserEdit TEdit* módem cuya IP se encuentra seleccionada. Componente con el intervalo entre las lecturas automáticas FrecEdit TEdit* desde el módem cuya IP se encuentra seleccionada. Gráfico de la variación en el tiempo de la característica de la HistoricChart TChart* SNR. DateLB TListBox* Ver Tabla 4.14. SpecReadChart TChart* Ver Tabla 4.15. Tabla 4.10. Variables y objetos utilizados en el Listado 4.15. 4.6.2. Gráficos La aplicación cuenta con 3 modos de presentación de las características de las SNRs leídas desde los módems (ver 4.3.1.2). Cada modo es presentado sobre una página de un componente TPageControl y la visualización del modo deseado se realiza a través de la selección de la pestaña correspondiente. Estas páginas contienen, cada una, un componente TChart donde es desplegado el gráfico de acuerdo con el modo escogido, y dos de ellas contienen, además, componentes adicionales que permiten al usuario controlar algunas características del gráfico desplegado. Durante la ejecución de la aplicación, todos estos componentes se encuentran siempre actualizados, independientemente de la página que se encuentre desplegada; es decir, las funciones encargadas de su actualización son ejecutadas sin importar el modo visualizado. Gracias a esto, no se producen demoras cada vez que el usuario selecciona una pestaña. 102 A continuación se describen los procesos relacionados con la actualización de los elementos gráficos de cada una de las páginas del componente TPageControl. 4.6.2.1. Página “Última lectura” En esta página se despliega la última característica de la SNR leída desde el módem cuya IP se encuentra seleccionada en la lista de IPs (ver 4.3.1.1). El gráfico es actualizado por la aplicación cuando se selecciona una IP y cuando se realiza un proceso de lectura remota (ver 4.5) desde el módem cuya IP se encuentra seleccionada (la característica leída pasa a ser la última). Una IP puede ser seleccionada por el usuario o a través del código del programa, desde alguna de sus funciones. Las funciones que seleccionan una IP son el manejador del evento OnCreate del formulario principal (Listado 4.4) – durante el proceso de iniciación de la aplicación –, la función AddModem (ejecutada cuando se añade una entrada a la base de módems – ver 4.7.1) y la función DeleteModem (ejecutada cuando se elimina una entrada de la base de módems – ver 4.7.2). En cualquiera de estos casos es invocado el manejador del evento OnClick de la lista de IPs (Listado 4.15) y desde él es invocada la función DrawLastReadChart (Listado 4.16), la cual actualiza el gráfico. Por otro lado, como se observa en el Listado 4.10, antes de finalizar el proceso de lectura remota, la hebra invoca el método UpdateLRChart (Listado A.18). Esta función comprueba si la IP seleccionada en la lista de IPs es igual a aquella desde la cual se realizó la lectura y de ser así, invoca también la función DrawLastReadChart. 103 La función DrawLastReadChart requiere como argumento un valor AnsiString que debe ser igual a la IP seleccionada en la lista de IPs. Cuando es invocada, carga a la memoria los datos almacenados en el archivo de SNRs (ver 4.2) correspondiente al módem con esa IP. Si desde éste se ha realizado al menos un lectura, determina la fecha y hora de la más reciente de ellas y los valores de las SNRs de los subcanales leídos en ese instante. La fecha y hora es utilizada para crear el título del gráfico, y los valores de las SNRs, en conjunto con los valores de las frecuencias centrales de los rangos ocupados por los subcanales, determinan los puntos del gráfico. Estos puntos son añadidos a una serie bidimensional de datos, a través del método AddXY de la clase TLineSeries. Si nunca se han realizado lecturas desde el módem, el gráfico es dejado en blanco y el título no incluye la fecha y hora. void __fastcall TCuLAMainForm::DrawLastReadChart(AnsiString IP) { // Borra la serie de datos del gráfico. LastReadChart->Series[0]->Clear(); // Determina el nombre del archivo de SNRs y carga el archivo a la memoria. AnsiString FileName = "SNR" + IP; while(FileName.Pos(".")) FileName.Delete(FileName.Pos("."),1); FileName += ".snr"; TMemoryStream *SNRDataArchive = new TMemoryStream(); SNRDataArchive->LoadFromFile(FileName); // Comprueba si se ha realizado al menos una lectura desde el módem. if(SNRDataArchive->Size) { double SNR[256], ReadoutDateDouble; // Determina la fecha y hora de la última lectura. SNRDataArchive->Seek(-257*8,soFromEnd); 104 SNRDataArchive->Read(&ReadoutDateDouble,8); // Despliega el título del gráfico con la fecha y hora de la última lectura. AnsiString &ReadoutDateStr = *new AnsiString; DateTimeToString(ReadoutDateStr, "dd/mm/yy hh:nn:ss", (TDateTime)ReadoutDateDouble); LastReadInfoLbl->Caption = "Razón Señal-Ruido - " + ReadoutDateStr; delete &ReadoutDateStr; // Determina las SNRs de los subcanales correspondientes a la última lectura. SNRDataArchive->Read(SNR,256*8); // Grafica la característica de la SNR, conviertiendo el número de cada subcanal // al valor de la frecuencia central del rango por él ocupado (en kHz). for(int i=0; i<=255; i++) LastReadChart->Series[0]->AddXY((i+0.5)*4.3125,SNR[i]); } else // Si nunca se han realizado lecturas desde el módem, el título del gráfico no // muestra la fecha y hora. LastReadInfoLbl->Caption = "Razón Señal-Ruido"; delete SNRDataArchive; } Listado 4.16. Función DrawLastReadChart. Actualiza el gráfico de la última característica de la SNR leída desde un módem. Variable u objeto Tipo IP AnsiString LastReadChart TChart* Explicación IP seleccionada en la lista de IPs (ver 4.3.1.1). Gráfico de la última característica de la SNR leída desde el módem. FileName AnsiString SNRDataArchive TMemoryStream* Nombre del archivo de SNRs del módem (ver 4.2). Stream utilizado para las operaciones de lectura del archivo de SNRs del módem (ver 4.2). Puntero a un arreglo de 256 elementos con los valores de las SNR double* SNRs de los subcanales. 105 ReadoutDateDouble double Fecha y hora de la última lectura realizada desde el módem. ReadoutDateStr AnsiString& Fecha y hora de la última lectura realizada desde el módem. LastReadInfoLbl TLabel* Componente con el título del gráfico. Tabla 4.11. 4.6.2.2. Variables y objetos utilizados en el Listado 4.16. Página “Archivo de lecturas en 3D” En esta página se despliega el gráfico de la variación en el tiempo de la característica de la SNR correspondiente al módem cuya IP se encuentra seleccionada en la lista de IPs (ver 4.3.1.1), así como también una ventana de opciones (ver 4.3.1.2) que permite rotar el gráfico y seleccionar el espacio de tiempo por él abarcado (mediante dos componentes TComboBox). El gráfico es actualizado cuando se selecciona una IP, cuando se realiza un proceso de lectura remota (ver 4.5) desde el módem cuya IP se encuentra seleccionada y cuando se selecciona un ítem en uno de los componentes TComboBox de la ventana de opciones. Por lo menos uno de los componentes TComboBox de la ventana de opciones es actualizado en las mismas circunstancias que el gráfico. Cuál de ellos, o si ambos, depende de una variedad de factores que serán mencionados más adelante. Es importante señalar que los ítems presentes en cada componente deben cumplir con la condición de que no sea posible seleccionar como límite más antiguo del período a graficar, una fecha y hora posterior a la seleccionada como su límite más reciente; y viceversa. Esto significa que el conjunto de ítems de un componente debe contener fechas y horas anteriores o posteriores, según sea el caso, a la seleccionada en el otro. Todas las funciones que actualizan uno o ambos componentes, lo hacen de manera tal que esta condición se cumpla en todo momento. 106 En el punto 4.6.2.1 se indicó las acciones que causan la selección de una IP. Dos funciones invocadas desde el manejador del evento OnClick de la lista de IPs (Listado 4.15) guardan relación con la actualización de elementos presentes en esta página: DrawHistoricChart (Listado 4.18), cuyo propósito es graficar la variación en el tiempo de la característica de la SNR, y FillCBs (Listado 4.17), la cual rellena ambos componentes TComboBox de la ventana de opciones con las fechas y horas en que se han realizado lecturas. A su vez, como se observa en el Listado 4.10, antes de finalizar el proceso de lectura remota, la hebra invoca los métodos UpdateHistChart (Listado A.19) y UpdateCBs (Listado A.20). Ambos métodos comprueban si la IP seleccionada en la lista de IPs es igual a aquella desde la cual se realizó la lectura y de ser así, el primero invoca la función DrawHistoricChart y el segundo añade la fecha y hora de la lectura realizada a uno de los componentes TComboBox de la ventana de opciones, de manera que este nuevo ítem esté disponible para ser seleccionado. El componente al cual UpdateCBs añade la fecha y hora de la lectura depende de si anteriormente se han realizado lecturas desde ese módem. En caso que así sea, la añade al componente que determina el límite más reciente del espacio de tiempo graficado; de lo contrario, la añade al otro (ya que ese no contiene ningún ítem). Cuando un ítem es seleccionado en uno de los componentes, se ejecuta su manejador del evento OnSelect: FromDateCBSelect (Listado A.5), para el componente que determina el límite más antiguo del período graficado, o ToDateCBSelect (Listado A.6), para el componente que determina el límite más reciente. Estos manejadores realizan dos acciones: actualizan el componente cuya selección no cambió, de manera que se siga cumpliendo la condición expuesta más arriba sobre los conjuntos de ítems presentes en cada uno (ya que cambió la selección), y actualizan el gráfico, invocando la función DrawHistoricChart. 107 La función FillCBs requiere como argumento un valor AnsiString que debe ser igual a la IP seleccionada en la lista de IPs. Cuando es invocada, elimina los ítems presentes en los componentes TComboBox, los deshabilita y carga a la memoria los datos almacenados en el archivo de SNRs (ver 4.2) correspondiente al módem con la IP entregada por el argumento. Luego, las acciones realizadas dependen de la cantidad de lecturas remotas que hayan sido efectuadas desde el módem. Así, si se ha realizado sólo una lectura, la función añade la fecha y hora de esa lectura a FromDateCB (componente que determina el límite más antiguo del período graficado). El otro componente es dejado sin cambio y ambos quedan deshabilitados. Si, por el contrario, se han realizado dos o más lecturas desde el módem, la función habilita los componentes y los rellena con las fechas y horas leídas desde el archivo de SNRs. Sin embargo, en FromDateCB se omite la fecha y hora de la lectura más reciente, y en ToDateCB (componente que determina el límite más reciente del período graficado) se omite la fecha y hora de la lectura más antigua. En ToDateCB la función selecciona siempre su último ítem (correspondiente a la fecha y hora de la última lectura); pero en FromDateCB la selección dependerá de si se han realizado más de 100 lecturas desde el módem. Si ese es el caso, se selecciona su ítem número 99, contando desde el último; si no, se selecciona su primer ítem (correspondiente a la fecha y hora de la primera lectura realizada). De esta manera (ya que FillCBs es invocada desde el manejador del evento OnClick de la lista de IPs), cuando se selecciona una IP, el gráfico inicialmente mostrado abarca 100 o menos características de la SNR. Las selecciones de los ítems de FromDateCB y ToDateCB realizadas desde la función FillCBs no invocan sus manejadores del evento OnSelect. 108 void __fastcall TCuLAMainForm::FillCBs(AnsiString IP) { AnsiString &ReadoutDateStr = *new AnsiString; double ReadoutDate; // Elimina sus ítems y deshabilita los componentes TComboBox. FromDateCB->Clear(); FromDateCB->Enabled = false; ToDateCB->Clear(); ToDateCB->Enabled = false; // Determina el nombre del archivo de SNRs y carga el archivo a la memoria. AnsiString FileName = "SNR" + IP; while(FileName.Pos(".")) FileName.Delete(FileName.Pos("."),1); FileName += ".snr"; TMemoryStream *SNRDataArchive = new TMemoryStream(); SNRDataArchive->LoadFromFile(FileName); // Si se ha realizado sólo una lectura desde el módem, añade a FromDateCB la fecha y // hora en que fue realizada. if(SNRDataArchive->Size/257/8 == 1) { SNRDataArchive->Read(&ReadoutDate,8); DateTimeToString(ReadoutDateStr, "dd/mm/yy hh:nn:ss", (TDateTime)ReadoutDate); FromDateCB->Items->Add(ReadoutDateStr); } // Comprueba si se han realizado 2 o más lecturas desde el módem. if(SNRDataArchive->Size/257/8 >= 2) { // Habilita los componentes TComboBox. FromDateCB->Enabled = true; ToDateCB->Enabled = true; // Carga a un arreglo las fechas y horas en que fueron realizadas las lecturas // desde el módem. TStringList *DateStrings = new TStringList; while(SNRDataArchive->Position < SNRDataArchive->Size) { SNRDataArchive->Read(&ReadoutDate,8); 109 DateTimeToString(ReadoutDateStr, "dd/mm/yy hh:nn:ss", (TDateTime)ReadoutDate); DateStrings->Add(ReadoutDateStr); SNRDataArchive->Seek(256*8,soFromCurrent); } // Rellena FromDateCB y ToDateCB con las fechas y horas de las lecturas // realizadas desde el módem, omitiendo en FromDateCB la fecha y hora de la // última y en ToDateCB, la fecha y hora de la primera. for(int i=0; i <= DateStrings->Count - 2; i++) { FromDateCB->Items->Add(DateStrings->Strings[i]); ToDateCB->Items->Add(DateStrings->Strings[i+1]); } // Si se han realizado más de 100 lecturas, selecciona el ítem número 99 de // FromDateCB, contando desde el último, y actualiza ToDateCB para que no // contenga ítems correspondientes a fechas y horas anteriores o iguales a la // seleccionada en FromDateCB. Si no, selecciona el primer ítem de FromDateCB. if(FromDateCB->Items->Count > 100) { FromDateCB->ItemIndex = FromDateCB->Items->Count - 101; for(int i=1; i <= FromDateCB->Items->Count - 101; i++) ToDateCB->Items->Delete(0); } else FromDateCB->ItemIndex = 0; // Selecciona el último ítem de ToDateCB. ToDateCB->ItemIndex = ToDateCB->Items->Count - 1; delete DateStrings; } delete &ReadoutDateStr; delete SNRDataArchive; } Listado 4.17. Función FillCBs. Rellena FromDateCB y ToDateCB con las fechas y horas en que se han realizado lecturas remotas de la característica de la SNR desde un módem. 110 Variable u objeto Tipo Explicación IP AnsiString IP seleccionada en la lista de IPs (ver 4.3.1.1). ReadoutDateStr AnsiString& Fecha y hora de una lectura realizada desde el módem. ReadoutDateDouble double Fecha y hora de una lectura realizada desde el módem. Componente con aquellas fechas y horas de lecturas FromDateCB TComboBox* realizadas desde el módem, seleccionables como límite más antiguo del período a graficar. Componente con aquellas fechas y horas de lecturas ToDateCB TComboBox* realizadas desde el módem, seleccionables como límite más reciente del período a graficar. FileName AnsiString SNRDataArchive TMemoryStream* Nombre del archivo de SNRs del módem (ver 4.2). Stream utilizado para las operaciones de lectura del archivo de SNRs del módem (ver 4.2). Lista de las fechas y horas en que han sido realizadas DateStrings TStringList* lecturas desde el módem. i int Tabla 4.12. Contador. Variables y objetos utilizados en el Listado 4.17. La función DrawHistoricChart (Listado 4.18) requiere como argumento un valor AnsiString que debe corresponder a la IP seleccionada en la lista de IPs. Cuando es invocada, borra el gráfico que pueda encontrarse desplegado y carga a la memoria los datos almacenados en el archivo de SNRs correspondiente al módem con la IP entregada por el argumento. Para que la función continúe con su ejecución es necesario que se hayan realizado por lo menos 2 lecturas desde el módem, ya que sólo entonces tiene sentido el gráfico. Si ese es el caso, la función lee progresivamente las fechas y horas en que fueron realizadas las lecturas desde el módem y cuando una de éstas se encuentra entre los límites determinados por los ítems seleccionados en FromDateCB y ToDateCB, procede a añadir 111 al gráfico la característica de la SNR leída en ese momento. Para ello se utiliza el método AddXYZ de la clase TSurfaceSeries, el cual añade puntos a la serie de datos del gráfico tridimensional. Las tres coordenadas de cada punto añadido son definidas por el valor de la fecha y hora en que se realizó la lectura, la SNR de un subcanal y la frecuencia central del rango ocupado por ese subcanal. void __fastcall TCuLAMainForm::DrawHistoricChart(AnsiString IP) { // Borra la serie de datos del gráfico. HistoricSNRSeries->Clear(); // Determina el nombre del archivo de SNRs y carga el archivo a la memoria. AnsiString FileName = "SNR" + IP; while(FileName.Pos(".")) FileName.Delete(FileName.Pos("."),1); FileName += ".snr"; TMemoryStream *SNRDataArchive = new TMemoryStream(); SNRDataArchive->LoadFromFile(FileName); // Comprueba si se han realizado por lo menos 2 lecturas de la característica de la // SNR desde el módem. if(SNRDataArchive->Size/257/8 >= 2) { double ChannelSNR, ReadoutDateDouble; AnsiString &ReadoutDateStr = *new AnsiString; // Se repite mientras no se haya leído completamente el archivo de SNRs. while(SNRDataArchive->Position < SNRDataArchive->Size) { // Lee la fecha y hora de una lectura realizada desde el módem y la convierte // a AnsiString. SNRDataArchive->Read(&ReadoutDateDouble,8); DateTimeToString (ReadoutDateStr, "dd/mm/yy hh:nn:ss", (TDateTime)ReadoutDateDouble); // Comprueba si la fecha y hora leída está comprendidas entre los límites // determinados por los TComboBox de la ventana de opciones. Si no, posiciona 112 // el stream al inicio de la próxima entrada en el archivo de SNRs. if(StrToDateTime(ReadoutDateStr) >= StrToDateTime(FromDateCB->Text) && StrToDateTime(ReadoutDateStr) <= StrToDateTime(ToDateCB->Text)) // Añade al gráfico la característica de la SNR leída en ese momento. Las // coordenadas de cada punto son determinadas por el valor de la frecuencia // central del rango ocupado por un subcanal (en kHz), el valor de la SNR // de ese subcanal y la fecha y hora de la lectura. for(int i=0; i<=255; i++) { SNRDataArchive->Read(&ChannelSNR,8); HistoricSNRSeries->AddXYZ((i+0.5)*4.3125,ChannelSNR,ReadoutDateDouble); } else SNRDataArchive->Seek(256*8,soFromCurrent); } delete &ReadoutDateStr; } delete SNRDataArchive; } Listado 4.18. Función DrawHistoricChart. Grafica la variación en el tiempo de la característica de la SNR leída desde un módem. Variable u objeto Tipo IP AnsiString HistoricSNRSeries TSurfaceSeries* Explicación IP seleccionada en la lista de IPs (ver 4.3.1.1). Serie de datos del gráfico de la variación en el tiempo de la característica de la SNR. FileName AnsiString SNRDataArchive TMemoryStream* Nombre del archivo de SNRs del módem (ver 4.2). Stream utilizado para las operaciones de lectura del archivo de SNRs del módem (ver 4.2). ChannelSNR double Valor de la SNR de un subcanal. ReadoutDateDouble double Fecha y hora de una lectura realizada desde el módem. ReadoutDateStr AnsiString& Fecha y hora de una lectura realizada desde el módem. FromDateCB TComboBox* Ver Tabla 4.12. 113 ToDateCB TComboBox* Ver Tabla 4.12. i int Contador. DateStrings TStringList* Lista de las fechas y horas en que fueron realizadas lecturas desde el módem. Tabla 4.13. Variables y objetos utilizados en el Listado 4.18. Además de los componentes TComboBox, la ventana de opciones contiene 5 botones que permiten la rotación del gráfico. Esta rotación es realizada en los manejadores de los eventos OnClick de los botones (RightSBtnClick, LeftSBtnClick, UpSBtnClick, DownSBtnClick y CenterSBtnClick, Listado A.10), mediante la variación de las propiedades Rotation y Elevation de la clase TView3DOptions (que es una propiedad de la clase TChart de la cual el gráfico es una instancia). La ventana de opciones puede ser desplegada y ocultada presionando un botón. Este botón puede asumir los estados de presionado y no presionado y su manejador del evento OnClick (ShowChartOptsSBClick, Listado A.10) cambia la propiedad Visible del componente TPanel sobre el cual están dispuestos los componentes de la ventana. 4.6.2.3. Página “Archivo de lecturas en 2D” En esta página se despliega el gráfico de la característica de la SNR leída en el instante seleccionado en la lista de fechas y horas (ver 4.3.1.2), desde el módem cuya IP se encuentra seleccionada en la lista de IPs (ver 4.3.1.1). La lista de fechas y horas es actualizada cuando se selecciona una IP y cuando se realiza un proceso de lectura remota (ver 4.5) desde el módem cuya IP se encuentra seleccionada. El gráfico es actualizado cuando se selecciona una fecha y hora en la lista susodicha. 114 Una IP es seleccionada por las acciones y funciones descritas en el punto 4.6.2.1 y el manejador del evento OnClick de la lista de IPs (Listado 4.15) invoca la función FillDateLB (Listado 4.19). Ésta rellena la lista con las fechas y horas en que han sido realizadas lecturas de la característica de la SNR desde el módem cuya IP se ha seleccionado. Además, desde el código de este manejador se selecciona el último elemento de la lista de fechas y horas (es decir, la fecha y hora más reciente). Cuando se realiza una lectura remota, la hebra, antes de finalizar su ejecución, invoca la función UpdateDateLB (Listado A.21). Ésta comprueba si la IP seleccionada corresponde a la IP desde la cual se realizó la lectura y, de ser así, añade a la lista la fecha y hora de esa lectura. Además, si esa es la primera que se ha realizado desde el módem, selecciona desde el código el nuevo (y único) ítem de la lista. Al ser seleccionado un ítem de la lista de fechas y horas – ya sea desde el código, en los dos casos descritos, o por el usuario –, se ejecuta su manejador del evento OnClick (DateLBClick, Listado A.11). Desde este manejador se invoca la función DrawSpecChart (Listado 4.20), la cual grafica la característica de la SNR leída desde ese módem en el momento indicado por la selección. La función FillDateLB requiere como argumento un valor AnsiString que debe ser igual a la IP seleccionada en la lista de IPs. Cuando es invocada, elimina los ítems que puedan estar contenidos en la lista y carga a la memoria los datos almacenados en el archivo de SNRs (ver 4.2) correspondiente al módem con la IP entregada por el argumento. Luego, si se ha realizado al menos una lectura desde ese módem, lee secuencialmente las fechas y horas en que fueron realizadas, las convierte a una forma alfanumérica y las añade a la lista. 115 void __fastcall TCuLAMainForm::FillDateLB(AnsiString IP) { // Elimina los ítem de la lista de fechas y horas. DateLB->Clear(); // Determina el nombre del archivo de SNRs y carga el archivo a la memoria. AnsiString FileName = "SNR" + IP; while(FileName.Pos(".")) FileName.Delete(FileName.Pos("."),1); FileName += ".snr"; TMemoryStream *SNRDataArchive = new TMemoryStream(); SNRDataArchive->LoadFromFile(FileName); // Comprueba si se ha realizado por lo menos una lectura desde el módem. if(SNRDataArchive->Size) { AnsiString &ReadoutDateStr = *new AnsiString; double ReadoutDateDouble; // Se repite mientras no se haya leído completamente el archivo de SNRs. while(SNRDataArchive->Position < SNRDataArchive->Size) { // Lee una fecha y hora, la convierte a una representación alfanumérica y la // añade a la lista de fechas y horas. SNRDataArchive->Read(&ReadoutDateDouble,8); DateTimeToString(ReadoutDateStr, "dd/mm/yy hh:nn:ss", (TDateTime)ReadoutDateDouble); DateLB->Items->Add(ReadoutDateStr); // Posiciona el stream al inicio de la próxima entrada en el archivo de SNRs. SNRDataArchive->Seek(256*8,soFromCurrent); } delete &ReadoutDateStr; } delete SNRDataArchive; } Listado 4.19. Función FillDateLB. Rellena la lista de fechas y horas con las fechas y horas en que han sido realizadas lecturas de la característica de la SNR desde un módem. 116 Variable u objeto Tipo IP AnsiString DateLB TListBox* Explicación IP seleccionada en la lista de IPs (ver 4.3.1.1). Lista de fechas y horas en que se han realizado lecturas desde el módem. FileName AnsiString SNRDataArchive TMemoryStream* Nombre del archivo de SNRs del módem (ver 4.2). Stream utilizado para las operaciones de lectura del archivo de SNRs del módem (ver 4.2). ReadoutDateStr AnsiString& Fecha y hora de una lectura realizada desde el módem. ReadoutDateDouble double Fecha y hora de una lectura realizada desde el módem. Tabla 4.14. Variables y objetos utilizados en el Listado 4.19. La función DrawSpecChart requiere como argumentos dos valores AnsiString, de los cuales el primero debe corresponder a la IP seleccionada en la lista de IPs y el segundo, a la fecha y hora seleccionada en la lista de fechas y horas. Cuando es invocada, borra el gráfico que pueda encontrarse desplegado y carga a la memoria los datos almacenados en el archivo de SNRs correspondiente al módem con la IP entregada por el argumento. Luego, lee secuencialmente las fechas y horas en que fueron realizadas las lecturas desde ese módem, las convierte a su representación alfanumérica y las compara con la entregada por el argumento de la función. Cuando las dos coinciden, procede a graficar la característica de la SNR leída en ese momento. Para ello lee los valores almacenados de las SNRs de los subcanal y añade cada uno de ellos, junto con el valor de la frecuencia central del rango por él ocupado, a la serie de datos del gráfico bidimensional. Seguidamente, actualiza el título del gráfico para que despliegue información sobre la fecha y hora en la que fue leída la característica de la SNR desplegada. void __fastcall TCuLAMainForm::DrawSpecChart(AnsiString IP, AnsiString ReadoutDateSel) { // Borra la serie de datos del gráfico. SpecReadChart->Series[0]->Clear(); 117 // Determina el nombre del archivo de SNRs y carga el archivo a la memoria. AnsiString FileName = "SNR" + IP; while(FileName.Pos(".")) FileName.Delete(FileName.Pos("."),1); FileName += ".snr"; TMemoryStream *SNRDataArchive = new TMemoryStream(); SNRDataArchive->LoadFromFile(FileName); // Definiciones. double SNR[256], ReadoutDateDouble; AnsiString &ReadoutDateStr = *new AnsiString; // Se repite mientras no se haya leído completamente el archivo de SNRs. while(SNRDataArchive->Position < SNRDataArchive->Size) { // Lee una fecha y hora y la convierte a una representación alfanumérica. SNRDataArchive->Read(&ReadoutDateDouble,8); DateTimeToString(ReadoutDateStr, "dd/mm/yy hh:nn:ss", (TDateTime)ReadoutDateDouble); // Si la fecha y hora coincide con aquella entregada por el argumento, grafica la // característica de la SNR. Si no, posiciona el stream al inicio de la próxima // entrada en el archivo de SNRs. if(ReadoutDateStr == ReadoutDateSel) { // Lee los valores de las SNRs de los subcanales. SNRDataArchive->Read(SNR,256*8); // Grafica la característica de la SNR, convirtiendo el número de cada // subcanal al valor de la frec. central del rango por él ocupado (en kHz). for(int i=0; i<=255; i++) SpecReadChart->Series[0]->AddXY((i+0.5)*4.3125,SNR[i]); // Actualiza el título del gráfico. SpecChartInfoLbl->Caption = "Razón Señal-Ruido - " + ReadoutDateSel; // Interrumpe el bucle while. break; } else SNRDataArchive->Seek(256*8,soFromCurrent); 118 } delete &ReadoutDateStr; delete SNRDataArchive; } Listado 4.20. Función DrawSpecChart. Grafica la característica de la SNR leída desde un módem en un momento determinado. Variable u objeto Tipo IP AnsiString ReadoutDateSel AnsiString Explicación IP seleccionada en la lista de IPs (ver 4.3.1.1). Fecha y hora seleccionada en la lista de fechas y horas (ver 4.3.1.2). Gráfico de la característica de la SNR leída desde el módem SpecReadChart TChart* en la fecha y hora seleccionada en la lista de fechas y horas (ver 4.3.1.2). FileName AnsiString SNRDataArchive TMemoryStream* Nombre del archivo de SNRs del módem (ver 4.2). Stream utilizado para las operaciones de lectura del archivo de SNRs del módem (ver 4.2). Puntero a un arreglo de 256 elementos que contiene los SNR double* valores de las SNRs de los subcanales. ReadoutDateDouble double Fecha y hora de una lectura realizada desde el módem. ReadoutDateStr AnsiString& Fecha y hora de una lectura realizada desde el módem. SpecChartInfoLbl TLabel* Componente con el título del gráfico. Tabla 4.15. Variables y objetos utilizados en el Listado 4.20. 4.6.3. Barra de información En esta barra (ver 4.3.1.5) es desplegada la información sobre el nombre del modelo del módem, el nombre del usuario utilizado para acceder a éste y el intervalo entre las lecturas remotas automáticas realizadas desde el mismo por la aplicación. La información 119 desplegada pertenece al módem cuya IP se encuentra seleccionada en la lista de IPs (ver 4.3.1.1). Una IP es seleccionada por las acciones y funciones descritas en el punto 4.6.2.1 y la información es directamente actualizada desde el manejador del evento OnClick de la lista de IPs (Listado 4.15). Para ello asigna las cadenas de caracteres adecuadas a la propiedad Text de cada uno de los 3 componentes TEdit presentes en la barra. Estas cadenas son leídas de la entrada de la base de módems (ver 4.2) correspondiente al módem cuya IP se ha seleccionado. 4.6.4. Ventana de estado En la ventana de estado (ver 4.3.4) se despliega el número de entradas en la base de módems (ver 4.2), el número de conexiones activas y el estado de cada conexión con los módem de la base. La actualización de estos datos ocurre al ser iniciada la aplicación, al producirse algunos de los eventos relacionados con el proceso de lectura remota de la característica de la SNR (ver 4.5) y cuando el usuario realiza modificaciones a la base de módems. Cuando la aplicación es iniciada, ocurre el evento OnCreate del formulario de la ventana de estado. El manejador de este evento (Listado 4.21) inicializa algunas propiedades de la ventana y de los componentes TStringGrid en ella presentes, y rellena las celdas de estos componentes con los datos iniciales pertinentes. Esto último es llevado a cabo por las funciones FillGenStatusSG (Listado 4.22) y FillStatusSG (Listado 4.22). La función UncheckSG (Listado A.33), invocada dos veces desde el manejador del evento OnCreate 120 del formulario, tiene como propósito deseleccionar todas las celdas de un componente TStringGrid. void __fastcall TStatusForm::FormCreate(TObject *Sender) { // Fija la posición inicial del formulario en la parte derecha de la ventana de // la aplicación. StatusForm->Left = CuLAMainForm->Width - StatusForm->Width - 8; // Define los anchos de las columnas de GenStatusSG. GenStatusSG->ColWidths[0] = 110; GenStatusSG->ColWidths[1] = GenStatusSG->Width - 115 - 16; // Rellena GenStatusSG con los datos iniciales. FillGenStatusSG(); // Deselecciona las celdas de GenStatusSG. UncheckSG(GenStatusSG); // Define los anchos de las columnas de StatusSG. StatusSG->ColWidths[0] = 80; StatusSG->ColWidths[1] = StatusSG->Width - 85 - 16; // Rellena StatusSG con los datos iniciales. FillStatusSG(CuLAMainForm->IPListBox->Items); // Deselecciona las celdas de StatusSG. UncheckSG(StatusSG); } Listado 4.21. Función FormCreate. Manejador del evento OnCreate del formulario StatusForm. Variable u objeto Tipo Explicación Formulario de la ventana de estado. Instancia de un StatusForm TStatusForm* descendiente de la clase TForm. CuLAMainForm TCuLAMainForm* Ver Tabla 4.1. 121 Componente con el número de módems en la base de GenStatusSG TStringGrid* módems y el número de conexiones activas. Componente con el estado de las conexiones con cada uno StatusSG TStringGrid* de los módems de la base de módems. Tabla 4.16. Variables y objetos utilizados en el Listado 4.21. La función FillGenStatusSG no requiere argumentos y su propósito es rellenar las dos columnas del componente GenStatusSG con la información sobre el número de módems en la base de módems, el número de conexiones activas y las descripciones de estos dos parámetros. El número de módems en la base de módems es determinado leyendo la cantidad de punteros presentes en la lista de punteros a los temporizadores (ver 4.4). El número de conexiones activas es igual a 0 en el momento en que es ejecutada la función, ya que ésta es invocada al iniciarse la aplicación. La función FillStatusSG requiere como argumento un puntero a un objeto TStrings que debe contener una lista de las IPs de los módems presentes en la base de módems. Su propósito es rellenar la columna izquierda del componente StatusSG con esas IPs y la columna derecha, con los estados de las conexiones con los módem correspondientes. Los estados “Desconectado” e “Inactivo” (ver 4.3.4) son los únicos posibles inicialmente y la función determina cuál de ellos es el apropiado, evaluando la propiedad Interval del temporizador asociado al módem. void __fastcall TStatusForm::FillGenStatusSG(void) { // Despliega en la primera fila de GenStatusSG la descripción y el número de // entradas en la base de módems. GenStatusSG->Cols[0]->Add("Número de entradas:"); GenStatusSG->Cols[1]->Add(IntToStr(CuLAMainForm->TimerList->Count)); // Añade una fila a GenStatusSG. GenStatusSG->RowCount++; 122 // Despliega en la segunda fila de GenStatusSG la descripción y el número de // conexiones activas. GenStatusSG->Cols[0]->Add("Conexiones activas:"); GenStatusSG->Cols[1]->Add("0"); } void __fastcall TStatusForm::FillStatusSG(TStrings *Modems) { TTimer *TimerPtr; int TimerIdx; // Se repite tantas veces como hayan IPs en la lista. for(int i=1; i<=Modems->Count; i++) { // Añade una IP a la columna izquierda de StatusSG. StatusSG->Cols[0]->Add(Modems->Strings[i-1]); // Encuentra el puntero al temporizador asociado al módem con esa IP. TimerIdx = CuLAMainForm->UnsoModList->IndexOf("IP:"+Modems->Strings[i-1])/5; TimerPtr = (TTimer *)CuLAMainForm->TimerList->Items[TimerIdx]; // Determina cuál es el estado de la conexión y lo añade a la columna derecha de // StatusSG. if(TimerPtr->Interval > 0) StatusSG->Cols[1]->Add("Desconectado"); else StatusSG->Cols[1]->Add("Inactivo"); // Añade una fila a GenStatusSG. StatusSG->RowCount++; } // Elimina la última fila de StatusSG (no contiene datos). StatusSG->RowCount--; } Listado 4.22. Funciones FillGenStatusSG y FillStatusSG. Rellenan los componentes GenStatusSG y StatusSG con los datos iniciales. 123 Variable u objeto Tipo Explicación Ver Tabla 4.16. GenStatusSG TStringGrid* CuLAMainForm TCuLAMainForm* Ver Tabla 4.1. TimerList TList* Modems TStrings* Ver Tabla 4.1. Puntero a una lista de las IPs de los módems presentes en la base de módems (ver 4.2). Puntero a un temporizador de la lista de punteros a los TimerPtr TTimer* temporizadores (ver 4.4). Una posición en la lista de punteros a los temporizadores TimerIdx int (ver 4.4). i int Contador. StatusSG TStringGrid* Ver Tabla 4.16. UnsoModList TStringList* Ver Tabla 4.1. Tabla 4.17. Variables y objetos utilizados en el Listado 4.22. Durante el proceso de lectura remota la conexión con un módem puede adoptar varios estados: “Conectando...”, cuando la aplicación está intentando establecer la conexión; “Conectado”, cuando la conexión ha sido establecida; “Desconectado”, cuando la conexión ha sido cerrada; y “Error”, cuando la aplicación no logró finalizar con éxito el proceso de lectura desde el módem. Además, el número de conexiones activas se incrementa cada vez que se inicia un proceso de lectura remota y disminuye cuando éste finaliza. La información desplegada en la ventana de estado sobre el número de conexiones activas es actualizado en el manejador del evento OnTimer de los temporizadores (Listado 4.6), inmediatamente antes de iniciarse un proceso de lectura remota, y por el manejador del evento OnTerminate de la hebra (NewReadoutThreadTerminate, Listado A.4), justo antes de que la hebra sea destruida. En ambos casos este número es determinado evaluando la cantidad de punteros presentes en la lista de punteros a las hebras activas y asignado (en forma alfanumérica) a la celda apropiada de GenStatusSG. 124 El estado de la conexión durante el proceso de lectura remota es actualizado en la ventana de opciones por el método UpdateLabels (Listado A.17) de la hebra, el cual es invocado desde los métodos Execute (2 veces – ver Listados 4.8 y 4.9), ATelnetClientSessionConnected (Listado A.16), que es ejecutado cuando se establece la conexión, y ATelnetClientSessionClosed (Listado 4.11), que es ejecutado cuando se cierra la conexión. Estos métodos modifican el contenido de un objeto AnsiString (de alcance global dentro de la hebra) y luego invocan UpdateLabels, el cual asigna esa cadena de caracteres a la celda apropiada de StatusSG. El estado de la conexión con un módem puede ser, además, modificado por el manejador del evento OnTerminate de la hebra, mencionado más arriba. En ese método se evalúa la propiedad Interval del temporizador asociado al módem desde el cual se realizó la lectura remota y, si ésta es igual a 0, el estado de la conexión es cambiado a “Inactivo”; lo que significa que no se realizan lecturas automáticas desde ese módem y que el proceso apenas finalizado fue iniciado por el usuario. Cada estado es desplegado en StatusSG con un color diferente (ver 4.3.4). Para ello se utiliza el manejador del evento OnDrawCell de este objeto (Listado 4.23), el cual se ejecuta cada vez que la aplicación debe dibujar una celda (por ejemplo, cuando cambia su contenido). En este manejador se evalúa el contenido de la celda que está siendo dibujada (es decir, el estado de la conexión) y, dependiendo de éste, se asigna el color apropiado al texto desplegado. Si el estado de la conexión es “Desconectado”, el manejador no modifica el color del texto, de manera que permanece negro, que es el color por omisión. 125 void __fastcall TStatusForm::StatusSGDrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect, TGridDrawState State) { // Comprueba el estado de la conexión. if(StatusSG->Cells[ACol][ARow] == "Inactivo") { // Borra el contenido de la celda. StatusSG->Canvas->FillRect(Rect); // Define el color del texto. StatusSG->Canvas->Font->Color = clGray; // Despliega el estado de la conexión. StatusSG->Canvas->TextOut(Rect.Left+2, Rect.Top+1,StatusSG->Cells[ACol][ARow]); } if(StatusSG->Cells[ACol][ARow] == "Conectando...") { StatusSG->Canvas->FillRect(Rect); StatusSG->Canvas->Font->Color = clNavy; StatusSG->Canvas->TextOut(Rect.Left+2, Rect.Top+1,StatusSG->Cells[ACol][ARow]); } if(StatusSG->Cells[ACol][ARow] == "Conectado") { StatusSG->Canvas->FillRect(Rect); StatusSG->Canvas->Font->Color = clGreen; StatusSG->Canvas->TextOut(Rect.Left+2, Rect.Top+1,StatusSG->Cells[ACol][ARow]); } if(StatusSG->Cells[ACol][ARow] == "Error") { StatusSG->Canvas->FillRect(Rect); StatusSG->Canvas->Font->Color = clRed; StatusSG->Canvas->TextOut(Rect.Left+2, Rect.Top+1,StatusSG->Cells[ACol][ARow]); } } Listado 4.23. Función StatusSGDrawCell. Manejador del evento OnDrawCell de StatusSG. 126 Variable u objeto Tipo Explicación ACol int Número de la columna donde se encuentra celda dibujada. ARow int Número de la fila donde se encuentra celda dibujada. Rect TRect& Coordenadas límites de la celda dibujada. StatusSG TStringGrid* Ver Tabla 4.16. Tabla 4.18. Variables y objetos utilizados en el Listado 4.23. La ventana de estado es también actualizada cuando el usuario añade, elimina o reconfigura una entrada de la base de módems. En el primer caso, se añade una nueva fila a StatusSG con la IP y el estado de la conexión correspondientes a la nueva entrada, y se incrementa en 1 el número de entradas en la base, desplegado en GenStatusSG; y en el segundo caso, se elimina de StatusSG la fila correspondiente a la entrada eliminada y se disminuye en 1 el número de entradas en la base, desplegado en GenStatusSG. El tercer caso es equivalente a, primero, eliminar una entrada y, luego, añadir una nueva. Las funciones ejecutadas cuando se añade o elimina una entrada son AddModem (Listado 4.24) y DeleteModem (Listado 4.25), respectivamente. La primera de ellas invoca la función AddToStatusSG (Listado A.30) y la segunda, la función DelFromStatusSG (Listado A.31). Estas últimas funciones cumplen con el propósito mencionado de añadir o eliminar una línea del componente StatusSG y de incrementar o disminuir el número de conexiones activas desplegado en GenStatuSG. Otros detalles sobre los procesos involucrados en la adición, eliminación y reconfiguración de las entradas de las base de módems serán analizados más adelante, en el punto 4.7. Por último, es necesario mencionar que la ventana de estado se encuentra oculta cuando la aplicación es iniciada. Las acciones que causan su despliegue o posterior ocultamiento fueron descritas en el punto 4.3.4. Estas acciones producen diferentes eventos que causan la 127 ejecución de los manejadores pertinentes. Sin embargo, cualquiera sea el manejador ejecutado como consecuencia de una de estas acciones, éste invoca el manejador del evento OnClick del botón para mostrar u ocultar la ventana (ShowStatusSBClick, Listado A.12). Este manejador oculta la ventana, si ésta se encuentra desplegada, y la despliega, si se encuentra oculta. Además, modifica ciertas propiedades del botón y del ítem correspondiente del menú, para que el primero se encuentre presionado y el segundo posea una marca cuando la ventana está desplegada, y lo contrario, si está oculta. 4.7. Otros procesos 4.7.1. Adición de una entrada a la base de módems El proceso de adición de una entrada a la base de módems (ver 4.2) puede ser iniciado presionando un botón, una combinación de teclas o un ítem del menú, según lo descrito en los puntos 4.3.1.3 y 4.3.1.4. Cualquiera de estas acciones causa la ejecución del manejador del evento OnClick del botón (AddModemSBtnClick, Listado A.7), el cual despliega la ventana de diálogo descrita en detalle en el punto 4.3.2. Cuando el usuario presiona el botón “Guardar” de la ventana de diálogo, se ejecuta su manejador del evento OnClick (SaveBtnClick, Listado A.24), definido en el formulario de la ventana. Éste comprueba que no exista ya una entrada con la IP introducida por el usuario, ya que no deben existir dos entradas para el mismo módem. Si se cumple esa condición, el manejador invoca la función AddModem (Listado 4.24), definida en el formulario principal, la cual prepara el sistema para operar con el nuevo módem. 128 La función AddModem requiere 6 argumentos: 5 valores AnsiString (la IP del módem, el nombre del modelo del módem, el nombre del usuario con acceso al módem, la contraseña del usuario y el intervalo entre las lecturas remotas automáticas) y un valor int. Este último valor informa a la función sobre el origen del archivo de SNRs que será utilizado para almacenar los datos leídos desde el módem asociado a la nueva entrada: un valor igual a 0 indica que debe ser creado un nuevo archivo de SNRs; un valor igual a 1 indica que debe ser utilizado uno existente, el cual debe ser señalado por el usuario; cualquier otro valor indica se debe utilizar uno existente y que, además, éste se encuentra en la carpeta adecuada y su nombre es el apropiado (el usuario no debe entonces señalar el archivo a utilizar). La función primero añade la entrada al archivo que contiene la base de módems. Los datos para ello son determinados por los argumentos. Luego añade una entrada idéntica a la lista que contiene la base de módems en la memoria dinámica. Seguidamente, si así es dictado por el argumento correspondiente, la función crea un nuevo archivo de SNRs con un nombre de acuerdo con la norma descrita en el punto 4.2. Si es el usuario quien debe indicar un archivo de SNRs, la función despliega una ventana de diálogo desde la cual es posible hacerlo. En ese caso, el archivo seleccionado es renombrado, de manera que su nombre cumpla con la norma susodicha, y movido a la carpeta donde se encuentra el ejecutable de la aplicación. Si el usuario cancela la ventana de diálogo, la función crea un nuevo archivo de SNRs e informa sobre esto a través de un mensaje. Si el argumento indica que el archivo ya existe y que se encuentra en la carpeta apropiada, la función no realiza ninguna acción. El siguiente paso consiste en crear un nuevo temporizador, lo cual es realizado a través de la función AddTimers (Listado 4.5). Luego, la función agrega la nueva IP a la lista de IPs 129 (ver 4.3.1.1) y selecciona ese nuevo ítem. La adición de la nueva IP se lleva a cabo eliminando primero el contenido completo de la lista e invocando luego la función FillStringsWithIPs (Listado 4.14) (la cual lee las IPs desde el archivo que contiene la base de módems). La selección de la nueva IP incluye la ejecución del manejador del evento OnClick de la lista de IPs (Listado 4.15), el cual actualiza algunos elementos de la interfaz gráfica. Finalmente, la función actualiza la ventana de estado, de acuerdo a lo descrito en el punto 4.6.4. void __fastcall TCuLAMainForm::AddModem(AnsiString IP, AnsiString MM, AnsiString UN, AnsiString PW, AnsiString RF, int Opt) { //*** Añade la nueva entrada al archivo con la base de módems. *** TFileStream *ModemDB; ModemDB = new TFileStream("ModemDB.txt",fmOpenReadWrite); AnsiString MdmRec = "IP:"+IP+"\r\nMM:"+MM+"\r\nUN:"+UN+"\r\nPW:"+PW+"\r\nRF:"+RF+"\r\n"; ModemDB->Seek(0,soFromEnd); ModemDB->Write(MdmRec.c_str(),MdmRec.Length()); delete ModemDB; //*** Añade la nueva entrada a la base de módems en la memoria dinámica *** TStringList *Modem = new TStringList; Modem->Add("IP:"+IP); Modem->Add("MM:"+MM); Modem->Add("UN:"+UN); Modem->Add("PW:"+PW); Modem->Add("RF:"+RF); UnsoModList->AddStrings(Modem); //*** Si Opt=0 u Opt=1, crea el archivo de SNRs para la nueva entrada. *** // Determina el nombre del archivo. AnsiString NewFileName = "SNR" + IP; while(NewFileName.Pos(".")) NewFileName.Delete(NewFileName.Pos("."),1); 130 NewFileName = ExtractFilePath(Application->ExeName)+NewFileName+".snr"; // Selecciona la acción, dependiendo del argumento. switch(Opt) { // Crea un nuevo archivo de SNRs. case 0: FileClose(FileCreate(NewFileName)); break; // Utiliza un archivo existente. Su selección se realiza a través de una // ventana de diálogo. case 1: // Despliega la ventana de diálogo. OpenSNRArchDlg->InitialDir = ExtractFilePath(Application->ExeName); if(OpenSNRArchDlg->Execute()) RenameFile(OpenSNRArchDlg->FileName, NewFileName); // Si el usuario cancela la ventana de diálogo, se crea un nuevo archivo. else { FileClose(FileCreate(NewFileName)); // (Código omitido) } // Cambia el directorio de trabajo de la aplicación a aquel donde se encuentra // el ejecutable. ChDir(ExtractFilePath(Application->ExeName)); break; // No es necesario (añadido para mayor claridad). default: break; } //*** Crea un temporizador para el módem. *** AddTimers(TimerList, Modem); //*** Agrega la nueva IP a la lista de IPs. *** IPListBox->Clear(); FillStringsWithIPs(IPListBox->Items,UnsoModList); // Selecciona la nueva IP. 131 IPListBox->ItemIndex = IPListBox->Items->IndexOf(IP); IPListBoxClick(this); //*** Actualiza la ventana de estado. *** AnsiString ConnStatus; if(RF == "00.00.00") ConnStatus = "Inactivo"; else ConnStatus = "Desconectado"; StatusForm->AddToStatusSG(IPListBox->ItemIndex, IP, ConnStatus); StatusForm->GenStatusSG->Cells[1][0] = IntToStr(TimerList->Count); delete Modem; } Listado 4.24. Función AddModem. Prepara el sistema para que opere con un nuevo módem. Variable u objeto Tipo IP AnsiString MM AnsiString Explicación IP del módem de la nueva entrada en la base de módems. Nombre del modelo del módem de la nueva entrada en la base de módems. Nombre del usuario con acceso al módem de la nueva UN AnsiString entrada en la base de módems. Contraseña del usuario con acceso al módem de la nueva PW AnsiString entrada en la base de módems. Intervalo entre las lecturas automáticas en la nueva RF AnsiString entrada en la base de módems. Valor que informa a la función sobre el origen del archivo Opt int de SNRs asociado a la nueva entrada en la base de módems. Stream utilizado para las operaciones de escritura al ModemDB TFileStream* archivo que contiene la base de módems. Datos a escribir en el archivo que contiene la base de MdmRec AnsiString módems. Modem TStringList* Nueva entrada de la base de módems. 132 UnsoModList TStringList* NewFileName AnsiString Ver Tabla 4.1. Nombre del archivo de SNRs asociado a la nueva entrada en la base de módems. Ventana de diálogo para la selección de un archivo de OpenSNRArchDlg TOpenDialog* SNRs existente. TimerList TList* Ver Tabla 4.1. IPListBox TListBox* Ver Tabla 4.10. ConnStatus AnsiString Estado de la conexión con el módem de la nueva entrada en la base de módems. StatusForm TStatusForm* Ver Tabla 4.16. GenStatusSG TStringGrid* Ver Tabla 4.16. Tabla 4.19. Variables y objetos utilizados en el Listado 4.24. 4.7.2. Eliminación de una entrada de la base de módems El proceso de eliminación de una entrada de la base de módems (ver 4.2) puede ser iniciado presionando un botón, una combinación de teclas o un ítem del menú, según lo descrito en los puntos 4.3.1.3 y 4.3.1.4. Cualquiera de estas acciones causa la ejecución del manejador del evento OnClick del botón (DelModemSBtnClick, Listado A.8). El manejador DelModemSBtnClick comprueba que existan módems en la base y que la conexión con el módem cuya entrada se desea eliminar no esté activa. Si se cumplen esas condiciones, invoca la función DeleteModem (Listado 4.25), la cual elimina la entrada de la base de módems determinada por la IP seleccionada en la lista de IPs (ver 4.3.1.1) y realiza operaciones de actualización de la interfaz gráfica y otros elementos de la aplicación. 133 DeleteModem requiere como argumento la IP del módem cuya entrada debe ser eliminada. Primero, la función elimina la entrada de la lista que contiene la base de módems en la memoria dinámica (UnsoModList) y sobrescribe con ella la base de módems (ModemDB.txt). Luego, destruye el temporizador asociado a la entrada eliminada y elimina el puntero a él de la lista de punteros a los temporizadores (ver 4.4). Seguidamente, elimina la IP de la lista de IPs. Si esa IP no era la última de la lista, la función selecciona la IP que tomó la posición de la eliminada. En caso contrario, intenta seleccionar la IP en la posición anterior a la eliminada – acción que es posible sólo si la eliminada no era la única existente. Si fue posible seleccionar una IP, la función invoca el manejador del evento OnClick de la lista de IPs (Listado 4.15), el cual actualiza algunos elementos de la interfaz gráfica. Si no fue posible (es decir, no hay más entradas en la base de módems), se actualizan todos los elementos de la interfaz gráfica relacionados con la selección en la lista de IPs, de manera que no desplieguen información específica. Finalmente, la función actualiza la ventana de estado, de acuerdo a lo descrito en el punto 4.6.4. void __fastcall TCuLAMainForm::DeleteModem(AnsiString IP) { // Elimina la entrada de UnsoModList y sobrescribe la base de módems. int IPIdxMDB = UnsoModList->IndexOf("IP:"+IP); for(int i=1; i<=5; i++) UnsoModList->Delete(IPIdxMDB); UnsoModList->SaveToFile("ModemDB.txt"); // Destruye el temporizador asociado a la entrada eliminada y elimina su puntero // de la lista. TTimer *TimerPtr; TimerPtr = (TTimer*)TimerList->Items[IPIdxMDB/5]; delete TimerPtr; TimerList->Delete(IPIdxMDB/5); 134 // Elimina la IP de la lista de IPs int IPIdxLB = IPListBox->Items->IndexOf(IP); IPListBox->Items->Delete(IPIdxLB); // Si en la lista de IPs hay una IP en la posición de la eliminada, selecciona // esa IP. Si no, intenta seleccionar la IP anterior. if(IPListBox->Items->Count - 1 >= IPIdxLB) IPListBox->ItemIndex = IPIdxLB; else IPListBox->ItemIndex = IPIdxLB - 1; // Si hay una IP seleccionada, invoca IPListBoxClick. Si no (no hay más IPs), // actualiza los elementos gráficos pertinentes. if(IPListBox->ItemIndex >= 0) IPListBoxClick(this); else { ModModelEdit->Clear(); UserEdit->Clear(); FrecEdit->Clear(); LastReadChart->Series[0]->Clear(); LastReadInfoLbl->Caption = "Razón Señal-Ruido"; FromDateCB->Clear(); FromDateCB->Enabled = false; ToDateCB->Clear(); ToDateCB->Enabled = false; HistoricSNRSeries->Clear(); HistoricChart->View3DOptions->Rotation = 310; HistoricChart->View3DOptions->Elevation = 340; DateLB->Clear(); SpecSNRSeries->Clear(); SpecChartInfoLbl->Caption = "Razón Señal-Ruido"; } // Actualiza la ventana de estado. StatusForm->GenStatusSG->Cells[1][0] = IntToStr(TimerList->Count); StatusForm->DelFromStatusSG(IPIdxLB); } Listado 4.25. Función DeleteModem. Elimina una entrada de la base de módems y actualiza la aplicación para que no opere con el módem eliminado. 135 Variable u objeto Tipo Explicación IP del módem cuya entrada en la base de módems (ver 4.2) IP AnsiString debe ser eliminada. Posición en la lista de IPs (ver 4.3.1.1) de la IP del módem IPIdxLB cuya entrada en la base de módems (ver 4.2) debe ser int eliminada. Posición de la primera línea de la entrada en la base de IPIdxMDB int módems (ver 4.2) que debe ser eliminada. i int Variable utilizada como contador. UnsoModList TStringList* Ver Tabla 4.1. "ModemDB.txt" AnsiString Ver Tabla 4.1. TimerPtr TTimer* Puntero al temporizador asociado a la entrada en la base de módems (ver 4.2) que debe ser eliminada. TimerList TList* Ver Tabla 4.1. StatusForm TStatusForm* Ver Tabla 4.16. GenStatusSG TStringGrid* Ver Tabla 4.16. IPListBox TListBox* Ver Tabla 4.10. Tabla 4.20. Variables y objetos utilizados en el Listado 4.25. 4.7.3. Reconfiguración de una entrada de la base de módems El proceso de reconfiguración de una entrada de la base de módems (ver 4.2) puede ser iniciado presionando un botón, una combinación de teclas o un ítem del menú, según lo descrito en los puntos 4.3.1.3 y 4.3.1.4. Cualquiera de estas acciones causa la ejecución del manejador del evento OnClick del botón (ReprogSBtnClick, Listado A.9). El manejador ReprogSBtnClick primero comprueba que no esté activa la conexión con el módem cuya entrada se desea reconfigurar. Si se cumple esa condición, inicializa 136 algunas propiedades y componentes de la ventana de diálogo para la reconfiguración de una entrada (ver 4.3.3), la cual es seguidamente desplegada. Si la conexión con el módem está activa, se muestra un mensaje de error que informa sobre este hecho. Cuando el usuario presiona el botón “Guardar” de la ventana de diálogo, se ejecuta su manejador del evento OnClick (SaveBtnClick – ver Listado 4.26), definido en el formulario de la ventana. Éste comprueba que no exista otra entrada con la IP de la entrada reconfigurada, ya que no deben existir dos entradas para el mismo módem. Si no se cumple esa condición, se despliega un mensaje de error. Si se cumple la condición, el manejador invoca la función DeleteModem (Listado 4.25) con la IP de la entrada reconfigurada, de manera de eliminar esa entrada del sistema. Luego determina el nuevo nombre del archivo de SNRs y, dependiendo de la selección en las “Opciones de archivo” de la ventana de diálogo, crea un nuevo archivo de SNRs o renombra el existente para que su nombre cumpla con la norma descrita en el punto 4.2. Seguidamente el manejador añade al sistema una nueva entrada invocando la función AddModem (Listado 4.24) con los datos de la entrada reconfigurada e indicando que el archivo de SNRs existe y se encuentra en la carpeta apropiada. Finalmente informa mediante un mensaje la finalización del proceso y cierra la ventana de diálogo. void __fastcall TIPReprogDlgForm::SaveBtnClick(TObject *Sender) { // Comprueba que no exista otra entrada con la IP de la entrada reconfigurada. if(CuLAMainForm->IPListBox->Items->IndexOf(IPEdit->Text) == -1 || OldIP == IPEdit->Text) { // Elimina la entrada del sistema. CuLAMainForm->DeleteModem(OldIP); // Determina el nuevo nombre del archivo de SNRs. 137 AnsiString NewFileName = "SNR" + IPEdit->Text; while(NewFileName.Pos(".")) NewFileName.Delete(NewFileName.Pos("."),1); NewFileName += ".snr"; // Ejecuta una acción, dependiendo de la selección en las "Opciones de archivo". switch(FileRGrp->ItemIndex) { // Si se seleccionó "Crear nuevo archivo de SNRs.", crea el nuevo archivo. case 0: FileClose(FileCreate(NewFileName)); break; // Si se seleccionó "Continuar usando el mismo archivo de SNRs.", renombra // el archivo existente. case 1: { AnsiString OldFileName = "SNR" + OldIP; while(OldFileName.Pos(".")) OldFileName.Delete(OldFileName.Pos("."),1); OldFileName += ".snr"; RenameFile(OldFileName, NewFileName); } } // Añade al sistema la entrada reconfigurada indicando que el archivo de SNRs // existe y se encuentra en la carpeta apropiada CuLAMainForm->AddModem (IPEdit->Text,MModelCBox->Text,UserEdit->Text,PWEdit->Text,freqEdit->Text,-1); // Informa que la entrada fue reconfigurada. MessageDlg("El entrada fue reconfigurada.", mtInformation,TMsgDlgButtons() << mbOK,0); // Cierra la ventana de diálogo. Close(); } 138 // Si existe otra entrada con la IP de la entrada reconfigurada, despliega un // mensaje de error. else MessageDlg("Ya existe una entrada configurada con IP "+IPEdit->Text, mtError, TMsgDlgButtons() << mbOK, 0); } Listado 4.26. Función SaveBtnClick. Manejador del evento OnClick del botón “Guardar” de la ventana de diálogo para reconfigurar una entrada. Variable u objeto Tipo Explicación CuLAMainForm TCuLAMainForm* Ver Tabla 4.1. IPListBox TListBox* Ver Tabla 4.10. IPEdit TLabeledEdit* Componente para introducir la IP del módem. OldIP AnsiString IP del módem antes de ser reconfigurada la entrada de la base de módems (ver 4.2). NewFileName AnsiString FileRGrp TRadioGroup* Nombre del nuevo archivo de SNRs (ver 4.2). Componente donde se selecciona la opción concerniente al archivo de SNRs. Nombre del archivo de SNRs (ver 4.2) antes de ser OldFileName AnsiString reconfigurada la entrada de la base de módems (ver 4.2). Componente para introducir o seleccionar el nombre del MModelCBox TComboBox* modelo del módem. UserEdit TLabeledEdit* Componente para introducir el nombre del usuario. PWEdit TLabeledEdit* Componente para introducir la contraseña del usuario. freqEdit TMaskEdit* Componente para introducir el intervalo entre lecturas remotas de la característica de la SNR. Tabla 4.21. Variables y objetos utilizados en el Listado 4.26. 139 5. Resultados de lecturas experimentales 5. Inicio de numeración figuras, tablas y listados El sistema desarrollado en el presente trabajo fue utilizado para la lectura, almacenamiento y despliegue de las SNRs de los subcanales de transmisión de conexiones ADSL con módems SpeedTouch Pro (ver 3.5). Los datos adquiridos muestran diversos patrones de características de la SNR y, en la mayoría de los casos, marcadas variaciones de ésta en el tiempo. Se observó que a menudo cambios pronunciados ocurren durante espacios de tiempo relativamente cortos, razón por la cual se configuró las entradas de la base de módems de manera que la aplicación realizara lecturas frecuentes desde los módems – en intervalos entre 20 y 60 min. El espacio de tiempo durante el cual se realizaron lecturas remotas desde los módems estuvo entre 15 y 30 días para la mayor parte de los casos. Este período demostró ser suficiente como para observar la ocurrencia de variaciones en el tiempo de la característica de la SNR, así como su periodicidad o aleatoriedad. Las SNRs adquiridas desde los módems SpeedTouch Pro corresponden a las subportadoras del canal descendente, como se vio en el punto 3.5. Así, los gráficos presentados en este capítulo muestran las características para las frecuencias desde 164 hasta 1104 kHz, aproximadamente (equivalentes a los subcanales del 38 al 255). La Fig. 5.1 muestra dos características de la SNR leídas desde dos módems distintos. Entre ellas se observan marcadas diferencias que reflejan las disímiles condiciones bajo las que operan esos servicios ADSL. Una diferencia evidente es la magnitud de las SNRs. En el caso de la característica (a), la SNR se mantiene sobre los 36 dB a lo ancho de casi todo el rango de frecuencias del canal de bajada; en cambio, en la característica (b), la SNR 140 disminuye paulatinamente desde unos 29 dB, para las frecuencias más bajas, hasta unos 10 dB, para las frecuencias más altas. Si se asume que estas características no varían significativamente en el tiempo, esto implica que la conexión a la que corresponde la primera de ellas es capaz de soportar velocidades de transmisión mayores. Otra diferencia notoria entre estas dos características es la presencia en la Fig. 5.1 (a) de interferencias de banda angosta que se manifiestan como caídas repentinas de la SNR para las frecuencias de 590, 620, 680, 860 y 1030 kHz, aproximadamente. Dadas las frecuencias y la forma de las interferencias, es probable que éstas se deban a la presencia de señales de radio de onda media (ver 2.4.6). En algunos bucles del abonado se observaron cambios fuertes y repentinos en la magnitud de las SNRs de los subcanales de transmisión en sentido descendente. La línea a la cual pertenecen las características en la Fig. 5.2 representa un ejemplo de ello. Estas características fueron leídas desde un mismo módem con un intervalo de 28 min. entre ellas. En el gráfico de la Fig. 5.2 (a) se observa que las SNRs poseen valores sobre los 32 dB a lo ancho de la mayor parte del rango de frecuencias utilizado por el canal de bajada. En cambio, la característica leída desde el módem 28 minutos más tarde, mostrada en la Fig. 5.2 (b), refleja un drástico cambió en las SNRs, las cuales adoptaron valores entre los 20 y 6 dB, aproximadamente. Esto sugiere que la potencia del ruido en ese rango de frecuencias aumentó aproximadamente 100 veces. 141 (a) (b) Fig. 5.1. Características de la SNR de dos conexiones ADSL con visibles diferencias en sus magnitudes y patrones. 142 Luego de alrededor de 22 hrs., la característica de la SNR retornó a niveles relativamente altos, cercanos al mostrado en la Fig. 5.2 (a), y así se mantuvo, con ligeras fluctuaciones, durante los siguientes 3 días en que fueron realizadas lecturas desde ese módem. Los bajos valores alcanzados por las SNRs en la Fig. 5.2 (b) habían tenido precedentes; sin embargo, las otras dos disminuciones tuvieron lugar 16 y 17 días antes (dentro del espacio de tiempo abarcado por las lecturas experimentales realizadas desde ese módem). Este hecho sugiere que normalmente la conexión puede soportar velocidades de transmisión relativamente altas, pero que es necesario, si se quiere evitar interrupciones prolongadas del servicio, que el sistema esté configurado para disminuir la velocidad cuando las condiciones empeoran; es decir, que esté configurado como RADSL (ver 2.8.2). En algunos casos, las variaciones en el tiempo de las características de la SNR presentaron un patrón periódico que era a veces interrumpido por períodos de relativa estabilidad. En todos los casos en que se observó esta periodicidad, el ciclo de cambios se completaba en 24 hrs. Sin embargo, hubo diferencias en las horas en que las SNRs adoptaban sus valores máximos y mínimos, así como también en las velocidades y magnitud de los cambios. La Fig. 5.3 (a) muestra la variación en el tiempo de la característica de la SNR leída desde un módem. El gráfico abarca un espacio de tiempo de 7 días – desde el lunes 14/03/2005 hasta el domingo 20/03/2005 –, durante los cuales el sistema realizó lecturas cada 32 min. En la figura se observan cambios bruscos, amplios y periódicos de la característica de la SNR, iniciando a las 19 hrs., aproximadamente, del día 15/03/2005 y continuando hasta el último día. Los cambios de las SNRs de valores mayores a menores ocurrieron todos alrededor de las 19 hrs. de cada día y los cambios en sentido contrario, alrededor de las 8:30 hrs. 143 (a) (b) Fig. 5.2. Cambio fuerte y repentino de la magnitud de las SNRs de los subcanales de transmisión en sentido descendente de una conexión ADSL. 144 La Fig. 5.3 (b) representa otro ejemplo de este tipo de variaciones. El gráfico abarca un período de 5 días – desde el sábado 19/03/2005 hasta el jueves 24/03/2005, durante los cuales las lecturas fueron realizadas en intervalos de 32 min. A diferencia de la Fig. 5.3 (a), la característica de la SNR presenta aquí variaciones menos repentinas y de menor magnitud y, además, la disminución de las SNRs tiene lugar en otro momento del día – entre las 9 y las 20 hrs., aproximadamente. Entre los resultados obtenidos, se encontraron también situaciones en que se produjeron cambios relativamente permanentes en el patrón de las variaciones en el tiempo de la característica de la SNR. Este hecho sugiere que en un momento dado tuvo lugar un cambio en uno o varios de los factores que influyen en las transmisiones ADSL (ver 2.4). Dado el impacto que esto puede tener en la calidad del servicio, probablemente sería de utilidad para el proveedor determinar las causas que condujeron a ello. De esa manera, si el impacto fue negativo, puede buscarse evitar situaciones similares en el futuro. El gráfico de la Fig. 5.4 (a) muestra la variación en el tiempo de la característica de la SNR en un período de aproximadamente 4 días – desde el sábado 12/03/2005 hasta el miércoles 16/03/2005. En él se observa que la característica no presenta variaciones significativas. Tampoco se habían observado variaciones durante el período de 10 días anteriores al mostrado (que, para mayor claridad, el gráfico no los incluye). 145 (a) (b) Fig. 5.3. Variación en el tiempo de dos características de la SNR de dos conexiones ADSL, donde se observan patrones periódicos. 146 No obstante, aproximadamente a las 8:30 hrs. del miércoles 16/03/2005, los valores de las SNRs comienzan a cambiar. El gráfico de la Fig. 5.4 (b) muestra el resultado. El período abarcado comienza donde termina el del gráfico de la Fig. 5.4 (a) y termina el lunes 21/03/2005. Un aspecto interesante de las variaciones que se observan es que presentan un patrón repetitivo, con un período de 24 hrs., tal como en los ejemplos expuestos más arriba. Aunque las SNRs después del cambio conservan valores relativamente altos, capaces de soportar velocidades de transmisión de unos 4 mbps4 (4·106 bps), es importante señalar que la capacidad del enlace se redujo a casi la mitad. En otras situaciones (por ejemplo, donde la longitud del par trenzado de cobre es mayor), un cambio como el observado puede deteriorar significativamente el servicio ADSL del abonado. En contraste con los casos anteriores, también se dieron situaciones en que los bucles del abonado exhibieron patrones relativamente planos de la característica de la SNR a lo ancho del rango de frecuencias del canal de bajada; los cuales, además, no acusaron cambios mayores durante el período en que se realizaron las lecturas. Es probable que este hecho se deba a longitudes relativamente pequeñas de los bucles, ya que en esos casos, el sistema ADSL puede compensar las variaciones de las SNR de los subcanales mediante el aumento de las potencias de transmisión. 4 Capacidad estimada con la ecuación del punto 2.5.2, para un margen SNR mínimo de 6 dB y una ganancia de codificación de 4 dB. 147 (a) (b) Fig. 5.4. Cambio en el patrón de la variación en el tiempo de la característica de la SNR de una conexión ADSL. 148 Dos ejemplos de esto se observan en la Fig. 5.5, la cual muestra las variaciones en el tiempo de las características de la SNR leídas desde dos módems distintos. Ambos gráficos abarcan un período de 7 días – desde el lunes 14/03/2005 hasta el domingo 20/03/2005 –, y en ellos se observa el patrón relativamente plano y constante de las características. Durante los 8 días anteriores al espacio de tiempo graficado (de un total de 15 días en que se realizaron lecturas) el comportamiento de las características fue similar. Los resultados de las lecturas realizadas durante esos días no se incluyen en los gráficos, de manera de conservar la claridad. En este capítulo se han mostrado diversas representaciones de las características de las SNRs adquiridas durante procesos de lectura desde los módems ADSL, utilizando para ello el sistema diseñado en el capítulo 3 e implementado en el capítulo 4. En el siguiente capítulo se presentan comentarios y conclusiones acerca del sistema desarrollado y de los resultados experimentales obrtenidos. 149 (a) (b) Fig. 5.5. Variación en el tiempo de dos características de la SNR de dos conexiones ADSL, donde se observan patrones relativamente planos y constantes. 150 6. Conclusiones y comentarios Los resultados obtenidos utilizando el sistema desarrollado en el presente trabajo, en muchos casos, muestran claramente la presencia de factores no constantes en el tiempo que afectan marcadamente las condiciones de los bucles de los abonados ADSL. Esto se manifiesta en cambios repentinos, fuertes y a veces periódicos, de los valores de las SNRs de los subcanales a todo lo ancho del rango de frecuencias utilizado para la transmisión. Estas variaciones se traducen en cambios en la capacidad de los enlaces ADSL y, como resultado, en algunos casos, el bucle no es capaz de soportar sostenidamente las velocidades de transmisión deseadas. De esto se deduce que las velocidades máximas que pueden ser ofrecidas a los abonados están determinadas por los niveles mínimos que alcanzan los valores de las SNRs y que la eliminación del factor o factores responsables del deterioro de la conexión permite prestar un mejor servicio. Se observaron también situaciones en que las variaciones de las magnitudes de las SNRs fueron menos amplias o más efímeras. En esos casos, los cambios no representan un problema importante. A lo sumo el servicio experimentará una corta desconexión o una caída momentánea de la velocidad (si el sistema está configurado como RADSL). El sistema aquí desarrollado demostró ser una herramienta que ayuda a determinar las causas de las variaciones de las condiciones de los bucles monitoreados. Basándose en los datos adquiridos, almacenados y desplegados por el sistema, un operador capacitado y experimentado puede realizar el diagnóstico necesario para la erradicación posterior del problema. 151 Un inconveniente que se presenta a la hora de realizar un diagnóstico basándose en un sistema como el aquí creado es que no es posible leer las SNRs de los subcanales de transmisión (o cualquier otro parámetro) desde una unidad remota de terminación ADSL (ATU-R) que no posee sincronización con la unidad de terminación ADSL en la central (ATU-C) del DSLAM. Esto implica que se cuenta sólo con los datos adquiridos desde el módem cuando éste se encontraba en su estado de operación normal (showtime). Esta condición tiene relevancia si el problema que se desea solucionar está relacionado con la imposibilidad del establecimiento de la conexión ADSL. Esto es así porque en algunos casos, la falta de sincronización se debe a interferencias repentinas, no relacionadas con el comportamiento pasado de la característica, lo cual dificulta el diagnóstico. En otros casos, sin embargo, la variación de la característica de la SNR en el tiempo anterior a la desconexión, así como también el patrón que presentaba, sugiere las causas del problema y el diagnóstico puede ser realizado basándose en la herramienta desarrollada. El estudio de las capacidades de los módems ADSL demostró que, a pesar de que los distintos modelos permiten la gestión a través de diversas interfaces, sólo unos pocos ponen a la disposición del operador las SNRs de los subcanales de transmisión. Este hecho, además de limitar la variedad de equipos aptos para trabajar con la presente herramienta de diagnóstico, también constituyó una restricción a las posibilidades de desarrollar el sistema de manera que utilizara otros protocolos de comunicación. En un ámbito más específico, relacionado con el funcionamiento del software desarrollado, es importante llamar la atención sobre la gran cantidad de datos que son leídos desde los módems. Estos datos son almacenados en archivos y utilizados para el despliegue de gráficos a solicitud del operador. Si se extiende el espacio de tiempo en que los módems son monitoreados, es decir, si el número de lecturas realizadas desde cada uno de ellos es elevado, se presenta una situación en que los archivos se tornan demasiado voluminosos. 152 Esto afecta el desempeño de la aplicación, dadas las continuas operaciones de lectura y escritura que se realizan con ellos. El problema mencionado tiene también un impacto negativo en la claridad que presenta el gráfico de la variación en el tiempo de la SNR. Esto es así porque en ese gráfico se despliegan los datos adquiridos en múltiples lecturas. Mientras mayor es el espacio de tiempo abarcado por el gráfico, mayor es la cantidad de datos que debe incluir, lo cual lo hace menos legible y su actualización más lenta. El sistema desarrollado en el presente trabajo demostró ser una alternativa viable a los métodos tradicionales de diagnóstico y solución de problemas de los bucles de los abonados ADSL. Los métodos tradicionales requieren la realización de mediciones en terreno, o la inferencia de las causas de los problemas a partir de datos almacenados por el sistema de gestión del DSLAM, o bien, demandan el cambio del par trenzado del abonado. La herramienta creada brinda la posibilidad de realizar un análisis de las condiciones existentes en un período anterior al momento en que se detectó una falla, y hacerlo desde una estación centralizada de administración, lo cual la convierte en una herramienta útil para la gestión de un importante ámbito en la prestación de servicios ADSL. Comentarios. Además de la realización de análisis de las condiciones de bucles individuales, el sistema creado puede ser utilizado para observar el impacto que tiene la adición de nuevos servicios digitales (ADSL u otros) en el resto de las conexiones ADSL de un mismo cable multipar. El impacto observado será producto de la diafonía introducida por la nueva 153 señal digital. Esta información puede ser de ayuda para estimar la cantidad y el tipo de servicios que pueden ser transportados dentro del cable. Dado que el sistema desarrollado mantiene un registro de los datos leídos desde los módems, sería posible que éste analizara automáticamente el comportamiento pasado de las características de las SNRs con el fin de determinar las máximas velocidades que pueden ser alcanzadas a través del enlace. Esta información sería de utilidad para los proveedores en el momento de evaluar si un bucle posee la capacidad de soportar velocidades mayores (como respuesta a una solicitud de un cliente, a un cambio de política, etc.). En su etapa de desarrollo actual, el sistema no presenta esta funcionalidad, pero podría ser fácilmente implementada en futuras mejoras. Existe una alternativa a la realización de las lecturas desde los módems ADSL que consiste en hacerlo desde los DSLAMs. Sin embargo, como se vio en el punto 2.8.4, éstos tampoco están sujetos a estándares que exijan de los fabricantes posibilitar la lectura de las SNRs de los subcanales (aunque el reporte técnico TR-024 [7] del DSL Forum lo sugiere). Es probable que algunas interfaces de gestión de los DSLAMs faciliten la lectura de esta información, pero durante el desarrollo del presente trabajo no se tuvo acceso a ellas para comprobarlo. No obstante, si así se requiriera, el sistema creado podría ser fácilmente modificado en función de lo planteado, ya que el cambio afectaría únicamente a la hebra de lectura remota y a algunos de los archivos con que trabaja la aplicación. En ADSL las ATUs no tienen la capacidad de monitorear las condiciones de la línea si no se alcanza el estado showtime. En esa situación se torna inaplicable una herramienta de diagnóstico que adquiera los datos sobre las condiciones del bucle desde el DSLAM o, localmente, desde la ATU-R. Sin embargo, los sistemas ADSL2 y ADSL2+ más modernos, que constituyen una nueva generación de ADSL, sí poseen esta capacidad. En ellos se 154 implementó el llamado “modo de diagnóstico del bucle”, al cual las ATUs pueden ingresar en la etapa de inicialización y el cual permite la medición de las SNRs, el ruido y la atenuación de los subcanales de transmisión y el intercambio de los resultados entre ellas. La herramienta aquí desarrollada podría adaptarse para trabajar con esas nuevas tecnologías y sacar provecho de las nuevas capacidades mencionadas. Se observó que es posible que se presenten problemas con el despeño de la aplicación aquí desarrollada, si la cantidad de datos almacenados se incrementa demasiado. Una sencilla solución sería limitar el espacio de tiempo abarcado por las lecturas almacenadas. De esa manera, las lecturas más antiguas serían descartadas a medida que se realizan otras. Un segunda solución podría consistir almacenar los valores leídos de las SNRs de los subcanales sólo si éstos se diferencian suficientemente de los últimos almacenados. Una tercera alternativa sería definir un tamaño máximo para los archivos de SNRs. Una vez que un archivo alcance ese tamaño, se crearía uno nuevo y se conservaría el antiguo. La aplicación, entonces, operaría con archivos menores y sólo con aquellos que necesita en un determinado momento. Como se ha visto, existen varias líneas de desarrollo que pueden mejorar el sistema creado, así como también, adaptarlo a las nuevas tecnologías o a nuevas premisas. Esto le otorga a la herramienta flexibilidad y la capacidad de ser un valioso instrumento de apoyo para la gestión de redes digitales ADSL, o eventualmente ADSL2 y ADSL2+. 155 Bibliografía [1] ITU-T Recommendation G.992.1. “Asymmetric digital subscriber line (ADSL) transceivers”. Jun. 1999. [2] ITU-T Recommendation G.992.3. “Asymmetric digital subscriber line transceivers 2 (ADSL2)”. Ene. 2005. [3] ITU-T Recommendation G.994.1. “Handshake procedures for digital subscriber line (DSL) transceivers”. Jun. 1999. [4] ITU-T Recommendation G.997.1. “Physical layer management for digital subscriber line (DSL) transceivers”. Jun. 1999. [5] ANSI Standard T1.413. “Network to Customer Installation Interfaces - Asymmetric Digital Subscriber Line (ADSL) Metallic Interface”. 1998. [6] ADSL Forum Technical Report TR-005. “ADSL Network Element Management”. Mar. 1998. Disponible: http://www.dslforum.org/techwork/tr/TR-005.pdf [7] ADSL Forum Technical Report TR-024. “DMT Line Code Specific MIB”. Jun. 1999. Disponible: http://www.dslforum.org/techwork/tr/TR-024.pdf [8] ADSL Forum Technical Report TR-027. “SNMP-based ADSL LINE MIB”. Sep. 1999. Disponible: http://www.dslforum.org/techwork/tr/TR-027.pdf. [9] “ADSL Tutorial”. DSL Forum. 2001. Disponible: http://www.dslforum.org/aboutdsl/adsl_tutorial.html. [10] Sitio web del DSL Forum. Disponible: http://www.dslforum.org/. [11] RFC-1213. “Management Information Base for Network Management of TCP/IPbased internets: MIB-II”. RFC Editor. Mar. 1991. Disponible: ftp://ftp.rfceditor.org/in-notes/rfc1213.txt. [12] RFC-2662. “Definitions of Managed Objects for the ADSL Lines”. RFC Editor. Ago. 1999. Disponible: ftp://ftp.rfc-editor.org/in-notes/rfc2662.txt. 156 [13] Conjunto de componentes Internet Component Suite. OverByte - François Piette. Disponible: http://www.overbyte.be/. [14] Louis Litwin, Michael Pugel, Rob Rhodes, John Richardson. “ADSL Technology Explained, Part 1: The Physical Layer”. CommsDesign. Mar. 2001. Disponible: http://www.commsdesign.com/showArticle.jhtml?articleID=16502655. [15] Louis Litwin, Michael Pugel, Rob Rhodes, John Richardson. “ADSL Technology Explained, Part 2: Getting to the Application Layer”. CommsDesign. Abr. 2001. Disponible: http://www.commsdesign.com/showArticle.jhtml?articleID=16502772. [16] Arthur Redfern, Fernando Mujica, Murtaza Ali. “Expanding the Reach of ADSL”. CommsDesign. Jul. 2003. Disponible: http://www.commsdesign.com/design_corner/OEG20030717S0028. [17] “TN089. ADSL Integral. Planta Interna”. Tomos I, II y III. Edición 2. Telefónica. Ago. 2002. [18] John A. C. Bingham. “ADSL, VDSL, and Multicarrier Modulation”. John Wiley & Sons, Inc. 2000. [19] John M. Cioffi "A Multicarrier Primer", Amati Communications Corporation and Stanford University. Nov. 1991. [20] Dimitrios Sofos, Vassilis Stylianakis. “An Applied Bit Rate Estimation Method for ADSL-based Networks”. Department of Electrical and Computer Engineering. University of Patras. Greece. Jul. 2002. Disponible: http://www.scit.wlv.ac.uk/~jphb/cp4040/rolandonotes/CSNDSP2002/Papers/C1/C1. 1.pdf. [21] “The DSL Sourcebook – The Comprehensive Resource on Digital Subscriber Line Technology”. Paradyne Corporation. 2000. Disponible: http://www.paradyne.com/solutions/whitepapers/dsl_sourcebook/sb_1file.pdf. 157 [22] Peter J.W. Melsa, Krista S. Jacobsen. “Single-Ended Loop Testing (SELT). Expectations and Realities”. Texas Instruments, Broadband Communications Group. Mar. 2003. Disponible: http://focus.ti.com/pdfs/bcg/selt_wp.pdf. [23] Walter Goralski. "xDSL Loop Qualification and Testing". IEEE Communications Magazine, vol. 37, no. 5, pp. 79-83. May. 1999. [24] “ADSL Basics (DMT) – Technical Note”. TTC. May. 1998. Disponible: http://www.livingston.co.uk/fileadmin/downloads/uk/PDFs/ADSL_Basics.pdf. [25] “ADSL technology – Overview, line qualification and service turn-up”. Acterna. Abr. 2002. Disponible: http://www.acternaservices.com/united_states/technical_resources/downloads/white_papers/ADSL_T echnology_White_Paper.pdf. [26] “Optimized ADSL Performance – Central Office Practices”. Rev. A. Allied Telesyn. May. 2004. Disponible: http://www.alliedtelesyn.com/corporate/media/whitepapers/optim_adsl_wp.pdf [27] Jim Lane. “Personal Broadband Services: DSL and ATM”. Virata. 1998. Disponible: http://www.protocols.com/papers/pdf/virata_dsl2.pdf. [28] Liang C. Chu. “ADSL System Enhancement with Multiuser Detection”. Thesis Presented to The Faculty of the Division of Graduate Studies. Georgia Institute of Technology. Jul. 2001. Disponible: http://citeseer.csail.mit.edu/cache/papers/cs/29909/http:zSzzSzusers.ece.gatech.edu zSz~mbrookezSzThesiszSzliang.pdf/adsl-system-enhancement-with.pdf [29] Michael Schlegel. “High Bit Rate Data Transmission over the Telephone loop plant, Emphasising on DMT Modulation Scheme”. Diploma Thesis. Technological Educational Institute of Piraeus. 2001. Disponible: http://people.freenet.de/michael.schlegel/diplomarbeit.pdf. [30] “Copper Qualification Application Note – The ALT2000 from Trend Communications”. Trend Communications. Disponible: 158 http://www.trendcomms.com/trendweb/resource.nsf/vlFileURLLookup/The+Case +for+copper+qualification/$FILE/copperqual2.pdf. [31] Ildefonso M. Polo. “Técnicas de Prueba en Banda Ancha – Más allá del ADSL”. Sunrise Telecom, Inc. Jun. 2002. Disponible: www.sunrisetelecom.com/espanol/presentacion_pruebas_en_xdsl.pdf. [32] “NetAtlas Access User’s Guide”. Version 2.02. ZyXEL Communications Corporation. Oct. 2005. Disponible: ftp://ftp.zyxel.com/NetAtlas_IES_2000_3000/document/NetAtlas_IES_2000_3000_v 2-02Win_UsersGuide.pdf. [33] “Cisco DSL Manager NI-2 User Guide”. Release 3.4. Cisco Systems, Inc. Mar. 2002. Disponible: http://www.cisco.com/application/pdf/en/us/guest/products/ps4877/c2001/ccmigra tion_09186a008012a39a.pdf. [34] “OfficeConnect® Remote 812 ADSL Router CLI User’s Guide”. Release 2.0. 3Com Corporation. Jun. 2001. Disponible: http://support.3com.com/infodeli/tools/remote/ocradsl/20/812_cli20.pdf. [35] “DSL-504T User’s Manual”. Version 1.0. D-Link Systems, Inc. Disponible: ftp://ftp.dlink.com/Broadband/dsl504T/Manual/DSL-504T_manual_07142005.zip. 159 Anexo A. Declaraciones y funciones no incluidas en el capítulo 4 class TCuLAMainForm : public TForm { __published: // IDE-managed Components TListBox *IPListBox; TStatusBar *StatusBar1; TMainMenu *MainMenu; TMenuItem *File; TMenuItem *Exit; TToolBar *ToolBar; TPanel *RightBottPanel; TPageControl *OutputPageControl; TTabSheet *LastReadTabSheet; TSpeedButton *AddModemSBtn; TPanel *InfoPanel; TLabel *ModModelLbl; TLabel *UserLbl; TLabel *FrecLbl; TEdit *ModModelEdit; TEdit *UserEdit; TEdit *FrecEdit; TChart *LastReadChart; TLineSeries *LastSNRSeries; TTabSheet *HistoricTabSheet; TChart *HistoricChart; TSurfaceSeries *HistoricSNRSeries; TRotateTool *ChartTool1; TSpeedButton *DelModemSBtn; TSpeedButton *ReadoutSBtn; TSpeedButton *ReprogSBtn; TTabSheet *SpecTabSheet; TListBox *DateLB; TChart *SpecReadChart; TLineSeries *SpecSNRSeries; TBevel *Bevel1; TBevel *Bevel2; TPanel *HistChartInfoPanel; TLabel *HistChartInfoLbl; 160 TPanel *LastReadInfoPanel; TLabel *LastReadInfoLbl; TPanel *SpecChartInfoPanel; TLabel *SpecChartInfoLbl; TPanel *ShowChartOptsPanel; TSpeedButton *ShowChartOptsSB; TLabel *ShowChartOptsLbl; TPanel *ChartOptsPanel; TGroupBox *DisplayLmtsGB; TLabel *FromDateLbl; TLabel *ToDateLbl; TComboBox *FromDateCB; TComboBox *ToDateCB; TGroupBox *RotateGB; TSpeedButton *LeftSBtn; TSpeedButton *RightSBtn; TSpeedButton *UpSBtn; TSpeedButton *DownSBtn; TSpeedButton *CenterSBtn; TSpeedButton *ShowStatusSB; TBevel *Bevel3; TBevel *Bevel4; TPanel *Panel1; TPanel *Panel2; TLabel *Label1; TPanel *Panel3; TLabel *Label2; TPanel *Panel4; TBevel *Bevel5; TMenuItem *Modem; TMenuItem *Add; TMenuItem *Delete; TMenuItem *Reconfigure; TMenuItem *N1; TMenuItem *Read; TMenuItem *View; TMenuItem *Status; TMenuItem *Help; TMenuItem *About; TOpenDialog *OpenSNRArchDlg; TLabel *SpeedLbl; void __fastcall AddModemSBtnClick(TObject *Sender); void __fastcall FormCreate(TObject *Sender); 161 void __fastcall IPListBoxClick(TObject *Sender); void __fastcall FormDestroy(TObject *Sender); void __fastcall DelModemSBtnClick(TObject *Sender); void __fastcall ReadoutSBtnClick(TObject *Sender); void __fastcall ReprogSBtnClick(TObject *Sender); void __fastcall DateLBClick(TObject *Sender); void __fastcall ToDateCBSelect(TObject *Sender); void __fastcall FromDateCBSelect(TObject *Sender); void __fastcall RightSBtnClick(TObject *Sender); void __fastcall LeftSBtnClick(TObject *Sender); void __fastcall UpSBtnClick(TObject *Sender); void __fastcall DownSBtnClick(TObject *Sender); void __fastcall CenterSBtnClick(TObject *Sender); void __fastcall ShowChartOptsSBClick(TObject *Sender); void __fastcall ShowStatusSBClick(TObject *Sender); void __fastcall AddClick(TObject *Sender); void __fastcall ExitClick(TObject *Sender); void __fastcall DeleteClick(TObject *Sender); void __fastcall ReconfigureClick(TObject *Sender); void __fastcall ReadClick(TObject *Sender); void __fastcall StatusClick(TObject *Sender); void __fastcall AboutClick(TObject *Sender); private: public: // User declarations // User declarations __fastcall TCuLAMainForm(TComponent* Owner); void __fastcall FillStringsWithIPs(TStrings*,TStringList*); void __fastcall AddTimers(TList*, TStringList*); void __fastcall ATimerOnTimer(TObject *Sender); void __fastcall NewReadoutThreadTerminate(TObject *Sender); void __fastcall AddModem (AnsiString IP, AnsiString MM, AnsiString UN, AnsiString PW, AnsiString RF, int Opt); void __fastcall DrawLastReadChart(AnsiString IP); void __fastcall DrawHistoricChart(AnsiString IP); void __fastcall DrawSpecChart(AnsiString IP, AnsiString ReadoutDateSel); void __fastcall FillCBs(AnsiString IP); void __fastcall FillDateLB(AnsiString IP); void __fastcall DeleteModem(AnsiString IP); bool __fastcall ReadingModem(AnsiString IP); TStringList *UnsoModList; TTimer *ATimer; 162 TList *TimerList; TList *ActiveThreads; }; Listado A.1. Declaración de la clase TCuLAMainForm de la cual el formulario CuLAMainForm es una instancia. void __fastcall TCuLAMainForm::FormDestroy(TObject *Sender) { // Destruye los temporizadores. for(int i=0; i<TimerList->Count; i++) { ATimer = (TTimer *)TimerList->Items[i]; delete ATimer; } // Destruye los objetos creados en FormCreate. delete TimerList; delete ActiveThreads; delete UnsoModList; } Listado A.2. Función FormDestroy. Manejador del evento OnDestroy del formulario TCuLAMainForm. bool __fastcall TCuLAMainForm::ReadingModem(AnsiString IP) { // Crea un puntero a una hebra de lectura remota. ReadoutThread *ThreadPtr; // Recorre la lista de punteros a las hebras. for(int i=1; i<=ActiveThreads->Count; i++) { // Si la hebra está leyendo desde IP, la función devuelve true. ThreadPtr = (ReadoutThread *)ActiveThreads->Items[i-1]; if(ThreadPtr->IP == IP) return true; } 163 // Si ninguna hebra está leyendo desde IP, la función devuelve false. return false; } Listado A.3. Función ReadingModem. Comprueba si existe una conexión activa con un módem. void __fastcall TCuLAMainForm::NewReadoutThreadTerminate(TObject *Sender) { // Crea un puntero a la hebra que está terminando y al temporizador que la lanzó. ReadoutThread *ThreadPtr = (ReadoutThread *)Sender; int TimerIdx = UnsoModList->IndexOf("IP:"+ThreadPtr->IP)/5; TTimer *TimerPtr = (TTimer *)TimerList->Items[TimerIdx]; // Si el temporizador está inactivo, cambia el estado de la conexión con este // módem a "inactivo" if(!TimerPtr->Interval) StatusForm->StatusSG->Cells[1][StatusForm->StatusSG->Cols[0]->IndexOf (ThreadPtr->IP)] = "Inactivo"; // Elimina el puntero a la hebra de la lista de hebras activas y actualiza el // número de conexiones activas en la ventana de estado. ActiveThreads->Delete(ActiveThreads->IndexOf(Sender)); StatusForm->GenStatusSG->Cells[1][1] = IntToStr(ActiveThreads->Count); } Listado A.4. Función NewReadoutThreadTerminate. Manejador del evento OnTerminate de una hebra ReadoutThread. void __fastcall TCuLAMainForm::FromDateCBSelect(TObject *Sender) { int i; // Reccorre desde el segundo ítem de FromDateCB hasta el último. for(i=1; i <= FromDateCB->Items->Count - 1; i++) { // Si el índice i apunta a un ítem anterior o igual al seleccionado y éste 164 // se encuentra en ToDateCB, se elimina de éste último. if(i <= FromDateCB->ItemIndex && ToDateCB->Items->IndexOf(FromDateCB->Items->Strings[i]) == 0) ToDateCB->Items->Delete(0); // Si el índice i apunta a un ítem posterior al seleccionado y éste no se // encuentra en ToDateCB, se añade a éste último. if(i > FromDateCB->ItemIndex && ToDateCB->Items->IndexOf(FromDateCB->Items->Strings[i]) == -1) ToDateCB->Items->Insert (i - FromDateCB->ItemIndex - 1,FromDateCB->Items->Strings[i]); } // Actualiza el gráfico de la variación en el tiempo de la característica de la SNR. DrawHistoricChart(IPListBox->Items->Strings[IPListBox->ItemIndex]); } Listado A.5. Función FromDateCBSelect. Manejador del evento OnSelect de FromDateCB. void __fastcall TCuLAMainForm::ToDateCBSelect(TObject *Sender) { int i; // Recorre desde el primer ítem de ToDateCB hasta el penúltimo. for(i=0; i <= ToDateCB->Items->Count - 2; i++) { // Si el índice i apunta a un ítem posterior o igual al seleccionado y éste // se encuentra en FromDateCB, se elimina de éste último. if(i >= ToDateCB->ItemIndex && FromDateCB->Items->IndexOf(ToDateCB->Items->Strings[i]) > 0) FromDateCB->Items->Delete (FromDateCB->Items->IndexOf(ToDateCB->Items->Strings[i])); // Si el índice i apunta a un ítem anterior al seleccionado y éste no se // encuentra en FromDateCB, se añade a éste último. if(i < ToDateCB->ItemIndex && 165 FromDateCB->Items->IndexOf(ToDateCB->Items->Strings[i]) == -1) FromDateCB->Items->Add(ToDateCB->Items->Strings[i]); } // Actualiza el gráfico de la variación en el tiempo de la característica de la SNR. DrawHistoricChart(IPListBox->Items->Strings[IPListBox->ItemIndex]); } Listado A.6. Función ToDateCBSelect. Manejador del evento OnSelect de ToDateCB. void __fastcall TCuLAMainForm::AddModemSBtnClick(TObject *Sender) { // Despliega la ventana para agregar una entrada. IPProgDlgForm->ShowModal(); } Listado A.7. Función AddModemSBtnClick. Manejador del evento OnClick del botón para añadir una entrada. void __fastcall TCuLAMainForm::DelModemSBtnClick(TObject *Sender) { // Si no existen módems en la base finaliza la ejecución de la función. if(!IPListBox->Items->Count) { // Informa que no hay entradas en la base. MessageDlg("No existen módems en la base.", mtError, TMsgDlgButtons() << mbOK, 0); return; } // Comprueba que no esté activa la conexión con el módem. if(!ReadingModem(IPListBox->Items->Strings[IPListBox->ItemIndex])) { // Solicita confirmar la eliminación de la entrada. if(MessageDlg("¿Está seguro de que desea eliminar el modem con IP "+ IPListBox->Items->Strings[IPListBox->ItemIndex]+"?", mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes) 166 // Elimina la entrada de la base de módems. DeleteModem(IPListBox->Items->Strings[IPListBox->ItemIndex]); } // Si la conexión con el módem está activa, informa sobre el hecho y finaliza. else MessageDlg("La conexión con este módem está activa\ren este momento.", mtError, TMsgDlgButtons() << mbOK, 0); } Listado A.8. Función DelModemSBtnClick. Manejador del evento OnClick del botón para eliminar una entrada. void __fastcall TCuLAMainForm::ReprogSBtnClick(TObject *Sender) { // Comprueba que no esté activa la conexión con el módem. if(!ReadingModem(IPListBox->Items->Strings[IPListBox->ItemIndex])) { int Idx = UnsoModList->IndexOf ("IP:"+IPListBox->Items->Strings[IPListBox->ItemIndex]); // Inicializa las propiedades de la ventana para la reconfiguración de // una entrada. IPReprogDlgForm->OldIP = UnsoModList->Strings[Idx].SubString (4,UnsoModList->Strings[Idx].Length()-3); IPReprogDlgForm->IPEdit->Text = IPReprogDlgForm->OldIP; IPReprogDlgForm->UserEdit->Text = UnsoModList->Strings[Idx+2].SubString (4,UnsoModList->Strings[Idx+2].Length()-3); IPReprogDlgForm->PWEdit->Text = UnsoModList->Strings[Idx+3].SubString (4,UnsoModList->Strings[Idx+3].Length()-3); IPReprogDlgForm->freqEdit->Text = UnsoModList->Strings[Idx+4].SubString (4,UnsoModList->Strings[Idx+4].Length()-3); IPReprogDlgForm->FileRGrp->ItemIndex = 1; // Despliega la ventana para la reconfiguración de una entrada. IPReprogDlgForm->ShowModal(); } // Si la conexión con el módem está activa, informa sobre este hecho y finaliza. 167 else MessageDlg("La conexión con este módem está activa\ren este momento.", mtError, TMsgDlgButtons() << mbOK, 0); } Listado A.9. Función ReprogSBtnClick. Manejador del evento OnClick del botón para reconfigurar una entrada. void __fastcall TCuLAMainForm::ShowChartOptsSBClick(TObject *Sender) { // Desliega u oculta la ventana de opciones del gráfico. ChartOptsPanel->Visible = !ChartOptsPanel->Visible; } void __fastcall TCuLAMainForm::RightSBtnClick(TObject *Sender) { // Si no se ha alcanzado el límite, rota el gráfico 5º a la derecha. if(HistoricChart->View3DOptions->Rotation < 360) HistoricChart->View3DOptions->Rotation += 5; } void __fastcall TCuLAMainForm::LeftSBtnClick(TObject *Sender) { // Si no se ha alcanzado el límite, rota el gráfico 5º a la izquierda. if(HistoricChart->View3DOptions->Rotation > 270) HistoricChart->View3DOptions->Rotation -= 5; } void __fastcall TCuLAMainForm::UpSBtnClick(TObject *Sender) { // Si no se ha alcanzado el límite, rota el gráfico 5º hacia arriba. if(HistoricChart->View3DOptions->Elevation < 360) HistoricChart->View3DOptions->Elevation += 5; } void __fastcall TCuLAMainForm::DownSBtnClick(TObject *Sender) 168 { // Si no se ha alcanzado el límite, rota el gráfico 5º hacia abajo. if(HistoricChart->View3DOptions->Elevation > 300) HistoricChart->View3DOptions->Elevation -= 5; } void __fastcall TCuLAMainForm::CenterSBtnClick(TObject *Sender) { // Fija la rotación del gráfico en sus valores por omisión. HistoricChart->View3DOptions->Rotation = 310; HistoricChart->View3DOptions->Elevation = 340; } Listado A.10. Funciones ShowChartOptsSBClick, RightSBtnClick, LeftSBtnClick, UpSBtnClick, DownSBtnClick y CenterSBtnClick. Manejadores del evento OnClick del botón para desplegar u ocultar la ventana de opciones del gráfico de la variación en el tiempo de la característica de la SNR y de los botónes para rotar el gráfico. void __fastcall TCuLAMainForm::DateLBClick(TObject *Sender) { // Determina la IP seleccionada en la lista de IPs. AnsiString IP = IPListBox->Items->Strings[IPListBox->ItemIndex]; // Determina la fecha y hora seleccionada en la lista de fechas y horas. AnsiString ReadoutDatePar = DateLB->Items->Strings[DateLB->ItemIndex]; // Actualiza el gráfico. DrawSpecChart(IP, ReadoutDatePar); } Listado A.11. Función DateLBClick. Manejador del evento OnClick de la lista de fechas y horas. void __fastcall TCuLAMainForm::ShowStatusSBClick(TObject *Sender) 169 { // Si la ventana de estado está visible, la oculta, desaprieta el botón // ShowStatusSB y deselecciona el ítem Status del menú Ver. Si no está // visible, hace lo contrario. if(StatusForm->Visible) { ShowStatusSB->Down = false; Status->Checked = false; StatusForm->Hide(); } else { ShowStatusSB->Down = true; Status->Checked = true; StatusForm->Show(); } } Listado A.12. Función ShowStatusSBClick. Manejador del evento OnClick del botón para mostrar u ocultar la ventana de estado. void __fastcall TCuLAMainForm::ExitClick(TObject *Sender) { // Finaliza la aplicación. Application->Terminate(); } void __fastcall TCuLAMainForm::AddClick(TObject *Sender) { // Invoca el manejador del evento OnClick del botón para agregar una entrada. AddModemSBtnClick(this); } void __fastcall TCuLAMainForm::DeleteClick(TObject *Sender) { // Invoca el manejador del evento OnClick del botón para eliminar una entrada. DelModemSBtnClick(this); } 170 void __fastcall TCuLAMainForm::ReconfigureClick(TObject *Sender) { // Invoca el manejador del evento OnClick del botón para reconfigurar una entrada. ReprogSBtnClick(this); } void __fastcall TCuLAMainForm::ReadClick(TObject *Sender) { // Invoca el manejador del evento OnClick del botón para realizar una lectura. ReadoutSBtnClick(this); } void __fastcall TCuLAMainForm::StatusClick(TObject *Sender) { // Invoca el manejador del evento OnClick del botón para desplegar la ventana // de estado. ShowStatusSBClick(this); } void __fastcall TCuLAMainForm::AboutClick(TObject *Sender) { // Despliega la ventana "Acerca de Cu Line Analyzer. AboutForm->ShowModal(); } Listado A.13. Funciones ExitClick, AddClick, DeleteClick, ReconfigureClick, ReadClick, StatusClick y AboutClick. Manejadores del evento OnClick de los ítems del menú. class ReadoutThread : public TThread { private: TTnCnx *ATelnetClient; protected: void __fastcall ATelnetClientDataAvailable 171 (TTnCnx *Sender, Pointer Buffer, int Len); void __fastcall ATelnetClientSessionConnected (TTnCnx *Sender, WORD Error); void __fastcall ATelnetClientSessionClosed (TTnCnx *Sender, WORD Error); void __fastcall TimeoutTimerOnTimer(TObject *Sender); void __fastcall Execute(); void __fastcall UpdateLabels(); void __fastcall LoadCmdList(); void __fastcall UpdateLRChart(); void __fastcall UpdateHistChart(); void __fastcall UpdateCBs(); void __fastcall UpdateDateLB(); void __fastcall DecodeSNR(double *SNR, AnsiString *RawSNR); public: __fastcall ReadoutThread(bool CreateSuspended); AnsiString IP; AnsiString MMod; AnsiString Pwd; TStringList *CmdList; AnsiString *RawSNR; int InstrIdx; bool DataRcvdOK; double SNR[256]; bool Timedout; AnsiString ConnStatus; double ReadoutDateDouble; }; Listado A.14. Declaración de la clase ReadoutThread de la cual las hebras son instancias. __fastcall ReadoutThread::ReadoutThread(bool CreateSuspended) : TThread(CreateSuspended) { // Indica que la hebra es destruida cuando termina su ejecución. FreeOnTerminate = true; } Listado A.15. Constructor de la clase ReadoutThread. 172 void __fastcall ReadoutThread::ATelnetClientSessionConnected (TTnCnx *Sender, WORD Error) { // Actualiza la ventana de estado. ConnStatus = "Conectado"; Synchronize(UpdateLabels); } Listado A.16. Función ATelnetClientSessionConnected. Manejador del evento OnSessionConnected del cliente Telnet. void __fastcall ReadoutThread::UpdateLabels() { // Determina el número de la línea en la ventana de estado, de la IP desde la // cual se está realizando la lectura. int Idx = StatusForm->StatusSG->Cols[0]->IndexOf(IP); // Actualiza el estado de la conexión. StatusForm->StatusSG->Cells[1][Idx] = ConnStatus; } Listado A.17. Función UpdateLabels. Actualiza el estado de la conexión en la ventana de estado. void __fastcall ReadoutThread::UpdateLRChart() { // Encuentra la IP seleccionada en la lista de IPs. AnsiString SelectedIP = CuLAMainForm->IPListBox->Items->Strings [CuLAMainForm->IPListBox->ItemIndex]; // Si la IP del módem corresponde a la IP seleccionada, actualiza el gráfico // de la última lectura. if(SelectedIP == IP) CuLAMainForm->DrawLastReadChart(IP); } Listado A.18. Función UpdateLRChart. Actualiza el gráfico de la última lectura. 173 void __fastcall ReadoutThread::UpdateHistChart() { // Encuentra la IP seleccionada en la lista de IPs. AnsiString SelectedIP = CuLAMainForm->IPListBox->Items->Strings [CuLAMainForm->IPListBox->ItemIndex]; // Si la IP del módem corresponde a la IP seleccionada, actualiza el gráfico // de la variación en el tiempo de la característica de la SNR. if(SelectedIP == IP) CuLAMainForm->DrawHistoricChart(IP); } Listado A.19. Función UpdateHistChart. Actualiza el gráfico de la variación en el tiempo de la característica de la SNR. void __fastcall ReadoutThread::UpdateCBs() { // Determina la IP seleccionada en la lista de IPs. AnsiString SelectedIP = CuLAMainForm->IPListBox->Items->Strings[CuLAMainForm->IPListBox->ItemIndex]; // Comprueba si la lectura actual fue realizada desde el módem cuya IP se encuentra // seleccionada en la lista de IPs. if(SelectedIP == IP) { AnsiString &ReadoutDateStr = *new AnsiString; DateTimeToString(ReadoutDateStr, "dd/mm/yy hh:nn:ss",(TDateTime)ReadoutDateDouble); // Si es la primera lectura realizada de este módem, agrega la fecha y hora de la // lectura actual a FromDateCB. No se debe habilitar los TComboBox, ni agregar // ítems a ToDateCB. if(!CuLAMainForm->FromDateCB->Items->Count) CuLAMainForm->FromDateCB->Items->Add(ReadoutDateStr); // Si se han realizado más de una lectura de este módem... else { // Agrega a ToDateCB la fecha y hora de la lectura actual. CuLAMainForm->ToDateCB->Items->Add(ReadoutDateStr); 174 // Si se han realizado exactamente dos lecturas desde el módem, habilita los // TComboBox y selecciona en FromDateCB el instante correspondiente a la // primera lectura y en ToDateCB, el instante correspondiente a la segunda. if(CuLAMainForm->ToDateCB->Items->Count == 1) { CuLAMainForm->FromDateCB->Enabled = true; CuLAMainForm->ToDateCB->Enabled = true; CuLAMainForm->FromDateCB->ItemIndex = 0; CuLAMainForm->ToDateCB->ItemIndex = 0; } // Si se han realizado más de 2 lecturas desde el módem y si el ítem // seleccionado en ToDateCB corresponde a la fecha y hora de la lectura // anterior a la actual, agrega ese ítem a FromDateCB y selecciona en // ToDateCB la fecha y hora de la lectura actual. if(CuLAMainForm->ToDateCB->ItemIndex == CuLAMainForm->ToDateCB->Items->Count-2) { CuLAMainForm->FromDateCB->Items->Add (CuLAMainForm->ToDateCB->Items->Strings[CuLAMainForm->ToDateCB->ItemIndex]); CuLAMainForm->ToDateCB->ItemIndex++; } } delete &ReadoutDateStr; } } Listado A.20. Función UpdateCBs. Actualiza los componentes TComboBox de la ventana de opciones del gráfico de la variación en el tiempo de la característica de la SNR. void __fastcall ReadoutThread::UpdateDateLB() { // Determina la IP seleccionada en la lista de IPs. AnsiString SelectedIP = CuLAMainForm->IPListBox->Items->Strings[CuLAMainForm->IPListBox->ItemIndex]; // Comprueba si la IP desde la cual se está realizando la lectura es aquella // seleccionada en la lista de IPs. if(SelectedIP == IP) { 175 AnsiString &ReadoutDateStr = *new AnsiString; // Añade la fecha y hora actual a la lista de fechas y horas. DateTimeToString(ReadoutDateStr, "dd/mm/yy hh:nn:ss",(TDateTime)ReadoutDateDouble); CuLAMainForm->DateLB->Items->Add(ReadoutDateStr); // Si la fecha y hora actual es la primera de la lista, la selecciona. if(CuLAMainForm->DateLB->Count == 1) { CuLAMainForm->DateLB->ItemIndex = 0; CuLAMainForm->DateLBClick(this); } } } Listado A.21. Función UpdateDateLB. Actualiza la lista de fechas y horas. class TIPProgDlgForm : public TForm { __published: // IDE-managed Components TComboBox *MModelCBox; TLabeledEdit *UserEdit; TLabeledEdit *PWEdit; TMaskEdit *freqEdit; TLabel *freqLabel; TButton *SaveBtn; TButton *CancelBtn; TLabeledEdit *IPEdit; TGroupBox *ModemGrpBox; TLabel *MModelLbl; TRadioGroup *FileRGrp; TLabel *fFormatLbl; void __fastcall SaveBtnClick(TObject *Sender); void __fastcall CancelBtnClick(TObject *Sender); private: public: // User declarations // User declarations __fastcall TIPProgDlgForm(TComponent* Owner); }; Listado A.22. Declaración de la clase TIPProgDlgForm de la cual es una instancia el formulario de la ventana para añadir una entrada a la base de módems. 176 __fastcall TIPProgDlgForm::TIPProgDlgForm(TComponent* Owner) : TForm(Owner) { // Inicializa el texto desplegado por freqEdit. freqEdit->Text = "00.00.00"; } Listado A.23. Constructor de la clase TIPProgDlgForm. void __fastcall TIPProgDlgForm::SaveBtnClick(TObject *Sender) { // Comprueba que no exista una entrada con la IP introducida por el usuario. if(CuLAMainForm->IPListBox->Items->IndexOf(IPEdit->Text) == -1) { // Añade la entrada a la base de módems. CuLAMainForm->AddModem(IPEdit->Text, MModelCBox->Text, UserEdit->Text, PWEdit->Text, freqEdit->Text, FileRGrp->ItemIndex); MessageDlg("La nueva entrada fue agregada a la base.", mtInformation,TMsgDlgButtons() << mbOK,0); } // Si existe una entrada con la IP introducida por el usuario, despliega un // mensaje de error. else MessageDlg("Ya existe una entrada configurada con IP "+IPEdit->Text, mtError, TMsgDlgButtons() << mbOK, 0); } Listado A.24. Función SaveBtnClick. Manejador del evento OnClick del botón “Guardar” de la ventana para añadir una entrada a la base de módems. void __fastcall TIPProgDlgForm::CancelBtnClick(TObject *Sender) { // Oculta la ventana de diálogo. Close(); 177 } Listado A.25. Función CancelBtnClick. Manejador del evento OnClick del botón “Cancelar” de la ventana para añadir una entrada a la base de módems. class TIPReprogDlgForm : public TForm { __published: // IDE-managed Components TLabeledEdit *PWEdit; TComboBox *MModelCBox; TLabeledEdit *UserEdit; TLabeledEdit *IPEdit; TLabel *freqLabel; TMaskEdit *freqEdit; TRadioGroup *FileRGrp; TGroupBox *MdmGrpBox; TButton *SaveBtn; TButton *CancelBtn; TLabel *MModelLbl; TLabel *freqFormatLbl; void __fastcall CancelBtnClick(TObject *Sender); void __fastcall SaveBtnClick(TObject *Sender); private: // User declarations public: // User declarations __fastcall TIPReprogDlgForm(TComponent* Owner); AnsiString OldIP; }; Listado A.26. Declaración de la clase TIPReprogDlgForm de la cual es una instancia el formulario de la ventana para reconfigurar una entrada de la base de módems. void __fastcall TIPReprogDlgForm::CancelBtnClick(TObject *Sender) { // Oculta la ventana de diálogo. Close(); } 178 Listado A.27. Función CancelBtnClick. Manejador del evento OnClick del botón “Cancelar” de la ventana para reconfigurar una entrada de la base de módems. class TStatusForm : public TForm { __published: // IDE-managed Components TStringGrid *StatusSG; TPanel *Panel1; TStringGrid *GenStatusSG; TPanel *Panel2; void __fastcall FormCreate(TObject *Sender); void __fastcall StatusSGClick(TObject *Sender); void __fastcall GenStatusSGClick(TObject *Sender); void __fastcall StatusSGDrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect, TGridDrawState State); void __fastcall FormClose(TObject *Sender, TCloseAction &Action); private: public: // User declarations // User declarations __fastcall TStatusForm(TComponent* Owner); void __fastcall FillStatusSG(TStrings *Modems); void __fastcall FillGenStatusSG(void); void __fastcall DelFromStatusSG(int Idx); void __fastcall AddToStatusSG(int Idx, AnsiString IP, AnsiString Status); void __fastcall UncheckSG(TStringGrid *SG); }; Listado A.28. Declaración de la clase TStatusForm de la cual es una instancia el formulario de la ventana de estado. void __fastcall TStatusForm::FormClose(TObject *Sender, TCloseAction &Action) { CuLAMainForm->ShowStatusSBClick(this); } Listado A.29. Función FormClose. Manejador del evento OnClose del formulario de la ventana de estado. 179 void __fastcall TStatusForm::AddToStatusSG(int Idx, AnsiString IP, AnsiString Status) { // Si la primera fila de StatusSG contiene datos (existe al menos una entrada en // la base de módems), añade una fila vacía al final del componente. if(StatusSG->Cols[0]->Strings[0] != "") StatusSG->RowCount++; // Desplaza en 1 hacia adelante los contenidos de las filas en la misma posición // y posteriores a aquella donde debe ser insertada la nueva fila. for(int i=StatusSG->RowCount-1; i>=Idx+1; i--) StatusSG->Rows[i] = StatusSG->Rows[i-1]; // Asigna los datos a la nueva fila. StatusSG->Cells[0][Idx] = IP; StatusSG->Cells[1][Idx] = Status; } Listado A.30. Función AddToStatusSG. Añade una posición al componente StatusSG de la ventana de estado. void __fastcall TStatusForm::DelFromStatusSG(int Idx) { // Desplaza en 1 hacia atrás los contenidos de las filas posteriores a aquella // que debe ser eliminada (su contenido es remplazado). Sucede sólo si la fila // que debe ser eliminada no es la última. for(int i=Idx; i<=StatusSG->RowCount-2; i++) StatusSG->Rows[i] = StatusSG->Rows[i+1]; // Si la fila que debe ser eliminada es la única que existe, borra el contenido // de StatusSG. if(StatusSG->RowCount == 1) { StatusSG->Cols[0]->Clear(); StatusSG->Cols[1]->Clear(); } // Si existe más de una fila en StatusSG, elimina la última (su contenido fue // copiado a la penúltima). 180 else StatusSG->RowCount--; } Listado A.31. Función DelFromStatusSG. Elimina una posición del componente StatusSG de la ventana de estado. void __fastcall TStatusForm::GenStatusSGClick(TObject *Sender) { // Deselecciona la celda. UncheckSG(GenStatusSG); } void __fastcall TStatusForm::StatusSGClick(TObject *Sender) { // Deselecciona la celda. UncheckSG(StatusSG); } Listado A.32. Funciones GenStatusSGClick y StatusSGClick. Manejadores del evento OnClick de los componente GenStatusSG y StatusSG de la ventana de estado. void __fastcall TStatusForm::UncheckSG(TStringGrid *SG) { // Deselecciona todas las celdas. TGridRect Xr; Xr.Left = -1; Xr.Right = -1; Xr.Top = -1; Xr.Bottom = -1; SG->Selection = Xr; } Listado A.33. Función UncheckSG. Deselecciona las celdas de un componente TStringGrid. 181