Introducción
Una vez desplegada la infraestructura en nuestra instalación y teniendo las pasarelas configuradas en nuestro servidor, disponemos de un mecanismo para acceder a todos los datos que cada pasarela tiene disponibles.
Sin embargo todos estos datos a los que podemos acceder mediante nuestras pasarelas proporcionarán la información en una de estas dos unidades básicas:
1 bit que representa un valor lógico o
un registro de 16 bits.
Para poder explotar los datos necesitamos prepararlos adecuadamente.
Datos del tipo BINARY
Cuando accedemos a los bancos
COIL_STATUS y
INPUT_STATUS del modelo de memoria modbus de un dispositivo al cual estamos llegando a través de la pasarela declarada en el servidor, podremos obtener un bit de información.
Por otro lado si al acceder a uno de los registros de 16 bits de los
bancos
HOLDING_REGISTER o
INPUT_REGISTER indicamos uno de sus 16 bits, también obtendremos 1 bit de información.
En el servidor, 1 bit de información será convertido en un tipo java
Boolean.
Resto de tipos
Evidentemente en un registro de 16 bits sólo podemos almacenar un determinado rango de valores.
Muchos dispositivos se ven obligados a utilizar varios registros para poder almacenar valores de mayores dimensiones, lo cual nos trae alguna complicación más ya que distintos fabricantes para un mismo valor pueden utilizarlos en distinto orden.
En la siguiente tabla se indica para cada tipo de almacenamiento que podremos configurar, el número de registros que el servidor leerá desde la posición que hayamos indicado y el tipo java con el que obtendremos su valor.
| Almacenamiento | Numero de registros
| Tipo java
|
| TWO_BYTE_INT_UNSIGNED | 1 | Integer |
| TWO_BYTE_INT_SIGNED | 1
| Integer |
| FOUR_BYTE_INT_UNSIGNED | 2
| Long
|
| FOUR_BYTE_INT_SIGNED | 2
| Long
|
| FOUR_BYTE_INT_UNSIGNED_SWAPPED | 2
| Long
|
| FOUR_BYTE_INT_SIGNED_SWAPPED | 2
| Long
|
| FOUR_BYTE_FLOAT | 2
| Float
|
| FOUR_BYTE_FLOAT_SWAPPED | 2
| Float
|
| EIGHT_BYTE_INT_UNSIGNED | 4
| Long
|
| EIGHT_BYTE_INT_SIGNED | 4
| Long
|
| EIGHT_BYTE_INT_UNSIGNED_SWAPPED | 4
| Long
|
| EIGHT_BYTE_INT_SIGNED_SWAPPED | 4
| Long
|
| EIGHT_BYTE_FLOAT | 4
| Double
|
| EIGHT_BYTE_FLOAT_SWAPPED | 4
| Double
|
Escalado del valor
Como hemos indicado, el servidor leerá el valor y lo transformará en un tipo java según la tabla anterior. Después de esta transformación tendremos el valor en la unidad en la que el dispositivo lo está generando, pero puede ocurrir que nosotros deseemos cambiar la escala del valor para nuestra conveniencia.
Para ello podremos multiplicar el valor obtenido por un factor que nos permite realizar este cambio de escala. En caso de no indicarle ninguna escala el servidor estará utilizando el valor 1.0, el cual naturalmente deja el valor sin modificar.
Como ejemplo podemos pensar en un analizador de red eléctrica, el cual entrega el valor de la tensión instantánea en milivoltios. Si nosotros deseamos tratar el valor en voltios indicaremos para el valor de escalado 0.001
Tipo de dato final
Puede ocurrir que en el caso de querer aplicar un escalado al valor obtenido nos encontremos con que el valor resultante tuviese que ser de un tipo distinto para no perder información.
Por ese motivo podremos indicar el tipo que el valor finalmente tendrá, aunque si se utiliza incorrectamente podríamos tener el resultado contrario de perder parte de la información (por ejemplo transformando un float a entero se perderían los decimales).
Si no indicamos este tipo, se utilizará como final el mismo tipo que el obtenido automáticamente después de la transformación desde el formato de almacenamiento.
Siguiendo con el ejemplo anterior, podríamos tener un valor long que representa 123750 milivoltios y que podemos convertir en un valor float de 123,75 voltios.
Valor inicial
Una vez hemos realizado todas las transformaciones anteriores podemos querer darle un valor inicial, que será siempre sumado al valor obtenido.
Imaginemos que tenemos un equipo lector de consumo de agua que emite un impulso por cada metro cúbico de agua que pasa a través de él. Este impulso será leído por una pasarela que incrementará una unidad cada vez que detecte el impulso.
Desde nuestro servidor podremos leer el valor del contador y saber los metros cúbicos que han pasado desde que instalamos la pasarela. Sin embargo, si el equipo lector de consumo de agua ya estaba instalado previamente nuestras lecturas no coincidirán con las lecturas mecánicas que muestra el equipo de lectura porque éste ya había estado un tiempo realizando sus mediciones.
Si indicamos como valor inicial el valor que marcaba el equipo de medida, conseguiremos que ambas lecturas coincidan.
Lectura del valor
Hemos explicado como se transforman los datos que leemos desde las pasarelas pero no hemos indicado en que momento se realizan las lecturas de estos datos.
Para cada valor podremos indicar la unidad de tiempo con la que indicaremos esta información:
- MILLISECONDS
- SECONDS
- MINUTES
- HOURS
- DAYS
Indicaremos también el tiempo. Por ejemplo si anteriormente hemos seleccionado
MINUTES e indicamos un tiempo de 15, como parece evidente se realizará una lectura cada 15 minutos.
Con lo indicado hasta este momento, desde el momento que el servidor está en funcionamiento, un valor con la configuración anterior se leería cada 15 minutos siendo la primera lectura inmediatamente después de activarse el servidor.
Sin embargo queremos controlar mejor el momento de la lectura para seguir el modo de trabajo de algunas especificaciones de distribuidoras eléctricas europeas.
Por ese motivo podremos indicar si queremos que los periodos de lectura estén sincronizados con el principio de cada día o lo que es lo mismo con las 0 horas, 0 minutos y 0 segundos. En caso de activarse esta funcionalidad y siguiendo la configuración del ejemplo anterior (cada 15 minutos), las lecturas se realizarían siempre a la horas en punto, pasado un cuarto, pasado media hora, pasado tres cuartos y de nuevo a la hora en punto (ejemplo 16:00:00, 16:15:00, 16:30:00, 16:45:00, 17:00:00 y continuaría así).
Hay que tener en cuenta que no podemos garantizar que las lecturas se realizarán en el milisegundo exacto por distintos motivos. El servidor utilizará un thread para cada pasarela y en caso de que obtengamos varios valores en una misma pasarela con la misma configuración en el periodo de lectura, las lecturas de estos valores se realizaran secuencialmente y no simultáneamente. Como resultado entre las lecturas de los valores de una misma pasarela habrá una diferencia de algunos milisegundos.
Sin embargo, estos retrasos no son acumulables ya que la próxima lectura (15 minutos mas tarde según el ejemplo) se recalculará sin tener en cuenta estos retrasos.
Importante
Imaginemos que arrancamos el servidor y éste se encuentra funcional a las 16:34:01, los valores que utilicen la configuración del ejemplo no se leerán hasta las 16:45:00.
Mientras tanto el valor tendrá un valor inválido y si no tenemos ésto en cuenta podremos pensar que el servidor no está funcionando correctamente.
Validez de la lectura y marca de tiempo
Cada valor que obtiene el servidor, además de su propio valor, tiene también un indicador de calidad el cual simplemente nos dirá si el valor actual es
válido o
inválido.
Además en cada valor obtenido consta una marca de tiempo que nos indicará exactamente el momento en el que este valor se obtuvo.
Almacenamiento del valor
Nuestras aplicaciones pueden utilizar un valor que obtenemos desde una pasarela cuando el servidor nos informe que éste ha cambiado (esta funcionalidad estará disponible en la próxima versión del SDK) y también podemos querer que los valores que obtenemos se almacenen en nuestra base de datos.
Sin embargo almacenar todos los valores en la base de datos sin aplicar ninguna restricción puede generar demasiada información, lo cual puede afectar al rendimiento de nuestros sistemas.
Imaginemos que el tiempo indicado para la lectura de un valor es 5 y la unidad
SECONDS porque queremos tener una actualización permanente de una gráfica, pero sin embargo no nos interesa almacenar un registro cada 5 segundos en la base de datos.
Para evitar esta circunstancia podemos indicar cada cuantas lecturas del valor insertaremos un registro en la base de datos. Imaginemos que deseamos almacenar un valor cada 15 minutos que son 900 segundos. Si dividimos los 900 segundos por 5 segundos obtendremos que debemos configurar que cada 180 lecturas almacenaremos un valor.
Además podemos indicar unos condicionantes finales para que realmente se almacene el valor en la base de datos:
- El valor no se almacenará nunca.
- El valor se almacenará siempre.
- El valor sólo se almacenará cuando sea distinto del último valor que se almacenó.