Download Desarrollo de una interfaz hombre-máquina para la supervisión de
Document related concepts
no text concepts found
Transcript
UNIVERSIDAD SIMÓN BOLÍVAR Decanato de Estudio Profesionales Coordinación de Ingeniería Electrónica DESARROLLO DE UNA INTERFAZ HOMBRE – MÁQUINA PARA LA SUPERVISIÓN DE EQUIPOS INDUSTRIALES Por Jordana Bratt Perkinson Sartenejas, Octubre de 2005. UNIVERSIDAD SIMÓN BOLÍVAR Decanato de Estudio Profesionales Coordinación de Ingeniería Electrónica DESARROLLO DE UNA INTERFAZ HOMBRE – MÁQUINA PARA LA SUPERVISIÓN DE EQUIPOS INDUSTRIALES Por Jordana Bratt Realizado con la asesoría de: Ing. Ricardo Casallas Prof. Miguel Díaz INFORME FINAL DE GRADO Presentado ante la Ilustre Universidad Simón Bolívar como requisito parcial para optar al título de Ingeniero Electrónico Sartenejas, Octubre de 2005 UNIVERSIDAD SIMÓN BOLÍVAR Decanato de Estudio Profesionales Coordinación de Ingeniería Electrónica DESARROLLO DE UNA INTERFAZ HOMBRE – MÁQUINA PARA LA SUPERVISIÓN DE EQUIPOS INDUSTRIALES INFORME FINAL DE GRADO presentado por Jordana Bratt Perkinson REALIZADO CON LA ASESORÍA DE: Ing. Ricardo Casallas, Tutor Industrial. Prof. Miguel Díaz, Tutor Académico RESUMEN El proyecto abarca la elaboración de una interfaz hombre – maquina que permita el monitoreo de un proceso diseñada por el cliente. El software tiene dos modos de funcionamiento: el modo de diseño y el modo de ejecución. En el primero el cliente es capaz de diseñar la planta que desee y asociarlo a las variables de ejecución. En el segundo modo, el cliente es capaz de monitorear el estado de la planta continuamente. Dicho software fue diseñado en una plataforma Java, para que sea utilizable en todas los Sistemas Operativos. Su desarrollo requirió de varios pasos, siendo estos: la documentación inicial, el planteamiento del problema, programación de las clases a usar y de los objetos graficos y la fase final de pruebas. Este proyecto se logro fabricar exitosamente, ya que el programa funcionó repetidas veces de manera adecuada, en las diferentes pruebas que se le administraron para verificar todas sus características. PALABRAS CLAVES: Ambiente de desarrollo, programación orientada a objetos, lenguaje de programación Java, interfaz hombre maquina, monitoreo. Aprobado con Mención: . Postulado para el premio: . Sartenejas, Octubre de 2005 11 A mi hermanito, A mi primo, A Granny y a Grandpa, A Mamá y a Papá 12 Agradecimientos A mi familia por siempre haber estado allí., apoyándome, dándome fuerzas y ánimos para seguir adelante. Los quiero a todos, no estaría donde estoy sin ustedes. A Francisco, quien nunca dudo de mí, en todo momento estuvo a mi lado, y me ha comprendido por muchos años, haciéndome muy feliz. A la mejor compañera de pasantía que pude haber tenido, Damarys, gracias de todo corazón. Me ayudaste cuando lo necesite, todos los días, por las conversaciones, el ánimo que me diste, y el compañerismo y amistad que me demostraste. A Orlando, Melissa, Ambrosio, Andrés, Rubén, Diana, Tommislav y Michele. Las experiencias que pasamos en la CCIE 2004-05 me hicieron crecer mucho y ustedes formaron parte de ello. Al Ing. Ricardo Casallas, quien siempre aclaró mis dudas, me enseñó con mucha paciencia, y siempre estuvo atentó, guiándome durante todo el desarrollo del proyecto. Al Profesor Miguel Díaz, gracias por sus consejos, su interés, su apoyo, durante una gran parte de mi carrera, y estar a mi lado en estas etapas finales. Al Ing. Pablo Mosquera e Ing. José M. Buceta, por darme la oportunidad de trabajar en el talentoso equipo de la compañía Intelcon. 13 Índice General Glosario..........................................................................................................................vii CAPÍTULO 1: Introducción………………………………………………………….11 1.1 Descripción del Proyecto……………………………………………………….12 1.2 Breve Descripción de la Empresa………………………………………………13 1.2 Resumen General de Contenidos…………………………………………. …...14 CAPÍTULO 2: Fundamentos Teóricos………………………………………………16 2.1 Historia de Java………………………………………………………………...16 2.2 Programación Orientada a Objetos……………………………………..............18 2.3 Java………………………………………………………………………… ….20 CAPÍTULO 3: Desarrollo del Software……………………………………………..25 . 3.1 Justificación de la selección del lenguaje de Programación Java………….. ….25 3.2 Desarrollo del Ambiente de Programación…………………………………….27 3.2.1 Clases……………………………………………………………………. 27 EditorApplet…………………………………………………………….29 EditorWorkspace…………………………………….…..……………. 30 EditorDesktop………………………………………………………..…38 EditorToolbar…………………………………………………………...39 EditorFileToolbar…………………………………………….....39 EditorObjectToolbar………………………………………..…...41 EditorFrame………………………………………………………..…...42 EditorComponent………………………………………………….…...43 EditorEvent……………………………………………………….…….44 EditorEventPerformer…………………………………………….…….44 EditorPropierties………………………………………………….…….45 EditorRectangles…………………………………………………..……46 EditorSquares …………………………………………………….…….46 3.2.2Interfaces………………………………………………………………….47 EditorListener…………………………………………………….…….48 3.3 Desarrollo del Ambiente de Ejecución…………………………………..……..48 3.3.1 Clases…………………………………………………………….……….48 EditorConnect………………………………………………….……….49 3.4 Desarrollo del los Objetos…………………………………………………….50 3.4.1 Válvulas……………………………………………………………….….50 14 3.4.2 Tanque……………………………………………………………………51 3.4.3 Botón……………………………………………………………………..51 3.4.4 Tubería……………………………………………………………………52 3.4.5 Indicador……………………………………………………………...…..52 CAPÍTULO 4: Pruebas y Resultados……………………………..……..…………..54 4.1 Prueba de Ambiente de Programación…………………….………………..54 4.2 Prueba de Ejecución………………………………………..……………….62 CAPÍTULO 5: Conclusiones y Recomendaciones……………………..……………66 Referencias Bibliográficas…………………………………………………………....67 Apéndice……………………………………………………………………………….68 A. 1 Código…………………………………………………………………………68 A.2 Eclipse – Plataforma de desarrollo…………………………………………..110 15 Índice de Figuras CAPITULO 2 Figura 1: Máquina Virtual de Java……………………………………………23 CAPITULO 3: Figura 2: Pantalla Inicial del Proyecto…………………………………………28 Figura 3: Descripción de la plataforma del desarrollo………………………….29 Figura 4: BorderLayout………………………………………………………...31 Figura 5: Asociación de etiquetas a los Componentes………………………...36 Figura 6: EditorFileToolbar…………………………………………………….40 Figura 7: Elementos de EditorFileToolbar……………………………………..41 Figura 8: Objeto EditorObjectToolbar………………………………………….42 Figura 9: Componente EditorFrame………………………………………...….43 Figura 10: Objeto EditorPropierties……………………………………………46 Figura 11: Tanque con Objetos EditorSquares…………………………………47 Figura 12: Válvula………………………………………………………..…….50 Figura 13: Tanque………………………………………………………………51 Figura 14: Objetos Botón y Etiqueta……………………………………...……52 Figura 15: Objeto Tubería………………………………………………………52 Figura 16: Fórmula de relación de Líneas…………………………………..….53 Figura 17: Parámetros………………………………………………………..…53 Figura 18: Objeto Indicador…………………………………………………….53 CAPITULO 4: Figura 19: Ejecución inicial del Programa………………………..……………55 Figura 20: Un despliegue sin Elementos…………………………...…………..55 Figura 21: Dos despliegues simultáneos………………………………………..56 Figura 22: Un despliegue minimizado……………………………...…………..57 Figura 23: Un despliegue Maximizado……………………………...………….57 Figura 24: Diseño de un despliegue…………………………………...………..58 Figura 25: Diseño de dos despliegues simultáneos………………….……...….59 Figura 26: Agrandando un Componente……………………………….………60 Figura 27: Cambio de Color 1………………………………………………….60 Figura 28: Cambio de Color 2………………………………………………….61 Figura 29: Cambio de Color 3………………………………………………….61 Figura 30: Despliegue Conectado…………………………………….………..62 Figura 31: Cuadro de Propiedades para seleccionar etiquetas…………………63 Figura 32: Asociación de etiqueta de los componentes………………………..63 Figura 33: Asociación de Límites a las Variables………………………....…..64 Figura 34: Despliegue en Ejecución………………………………………..….65 16 GLOSARIO Applet: referido al programa en lenguaje Java que es empleado en aplicaciones orientadas a Internet. Bytes: Agrupaciones de 8 bits. En este trabajo seran usadas como los paquetes en que se envia la informacion. Clase: Es el codigo que describe las caracteristicas y funciones que son propias de un objeto. Despligue: Area donde se desarrolla o diseña una nueva planta. Eventos: Son todas aquellas acciones que causan una interrupción en la corrida fluida del programa, y deben ser atendidas. Usualmente son usadas de tal manera que cuando se disparan es que el programa ejecuta. Excepciones: Son aquellas acciones indeseadas que no permiten que el programa corra correctamente. Java: Lenguaje de programación oriaentado a Objetos, independiente de la plataforma en que se use. JavaByteCode: es el lenguaje maquina al que se traduce un codigo despues de que este es pasado por la JavaVirtualMachine. JVM: Siglas de JavaVirtualMachine, quien es la encargada de traducer el codigo proviniente del IDE a JavaByteCode 17 Layouts: manera de distribuir components en el espacio. En Java existen varios layouts determinados, que facilitan la colocacion de componentes en un objeto Monitoreo: Accion de vigilar el estado de un equipo constantemente. Objeto: Implementacion de una clase. Package: Se refiere a la direccion en donde se encuentra el codigo fuente del programa. Servlet: Referido a una aplicación en Java capàz de manejar funciones como accesos de archivos y de data que corre en un servidor de la red. Software: Son el conjunto de instrucciones que componen un programa, e indican las funciones que este debe ejecutar al sistema operativo. Sistema Operativo: Es una serie de programas encargados del administrar los recursos del computador. Timer: Clase de Java capaz de llevar un contador. WebBrowser: Cualquier programa que permita el acceso a observar y navegar por Internet. 18 CAPÍTULO 1: Introducción Hoy en día se vive en un mundo automatizado. Grandes empresas son totalmente manejadas por máquinas. De alguna manera es necesario supervisar que dichas maquinas funcionen correctamente durante su operación, ya que la falla de las mismas podría terminar costando a la empresa un “gran” número de pérdida. Suena entonces lógico buscar una manera de evitar que dichas fallas ocurran. Aquí aparece el concepto de un sistema de supervisión para los equipos, que permita constantemente monitorear el estado de los mismos, para poder detectar una falla, inclusive antes de que ésta ocurra. Aún así, una vez creados los sistemas de monitoreo, éstos eran complicados de operar por lo cual las fallas se seguían generando. Al pasar el tiempo, con los nuevos sistemas operativos, las nuevas tecnologías cada vez las interfaces hombre – máquina se hacían mas comunes y “amigables”. Con la introducción de nuevos ambientes y modos de programación se ampliaron las posibilidades del mercado, por lo cual éste se volvió más competitivo. Cada interfaz era más sencilla de usar y ofrecía más información sobre el estado de la planta. Por último, la introducción de Internet ha permitido la expansión de los alcances de dichos sistemas de monitoreo, ya que con lenguajes como Java, fuertemente orientados a el uso de la red, es posible verificar el estado de la planta simplemente accesando, por ejemplo, una página específica. Hoy en día, existen empresas dedicadas puramente a esta rama de control, que como se sabe, se encuentra estrechamente ligada a la Ingeniería Electrónica. 19 1.1 DESCRIPCIÓN DEL PROYECTO Basado en lo expuesto anteriormente, la empresa Intelcon, ha decidido entrar en el mercado nacional para el monitoreo de empresas. Por ello requería primero del desarrollo de un prototipo de tal manera de estudiar la factibilidad del proyecto en cuanto a tiempo de desarrollo y elementos empleados. Por otro lado se buscaba que nueva característica atractiva se podía incluir de tal manera de atraer clientes potenciales. Esta característica resulto ser la posibilidad de que el usuario pudiese diseñar la planta que deseaba monitorear, o hacer cambios en ella después de que estuviese salvada. Aprovechando la nueva tendencia de los lenguajes de programación orientada a objetos, los cuáles proveen librerías pre- diseñadas específicamente para uso de la creación de interfaces hombre maquina, y teniendo el cuenta el requerimiento de la orientación a Internet, el lenguaje de programación seleccionado para el desarrollo del proyecto fue Java. Además, debido a los requerimientos de hoy en día, este lenguaje posee la característica de ser independiente del sistema operativo en que se diseñe, por lo cual permite mayor versatilidad. Al ser esto un prototipo, solo se implementarían las funciones básicas de un sistema de monitoreo, los cuales serían abrir despliegues, diseñar despliegues, y correr dichos despliegues. A estos despliegues sólo se le podrán insertar objetos previamente hechos y limitados, los cuales comprenden: tanques, válvulas, tuberías, indicadores, botones y etiquetas. Luego se permitiría realizar un applet de tal manera que cuando fuese necesario se podría colocar en un servidor para ser accesado de diferentes localidades. También se creó un ejecutable para usar en presentaciones del producto. 20 El desarrollo del proyecto abarco 4 etapas básicas: familiarización con el lenguaje de programación y el IDE a utilizar, el estudio básico de como desarrollar el proyecto, el desarrollo del software y las pruebas finales. La primera etapa consiste en la familiarización del programador con el lenguaje orientado a objetos y el IDE seleccionado para la ejecución del mismo, de tal manera que el programador se sienta cómodo y sea capaz de realizar cambios pertinentes a las necesidades del cliente. La segunda etapa requiere que el programador se siente y dedique tiempo a diseñar los algoritmos, estilo visual, de los componentes y el programa en general. La tercera etapa consiste en la programación del software en Java, esto requiere el desarrollo de las clases pertinentes, y los objetos necesarios, que permitan el diseño de los despliegues, el establecimiento de la colección y monitoreo de la planta. Por ultimo, siempre es necesario tener una fase de pruebas para verificar el funcionamiento correcto del software desarrollado. En esta fase se diseñó un despliegue y se verifico su correcto funcionamiento cuando se colocó en fase de monitoreo. 1.2 BREVE DESCRIPCIÓN DE LA EMPRESA El presente proyecto fue concebido por la compañía Intelcon Systems, en una búsqueda de ampliar sus alcances en el mercado nacional en el área de control. Las iniciales de dicha compañía nacen de: Informática, Telecomunicaciones y Control que son las áreas en donde se especializan sus investigaciones. Quizás la característica más resaltante de esta compañía es que es considerada una empresa que busca soluciones en todas las áreas mencionadas anteriormente, empleando el uso estratégico de la tecnología de hoy en día. 21 Como lo indica su misión: “Servir a nuestro entorno generando soluciones de alta calidad, aplicando las más avanzadas Tecnologías de Informática, Telecomunicaciones y Control en los campos de Servicios y Manufacturas, siendo ejemplo de creatividad, honestidad y rentabilidad, permitiendo el crecimiento integral de nuestra gente.”, se ve que apuntan a ser una de las mejores compañías de este entorno a nivel nacional, y ser reconocidos a nivel internacional. 1.3 RESUMEN GENERAL DE CONTENIDOS El siguiente informe consta de 5 capítulos más un apéndice general. Para facilidad del lector se tendrá un breve resumen de lo tratado en cada capítulo. • Capitulo 1: Introducción, que comprende motivos que llevaron a la realización del proyecto, conjunto de los objetivos trazados y una breve descripción del proyecto. También incluye una breve descripción de la empresa en donde se desarrolló el proyecto, y el resumen general de contenidos. • Capitulo 2: Se basa en el desarrollo de los fundamentos teóricos que son la base para la compresión del proyecto. Aquí se discuten las características de los lenguajes orientados a objetos, en particular las particularidades de Java. • Capitulo 3: Es la base de proyecto. Consta de la discusión de todas las clases empleadas y desarrolladas, el funcionamiento general del programa. Se entra en detalle sobre el manejo de eventos y la interacción con el servlet. • Capitulo 4: Para comprobar el estado funcional del proyecto se realizaron una serie de pruebas que son expuestas y explicadas en esta sección, con diferentes gráficos tomados de la corrida de la mismas. 22 • Capitulo 5: Son las conclusiones a las que se llegaron del proyecto, y aquellas recomendaciones para aquellas personas que decidan realizar un proyecto similar. También se tiene un índice de figuras, y un glosario de términos, para la fácil comprensión del lector del proyecto. 23 CAPÍTULO 2: Fundamentos Teóricos Para poder continuar con la explicación del proyecto, es necesario aclarar los conceptos y términos que se utilizarán en el desarrollo del informe, de tal manera que el lector se familiarice con los mismos, aun sin dominar la materia. Este capítulo consistirá de varios temas a tratar, los cuales comprenden: • Historia del lenguaje de Programación JAVA • Programación Orientada a Objetos • Características del lenguaje de programación JAVA • El método de envío de datos por HTTP-POST 2.1 HISTORIA DEL LENGUAJE DE PROGRAMACIÓN JAVA El origen del lenguaje de programación Java data a los 1970, cuando Bill Joy, presidente de Sun Microsystems concibió la idea de un lenguaje que combinara las mejores características que existían en los lenguajes MESA y C, ya que en un intento de re-escribir un sistema operativo UNIX sintió que C++ no era adecuado para el trabajo. Buscaba una herramienta que le permitiera escribir programas cortos de una manera efectiva. Para enero de 1991 Bill Joy, James Gosling, Mike Sheradin, Patrick Naughton se reunieron para la realización de un proyecto cuya visión era el desarrollo de un sistema que les permitiera realizar una red distribuida, heterogénea de productos electrónicos “inteligentes” capaces de comunicarse uno con otro. Este proyecto inicialmente llamado Stealth paso a ser conocido como el “Green Proyect”. 24 James Gosling fue el encargado en encontrar un lenguaje de programación adecuado para dicho proyecto, debido a su antecedentes en desarrollo de lenguajes de programación, entre ellos NeWs y GOSMACS. Gosling comenzó el desarrollo con C++ hasta darse cuenta de que este lenguaje le sería insuficiente, y que necesitaba un lenguaje “independiente”. Inicialmente el nombre que se le otorgó al lenguaje de programación Java fue “Oak” (roble), que por motivos legales tuvo que ser cambiado a Java, proveniente de las iniciales de algunos de sus creadores: James gosling, Arthur Van hoff, Andy bechtolsheim. Había varios criterios que debía satisfacer el lenguaje de programación Oak. Debido al enfoque que se le estaba dando al proyecto en relación a el mercado, este debería ser totalmente independiente de la plataforma y funcionar sin fallas independientemente del tipo de CPU en la máquina. Por esta razón es que el lenguaje pasó a ser conocido como “lenguaje interpretado”, ya que seria prácticamente imposible para una versión compilada correr en todas las plataformas/ sistemas operativos existentes. Para facilitar el trabajo del interpretador, el lenguaje sería convertido en una variante de código en bytes que seria transmitida por la red de dispositivos interconectados. Adicionalmente, la confiabilidad del código era muy importante, ya que no se podía tener un sistema que necesitase ser reseteado cada cierto tiempo, como también lo era la disminución de errores generados por el programador. Entre las cosas que se le añadieron a Oak fue la recolección implícita de basura, que permitía una mejor utilización de memoria. Las mejoras que trae el lenguaje de programación Oak/Java serán analizadas más adelante cuando se describa la programación orientada a Objetos, y el de las características del lenguaje de programación Java 25 2.2 PROGRAMACION ORIENTADA A OBJETOS Empezada a desarrollarse en los años 80, este estilo de programación presenta un nuevo enfoque que permite convertir estructuras de datos en los centros sobre los cuales se ejecutan las operaciones, llamadas Objetos, de tal manera que cualquier modificación de la estructura de datos tiene efecto inmediato sobre las acciones a realizar sobre ella, siendo esta una de la diferencias radicales respecto a la programación estructurada. Esta programación tiene los siguientes atributos inherentes: Uniformidad. Ya que la representación de los objetos lleva implicito tanto el análisis como el diseño y la codificación de los mismos. Comprensión. Tanto los datos que componen los objetos, como los procedimientos que los manipulan, están agrupados en clases, que se corresponden con las estructuras de información que el programa trata. Flexibilidad. Al tener relacionados los procedimientos que manipulan los datos con los datos a tratar, cualquier cambio que se realice sobre ellos quedará reflejado automáticamente en cualquier lugar donde estos datos aparezcan. Estabilidad. Dado que permite un tratamiento diferenciado de aquellos objetos que permanecen constantes en el tiempo sobre aquellos que cambian con frecuencia permite aislar las partes del programa que permanecen inalterables en el tiempo. Reusabilidad. La noción de objeto permite que programas que traten las mismas estructuras de información reutilicen las definiciones de objetos empleadas en otros programas e incluso los procedimientos que los manipulan. De esta forma, el desarrollo de un programa puede llegar a ser una simple combinación de objetos ya definidos donde estos están relacionados de una manera particular. Bajo estas premisas tenemos entonces que introducir el concepto de clase. Las clases permiten la agrupación de objetos que comparten las mismas propiedades y 26 comportamiento. Por lo cual una clase entonces es la definición formal de un Objeto a nivel de programación. Con esto se quiere decir que un objeto tendrá una serie de funciones y atributos propios que solo este podrá acceder, o aquellos objetos que hereden de el. Esto nos trae al concepto de herencia: Consiste en la propagación de los atributos y las operaciones a través de distintas sub-clases definidas a partir de una clase común. Introduce, por tanto, una posibilidad de refinamiento sucesivo del concepto de clase. Nos permite definir una clase principal y, a través de sub-clases agregar características mucho más especificas para las mismas. A partir de ahora se definirá como sub-clases todas aquellas clases obtenidas mediante la herencia de una (o varias) clases principales. La herencia nos permite crear estructuras jerárquicas de clases donde es posible la creación de sub-clases que incluyan nuevas propiedades y atributos. Estas sub-clases admiten la definición de nuevos atributos, así como crear, modificar o inhabilitar propiedades. De tal manera que se pueden tener objetos que accedan a procedimientos comunes sin ser estos de la misma clase. Por otro lado, tenemos que la Programación Orientada a Objetos, a nivel de un programador, facilita ciertos aspectos sobre la programación estructurada, estos aspectos son: Claridad: Permite de una manera sencilla observar el código. Complejidad: Es común que suceda que un problema complejo se pueda fraccionar en diferentes etapas. La Programación Orientada a Objetos teniendo un bloque de datos en común, donde más de un programador puede acceder en un momento para uso de su objeto. 27 Relación entre Datos: Los programas que tienen una relación compleja entre los datos se ven beneficiados, debido a la herencia, ya que estructuras y funciones que manejan la misma serie de datos pueden ser usadas en diferentes objetos. Aun así es necesario señalar las desventajas que trae la programación orientada a objetos, entre las cuales encontramos: Rapidez: Debido a su naturaleza de portabilidad que se basa en ser lenguajes interpretados, la mayoría se encuentran distancias ubicados lejos del lenguaje propio de la maquina, por lo cual su ejecución requiere una serie de pasos que consumen mayor tiempo. Manejo de Recursos: “Las aplicaciones orientadas a objetos demandan normalmente más recursos del sistema que las aplicaciones procedurales. La creación dinámica de objetos, que ocupa un lugar en la memoria del ordenador, puede acarrear graves problemas. Una de las soluciones, que incluyen algunos de los lenguajes OOP, es liberar a menudo el espacio que los objetos dejan de utilizar. Este procedimiento de optimización como garbage collection (recolección de basura, implementado en java), minimiza los efecto de la creación dinámica de objetos.” 1 2.3 JAVA En esta sección se darán a conocer las características primordiales del lenguaje de programación Java, las cuales le permiten ser reconocido como uno de los lenguajes orientados a objetos mas conocidos en el mercado. Orientado a Objetos: Ya anteriormente mencionamos todas las ventajas que trae un lenguaje orientado a objetos. Java utiliza esta metodología de programación para facilitar la portabilidad de su código. Simple: Hay muchos aspectos en que Java supera a los programas de índole estructurada. Entre los más comunes y más importantes destacan la eliminación de 1 http://www.monografias.com/trabajos14/progorie/progorie.shtml 28 punteros, lo cual facilita el manejo de la memoria, y su creación dinámica. Esto por supuesto acarrea como consecuencia un posible mal manejo de recursos de memoria si ocurriese el caso de un objeto “olvidado” sin usar. Para ello se creo el sistema de recolección de basura. Es una manera sencilla de liberar la memoria. Cada vez que un objeto deje de ser señalado este será destruido, liberando la memoria. Robustosidad: Además de poseer un poderoso compilador, que realizará chequeos a momentos de ejecución y previos momentos de compilación, para prever uso inadecuado de memoria entre otros errores que pueden llegar a ser fatales para la programación, se tiene el manejo de excepciones. Las excepciones ocurren cuando un evento esperado no ocurre de la manera prevista. Java te permite “atrapar” dichas fallas o errores que normalmente en un lenguaje tradicional no seria posible, y dependiendo de esta falla tomar una acción correspondiente, lo cual garantiza la continuidad de la ejecución del programa. Multi-hilo: Si definimos un hilo como un procedimiento que se ejecuta en base a eventos, entonces un programa multi-hilos se refiere a varios procesos que se pueden ejecutar de manera paralela. Esto permite de una manera muy eficiente manejar el uso del procesador, ya que este no estará en un momento del tiempo en estado de espera por un evento sino más bien invertirá el tiempo del procesador en otra función de mayor utilidad (otro hilo) Librería orientada a Interfaces de Usuario: Debido a la concepción original que tuvo el lenguaje de programación Java, muchas clases fueron creadas con el simple objeto de ser utilizadas para la realización de una interfaz para el usuario, por ello existe una librería extremadamente amplia para aquellos programas que requieran interfaces, lo cual salva mucho tiempo de programación. Esta librería también conocida como API es realmente una interfase de programación de aplicaciones. 29 Independencia de SistemaOperativo: Quizás la característica más interesante de Java es la independencia que este tiene del sistema operativo en que trabaja, debido a la manera en que el lenguje es compilado. Java es un lenguaje interpretado. Con esto se quiere decir que el código tal cual como lo conocemos pasara a lo que se denomina una “maquina virtual”. Esta maquina es la encargada de traducir el código a un lenguaje denominado el Java Bytecode. El JavaBytecode no es un lenguaje de alto nivel sino puramente un código maquina, proporcionado adecuadamente para cada plataforma o sistema operativo “La gran ventaja de la máquina virtual Java es aportar portabilidad al lenguaje de manera que desde SUN se han creado diferentes máquinas virtuales Java para diferentes arquitecturas y así un programa .class escrito en un Windows puede ser interpretado en un entorno Linux. Tan solo es necesario disponer de dicha máquina virtual para dichos entornos. Empero, los intentos de la compañía propietaria de Java y productos derivados, que es Sun Microsystems, de construir microprocesadores que aceptaran el Java bytecode como su lenguaje de máquina fueron más bien infructuosos. La máquina virtual de Java puede estar implementada en software, hardware, una herramienta de desarrollo o un Web browser; lee y ejecuta código precompilado bytecode que es independiente de la plataforma. JVM (Java Virtual Machine) provee definiciones para un conjunto de instrucciones, un conjunto de registros, un formato para archivos de clases, la pila, un heap con recolector de basura y un área de memoria. Cualquier implementación de la JVM que sea aprobada por SUN debe ser capaz de ejecutar cualquier clase que cumpla con la especificación. 30 Existen varias versiones, en orden cronológico, de la máquina virtual de Java. En general la definición del Java bytecode no cambia significativamente entre versiones, y si lo hacen, los desarrolladores del lenguaje procuran que exista compatibilidad hacia atrás con los productos anteriores.” 2 En la siguiente figura (Figura 1) se puede observar como la máquina virtual de Java se coloca de una manera estratégica entre el sistema operativo, y el código realizado por el programador. Figura 1: Máquina Virtual de Java Orientación hacia Internet: Por otro lado, se tiene que Java está fuertemente orientado a ser utlizado a nivel de Internet. Para ello existen los llamados applets. Estos son programas que se encuentran en un servidor de Internet y cuando un cliente accede a una página que los requiere estos automáticamente se bajan de Internet y se ejecutan desde el computador del cliente. Por ello deben tener estrictas medidas de seguridad, 2 http://es.wikipedia.org/wiki/M%C3%A1quina_virtual_Java 31 implementadas por Sun, de tal manera que no sean capaces de sobrescribir o crear archivos indeseados, Al igual que todos los programas en Java, estos applets son independientes de la plataforma del cliente ya que se encuentran en JavaBytecode. Usualmente los Java applets se comunican con servlets para poder salvar diferentes datos necesarios para su ejecución. 32 CAPÍTULO 3: Desarrollo del Software El proyecto consistia en desarrollar un interfaz hombre maquina para un sistema de monitoreo de una industria, que podría a su vez ser modelada por el cliente que adquiriese el software. Por lo cual el software debería cumplir ciertas especificaciones: • Ser adaptable a cualquier Sistema Operativo • Tener una ventana para el desarrollo de despliegues personales del cliente • Tener Objetos previamente creados para facilitar el uso al cliente del diseño de su despliegue • Permitir al cliente personalizar los objetos en su despliegue. • Poder comunicarse de una manera efectiva con el servlet que contenía la base de datos • Ver en tiempo real el estado de la empresa que esta bajo monitoreo. 3.1 JUSTIFICACIÓN DE LA SELECCIÓN DEL LENGUAJE DE PROGRAMACIÓN JAVA Teniendo en cuenta las especificaciones mencionadas anteriormente, se determino que el lenguaje de programación Java satisfacía de una manera apropiada las necesidades para la realización del programa. Inicialmente tenemos que Java posee una independencia de sistema operativo ya que se encuentra aislado de este por la maquina virtual de Java que traduce el código en JavaBytecode. Por otro lado, los applets permiten una ejecución en la red de una manera sencilla y segura, logrando una comunicación efectiva con un servlet para la extracción de datos. 33 Como se mencionó anteriormente, Java fue concebido para realizar interfaces usuario máquina, por lo cual la librería API que posee tiene una cantidad extensa de clases que facilitan la creación de Objetos para el desarrollo del software. Estas clases también tienen una serie de manejadores de eventos que permiten una manera práctica de interactuar con los mismos, tanto a nivel de hardware (el presionar del botón del ratón) como a nivel de software (el arrastre de una esquina de un componente para aumentar su tamaño). Java permite la creación de objetos gráficos de una manera sencilla, y la interacción con ellos es manejada de una manera prácticamente transparente hasta para el programador, debido a las interfaces de la librería API. También la creación de subclases permite que los objetos creados para el despliegue (tanques, válvulas, tuberías entre otros) pertenezcan a una misma clase de la cual heredan, compartiendo así características similares que facilitan el manejo de su personalización (cambiar el color, tamaño, etc.), mientras mantienen su independencia en otros aspectos (referente a su aspecto visual, un tanque no se parecerá “físicamente” a una válvula). La primera duda nace en referencia al tiempo real. Como se mencionó anteriormente Java es un leguaje mucho más lento que aquellos que se encuentran de una manera más cercana al lenguaje propio de la máquina. Un lenguaje interpretado consume mayor cantidad de recursos y mayor tiempo, pero a la vez, se debe tomar en cuenta que lo que se desea monitorear son procesos de lenta reacción (usualmente niveles de tanques, o temperaturas y presiones) por lo cual un tiempo de respuesta veloz no es prioritario y Java, aun siendo mas lento que los otros lenguajes de programación no tendrá problema en cumplir los requerimientos impuestos por el cliente También una de las especificaciones, es que dicho software desarrollado pueda ser utilizado en la red de Internet. Java posee esta característica de una manera muy sencilla a través de los applets. Estos programas se encuentran en un servidor y cuando el cliente accede a dicho servidor se descargan en el ordenador del cliente. 34 Por último se debe tener en cuenta el tema de la seguridad. Descargar programas de Internet puede ser peligroso para el cliente, ya que estos pueden tener instrucciones maliciosas, por lo cual se debe restringir el acceso que se le otorga al applet para escribir archivos, de tal manera que éste realmente sólo podrá ejecutarse temporalmente y cualquier cambio o modificación que exista se podrá salvar en un servidor en Internet. 3.2 DESARROLLO DEL AMBIENTE DE PROGRAMACION 3.2.1 CLASES Uno de los objetivos de este proyecto es desarrollar un ambiente donde se realicen despliegues. Para ellos se requiere una serie de objetos encargados del desarrollo de este despliegue. La idea general es tener una barra de herramientas en la cual existan opciones de despliegue de: • Nuevo • Abrir • Salvar • Cerrar • Conectar • Ejecutar Por otro lado se tendrá una barra de herramientas con los objetos diseñados • Tanque • Válvula • Tubería • Indicador • Botón • Etiqueta 35 Inicialmente la pantalla se observará como indica la siguiente figura (Figura 2): Figura 2: Pantalla Inicial del Proyecto En las siguientes páginas se describirán las clases que permiten el correcto funcionamiento del ambiente de desarrollo. Primero es importante analizar esta figura (Figura 3) donde se podrá observar como cada clase implementa objetos definidos por otras clases. 36 Figura 3: Descripción de la plataforma del desarrollo Así podemos ver que la clase que engloba todo es el EditorApplet, ya que esta implementa un objeto del estilo EditorWorkspace. A su vez, la clase EditorWorkspace implementa objetos estilo EditorToolbar y EditorFrames. En los EditorFrames es donde se desarrollaran los despliegues como tal. Es importante denotar que las acciones que se ejecutan sobre una de las barras de herramientas (los objetos estilo EditorToolbar) afectan los eventos que detectan los objetos tipo EditorFrame. La clase EditorFrame permite la inserción de nuevos objetos como lo serían las figuras de tanques válvulas etc. Bajo esta misma clase también se permite la interacción con ellos (cambio de color, tamaño) con la detección de eventos del ratón. Ahora se describirá en detalle cómo funciona esta sección del programa EditorApplet: Su única función es colocar dentro del applet un Objeto del estilo EditorWorkspace, de tal manera que el programa funcione dentro de un ambiente del 37 applet. Se realizo de esta manera ya que esta case puede ser fácilmente sustituida por una aplicación si no se desease ejecutar el programa a nivel de applet. Es en esta clase que se determina el “paquete” del programa. Este paquete es la dirección base donde estarán guardados todos los códigos fuentes de la programación. Se ha vuelto un estándar que esta dirección base corresponda la dirección de la compañía que desarrollo el software de tal manera que cada empaquetado es distinto. La compañía Intelcon tiene página en la dirección URL http://www.intelcon.com.ve de tal manera que el empaquetamiento de la programación viene dado por: ve.com.intelcon.scada.editor donde los dos últimos miembros (scada.editor) corresponden a las carpetas dentro de las cuales están ubicados los códigos fuentes. EditorWorkspace: Es la clase más compleja del desarrollo, ya que la mayoría de los eventos que se ejecutan son analizados por ella. Esta clase hereda de JPanel, la cual viene predeterminada por el lenguaje Java. JPanel es sencillamente tal como su nombre lo indica un Panel, donde se pueden añadir objetos. Inicialmente como observamos en la figura anterior (Figura 3) vemos que se declaran objetos tipo EditorToolbar. Una de las barras pertenecerá a la clase EditorFileToolbar, mientras que la otra será de la clase EditorObjectToolbar. Se puede apreciar cómo se aprovecha el concepto de herencia, ya que ambas barras de herramientas tendrían muchas funciones en común, y solo leves diferencias que las separasen. 38 A este EditorWorkspace se le debe colocar lo que se conoce como un “layout”. El layout corresponde a la manera en que serán distribuidos los objetos dentro de un espacio determinado (en esta instancia el EditorWorkspace). Java proporciona un a seria de layouts en la librería API. En este caso el más apropiado para la distribución de los objetos seria el BorderLayout, el cual secciona el espacio en norte, sur, este, oeste, y centro. Figura 4: BorderLayout La barra de herramientas correspondiente a la clase EditorObjectToolbar será colocada entonces en el oeste mientras la EditorFileToolbar será colocada al norte que también es referido como “inicio de página”. Por ultimo se debe añadir el objeto de clase EditorDesktop. Este objeto será al cual se le inserten los despliegues para que el cliente trabaje en ellos, por lo tanto el EditorWorkspace debe acceder a ellos a través de este Objeto. El EditorWorkspace implementa una serie de interfaces. Como ya se explicó anteriormente una interfaz permite el uso de ciertas funciones predeterminadas por el lenguaje Java. En este caso se usaron 5 interfaces predeterminadas y 1 personalizada. 39 • MouseMotionListener: Corresponde a las acciones del Mouse de arrastrar un componente, presionar el botón del ratón o soltar dicho botón. • MouseListener: Corresponde a las acciones entrar dentro de el área de un componente, salir del área de un componente, pulsar el ratón sobre un componente y a cualquier movimiento que se realice sobre el ratón. • ChangeListener: Evento que se dispara cuando una característica especifica de un componente cambia. • ItemListener: Corresponde a objetos que tienen más de una acción ejecutable sobre ellos posible (un menú con opciones) • ActionListener: Corresponde a objetos que pueden ejecutar una acción (por ejemplo un botón sólo puede ser presionado) • EditorListener: Son eventos creados propios por el programador. Serán discutidos a profundidad en capítulos siguientes. Son todos aquellos objetos que requerían eventos que no existían (el levantar de una bandera, el presionar un componente mientras una bandera estaba en alto, etc.) Esta clase funciona de la siguiente manera: Como en el lenguaje orientado a objetos, la programación no es estructurada, el programa siempre se encuentra es una espera de eventos. El primero evento posible sería el abrir un nuevo despliegue. Al presionar un botón en el cualquiera de las barras de herramienta se dispara un evento en dicho objeto (que es manejado internamente por su clase inherente). Este evento es redirigido al EditorWorkspace. 40 En primera instancia siempre se revisa el estado de la bandera que determina si existe un componente estilo EditorFrame (un despliegue como tal) colocado en el objeto EditorDesktop. Si este existe, entonces los botones de EditorObjectToolbar se encuentran “activos”. En caso contrario cualquier acción sobre estos botones será ignorada. Una vez que se tenga la opción de abrir un despliegue activo, se invocarán a través de las funciones del objeto EditorDesktop las funciones de añadir objetos llamados EditorFrames (los despliegues como tal). Los próximos eventos que se detectarán serán interacciones entre los objetos estilo EditorFrame que están activos y los botones presionados en la barras de herramientas. Ahora que existe un despliegue abierto y activo una bandera se levanta permitidiendo tomar acciones correspondientes a los eventos que los botones de las herramientas generen. En la barra de herramientas EditorObjectToolbar se tienen una serie de objetos que son los permitidos para inserción en el diagrama. El cliente que se encuentre diseñando un despliegue podrá seleccionar un botón presionándolo y luego pulsará sobre el despliegue donde desee que el objeto se coloque. Esto dispara dos eventos: el primero será la selección del objeto que levantara una bandera (con un valor dependiente del objeto seleccionado) y este valor será redirigido al EditorWorkspace. El segundo evento será capturado por objeto EditorDesktop. Debido a que este objeto se encuentra de una vez en el EditorWorkspace no es necesario redirigirlo. El evento que se dispara cuando se desea añadir el objeto al despliegue es el pulsado del botón del ratón. El EditorDesktop (el objeto dentro del EditorWorkspace, no la clase) esta implementado las interfaces MouseListener y MouseActionListener, por lo cual se dirigirá a la ejecución de la acción realizada. Una vez capturado el evento, se determinará que bandera está levantada y se le añadirá al objeto EditorFrame activo un componente (tanque, válvula, etc.). Este procedimiento se repetirá tantas veces como el diseñador del despliegue desee añadir objetos en su despliegue. 41 Después de tener un componente en despliegue el objeto EditorDesktop también se podrá detectar eventos del ratón que se ejecuten sobre ellos. Cuando este detecte el ratón sobre el componente y pulse sobre el mismo aparecerán recuadros en sus esquinas. Estos recuadros son objetos de la clase EditorSquares. Cuando el ratón los seleccione y arrastre sobre ellos, el EditorWorkspace detectará este evento y cambiará el diagrama del puntero del ratón indicando en que dirección se puede variar el tamaño del componente seleccionado. El usuario podrá arrastrar dichos cuadros, y dependiendo del porcentaje de arrastre que sucedan sobre ellos. Para el arrastre lateral se creo la clase EditorRectangles. Éstos son objetos que se colocan en el borde del componente seleccionado en el momento (tanque, válvula) con la característica de que éstos no son visibles para el cliente, de tal manera que en cualquier zona lateral, superior o inferior del componente están activos. Cuando se coloca el ratón sobre ellos, el diagrama del apuntador cambiara a una flecha que indique en que dirección puede ocurrir el cambio de tamaño. (Son usados para cambiar el tamaño del componente en las direcciones norte sur este oeste mientras que los cuadrados sirven para enloganmiento del objeto diagonalmente). Con respecto a la barra de herramientas correspondiente a la clase EditorFileToolbar esta tiene una serie de opciones. Ya se mencionó sobre el funcionamiento del botón de “nuevo”. El botón de “cerrar” acciona un evento que es inmediatamente redirigido al EditorWorkspace. Este buscará el objeto estilo EditorFrame que se encuentre activo y borrara todos los objetos introducidos en él, finalizando con la eliminación de todos las variables que le señalen. De esta manera se libera el espacio de la memoria ocupado por dichos objetos. 42 El botón de “abrir” establece la comunicación entre un servlet determinado y el programa, mediante una operación de HTTP – POST. Este se trae una lista de los despliegues guardados. Al seleccionar uno se envía nuevamente la información al servlet quien provee una lista de los elementos que tenia el despliegue y sus coordenadas. Con esta información automáticamente se puede abrir un nuevo objeto estilo EditorFrame e insertar los nuevos componentes en el despliegue abierto en las coordenadas indicadas por el servlet. El botón de “guardar” compila en una lista todos los componentes, su clase y su ubicación en donde se encuentran en el objeto EditorFrame activo. Una vez obtenida esta lista establece una conexión con el servlet mediante la inserción del objeto EditorConnect. Esta lista se pasa al servlet a través del método HTTP –POST. El botón de “conectar” dispara un evento que es redirigido nuevamente al EditorWorkspace. Aquí, se inserta un objeto de clase EditorConnect que establece una comunicación con el servlet que contiene las etiquetas que provee el PLC. Estas son cargadas a una lista que se mostrara si el usuario hace pulsar con el botón derecho del ratón sobre el componente que desea asociar a dichas etiquetas. Antes de explicar la función del botón ejecutar, es importante tener de una manera clara como se asocian las etiquetas a los componentes. Es imortane recordar que se tiene un objeto estilo EditorFrame con componentes añadidos a él, tales como taques válvulas etc. (que a su vez son objetos que heredan de la clase EditorComponent). Cuando se selecciona un objeto de èstos (los EditorComponents) y se pulsa sobre el botón derecho del ratón aparecerá una lista de etiquetas. Esto se puede asociar a la 43 variable “nivel” de los componentes o a la variable “color”. (Las características de la clase de EditorComponent serán discutidas en capítulos siguientes). La figura siguiente (Figura 5) ilustra el caso en el cual se asocian variables a un componente: Figura 5: Asociación de etiquetas a los Componentes Es importante denotar que cuando se asocia una etiqueta a una variable de un componente también se debe determinar el rango en que se encuentra esta variable, de tal manera que se pueda luego establecer una normalización, ya que las variables de los componentes son internamente manejados entre los valores 0-100. Ya que el método de asociación de etiquetas se encuentra establecido, se puede proceder a explicar como el EditorWorkspace ejecuta el evento que ocurre al presionar el botón “ejecutar”. Al igual que todos los botones presionados en cualquier barra de herramientas, el evento es redirigido al EditorWorkspace. Una vez allí, se inserta 44 nuevamente un objeto de la clase EditorConnect y se comienza un contador de la clase “Timer” facilitada por el API. Este contador interrumpirá cada 100ms, ejecutando un evento. Este evento tiene una comunicación siempre abierta con el servlet y por método de HTTP –POST. Inicialmente envía una lista invocando una función del objeto EditorConnect, que contiene todas las etiquetas de las cuales se desea el valor. El servlet buscará en la base de datos los valores de las etiquetas y las enviará de vuelta en el siguiente formato: ETIQUETA CLASE VALOR Repitiéndose el formato por cuantas etiquetas existan. El EditorWorkspace, en el evento del contador, con una serie de lazos anidados separará los valores de la clase del nombre de la etiqueta. Una vez tenido estos valores es necesario normalizarlos, como se mencionó anteriormente. Para esto se emplea el método de normalización lineal, debido a que es fácil de implementar y arroja un resultado. Existen dos aproximaciones que se realizan: la primera es para indicar el valor real del componente, que viene determinado por los rangos especificados por el usuario. La segunda normalización tiene como objetivo llevar este numero a un valor entre 0 -100 para que pueda ser graficado. La normalización lineal funciona de la siguiente manera: Se tienen los siguientes datos: • El valor máximo del componente ( X1) • El valor mínimo del componente (Y2) • El valor máximo asociado a la etiqueta del componente (X2) • El valor mínimo asociado a la etiqueta del componente (Y2) • Valor otorgado por el servlet ( j ) 45 La idea es con estos encontrar una pendiente para luego trazar una recta de la siguiente pendiente: m= Y1 − Y 2 X1 − X 2 Una vez obtenida la pendiente, a partir de la fórmula de la recta se puede encontrar el valor deseado ValorBusca do = Y 1 + m * ( j − Y 2) Luego este procedimiento se podrá repetir para hallar el valor correspondiente a los rangos 0 -100 que tiene este ValorBuscado asociado. Por último se tiene el botón de “detener” que es responsable de cerrar la comunicación con el servlet para que el diseñador pueda modificar su despliegue. EditorDesktop: Esta clase hereda de la clase JDekstopPane, proporcionada por la librería API de Java. Su característica principal es ser un contendor usado para crear interfaces de múltiples tipos de objetos. Esta clase utiliza el MouseListener, pero la única función de dicha interfaz de eventos que se aplica es la de el pulsar el botón del ratón sobre el componente EditorDekstop. 46 La funciones que tiene el EditorDesktop son de agregar componentes EditorFrames en su área de uso y detectar si estos han sido presionados con el ratón. En caso de ser cierto, se tiene un objeto y una interfaz llamada EditorEvent, quien es el responsable de dirigir cualquier evento capturado hacia el EditorWorkspace. La única función entonces del EditorDesktop es añadir componentes EditorFrames y redirigir sus eventos al EditorWorkspace. EditorToolbar Esta clase hereda de la clase JToolbar proveniente de la librería API. A su vez será la clase padre de las barras de herramientas que se implementarán. Se realizó de esta manera ya que ambas barras de herramientas compartirían muchas funciones comunes. Entre ellas su creación, la manera en que se le agregaban botones y se le insertaban imágenes a los mismos. A la misma vez se le inserto de una vez la interfaz que se deseaba que manejara los eventos que en este caso cada botón del las barras necesitaría. Como se puede apreciar por lo descrito anteriormente esta clase puede ser considerada una clase “creadora”. Tiene las funciones básicas para la formación de una barra de herramientas sin ser específicamente para un estilo. Nótese que en ningún momento se especifica que cantidad de botones se requieren o qué imágenes se desean usar, de tal manera que otra clase pueda heredar de ella y usar las funciones antes descritas. EditorFileToolbar: Es la clase que corresponde directamente a la barra de herramientas de archivos, y como mencionamos anteriormente hereda de EditorToolbar, de tal manera que no requiere declarar las funciones de agregar botones si no sencillamente las emplea. 47 A cada botón de la barra de herramientas que se desea usar se le asocia un número único: (extracto de código del programa) • public static final int BUTTON_NEW = 1; • public static final int BUTTON_OPEN = 2; • public static final int BUTTON_SAVE = 3; • public static final int BUTTON_CLOSE = 4; • public static final int BUTTON_CONNECT = 5; • public static final int BUTTON_PLAY = 6; • public static final int BUTTON_STOP = 7 ; cuando cualquier botón sea seleccionado activara el evento asociado a él, y través del objeto EditorEvent logra pasar el evento al EditorWorkspace para que este lo maneje con su debido identificador. La barra de herramientas de archivo es de la siguiente manera se encuentra ubicada en la zona norte de manera vertical en el programa. La siguiente figura (Figura 6) ilustra la barra de herramientas: Figura6: EditorFileToolbar Las imágenes que se asocian a los botones deben encontrarse en el archivo de los códigos fuentes de tal manera que puedan ser direccionadas adecuadamente. 48 Se debe notar que son sensitivas a las mayúsculas y minúsculas. Los gráficos usados para cada botón son los siguientes (Figura 7): Figura 7 Nuevo Abrir Guardar Cerrar Conectar Ejecutar Detener EditorObjectToolbar Esta clase es la encargada de la barra de herramientas de los objetos. Al igual que la EditorFileToolbar, esta hereda de la EditorToolbar y funciona de la misma manera. Las constantes asociadas a las botones que se le colocan son las siguientes: • public static final int BUTTON_TANK = 1; • public static final int BUTTON_VALVE = 2; • public static final int BUTTON_BUTTON = 3; • public static final int BUTTON_LABEL = 4; • public static final int BUTTON_GAUGE = 5; • public static final int BUTTON_PIPE = 6; • public static final int BUTTON_LINK = 7 ; Los eventos son redirigidos de la misma manera al EditorWorkspace. La siguiente figura (Figura 8) representa el objeto EditorObjectToolbar ubicado en el software desarrollado. 49 Figura 8: Objeto EditorObjectToolbar EditorFrame Esta clase hereda del JInternalFrame que es proporcionada por el API inherente a Java. Básicamente consta de un recuadro enmarcado al cual se le pueden añadir objetos interiormente. Su única función es creadora. Establece el tamaño, el color, el título del recuadro. Este objeto es implementado por EditorDesktop y llamado. Se ha establecido una uniformidad entre todos los recuadros. También se le han añadido características que las ofrece la clase padre, éstas son: • Maximizable • Minimizable • Cerrable • Visible • Con Titulo La siguiente figura (Figura9) ilustra como son los componentes/objetos EditorFrames: 50 Figura 9: Componente EditorFrame EditorComponent Esta clase tiene como objetivo lograr generalizar todos los objetos que se pongan en el despliegue y que estos mismos compartan ciertos atributos. Se hace de esta manera ya que cuando el cliente presiona sobre un componente en el objeto EditorFrame no hay manera de saber que tipo de componente fue presionado (tanque, válvula, etc.). Si todos heredan de la misma clase pueden ser tratados como un objeto de esta clase (EditorComponent). A la vez a este objeto capturado se le pueden modificar todos los atributos que tiene EditorComponent los cuales son los siguientes: • Nombre de la etiqueta asociada a la variable de nivel • Nombre de la etiqueta asociada a la variable de color • máximo valor del Componente • mínimo valor del componente • máximo valor de la etiqueta asociada al componente • mínimo valor de la etiqueta asociada al componente 51 • mínimo valor de la etiqueta de color • máximo valor de la etiqueta de valor. • Valor real del Nivel • Variable booleana Los componentes pueden usar todas estas variables sin la necesidad de declararlas, y y cualquier cambio que ocurra sobre ellas actuará sobre el componente seleccionado en el momento. EditorEvent Es sencillamente una clase que contiene la declaración de las variables que son requeridas que se pasen al EditorWorkspace. (El valor de la bandera que indica si se esta en modo de ejecución, el valor de la bandera que indica que objeto se pretende añadir, la posición del ratón sobre el despliegue, el componente seleccionado y el objeto EditorFrame activo. EditorEventPerformer Esta clase es la que permite como tal el redireccionamiento de los eventos de cualquiera de los objetos al EditorWorkspace. Todas las clases anteriores implementan el uso de este objeto. Básicamente se ha establecido varias veces que las barras de herramientas, el objeto EditorDesktop, los objetos EditorFrames son capaces de detectar acciones del ratón ejecutadas sobre ellos. En el caso de EditorDesktop, debido a que se encuentra directamente insertado sobre el EditorWorkspace la captura y manejo de estos eventos es directamente manejado por el mismo, Pero el caso de presionar botones en las barras de herramientas no es tan sencillo. Sin la ayuda de este implemento se tendrían que pasar punteros a cada uno de los objetos 52 hasta llegar al EditorWorkspace, creando una serie de dependencias y variables que pueden llegar a perderse, negando el sentido total de la programación orientada a objetos. El funcionamiento de esta clase es sencillo. Cuando sucede un evento que es detectado por las interfaces proporcionadas por el API de Java, éstas son redirigidas a través del objeto EditorEvent a EditorEventPerformer. Aquí se encontraran una serie de funciones desarrolladas que corresponden a la interfaz EditorListener. Estas funciones corresponden a los eventos de presionar un botón, presionar el componente EditorFrame, cambiar de color un componente y para mantener la formalidad presionar el componente EditorDesktop. Al entrar en estas funciones, se obtienen todos los datos pertinentes al origen del evento que sean necesarios y que permitan al EditorWorkspace identificarlo. Estas características son las siguientes: • Posición Inicial • Objeto Presionado • Botón del ratón presionado • Valor de la bandera del Objeto • Objeto EditorFrame activo Todos estos datos son redirigidos a la función pertinente del EditorWorkspace quien lo analizara de la manera descrita anteriormente. EditorPropierties Esta clase hereda de JPanel, que es como su nombre lo indica un panel editable, al cual se le pueden agregar diferentes tipos de objetos. Este componente será visible después que un objeto dentro del despliegue haya sido seleccionado y con el botón derecho del ratón se presione. Se le han agregado 3 botones y dos menús. 53 Uno de ellos corresponde al selector de color. Los otros dos botones corresponden a los límites tanto del componente como de la etiqueta asociada a ellos. Los menús son todas las opciones de etiquetas que tiene el diseñador disponible para asociar al componente a las variables que se encuentran en la base de datos. La siguiente figura (Figura 10) ilustra este componente: Figura 10: Objeto EditorPropierties EditorRectangles Clase muy simple que se encarga de realizar rectángulos invisibles que se colocaran en los bordes del objeto seleccionado. Es importante denotar que su tamaño es variable y depende del objeto al cual este asociado. EditorSquares: Clase encargada de realizar un cuadro de tamaño determinado ( 6 x 6 píxeles ) de color negro para colocarla en los bordes del objeto seleccionado. 54 En EditorWorkspace emplean una interfaz que detecta eventos del ratón sobre ellos, que se usan para agrandar el tamaño del componente seleccionado previamente. Es importante denotar que cuando el ratón se coloca sobre ellos, su sistema de coordenadas cambia: la esquina superior izquierda del cuadro negro se convierte en la posición (0,0) y va en orden creciente hacia la derecha y hacia el sur. La siguiente figura (Figura 11) ilustra como se observan los recuadros al borde del componente: Figura 11: Tanque con Objetos EditorSquares 3.2.2 INTERFACES Las interfaces a diferencias de las clases no son heredadas, si no más bien, implementadas. Estas facilitan una serie de funciones previamente establecidas por la librería API al usuario. Aun así a veces estas librerías son insuficientes para lo requerido a realizar por lo cual el programador puede realizar sus propias interfaces. En este programa se realizó una interfaz propia. 55 EditorListener: Es la interfaz encargada de redirigir los eventos al EditorWorkspace. Implementa las siguientes funciones: • onToolbarPressed(EditorEvent e): Accionado cuando se presione un botón en una barra de herramientas • onDesktopPressed(EditorEvent e): Accionado cuando se presiona algún componente del EditorDesktop (incluidos los EditorFrames) • onRightObjectPressed(EditorEvent e): Accionado cuando sobre un componente seleccionado se presiona el botón derecho del ratón. • onFlagActivated(EditorEvent e): Accionado cuando cualquier bandera de relevancia se coloca en TRUE. • onComponentPressed(EditorEvent e): Accionado cuando un componente es seleccionado por el ratón por primera vez. • onColorChooser(EditorEvent e): Accionado cuando se desea cambiar el color del componente seleccionado. 3.3 DESARROLLO DEL AMBIENTE DE EJECUCIÓN El ambiente de ejecución se refiere al estado en que entra el programa cuando se presiona el botón de ejecutar. Ya no se podrán hacer más modificaciones al despliegue si no más bien, observar el estado de las variables asociadas a cada componente. 56 Para establecer esta conexión siempre es necesario insertar el objeto EditorConnect. A continuación se tendrá una descripción de dicha clase. EditorConnect: Como esta clase puede dar muchas fallas que podrían llegar a hacer que el programa se detuviese, absolutamente todas las funciones deben estar dentro del modo “tratar- atrapar”. Este modo conocido como “try-catch” (tratar-atrapar) se refiere a la ejecución de un comando, y si este arroja un error, ejecutaria la subrutina encontrada en el “catch”, de tal manera que el programa nunca se encontraria en un bloqueo sin salida. Inicialmente tenemos que se intenta abrir una conexión con un dirección URL determinada otorgada previamente por el EditorWorkspace. Dependiendo de dicha dirección se abrirán diferentes conexiones a diferentes servlets. El primer caso sería abrir el servlet del cual se desean obtener las etiqueta que tiene la base de datos. Para ello sólo se requiere abrir la conexión y recibir lo enviado. Como se menciono anteriormente el HTTP-POST envía bytes, por lo cual hay que ir organizando todas las etiquetas enviadas en un solo arreglo de caracteres para luego entregarla al EditorWorkspace y que éste la divida pertinentemente. Si la conexión falla se le enviará al usuario un mensaje de error avisando que el servlet al cual se desea conectar no se encuentra en servicio. El segundo caso requiere que al abrir la conexión se envíen inicialmente las etiquetas que se solicitan en un solo arreglo de caracteres separadas por un espacio, de tal manera que se tendría el siguiente formato: “Etiqueta Etiqueta Etiqueta … Etiqueta”. Para obtener los valores se espera entonces que el servlet devuelva la información pertinente a las etiquetas proporcionadas. Como se menciono anteriormente este envía bytes en el siguiente orden: Etiqueta Tipo Valor. El objeto EditorConnect se 57 encarga de pasarlos a caracteres y colocarlos todos en un solo arreglo para así redirigirlo al EditorWorkspace. Nuevamente si la conexión falla se le enviará un mensaje de error al usuario y se vuelve al desarrollo del despliegue. 3.3 DESARROLLO DE LOS OBJETOS Los Objetos se refieren a los componentes que serán insertados en el despliegue para simular la planta que el diseñador desea monitorear. Todos estos objetos deben hacerse con la referencia al tamaño que son. Con esto se quiere decir que no tendrán un tamaño fijo si no dependerán del espacio que les otorgue el EditorWorkspace y se adaptarán al mismo. Todos estos objetos implementan la interfaz MouseListener de tal manera que pueden detectar cuando ocurra un evento del ratón sobre ellos y lo redirigen con la ayuda del EditorListener al EditorWorkspace. Válvulas Se eligió que el color inicial de la válvula sería negro (se podrá editar como se ha descrito en secciones anteriores). Para darle un efecto tri dimensional también se empleará el método de degradado de negro a blanco. Finalmente uniendo todos estos diagramas obtenemos la figura (Figura 12) final de la válvula: Figura 12: Válvula 58 Tanque Para el tanque se tiene el mismo efecto de degradado, siendo su color inicial el gris. El tanque consta de dos arcos y un rectángulo para su parte exterior, y para el nivel del agua consta de un arco, un óvalo y un rectángulo. Es importante denotar que el nivel del tanque, no sólo varía dependiendo del tamaño del componente sino también del porcentaje que se desee llenar del tanque. Finalmente uniendo las piezas tendríamos el siguiente tanque (Figura 13) Figura 13: Tanque Botón y Etiqueta El API de Java proporciona un botón que contiene todas las características necesarias para realizar esta clase. El único detalle es que dicho botón no puede heredad de EditorComponent, por lo cual no puede ser tratado genéricamente como los otros componentes. De tal manera que lo que se hizó fue realizar una clase para el botón que sencillamente lo tuviese declarado extendiendo a EditorComponent. El caso de la etiqueta es el mismo 59 La siguiente figura (Figura 14) muestra el botón y la etiqueta. Figura 14: Objetos botón y Etiqueta Tubería El color de la tubería será gris con degradado, y para sus terminales negro. Consta de un arco, un rectángulo y un ovalo. Finalmente se tiene una tubería de la siguiente manera (Figura 15): Figura 15: Objeto Tubería Indicador Quizás sea la figura más compleja de todas debido a las líneas de indicación que debe tener y la línea que marca a donde esta ubicado. Esta última no sólo debe variar en tamaño cuando se aumente el gráfico, sino en ángulo cuando se asocie a una etiqueta. Para realizar esta figura se emplearon tres arcos, y 100 líneas que son las particiones del medidor. Los arcos fueron sencillos de realizar pero las líneas debían tener una inclinación y corresponder al valor de un grado en específico. Finalmente con la siguiente fórmula se logró establecer la relación para las líneas (Figura 16): 60 L = A× B 1 A sen α + B 2 cos 2 α 2 2 Figura 16: Fórmula de relacion de Lineas Donde los parámetros se pueden establecer mediante la siguiente figura (Figura 17) Figura 17: Parametros Como resultado final se obtuvo el siguiente diagrama del indicador (Figura 18). Figura 18: Objeto Indicador 61 CAPÍTULO 4: Pruebas y Resultados Este capítulo presenta las pruebas realizadas para la verificación del correcto funcionamiento del software desarrollado. Estas pruebas son las siguientes: • Presentación del diagrama inicial y Propiedades de los componentes EditorFrames • Diseño de un despliegue • Diseño de dos despliegues • modificación de los atributos de los objetos en el despliegue o Color o Tamaño • Asociación de los despliegues a Etiquetas • Conectando el despliegue • Corriendo un Despliegue 4.1 PRUEBA Y RESULTADOS DE AMBIENTE DE PROGRAMACIÓN La primera prueba es la más sencilla. Comprobar que el programa puede ejecutar y abrir un despliegue. Para ello se compiló el programa y se ejecutó, con lo cual obtuvimos la siguiente pantalla (Figura 19) 62 Figura 19: Ejecución inicial del Programa Una vez que el resultado de la ejecución básica fue satisfactorio, se procedió a seleccionar el botón de “nuevo” para abrir un despliegue, obteniendo el siguiente resultado (Figura 20) Figura 20: Un despliegue sin Elementos 63 Como se menciono anteriormente estos despliegues deberían poder maximizarse y minimizarse y abrirse más de uno simultáneamente. Por lo cual se procedió a pulsar con el raton sobre el botón de “nuevo” nuevamente para obtener dos despliegues simultáneamente. Se obtuvo el siguiente resultado (Figura 21). Merece acotar que usualmente las figuras en Java se colocan detrás de la primera figura insertada, por lo cual, aquí se esta empleando un “panel” de formato especial como se mencionó en la descripción del objeto EditorDesktop. Figura 21: Dos Despliegues simultáneos 64 Luego se procedió a minimizar uno de ellos obteniendo el siguiente resultado (figura 22): Figura 22: Un despliegue minimizado Por ultimo se maximizó uno de los despliegues para finalizar de probar la funcionalidad de los mismos. El resultado obtenido fue el siguiente: (Figura 23) Figura 23: Un despliegue Maximizado 65 Una vez que se estableció que los objetos EditorFrame funcionaban adecuadamente se procedió a añadir objetos aleatorios en el despliegue verificando simultáneamente que los botones de la barra de herramienta funcionacen, que los eventos se redireccionaran adecuantamente y que pudiesen ser insertados en el despliegue. El resultado fue la siguiente figura (Figura 24) Figura 24: Diseño de un despliegue Como siguiente paso se procedió a diseñar dos despliegues simultáneamente, de tal manera que se observase que se podía distinguir entre el estado activo de un despliegue y otro. 66 Como resultado se obtuvo la siguiente figura (Figura 25) Figura 25: Diseño de dos despliegues simultáneos Por último en lo que respecta al ambiente de diseño se debe verificar el comportamiento de los objetos insertados en el despliegue. Para ello se debe verificar que se puedan cambiar de tamaño, y de color. (Se dejó la prueba de asociación de etiquetas al modo de ejecución ya que requiere un paso previo que es la conexión con el servidor) Al seleccionar un componente (tanque en este caso) y arrastrar una de sus esquinas se logró exitosamente cambiar su tamaño y que éste mantuviese la proporción de sus componentes. Esto se puede apreciar en la siguiente figura (Figura 26) 67 Figura 26: Agrandando un Componente Finalmente se procedió a realizar la prueba final que consistía en el cambio del color del componente. Como se puede observar en las figuras (Figura 21, Figura 22, Figura 27) hay tres modos de seleccionar el color del componente, las cuales funcionan exitosamente. Figura 27: Cambio de Color 1 68 Figura 28: Cambio de Color 2 Figura 29: Cambio de Color 3 69 4.2 PRUEBA Y RESULTADOS DE EJECUCIÓN Esta sección refiere a las pruebas realizadas para verificar la conexión correcta al servlet y la interacción entre el despliegue y los datos que se obtienen. Inicialmente la prueba inicial sería conectarse al servlet para obtener las etiquetas y asociarlas a las variables. Para ésto se presionó el botón de conectar y se esperó la indicación de que se había establecido exitosamente. El resultado se muestra en la siguiente figura (figura 30) Figura 30: Despliegue Conectado Una vez conectado al servidor se debe verificar la correcta recepción de las etiquetas. 70 En las siguientes figuras se puede observar la asociación de las etiquetas recibidas a los componentes. (Figura 31 y Figura 32) Figura 31: Cuadro de Propiedades para seleccionar etiquetas Figura 32: Asociación de etiqueta de los componentes. 71 Es necesario asociar los límites a las etiquetas que se han establecido, para que la normalización pueda entrar en efecto. Para ello se puede presionar el botón de establecer límites el cual presenta un recuadro donde se pueden escribir los datos y presionar el botón de aceptar. Si se omitiese este paso los límites pre-establecidos son siempre 0 -100. La siguiente figura es el resultado obtenido al establecer los límites de una de las etiquetas seleccionada (Figura 33) Figura 33: Asociación de Límites a las Variables Por ultimo se debe verificar el correcto funcionamiento del programa en modo de ejecutar. Al presionar dicho botón todos los despliegues dejaron de ser editables y al presionar los botones en las barras de herramientas ningún evento se disparaba. Luego se observó como el nivel de los tanques del despliegue iba variando al igual que su color dependiendo del valor de las variables que otorgara el servlet. 72 En este diagrama se asoció la misma variable color a 3 de los tanques, a uno de ellos no se le asoció color. Las tuberías dos de ellas comparten el valor de una variable booleana. Los tanques 3 comparten la misma variable de nivel y el último tiene una propia. La figura 34 ilustra el comportamiento capturado en un momento aleatorio del despliegue Figura 34: Despliegue en Ejecución 73 CAPÍTULO 5: Conclusiones y Recomendaciones Como se planteó inicialmente el objetivo primordial de este proyecto es desarrollar un software que permita el diseño y supervisión de una planta en tiempo real. Después del desarrollo realizado se ha demostrado que el desarrollo del prototipo fue exitoso, y por lo tanto, inversión de tiempo y dinero en él puede ser considerado para un futuro proyecto. La decisión de optar por Java como lenguaje de programación terminó siendo totalmente exitosa, ya que se desarrollo inicialmente el proyecto bajo un ambiente Windows y este luego fue migrado a Linux sin ningún tipo de modificación necesaria al código para su ejecución. Por otro lado, la programación orientada a objetos demostró su utilidad ya que las numerosas líneas de código pudieron ser convertidas en clases, de tal manera de ser reusables y convenientes a la lectura de cualquier otro programador que desease acceder al código. Las pruebas realizadas cumplieron las expectativas, y el programa probó ser capaz de realizar despliegues, hasta más de uno simultáneamente, y a los objetos introducidos en dichos despliegues se le lograron modificar los atributos esperados (tamaño y color). También se logó establecer exitosamente la conexión a un servlet para obtener los datos allí encontrados. Interesante es destacar que Intelcon siendo una empresa nacional sería la primera en lograr explorar este campo en Venezuela, colocándola así en competencia con compañías que son internacionales. Tuvieron la novedosa idea de diseñar la planta que se desea monitorear, observar y modificar en cualquier momento. 74 Una de las recomendaciones que se puede hacer para futuros diseñadores, que deseen realizar un programa más complejo, es ofrecer a los clientes maneras de personalizar los tiempos de adquisición de datos del servlet, que es este caso estaba fijado a un segundo. Por ultimo, vale la pena acotar que es importante mantener un cuaderno de anotaciones para documentar la evolución del proyecto, resultados, dudas, y cualquier percance ocurrido y la solución tomada para poder realizar un reporte final adecuado. También vale la pena acotar que el uso de Internet es muy importante, ya que existen innumerables foros e información donde se puede encontrar ayuda a temas específicos de la programación, o a nuevas ideas que se desean implementar. 75 Referencias Bibliográficas [1] 1 Martín, T., Programación orientada a Objetos (OOP, Object Oriented Programming) encontrado en: http://www.monografias.com/trabajos14/progorie/progorie.shtml [2] Paguina Oficial de Wikipedia: http://es.wikipedia.org/wiki/M%C3%A1quina_virtual_Java Encliclepedia Libre: 76 APÉNDICE 1 En este apéndice se colocara el código úicamente del EditorWorkspace, las otras clases se mantendrán privadas. EditorWorkspace package ve.com.intelcon.scada.editor; import import import import import import import import import import import import import import import javax.swing.JButton; javax.swing.JColorChooser; javax.swing.JComponent; javax.swing.JFrame; javax.swing.JLabel; javax.swing.JOptionPane; javax.swing.JPanel; javax.swing.JScrollPane; javax.swing.JTextArea; javax.swing.JTextField; javax.swing.SwingConstants; javax.swing.Timer; javax.swing.colorchooser.DefaultColorSelectionModel; javax.swing.event.ChangeEvent; javax.swing.event.ChangeListener; import java.lang.String; import import import import import import import import import import import import import import import java.awt.BorderLayout; java.awt.Button; java.awt.Choice; java.awt.Color; java.awt.Component; java.awt.Cursor; java.awt.Menu; java.awt.MenuItem; java.awt.Rectangle; java.awt.event.ActionEvent; java.awt.event.ActionListener; java.awt.event.ItemEvent; java.awt.event.ItemListener; java.awt.event.MouseEvent; java.awt.event.MouseListener; 77 import java.awt.event.MouseMotionListener; public class EditorWorkspace extends JPanel implements EditorListener,MouseMotionListener,MouseListener,ItemListen er,ChangeListener, ActionListener { BorderLayout layout; EditorToolbar fileToolbar; // Barra de herramientas de Archivos (New/Close/Save) EditorToolbar objectToolbar; // Barra de herramemientas de los Componentes JScrollPane scrollPane; EditorDesktop desktop; EditorBlockManager bm = new EditorBlockManager(); EditorPropierties ep; // Controlador de Propiedades de los Componentes Timer eventTimer = new Timer(100,this); int x1,y,x,w,h,flag=0,count=0,countbefore,tagcounter=0,typecoun ter=0,valuecounter=0; // Variables usadas para ordenar los Tags de los Componentes int y1,i=0,componentCounter=0; // Contador de los Componentes int objectflag =0,playFlag = 0 ; // Bandera que indica que un objeto ha sido seleccionado, Bandera que indica que estamos en modo de Ejecucion EditorSquares ms1 = new EditorSquares(); // Recuadro de la esquina izquierda superior EditorSquares ms2 = new EditorSquares(); // Recuadro de la esquina derecha superior EditorSquares ms3 = new EditorSquares(); // Recuadro de la esquina izquierda inferior EditorSquares ms4 = new EditorSquares(); // Recuadro de la esquina derecha inferior EditorRectangles mr1 = new EditorRectangles(); // Recuadro del borde superior EditorRectangles mr2 = new EditorRectangles(); // Recuadro del borde derecho EditorRectangles mr3 = new EditorRectangles(); // Recuadro del borde izquierdo EditorRectangles mr4 = new EditorRectangles(); // Recuadro del borde inferior Component g,gprevious; // Componentes auxiliares donde se almacenara el componente seleccionado despues de haer clic en el. 78 EditorConnect ed; // Para la conexion. Rectangle r; EditorEventPerformer performer = new EditorEventPerformer(); // Manejador de Eventos JColorChooser colorSelector = new JColorChooser(); // Seleccionador de Colores Choice tagLevel; // Lista de Selecciones de los Tags que indican el nivel Choice tagColor; // Lista de Selecciones de los Tags que indican el color EditorComponent[] componentList = new EditorComponent[30]; // Lista donde se almacenan los componentes que se van colocando en el Frame Activo int addObjectFlag = 0; // Indica si se ha seleccionado para anadir un objeto int activeFrame; // Indica el numero del Frame que esta siendo utilizado en el momento int limitFlag = 0; // Bandera que indica que el boton de acpetar limites ha sido utilizado String tag, colorTag; // String que recibe lo enviado de vuelta del PLC (para los valores se utliza tag y para los valores de los colores se usa colorTag) String[] tags = new String[50]; // Contiene los nombres de las Tags enviadas de vuelta por el PLC correspondiente a los valores String[] tags2 = new String[50]; // Contiene los nombres de las Tags enviadas de vuelta por el PLC correspondente a los colores String [] types = new String[50]; // Contiene los nombres de los tipos que son las tags de los valores String[] types2 = new String[50]; // Contiene los nombres de los tipos que son las tags de los colores String[] tagValues = new String[50]; // Contiene los valores numericos en forma de string de las tags de valores String[] tagValues2 = new String[50]; // Contiene los valores numericos en forma de string de las tags de colores JTextField levelLowerLimit = new JTextField("0"); // Contiene el valor del limite inferior de la variable del PLC asociada a un componente JTextField levelUpperLimit = new JTextField ("100"); // Contiene el valor del limite superior de la variable del PLC asociada a un componente JTextField colorLowerLimit = new JTextField("0"); // Contiene el valor del limite inferior de la variable del PLC asociada al color de un componente 79 JTextField colorUpperLimit = new JTextField ("100"); // Contiene el valor del limite superior de la variable del PLC asociada al color de un componente JTextField componentUpperLimit = new JTextField("100"); // Contiene el valor del limite superior del Componente JTextField componentLowerLimit = new JTextField("0"); // Contiene el valor del limite inferior del Componente JButton acceptLimits = new JButton("Aceptar"); EditorWorkspace() { layout = new BorderLayout(); desktop = new EditorDesktop(); fileToolbar = new EditorFileToolbar(); objectToolbar = new EditorObjectToolbar(); this.setLayout(layout); this.add(fileToolbar, BorderLayout.PAGE_START); this.add(objectToolbar, BorderLayout.WEST); this.add(desktop, BorderLayout.CENTER); this.desktop.addEditorListener(this); this.fileToolbar.addEditorListener(this); this.objectToolbar.addEditorListener(this); this.fileToolbar.setOrientation(SwingConstants.HORIZONTAL); this.objectToolbar.setOrientation(SwingConstants.VERTICAL); acceptLimits.addActionListener(this); /** ms1-ms4 y mr1-mr4 Son los responsables de el cambio de tamano del elemento dentro del Frame, para ello implentan interfeces que atrapan * movimientos de mouse, como lo son el clic, el arrastrado, el presionado, etc*/ ms1.addMouseMotionListener(this); ms1.addMouseListener(this); ms2.addMouseMotionListener(this); ms2.addMouseListener(this); ms3.addMouseMotionListener(this); 80 ms3.addMouseListener(this); ms4.addMouseMotionListener(this); ms4.addMouseListener(this); mr1.addMouseMotionListener(this); mr1.addMouseListener(this); mr2.addMouseMotionListener(this); mr2.addMouseListener(this); mr3.addMouseMotionListener(this); mr3.addMouseListener(this); mr4.addMouseMotionListener(this); mr4.addMouseListener(this); } /** Evento que se dispara cuando se presiona cualqueira de las barra, luego se aisla cual de las barras de herramientas fue que disparo * el evento y se toman acciones acordes a el boton que fue presionado dentro en la barra. */ public void onToolbarPressed(EditorEvent e) { if( e.getSource() == this.fileToolbar ) { switch(e.buttonPressed) { /** Se crea un nuevo frame*/ case EditorFileToolbar.BUTTON_NEW: this.desktop.addFrame(); break; /**Se elimina el estado de ejecucion del sistema, deshabilitando la bandera de flag y el timer que dispara el evento de busqueda de datos se detiene*/ case EditorFileToolbar.BUTTON_STOP: playFlag = 0 ; eventTimer.stop(); break; case EditorFileToolbar.BUTTON_OPEN: break; case EditorFileToolbar.BUTTON_SAVE: break; 81 /** Se elemina el frame que se encuentra seleccionado y todos los eventos asociados a el */ case EditorFileToolbar.BUTTON_CLOSE: this.desktop.remove(this.desktop.frames[this.activeFrame]); this.desktop.closeFrame(this.activeFrame); break; /** Activo la bandera del modo de ejecuccion, y abro una neuva conexion para la obtencion de valores. Activo el timer que disparara eventos cada 100ms * donde se refrescaran los valores */ case EditorFileToolbar.BUTTON_PLAY: playFlag = 1 ; ed = new EditorConnect("http://180.180.1.18/plc/get_values"); eventTimer.start(); break; /** Se abre una conexion a un servlet para obtener los tags disponibles del PLC, los cuales vienen en el formato "TAG TIPO", por lo cual hay que * separar los TAGS, que seran colocados en un arreglo de strings denominada tags[] y los tipos en una denominada types[] */ case EditorFileToolbar.BUTTON_CONNECT: ed = new EditorConnect("http://180.180.1.18/plc/get_tags"); char[] buffer = new char[32]; tag = ed.getTags(); while(count<tag.length()) { int aux = 0 ; while(aux <2) { while(tag.charAt(count)!= ' ') //eso es un espacio { count ++; } if(aux ==0) { 82 tags[tagcounter]= tag.substring(countbefore,count); tagcounter++; } if(aux==1) { types[typecounter] = tag.substring(countbefore,count); typecounter++; } count ++; countbefore = count; aux ++; } } JOptionPane.showMessageDialog(this, " Conectado ","WORKSPACE", 0); break; } } /** Si el evento fue disparado por la barra que contiene los Componentes se activa la bandera de Agregar Objetos */ if( e.getSource() == this.objectToolbar ) { this.addObjectFlag = e.buttonPressed; switch(e.buttonPressed) { case EditorObjectToolbar.BUTTON_VALVE: break; case EditorObjectToolbar.BUTTON_TANK: break; case EditorObjectToolbar.BUTTON_BUTTON: break; case EditorObjectToolbar.BUTTON_LABEL: break; case EditorObjectToolbar.BUTTON_GAUGE: break; case EditorObjectToolbar.BUTTON_PIPE: break; case EditorObjectToolbar.BUTTON_LINK: 83 break; } } } /** Evento que se dispara cuando se presiona en Frame activo, solo si no se encuentra en modo de ejecucion. Revisa el estado de ObjectFlag para ver * si ha sido presionada la barra de Componentes. Dependiendo de cual Componente haya sido presionado se entra al correspondiente caso. Se anade el * componente y se agrega a lista "componentList[]". Es importante denotar que se debe tener el Frame adecuado que se ecuentra activo en el momento. * A estos componentes se le agrega la interfaz del MouseListener y MouseMotionListener para que sean capaces de capturar eventos del mouse. */ public void onDesktopPressed(EditorEvent e) { this.activeFrame=e.frameNumber; if(playFlag == 0) { if( e.getSource() == this.desktop ) { switch(this.addObjectFlag) { case EditorObjectToolbar.BUTTON_VALVE: ValveBlock v = new ValveBlock(0); componentList[componentCounter]= v; v.setVisible(true); v.setBounds(e.x, e.y, 50, 50); v.addMouseListener( this ); v.addMouseMotionListener( this ); this.desktop.getFrame( e.frameNumber ).add( v ); 84 this.desktop.getFrame( e.frameNumber ).repaint(); componentCounter = componentCounter + 1; break; case EditorObjectToolbar.BUTTON_TANK: TankBlock2 t = new TankBlock2(50,0); componentList[componentCounter]= t; t.setVisible(true); t.setBounds(e.x, e.y, 60, 150); t.addMouseListener( this ); t.addMouseMotionListener( this ); this.desktop.getFrame( e.frameNumber ).add( t ); this.desktop.getFrame( e.frameNumber ).repaint(); componentCounter = componentCounter + 1; break; case EditorObjectToolbar.BUTTON_BUTTON: EditorButton button = new EditorButton(80,40); button.setBounds(e.x,e.y,80,40); componentList[componentCounter]= button; button.setVisible(true); button.addMouseListener( this ); button.addMouseMotionListener( this ); this.desktop.getFrame( e.frameNumber ).add( button ); this.desktop.getFrame( e.frameNumber ).repaint(); componentCounter = componentCounter + 1; break; case EditorObjectToolbar.BUTTON_LABEL: 85 JLabel label = new JLabel("Etiqueta"); label.setBounds(e.x,e.y,60,30); label.addMouseListener( this ); label.addMouseMotionListener( this ); this.desktop.getFrame( e.frameNumber ).add( label ); this.desktop.getFrame( e.frameNumber ).repaint(); break; case EditorObjectToolbar.BUTTON_GAUGE: GaugeBlock g = new GaugeBlock(0); componentList[componentCounter]= g; g.setVisible(true); g.setBounds(e.x, e.y, 150, 100); g.addMouseListener( this ); g.addMouseMotionListener( this ); this.desktop.getFrame( e.frameNumber ).add( g ); this.desktop.getFrame( e.frameNumber ).repaint(); componentCounter = componentCounter + 1; break; case EditorObjectToolbar.BUTTON_PIPE: PipeBlock p = new PipeBlock(0); componentList[componentCounter]= p; p.setVisible(true); p.setBounds(e.x, e.y, 200, 30); p.addMouseListener( this ); p.addMouseMotionListener( this ); this.desktop.getFrame( e.frameNumber ).add( p ); this.desktop.getFrame( e.frameNumber ).repaint(); 86 componentCounter = componentCounter + 1; break; case EditorObjectToolbar.BUTTON_LINK: LinkBlock l = new LinkBlock(2,0); componentList[componentCounter]= l; l.setVisible(true); l.setBounds(e.x, e.y, 50, 50); l.addMouseListener( this ); l.addMouseMotionListener( this ); this.desktop.getFrame( e.frameNumber ).add( l ); this.desktop.getFrame( e.frameNumber ).repaint(); componentCounter = componentCounter + 1; break; default: break; } this.addObjectFlag = 0; } } } public void onRightObjectPressed(EditorEvent e) { } /** Funcione para el giro de 90 grados. Todos los componentes tienen un parametro de entrada de angulo, el cual cambiaria de 90 en 90 grados */ public void onFlagActivated(EditorEvent e) { 87 int int int int x y w h = = = = e.component.getX(); e.component.getY(); e.component.getWidth(); e.component.getHeight(); e.component.setBounds(x,y,h,w); if(e.objectFlag==1) { GaugeBlock g = (GaugeBlock) e.component; g.rotate(90); g.repaint(); } if(e.objectFlag==2) { LinkBlock l = (LinkBlock) e.component; } if(e.objectFlag==3) { PipeBlock p = (PipeBlock) e.component; } if(e.objectFlag==4) { TankBlock2 t = (TankBlock2) e.component; } if(e.objectFlag==5) { ValveBlock v = (ValveBlock) e.component; } } public void onComponentPressed(EditorEvent e) { bm.setFlag(e.objectFlag); } /** Este evento se dispara cuando se presiona un componente. El objetivo es agarrar la posicion incial que tiene el mouse sobre el componente * para que se mantenga en la misma posicion relativa cuando se mueva el componente sobre el frame. */ 88 public void mousePressed(MouseEvent e) { x1 = e.getX(); y1 = e.getY(); int x3 = g.getX(); int y3 = g.getY(); int x0 = x1-x3; int y0 = y1-y3; } public void mouseReleased(MouseEvent e) { } /** Evento que se dispara cuando el Mouse es arrastra sobre un componente. Se tienen dos situaciones posibles: El evento se disparo sobre un Componente * por lo cual este sera movido sin modificar su tamano. Si el evento se disparo sobre ms1-ms4 o mr1-mr4 estos seran capaces de modificar el tamano * del componente. */ public void mouseDragged(MouseEvent e) { g = e.getComponent(); int int int int x = e.getX(); y = e.getY(); x2=g.getX(); y2=g.getY(); if( playFlag == 0) { if((g!=ms1)&&(g!=ms2)&&(g!=ms3)&&(g!=ms4)&&(g!=mr1)&&( g!=mr2)&&(g!=mr3)&&(g!=mr4)) { g.setBounds(x+x2-x1+10,y+y2y1+10,g.getWidth(),g.getHeight()); w=g.getWidth(); h=g.getHeight(); 89 mr1.setBounds(x+x2-x1+10,y+y2-y110,g.getWidth()-20,g.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr1 ); mr2.setBounds(x+x2-x1+g.getWidth(),y+y2y1+10,g.getWidth()/10,g.getHeight()-20); this.desktop.getFrame(this.activeFrame ).add( mr2 ); mr3.setBounds(x+x2-x1,y+y2y1+10,g.getWidth()/10,g.getHeight()-20); this.desktop.getFrame(this.activeFrame ).add( mr3 ); mr4.setBounds(x+x2-x1+10,y+y2y1+g.getHeight(),g.getWidth()-20,g.getHeight()/10); this.desktop.getFrame(this.activeFrame ).add( mr4 ); ms1.setBounds(x+x2-x1,y+y2y1,g.getWidth()/4,g.getHeight()/4); this.desktop.getFrame(this.activeFrame ).add( ms1 ); ms2.setBounds(x+x2-x1+w+10,y+y2y1,g.getWidth()/4,g.getHeight()/4); this.desktop.getFrame(this.activeFrame ).add( ms2 ); ms3.setBounds(x+x2-x1,y+y2y1+h+10,g.getWidth()/4,g.getHeight()/4); this.desktop.getFrame(this.activeFrame ).add( ms3 ); ms4.setBounds(x+x2-x1+w+10,y+y2y1+h+10,g.getWidth()/4,g.getHeight()/4); this.desktop.getFrame(this.activeFrame ).add( ms4 ); ms1.setVisible(true); ms2.setVisible(true); ms3.setVisible(true); ms4.setVisible(true); gprevious=(EditorComponent)g; } else { if(g==ms1) { 90 gprevious.setBounds(gprevious.getX()+x,gprevious.getY( )+y,gprevious.getWidth()-x, gprevious.getHeight()-y); x = gprevious.getX(); y = gprevious.getY(); w=gprevious.getWidth(); h=gprevious.getHeight(); ms1.setBounds(gprevious.getX()10,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms1 ); ms2.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms2 ); ms3.setBounds(gprevious.getX()10,gprevious.getY()+gprevious.getHeight()+10,gprevious.getW idth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms3 ); ms4.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()+gprevious.getHeight()+10,gprevious.getWid th()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms4 ); mr1.setBounds(gprevious.getX()+10,gprevious.getY()10,gprevious.getWidth()-20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr1 ); mr2.setBounds(gprevious.getX()+gprevious.getWidth(),gprevio us.getY(),gprevious.getWidth()/10,gprevious.getHeight()20); this.desktop.getFrame( this.activeFrame ).add( mr2 ); 91 mr3.setBounds(gprevious.getX()10,gprevious.getY()+10,gprevious.getWidth()/10,gprevious.ge tHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr3 ); mr4.setBounds(gprevious.getX()+10,gprevious.getY()+gpr evious.getHeight(),gprevious.getWidth()20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr4 ); ms1.setCursor(new Cursor(6)); } if(g==ms2) { gprevious.setBounds(gprevious.getX(),gprevious.getY()+ y,gprevious.getWidth()+x,gprevious.getHeight()-y); x = gprevious.getX(); y = gprevious.getY(); w=gprevious.getWidth(); h=gprevious.getHeight(); ms1.setBounds(gprevious.getX()10,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms1 ); ms2.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms2 ); ms3.setBounds(gprevious.getX()10,gprevious.getY()+gprevious.getHeight()+10,gprevious.getW idth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms3 ); 92 ms4.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()+gprevious.getHeight()+10,gprevious.getWid th()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms4 ); mr1.setBounds(gprevious.getX()+10,gprevious.getY()10,gprevious.getWidth()-20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr1 ); mr2.setBounds(gprevious.getX()+gprevious.getWidth(),gprevio us.getY(),gprevious.getWidth()/10,gprevious.getHeight()20); this.desktop.getFrame( this.activeFrame ).add( mr2 ); mr3.setBounds(gprevious.getX()10,gprevious.getY()+10,gprevious.getWidth()/10,gprevious.ge tHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr3 ); mr4.setBounds(gprevious.getX()+10,gprevious.getY()+gpr evious.getHeight(),gprevious.getWidth()20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr4 ); ms2.setCursor(new Cursor(7)); } if(g==ms3) { gprevious.setBounds(gprevious.getX()+x,gprevious.getY( ),gprevious.getWidth()-x,gprevious.getHeight()+y); x = gprevious.getX(); y = gprevious.getY(); w=gprevious.getWidth(); h=gprevious.getHeight(); 93 ms1.setBounds(gprevious.getX()10,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms1 ); ms2.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms2 ); ms3.setBounds(gprevious.getX()10,gprevious.getY()+gprevious.getHeight()+10,gprevious.getW idth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms3 ); ms4.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()+gprevious.getHeight()+10,gprevious.getWid th()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms4 ); mr1.setBounds(gprevious.getX()+10,gprevious.getY()10,gprevious.getWidth()-20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr1 ); mr2.setBounds(gprevious.getX()+gprevious.getWidth(),gprevio us.getY(),gprevious.getWidth()/10,gprevious.getHeight()20); this.desktop.getFrame( this.activeFrame ).add( mr2 ); mr3.setBounds(gprevious.getX()10,gprevious.getY()+10,gprevious.getWidth()/10,gprevious.ge tHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr3 ); mr4.setBounds(gprevious.getX()+10,gprevious.getY()+gpr evious.getHeight(),gprevious.getWidth()20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr4 ); 94 ms3.setCursor(new Cursor(4)); } if(g==ms4) { gprevious.setBounds(gprevious.getX(),gprevious.getY(), gprevious.getWidth()+x,gprevious.getHeight()+y); x = gprevious.getX(); y = gprevious.getY(); w=gprevious.getWidth(); h=gprevious.getHeight(); ms1.setBounds(gprevious.getX()10,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms1 ); ms2.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms2 ); ms3.setBounds(gprevious.getX()10,gprevious.getY()+gprevious.getHeight()+10,gprevious.getW idth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms3 ); ms4.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()+gprevious.getHeight()+10,gprevious.getWid th()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms4 ); mr1.setBounds(gprevious.getX()+10,gprevious.getY()10,gprevious.getWidth()-20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr1 ); mr2.setBounds(gprevious.getX()+gprevious.getWidth(),gprevio 95 us.getY(),gprevious.getWidth()/10,gprevious.getHeight()20); this.desktop.getFrame( this.activeFrame ).add( mr2 ); mr3.setBounds(gprevious.getX()10,gprevious.getY()+10,gprevious.getWidth()/10,gprevious.ge tHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr3 ); mr4.setBounds(gprevious.getX()+10,gprevious.getY()+gpr evious.getHeight(),gprevious.getWidth()20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr4 ); ms4.setCursor(new Cursor(5)); } if(g==mr1) { gprevious.setBounds(gprevious.getX(),gprevious.getY()+y,gpr evious.getWidth(),gprevious.getHeight()-y); x = gprevious.getX(); y = gprevious.getY(); w=gprevious.getWidth(); h=gprevious.getHeight(); ms1.setBounds(gprevious.getX()10,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms1 ); ms2.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms2 ); ms3.setBounds(gprevious.getX()10,gprevious.getY()+gprevious.getHeight()+10,gprevious.getW idth()/4,gprevious.getHeight()/4); 96 this.desktop.getFrame( this.activeFrame ).add( ms3 ); ms4.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()+gprevious.getHeight()+10,gprevious.getWid th()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms4 ); mr1.setBounds(gprevious.getX()+10,gprevious.getY()10,gprevious.getWidth()-20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr1 ); mr2.setBounds(gprevious.getX()+gprevious.getWidth(),gprevio us.getY(),gprevious.getWidth()/10,gprevious.getHeight()20); this.desktop.getFrame( this.activeFrame ).add( mr2 ); mr3.setBounds(gprevious.getX()10,gprevious.getY()+10,gprevious.getWidth()/10,gprevious.ge tHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr3 ); mr4.setBounds(gprevious.getX()+10,gprevious.getY()+gpr evious.getHeight(),gprevious.getWidth()20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr4 ); } if (g==mr2) { gprevious.setBounds(gprevious.getX(),gprevious.getY(),gprev ious.getWidth()+x,gprevious.getHeight()); x = gprevious.getX(); y = gprevious.getY(); w=gprevious.getWidth(); h=gprevious.getHeight(); 97 ms1.setBounds(gprevious.getX()10,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms1 ); ms2.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms2 ); ms3.setBounds(gprevious.getX()10,gprevious.getY()+gprevious.getHeight()+10,gprevious.getW idth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms3 ); ms4.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()+gprevious.getHeight()+10,gprevious.getWid th()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms4 ); mr1.setBounds(gprevious.getX()+10,gprevious.getY()10,gprevious.getWidth()-20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr1 ); mr2.setBounds(gprevious.getX()+gprevious.getWidth(),gprevio us.getY(),gprevious.getWidth()/10,gprevious.getHeight()20); this.desktop.getFrame( this.activeFrame ).add( mr2 ); mr3.setBounds(gprevious.getX()10,gprevious.getY()+10,gprevious.getWidth()/10,gprevious.ge tHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr3 ); mr4.setBounds(gprevious.getX()+10,gprevious.getY()+gpr evious.getHeight(),gprevious.getWidth()20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr4 ); 98 } if(g==mr3) { gprevious.setBounds(gprevious.getX()+x,gprevious.getY(),gpr evious.getWidth()-x,gprevious.getHeight()); x = gprevious.getX(); y = gprevious.getY(); w=gprevious.getWidth(); h=gprevious.getHeight(); ms1.setBounds(gprevious.getX()10,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms1 ); ms2.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms2 ); ms3.setBounds(gprevious.getX()10,gprevious.getY()+gprevious.getHeight()+10,gprevious.getW idth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms3 ); ms4.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()+gprevious.getHeight()+10,gprevious.getWid th()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms4 ); mr1.setBounds(gprevious.getX()+10,gprevious.getY()10,gprevious.getWidth()-20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr1 ); mr2.setBounds(gprevious.getX()+gprevious.getWidth(),gprevio us.getY(),gprevious.getWidth()/10,gprevious.getHeight()20); 99 this.desktop.getFrame( this.activeFrame ).add( mr2 ); mr3.setBounds(gprevious.getX()10,gprevious.getY()+10,gprevious.getWidth()/10,gprevious.ge tHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr3 ); mr4.setBounds(gprevious.getX()+10,gprevious.getY()+gpr evious.getHeight(),gprevious.getWidth()20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr4 ); } if(g==mr4) { gprevious.setBounds(gprevious.getX(),gprevious.getY(),gprev ious.getWidth(),gprevious.getHeight()+y); x = gprevious.getX(); y = gprevious.getY(); w=gprevious.getWidth(); h=gprevious.getHeight(); ms1.setBounds(gprevious.getX()10,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms1 ); ms2.setBounds(gprevious.getX()+gprevious.getWidth()+10 ,gprevious.getY()10,gprevious.getWidth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms2 ); ms3.setBounds(gprevious.getX()10,gprevious.getY()+gprevious.getHeight()+10,gprevious.getW idth()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms3 ); ms4.setBounds(gprevious.getX()+gprevious.getWidth()+10 100 ,gprevious.getY()+gprevious.getHeight()+10,gprevious.getWid th()/4,gprevious.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms4 ); mr1.setBounds(gprevious.getX()+10,gprevious.getY()10,gprevious.getWidth()-20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr1 ); mr2.setBounds(gprevious.getX()+gprevious.getWidth(),gprevio us.getY(),gprevious.getWidth()/10,gprevious.getHeight()20); this.desktop.getFrame( this.activeFrame ).add( mr2 ); mr3.setBounds(gprevious.getX()10,gprevious.getY()+10,gprevious.getWidth()/10,gprevious.ge tHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr3 ); mr4.setBounds(gprevious.getX()+10,gprevious.getY()+gpr evious.getHeight(),gprevious.getWidth()20,gprevious.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr4 ); } } } } /** Se dispara cuando el mouse sale del componente , y hace invisibles los cuadrados que aparecen en las esquinas */ public void mouseExited(MouseEvent e) { g = e.getComponent(); if((g==ms1)||(g==ms2)||(g==ms3)||(g==ms4)||(g!=gprevious)) { ms1.setVisible(false); ms2.setVisible(false); ms3.setVisible(false); ms4.setVisible(false); 101 } } /** Se dispara cuando el mouse entra al Componente, colocando visibles los recuadros a las equinas del componente. Flag 1 indica que el componente * ha sido seleccionado previamente con un clic del mouse. */ public void mouseEntered(MouseEvent e) { g = e.getComponent(); if( playFlag == 0 ) { if (flag == 1) { ms1.setVisible(true); ms2.setVisible(true); ms3.setVisible(true); ms4.setVisible(true); ms1.setCursor(new ms2.setCursor(new ms3.setCursor(new ms4.setCursor(new mr1.setCursor(new mr2.setCursor(new mr3.setCursor(new mr4.setCursor(new Cursor(6)); Cursor(7)); Cursor(4)); Cursor(5)); Cursor(8)); Cursor(10)); Cursor(11)); Cursor(9)); } } } 102 /** Evento que se dispara solo cuando no se encuentra el modo del Ejecucion activo. Cuando se presiona el boton "1" del mouse que corresponde al * boton Izquierdo, se activa la "flag" que indica que el Componente esta activo, y sobre el se pueden disparar eventos. Si el boton activado es el * derecho se muestra un editor de Propiedades donde se podran seleccionar los tags a asociar */ public void mouseClicked(MouseEvent e) { g = e.getComponent(); if(playFlag == 0) { if(e.getButton() == 1) { if(g==gprevious) { if(flag == 0) { flag =1; } else { if(flag == 1) { flag = 2 ; } else { flag=0; } } } } else { flag=1; } 103 if((g!=ms1)&&(g!=ms2)&&(g!=ms3)&&(g!=ms4)&&(g!=mr1)&&(g!=mr 2)&&(g!=mr3)&&(g!=mr4)) { gprevious = g; } if(e.getButton()==1) { g = e.getComponent(); ms1.setBounds(g.getX()-10,g.getY()10,g.getWidth()/4,g.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms1 ); ms2.setBounds(g.getX()+g.getWidth()+10,g.getY()10,g.getWidth()/4,g.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms2 ); ms3.setBounds(g.getX()10,g.getY()+g.getHeight()+10,g.getWidth()/4,g.getHeight()/4 ); this.desktop.getFrame( this.activeFrame ).add( ms3 ); ms4.setBounds(g.getX()+g.getWidth()+10,g.getY()+g.getHeight ()+10,g.getWidth()/4,g.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms4 ); mr1.setBounds(g.getX()+10,g.getY()-10,g.getWidth()20,g.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr1 ); mr2.setBounds(g.getX()+g.getWidth()+10,g.getY(),g.getWidth( )/10,g.getHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr2 ); mr3.setBounds(g.getX()10,g.getY()+10,g.getWidth()/10,g.getHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr3 ); 104 mr4.setBounds(g.getX()+10,g.getY()+g.getHeight(),g.getWidth ()-20,g.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr4 ); ms1.setVisible(true); ms2.setVisible(true); ms3.setVisible(true); ms4.setVisible(true); ms1.setVisible(true); ms2.setVisible(true); ms3.setVisible(true); ms4.setVisible(true); if(flag == 1) { if((g!=ms1)&&(g!=ms2)&&(g!=ms3)&&(g!=ms4)&&(g!=mr1)&&(g!=mr 2)&&(g!=mr3)&&(g!=mr4)) { gprevious=g; x=g.getX(); y=g.getY(); w=g.getWidth(); h=g.getHeight(); ms1.setBounds(g.getX()-10,g.getY()10,g.getWidth()/4,g.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms1 ); ms2.setBounds(g.getX()+g.getWidth()+10,g.getY()10,g.getWidth()/4,g.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms2 ); ms3.setBounds(g.getX()10,g.getY()+g.getHeight()+10,g.getWidth()/4,g.getHeight()/4 ); this.desktop.getFrame( this.activeFrame ).add( ms3 ); ms4.setBounds(g.getX()+g.getWidth()+10,g.getY()+g.getHeight ()+10,g.getWidth()/4,g.getHeight()/4); this.desktop.getFrame( this.activeFrame ).add( ms4 ); 105 mr1.setBounds(g.getX()+10,g.getY()10,g.getWidth()-20,g.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr1 ); mr2.setBounds(g.getX()+g.getWidth()+10,g.getY(),g.getWidth( )/10,g.getHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr2 ); mr3.setBounds(g.getX()10,g.getY()+10,g.getWidth()/10,g.getHeight()-20); this.desktop.getFrame( this.activeFrame ).add( mr3 ); mr4.setBounds(g.getX()+10,g.getY()+g.getHeight(),g.getWidth ()-20,g.getHeight()/10); this.desktop.getFrame( this.activeFrame ).add( mr4 ); ms1.setVisible(true); ms2.setVisible(true); ms3.setVisible(true); ms4.setVisible(true); ms1.setVisible(true); ms2.setVisible(true); ms3.setVisible(true); ms4.setVisible(true); } } if(flag == 2) { flag =0; EditorEvent ee = new EditorEvent(this); ee.component = (JComponent) gprevious; ee.objectFlag = objectflag; performer.fireOnFlagActivated(ee); } } else { if( flag >= 1) { 106 EditorComponent auxComponent = new EditorComponent(); auxComponent = (EditorComponent) gprevious; int int int int x y w h = = = = (g.getX()+g.getWidth()); (g.getY()+g.getHeight()); g.getWidth(); g.getHeight(); colorSelector.getSelectionModel().addChangeListener(this); tagColor = new Choice(); tagColor.setBounds(50,50,50,50); tagColor.addItemListener(this); tagLevel = new Choice(); tagLevel.setBounds(0,0,50,50); tagLevel.addItemListener(this); int j=0; while(tags.length!=j) { tagColor.add(""+tags[j]); tagLevel.add(""+tags[j]); j++; } ep = new EditorPropierties(x,y,w,h,tagColor,tagLevel,colorSelector); ep.addEditorListener(this); ep.setBounds(0,0,300,200); EditorFrame frame = new EditorFrame("Propiedades",0,0); ep.setBounds(x,y,300,200); frame.add(ep); this.desktop.addFrame3(frame,x,y,300,200); } 107 } } } public void mouseMoved(MouseEvent e) { } public void addEditorListener(EditorListener listener) { this.performer.addEditorListener(listener); } public void removeEditorListener(EditorListener listener) { this.performer.removeEditorListener(listener); } /**Evento que se dispara cuando en el seleccionador de los tags se selecciona un tag. Este inmediatamente se asocia al componente que se * encontraba previamente seleccionado */ public void itemStateChanged(ItemEvent e) { EditorComponent aux = new EditorComponent(); aux = (EditorComponent) gprevious; if(e.getSource()== this.tagColor) { aux.tagofColor = tagColor.getSelectedItem(); } if(e.getSource()== this.tagLevel) { aux.tagofLevel = tagLevel.getSelectedItem(); } } 108 /** Evento que se dipara cunado se cambia el color del componente, actualizado la variable "color" del componente, y repintandolo */ public void stateChanged(ChangeEvent e) { EditorComponent auxComponent = new EditorComponent(); auxComponent = (EditorComponent) gprevious; auxComponent.color = colorSelector.getColor(); auxComponent.repaint(); } /** Evento que se dispara cuando se selecciona en el Editor de Propiedades cambiar el color de un elemento o establecer los limites * en que se encuentra una variable de un componente o provenientes del PLC */ public void onColorChooser(EditorEvent e) {EditorFrame frame; switch (e.buttonPressed) { case EditorPropierties.BUTTON_COLOR: frame= new EditorFrame("Color",0,0); frame.setVisible(true); frame.add(colorSelector); colorSelector.setPreviewPanel(new JPanel()); colorSelector.setVisible(true); colorSelector.setBounds(0,0,400,100); this.desktop.addFrame3(frame,gprevious.getX()+ 2*gprevious.getWidth(), gprevious.getY(),400,200); break; case EditorPropierties.BUTTON_CLIMIT: frame = new EditorFrame ("Limites",0,0); frame.setVisible(true); frame.setLayout(null); acceptLimits.setBounds(90,10,90,50); colorLowerLimit.setBounds(10,10,60,20); colorUpperLimit.setBounds(10,30,60,20); frame.add(acceptLimits); frame.add(colorLowerLimit); 109 frame.add(colorUpperLimit); limitFlag = 1; this.desktop.addFrame3(frame,gprevious.getX()+ 2*gprevious.getWidth(), gprevious.getY(),200,100); break; case EditorPropierties.BUTTON_LEVEL: frame = new EditorFrame("Limites",0,0); JLabel l = new JLabel("Limite de la Variable"); JLabel l2 = new JLabel ("Limite del Componente"); frame.setVisible(true); frame.setLayout(null); l.setBounds(0,0,150,20); levelLowerLimit.setBounds(10,30,100,20); levelUpperLimit.setBounds(10,50,100,20); l2.setBounds(0,90,150,20); componentLowerLimit.setBounds(10,120,100,20); componentUpperLimit.setBounds(10,140,100,20); acceptLimits.setBounds(170,50,90,50); frame.add(l); frame.add(l2); frame.add(componentLowerLimit); frame.add(componentUpperLimit); frame.add(acceptLimits); frame.add(levelLowerLimit); frame.add(levelUpperLimit); limitFlag= 2; this.desktop.addFrame3(frame,gprevious.getX()+ 2*gprevious.getWidth(), gprevious.getY(),300,200); break; } } /** Evento que se dispara si se encuentra el modo de ejecucion activado. Ordena todos los tags asociados a los componentes y los envia al PLC para 110 * obtener los valores de dichos tags. Estos se proceden luego a ordenar, ya que vienen todos en un solo string del formato "TAG TIPO VALOR..." de * tal manera que es necesario aislar cada campo. Los valores correspondientes a porcentajes y niveles se colocan en tags[], types[] y values[] * mientas que los asociados a colores se coloan en tags2[], types2[], values2[]. Una vez arreglados se normalizan los valores obtenidos y se * actualizan las variables de cada componente en particular, finalizando en repintar el frame completamente para actualizar los valores. */ public void actionPerformed(ActionEvent e) { if(eventTimer==e.getSource()) { String valuetagsSelected = new String(); String colortagsSelected = new String(); for(int i = 0; i<componentCounter; i++) { valuetagsSelected = valuetagsSelected.concat(componentList[i].tagofLevel + " "); colortagsSelected = colortagsSelected.concat(componentList[i].tagofColor + " "); } tag = ed.getValues(valuetagsSelected); colorTag = ed.getValues(colortagsSelected); count = 0; countbefore=0; tagcounter=0; typecounter=0; valuecounter=0; while(count<tag.length()) { int aux = 0 ; while(aux <3) { 111 while(tag.charAt(count)!= ' ') { count ++; } if(aux ==0) { tags[tagcounter]= tag.substring(countbefore,count); tagcounter++; } if(aux==1) { types[typecounter] = tag.substring(countbefore,count); typecounter++; } if (aux==2) { tagValues[valuecounter] = tag.substring(countbefore,count); valuecounter++; } count ++; countbefore = count; aux ++; } } count = 0; countbefore=0; tagcounter=0; typecounter=0; valuecounter=0; while(count<colorTag.length()) { int aux = 0 ; while(aux <3) { 112 while(colorTag.charAt(count)!=' ') { count= count +1; } if(aux ==0) { tags2[tagcounter]= colorTag.substring(countbefore,count); tagcounter++; } if(aux==1) { types2[typecounter] = colorTag.substring(countbefore,count); typecounter++; } if (aux==2) { tagValues2[valuecounter] = colorTag.substring(countbefore,count); valuecounter++; } count = count+1; countbefore = count; aux ++; } } for(i=0;i<componentCounter;i++) { if((Integer.parseInt(types[i])==196)||(Integer.parseInt(typ es[i])==195)||(Integer.parseInt(types[i])==202)) 113 { double y,y2; y = this.convertNumber(componentList[i],Integer.parseInt(tagVal ues[i])); y2 = this.convert2hundred(componentList[i],y); componentList[i].P= (double)y2; componentList[i].Percent =(int)y2; } if(Integer.parseInt(types[i])==195) { double y,y2; y = this.convertNumber(componentList[i],Integer.parseInt(tagVal ues[i])); y2 = this.convert2hundred(componentList[i],y); componentList[i].Percent =(int)y2; componentList[i].P = (double)y2; } if(Integer.parseInt(types[i])==193) { if(Integer.parseInt(tagValues[i])==0) { componentList[i].b = false; componentList[i].color = Color.black; } if(Integer.parseInt(tagValues[i])==1) { componentList[i].b = true; componentList[i].color = Color.blue; 114 } } /*debo arreglar el numero que a veces me agarra un espacio*/ tagValues2[i]= tagValues2[i].trim(); types2[i]= types2[i].trim(); if((Integer.parseInt(types2[i])==196)||(Integer.parseInt(ty pes2[i])==195)||(Integer.parseInt(types2[i])==202)) { if((Integer.parseInt(tagValues2[i])>=0)&&((Integer.parseInt (tagValues2[i])<=100))) { double y; y = convert2hundred(componentList[i],(double)Integer.parseInt(t agValues2[i])); if(y <8) { componentList[i].color = Color.green; } if((8>y)&&(y<=15)) { componentList[i].color = Color.blue; } if((y>15)&&(y<=23)) { componentList[i].color = Color.cyan; } if((y>23)&&(y<=31)) { componentList[i].color = Color.pink; } 115 if((y>31)&&(y<=39)) { componentList[i].color = Color.magenta; } if((y>39)&&(y<=47)) { componentList[i].color = Color.red; } if((y>47)&&(y<=54)) { componentList[i].color = Color.orange; } if((y>54)&&(y<=62)) { componentList[i].color = Color.yellow; } if((y>62)&&(y<=70)) { componentList[i].color = Color.white; } if((y>70)&&(y<=79)) { componentList[i].color = Color.lightGray; } if((y>79)&&(y<=88)) { componentList[i].color = Color.gray; } if((y>88)&&(y<=93)) { componentList[i].color = Color.darkGray; } 116 if((y>93)&&(y<=100)) { componentList[i].color = Color.black; } } else { } } } for(int j=0;j<this.desktop.frameNumber+1;j++) { this.desktop.getFrame(j).repaint(); } } if(e.getSource()==acceptLimits) { EditorComponent aux = (EditorComponent)gprevious; if(limitFlag==1) { aux.minColor = Integer.parseInt(colorLowerLimit.getText()); aux.maxColor = Integer.parseInt(colorUpperLimit.getText()); } if(limitFlag==2) { aux.minLevel = Integer.parseInt(levelLowerLimit.getText()); aux.maxLevel = Integer.parseInt(levelUpperLimit.getText()); aux.maxCompLevel = Integer.parseInt(componentUpperLimit.getText()); aux.minCompLevel = Integer.parseInt(componentLowerLimit.getText()); 117 } } } /** Funcion que convierte el numero j en un numero equivalente del 1 al 100 */ private double convert2hundred(EditorComponent component,double j) { double y; double m; m = ((double)component.maxCompLevel (double)component.minCompLevel)/(100); y = (double)component.minCompLevel + m*((double)j); return y; } /** Funcion que convierte el numero j en un valor correspondiente a los limites asignados al componente. */ private double convertNumber(EditorComponent component, int j) { double y; double m; m = ((double)component.maxCompLevel(double)component.minCompLevel)/((double)component.maxLevel - (double)component.minLevel); y = (double)component.minCompLevel + (double)m*((double)j - (double)component.minLevel); return(y); } } 118 APÉDICE 2 La plataforma de donde se desarrollo el software es conocida como ECLIPSE. A continuación presentamos un extracto del un proyecto desarollado por el grupo COAL de la escuela de Ingenieria de la Universidad de Uruguay. El proyecto es llamado “Lead” y explora las posibilidades de la plataforma Eclipse. Debido a que esta fue usada en el proyecto, es interesante conocer las caracteristicas de la plataforma. A continuación un extracto de dicho proyecto que puede ser encontrado en su totalidad en la pagina de Internet: http://www.fing.edu.uy/inco/grupos/coal/investigacion/proyectos/lead/docs/Desar rolloDePlugins.pdf 119 120 121 122