Saltar al contenido principal

Script

El RTU-X puede ejecutar un programa que permite incorporar inteligencia local en el equipo. Este script, que se escribe en la interfaz de usuario en un lenguaje intuitivo y que guarda muchas similitudes con el lenguaje de programación C, permite realizar todo tipo de operaciones con las entradas y salidas, esclavos, log, etc.

Editor de script de la interfaz de usuario

A continuación, se describen las características del lenguaje y su utilización en la interfaz de usuario.

¿Preferís que te ayude un asistente de IA?

Existe una skill de Claude que conoce este lenguaje en detalle y puede escribir, revisar o depurar scripts en una conversación — ver Asistente de IA (Claude).

El editor de script​

La sección Script de la interfaz de usuario tiene, además del editor, varias herramientas para compilar y depurar el programa en tiempo real:

  • Compilar / Compilar y aplicar / Recuperar / Detener — controlan la compilación y ejecución del script en el equipo conectado.
  • Estado del script — indica si el script está Ejecutando o Detenido.
  • Memoria — porcentaje de uso de memoria de programa, datos y código, para llevar el margen disponible antes de llegar a los límites del equipo.
  • Mapa de esclavos — una grilla con el estado de cada esclavo Modbus/BLE configurado.
  • Visualizador de variables — muestra en tiempo real el valor de las variables que se elijan desde el botón de selección.
Selección de variables a visualizar

El modal de selección de variables organiza las variables disponibles en pestañas — Telemetry·Attribute·Shared, Queries a esclavos, Calendar, Otras + alias y Sistema — con un buscador y botones Seleccionar todas / Deseleccionar todas para armar rápido el set de variables a monitorear mientras el script corre.

Estructura del lenguaje​

El script debe comenzar con la declaración de todas las variables que vayan a utilizarse. No se permite declarar variables en el medio del programa.

Luego de la declaración de variables se debe escribir el código del programa. Este código se ejecuta una única vez, por lo que si se desea que se ejecute continuamente se debe colocar dentro de un bucle infinito.

 

Control de Flujo​

 

Sentencia if​

La sintaxis es la siguiente:

if (Condición1)
{
Instrucciones1
}
else if (Condición2)
{
Instrucciones2
}
else
{
Instrucciones3
}

Si se cumple Condición1, entonces se ejecuta el bloque Instrucciones1, de lo contrario si se cumple Condición2 se ejecuta el bloque Instrucciones2, y de lo contrario se ejecuta el bloque Instrucciones3.

Los bloques else if y else son opcionales.

 

Sentencia while​

La sintaxis es la siguiente:

while (Condición)
{
Instrucciones
}

Las instrucciones dentro del bloque while se ejecutan continuamente mientras se cumpla la Condición. El bloque de instrucciones puede ser vacío.

 

Sentencia for​

La sintaxis es la siguiente:

for (Exp1; Exp2; Exp3)
{
Instrucciones
}

Exp1 es una expresión que solo se ejecuta una vez al principio del bucle. Generalmente Exp1 suele contener una expresión que inicializa el contador utilizado en el bucle for.

Exp2 es la expresión que indica cuando debe finalizar el bucle, y por lo tanto se trata de una expresión condicional. Esta expresión se evalúa al inicio de cada ciclo del bucle, y el bucle deja de ejecutarse cuando esta expresión deja de cumplirse. Por lo tanto el bucle podría no ejecutarse ninguna vez.

Exp3 es una expresión que se ejecuta al final de cada iteración, y generalmente se utiliza para actualizar el contador utilizado en el bucle.

En cada una de las iteraciones, se ejecutan todas las instrucciones dentro del for.

Variables​

Existen dos tipos de variables, las variables de propósito general y las variables del sistema.

Variables de propósito general​

Las variables de propósito general son las definidas por el usuario en el script y pueden ser de uno de los siguientes tipos:

TipoDescripción
intEntero de 16 bits con signo. Puede ir desde -32.768 a 32.767
uintEntero de 16 bits sin signo. Puede ir desde 0 a 65.535
longEntero de 32 bits con signo. Puede ir desde -2.147.483.647 a 2.147.483.647
ulongEntero de 32 bits sin signo. Puede ir desde 0 a 4.294.967.295
floatReal con coma flotante de 32 bits. Representación IEEE 754 de precisión simple

Las variables de propósito general pueden definirse como arrays.

Algunos ejemplos de definición de variables:

int i; // Variable de tipo int llamada i
float f; // Variable de tipo float llamada f

Variables telemetry, attribute y shared​

Cualquier variable de propósito general puede ser definida con el prefijo telemetry, attribute o shared.

Las variables se deben definir como telemetry o attribute para poder ser utilizadas con las funciones log y report.

El prefijo shared se utiliza exclusivamente cuando el RTU-X se integra por MQTT al sistema Telemetry+ de Nettra, para el caso de variables que guardan parámetros de configuración que se ajustan desde el sistema.

Algunos ejemplos de definición de variables:

attribute float f; // Variable float de tipo type attribute llamada f
telemetry int t; // Variable entera de tipo telemetry llamada t

Arrays​

Es posible declarar arrays de una o dos dimensiones de cualquiera de los tipos de datos disponibles. Por ejemplo:

int a[10]; // Array de largo 10
float b[12,3]; // Array de tamaño 12 x 3

Con el fin de evitar evaluaciones fuera de rango, cuando en los ínidices se utiliza una expresión que no sea un número, la misma se evalúa módulo el máximo del rango según corresponda. Por ejemplo, para los ejemplos anteriores se cumple lo siguiente:

c = a[3+i]; // se evalúa el array en la posición (3+i)%10

El número máximo de elementos de un array 1D es 100. El número máximo de filas o columnas en un array de dos dimensiones es 10.

Un array puede ser declarado como telemetry o attribute para usar sus elementos como argumentos de las fucniones log, report, logonchange o report_on_change.

En el caso de arrays de una dimensíon, el nombre almacenado en el log de eventos será el nombre del array concatenado con el offset del argumento expresado en decimal. Para los arrays de dos dimensiones, el nombre del array se concatena con el número de fila y el número de columna expresados en hexadecimal.

Ejemplos:

telemetry int a[10];
telemetry float b[12,3];

log(a[4]); // se almacena en el log de eventos con el nombre a4
log(b[10,2]); //se almacena en el log de eventos con el nombre bA2

Variables calendar​

Las variables definidas con el prefijo calendar se asocian a eventos de calendario, definidos ya sea localmente desde la sección Eventos de la interfaz de usuario o de forma remota mediante comandos RPC cuando el RTU-X se integra al sistema Telemetry+ de Nettra. Supongamos que se definen las variables enteras a y b como

calendar int a = 0;
calendar int b = 0;

Cuando la variable del sistema unix_ts_utc está en el intervalo definido en un evento, decimos que el evento está activo y las variables toman los valores definidos en el evento. En otro caso, las variables toman el valor por defecto definido en su inicialización. En caso que se definan dos eventos que se superponen, se activa el que comienza antes.

Variables static​

Cualquier variable de propósito general puede ser definida con el prefijo static.

Al definirla de esta forma, la variable se almacena en memoria no volátil del RTU-X, de tal forma que su valor persista incluso en caso de pérdida de alimentación y batería.

Para darle un valor inicial a una variable static, se la debe inicializar al declararla. De esta manera, el valor inicial solo se carga en la primera ejecución del script, pero no en las siguientes ejecuciones.

Por ejemplo:

static int a = 10;
static int b[3] = {1,2,3};

Reservadas del sistema​

Existe un conjunto de variables predefinidas relacionadas al funcionamiento del RTU-X y sus periféricos que pueden ser utilizadas desde el script.

Las siguientes variables se encuentran disponibles:

 

VariableDescripciónTipo
ENTRADAS
ainEntradas analógicas Representa el voltaje en mV (0 – 10.000) para entradas de tensión o la corriente en uA (0 – 20.000) para entradas de corriente.int[8]
pulsesConteo de pulsos de las entradas digitalesulong[2]
MODBUS
slave_errorRefleja el estado de conexión entre la RTU-X y los esclavos. Se usa un bit por esclavo, donde 1 indica error. Por ejemplo, el bit 2 de la variable representa el estado de conexión con el esclavo 2.int
TIEMPO
hoursHora actual (0 – 24)uint
minutesMinutos actuales (0 – 59)uint
secondsSegundos actuales (0 – 59)uint
dayDía del mes (0 - 31)uint
monthMes actual (1 – 12)uint
yearAño actualuint
week_dayDía de la semana (0 = domingo)uint
time_syncedIndica si la hora se encuentra sincronizada. La variable puede valer 0 o 1.int
unix_ts_utcCantidad de segundos en formato Unix de la hora UTC del dispositivoulong
unix_ts_localCantidad de segundos en formato Unix de la hora local del dispositivoulong
calendar_events_countCantidad de eventos definidos en el sistema. Como máximo pueden ser 50uint
timer_etTiempo transcurrido (en milisegundos) de cada instancia de timer(), útil para telemetría o debug. El índice del array corresponde al orden de aparición de cada llamada a timer() en el script.ulong[16]
SMS
sms_message

Índice del mensaje recibido.

Si no hay mensajes recibidos, la variable vale -1. Luego de recibir y procesar un mensaje, el usuario debe poner esta variable nuevamente en -1.

int
sms_parameterParámetro del mensaje recibidofloat
sms_phoneÍndice del teléfono que envió el mensaje recibidoint
MODEM
modem_onEn caso de que el módulo WAN no esté configurado para encenderse automáticamente al encenderse la RTU-X, poniendo esta variable en 1 o 0 permite encender o apagar el módem desde el script.int
modem_status

Refleja el estado de funcionamiento del módem. Los posibles valores son: 

  • MODEM_STATUS_NO_SIM (-3) – si el módem detecta que no tiene SIM.
  • MODEM_STATUS_WAITING_PIN (-2) – si la SIM instalada requiere PIN pero no hay un PIN configurado.
  • MODEM_STATUS_WRONG_PIN (-1) – si el pin configurado no es correcto.
  • MODEM_STATUS_OFF (0) – si el modem está apagado.
  • MODEM_STATUS_TURNING_ON (1) – si del modem se está encendiendo.
  • MODEM_STATUS_ON (2) – si el modem está encendido. Normalmente de este estado pasa automáticamente a registrarse y conectarse, pero si el módem se usa solo como GPS, este estado indica que está encendido.
  • MODEM_STATUS_REGISTERING (3) – si el modem se está registrando en la red celular.
  • MODEM_STATUS_REGISTERED (4) – si el módem está registrado en la red celular. Queda en este estado solo cuando no se utiliza una conexión de datos, pues en ese caso pasa a conectar.
  • MODEM_STATUS_CONNECTING (5) – si el modem está estableciendo la conexión de datos con la red celular.
  • MODEM_STATUS_CONNECTED (6) – si el modem estableció correctamente la conexión de datos con la red celular.
int
modem_signalNivel de señal del módem en dBmint
LORA
lora_onEn caso de que el módulo WAN no esté configurado para encenderse automáticamente al encenderse la RTU-X, poniendo esta variable en 1 o 0 permite encender o apagar el módulo LoraWan desde el script.int
lora_status

Refleja el estado de funcionamiento del módulo LoraWan. Los posibles valores son: 

  • LORA_STATUS_OFF (0) – El módulo está apagado.
  • LORA_STATUS_TURNING_ON (1) – El módulo está en proceso de encendido.
  • LORA_STATUS_ON (2) – El módulo está encendido.
  • LORA_STATUS_JOINING (3) – El módulo está conectándose a la red LoraWan.
  • LORA_STATUS_JOINED (4) - El módulo se unió a la red LoraWan configurada
  • LORA_STATUS_JOIN_TIMEOUT (5) – El módulo intentó conecectarse y se dió un timeout.
int
lora_snrRelación señal a ruido en dB medida por el módulo LoraWan en la última transmisiónint
lora_rssiPotencia de señal a ruido en dBm medida por el módulo LoraWan en la última transmisiónint
WIFI
wifi_status

Refleja el estado de funcionamiento del wifi. Los posibles valores son: 

  • WIFI_STATUS_OFF (0) – cuando el módulo wifi se encuentra deshabilitado.
  • WIFI_STATUS_DISCONNECTED (1) – cuando el wifi se encuentra desconectado.
  • WIFI_STATUS_CONNECTING (2) – cuando se está estableciendo la conexión wifi.
  • WIFI_STATUS_CONNECTED (3) – cuando la conexión wifi se encuentra establecida.
  • WIFI_STATUS_LISTENING (4) – cuando el wifi funciona en modo AP (access point).
int
wifi_signalNivel de señal del wifi en dBmint
MQTT
mqtt_status

Refleja el estado de la conexión MQTT. Los posibles valores son: 

  • MQTT_STATUS_DISCONNECTED (0) – cuando la conexión MQTT está desconectada.
  • MQTT_STATUS_CONNECTING (1) – cuando se está estableciendo al conexión MQTT.
  • MQTT_STATUS_CONNECTED (2) – cuando la conexión MQTT se encuentra establecida.
int
mqtt_pending_logCantidad de registros pendientes de ser enviados por mqtt.ulong
GPS
latitudeLatitud del GPSfloat
longitudeLongitud del GPSfloat
altitudeAltitud del GPSfloat
speedVelocidad del GPSfloat
BATERÍA
battery_percentagePorcentaje de bateríauint
battery_protectionLa bateria interna del RTU-X cuenta con una protección contra sobre calentamiento que corta el proceso de carga cuando la temperatura supera los 40°C aproximadamente. Si bien esta protección es necesaria, cuando la temperatura ambiente es alta se genera el efecto no deseado de corte del proceso de carga. Con valor 1 (por defecto) la protección está habilitada mientras que con valor 0 la protección se deshabilita.int
battery_status

Refleja el estado de funcionamiento de la batería. Los posibles valores son: 

  • BATTERY_STATUS_CHARGING (0) – si la alimentación externa está conectada y la batería está cargando.
  • BATTERY_STATUS_CHARGED (1) – si la alimentación externa está conectada y la batería está completamente cargada.
  • BATTERY_STATUS_NO_POWER (2) – si el equipo se encuentra funcionando a batería sin alimentación externa.
  • BATTERY_STATUS_NO_BATTERY (3) – si la alimentación externa está conectada y no hay ninguna batería conectada.
  • BATTERY_STATUS_OTHER (4) – estado de error
int

 

Acceso a bits​

Se puede acceder a cualquier bit individual de cualquier variable colocando un punto y el número de bit luego del nombre de la variable.

Ejemplo que guarda el bit 2 de la variable x en el bit 3 de la variable y:

y.3 = x.2;

 

Alias​

Es posible utilizar un alias para referirse tanto a las variables de propósito general como a las variables del sistema. Se puede definir un alias a cualquier variable, a un elemento de un array o incluso a un bit de una variable.

Los siguientes ejemplos muestras la definición de diferentes alias:

alias error as slave_error.2; // Alias al error del esclavo 3
alias analogica2 as ain[1]; // Alias a la entrada analógica 2

 

Constantes​

Si se van a utilizar constantes en el script, éstas pueden definirse también al comienzo del mismo. Por ejemplo, para definir una constante llamada UMBRAL cuyo valor sea 30 se debe hacer lo siguiente:

const UMBRAL = 30;

El compilador remplazará la palabra UMBRAL por el valor 30 siempre que ésta aparezca en el script.

Al igual que en el caso de las variables, existe un conjunto de constantes predefinidas relacionadas al funcionamiento del RTU-X y sus periféricos que pueden ser utilizadas desde el script cuando sea pertinente.

 

Operaciones​

 

OperaciónDescripción
+Suma
-Resta
*Multiplicación
/División
%Resto de la división entera
&AND (bit a bit)
|OR (bit a bit)
^XOR (bit a bit)
~NOT (bit a bit)
&&AND lógico
||OR lógico
!NOT lógico
==Igual
! =Distinto
>Mayor
> =Mayor o igual
<Menor
< =Menor o igual

++

pre o post incremento

--

pre o post decremento

 

Esclavos y consultas​

El RTU-X puede funcionar como maestro de hasta 32 dispositivos (a partir de la versión de firmware 3.3.02). Actualmente, estos esclavos pueden ser Modbus sobre RS-485 o BLE (Bluetooth).

Para cada esclavo se pueden definir consultas. Los tipos de consulta dependen del tipo de esclavo.

La configuración de los esclavos y las consultas se debe hacer al principio del script, antes de la definición de las variables y el código.

Para definir un esclavo se usa la palabra reservada slave, indicando los parámetros de configuración, y luego dentro del bloque de ese esclavo se definen las consultas usando la palabra reservada query.

A continuación, se muestra la forma general de definir un esclavo y sus consultas:

slave(interface, …)
{
var_type var1 = query(query_type, …);
var_type var2 = query(query_type, …);
}

Los parámetros de las funciones slave y query dependen de la interface y query_type, y a continuación se detalla cada caso.

 

Esclavos Modbus​

La definición del esclavo se realiza de la siguiente forma:

slave(modbus_rs485_ext1, slave_id, polling_period, format)
slave(modbus_rs485_ext2, slave_id, polling_period, format)

donde:

  • slave_id: es el número de slave id Modbus del esclavo
  • polling_period: es el intervalo de tiempo entre dos consultas consecutivas, en segundos
  • format: puede ser little_endian o big_endian. Define la forma en que se ordenan los bytes para variables de más de un byte. Lo más usual es little_endian.

La definición de las consultas se realiza de la siguiente forma:

var_type var1 = query(coils, address, r/w);
var_type var2 = query(inputs, address);
var_type var3 = query(input_registers, address);
var_type var4 = query(holding_registers, address, r/w);

donde:

  • address: es la dirección dentro del bloque Modbus (comenzando en cero).
  • r/w: indica si la variable a definir es solo lectura (r) o solo escritura (w)

 

Esclavos BLE​

 

slave(ble, “mac”, timeout)

donde:

  • mac: es la dirección mac del dispositivo Bluetooth.
  • timeout: es el tiempo que debe pasar, en segundos, sin recibir ningún mensaje para considerar que hay un error de comunicación con el esclavo.

Hasta el momento se ha integrado la posibilidad de definir esclavos de sensores BLE de marca Efento.

La definición de las consultas se realiza de la siguiente forma:

float var1 = query(efento, temperature); // Consulta de temperatura
uint var2 = query(efento, humidity); // Consulta de humedad relativa
float var3 = query(efento, pressure); // Consulta de presión atmosférica
uint var4 = query(efento, onoff); // Consulta de sensores on/off
uint var5 = query(efento, iaq); // Consulta de calidad de aire

 

Esclavos SDI-12​

 

slave(sdi12_ext1,“address”, polling_period)
slave(sdi12_ext2,“address”, polling_period)

donde:

  • address: es la dirección del dispositivo SDI-12 en el bus.
  • polling_period: es el tiempo entre consultas al sensor.

La definición de las consultas se realiza de la siguiente forma:

float var = query(sdi12, index);

Las consultas a los sensores se implementan mediante comandos C de acuerdo a la versión 1.4 del estándar SDI-12, publicado en Enero de 2019. Donde se establece que el formato del comando de inicio de medición es de la forma <address>C<index>!

Todas las variables que resultan de un query de sdi12 deben ser declaradas como float.

Multitarea​

El lenguaje soporta la definición de varias tareas que se ejecutan en forma de multitarea cooperativa.

En un esquema de multitarea cooperativa, las tareas ceden voluntariamente el control en forma periódica o cuando están inactivos o bloqueados lógicamente.

La forma en que se implementa la multitarea en el script es mediante el uso de la palabra reservada task.

Al llegar a una tarea, la misma se ejecuta hasta terminar o ceder el control. La forma de ceder el control es mediante el uso de alguna de las siguientes funciones: wait, delay, delay_loop. Estas funciones se explican más adelante.

A continuación, un ejemplo de código donde conviven dos tareas ejecutándose "en paralelo":

while (1)
{
task
{
// Esta sección de código se ejecuta periódicamente cada 1 segundo
delay(1000);
}
task
{
// Esta sección de código se ejecuta periódicamente cada 3 segundos
delay(3000);
}
}
Límites de las tareas
  • No está permitido definir una tarea dentro de otra tarea.
  • Todas las variables son globales: no está permitido definir variables locales dentro de una tarea.
  • El máximo número de tareas que se pueden definir es 16.

 

Funciones​

Se pueden utilizar dos tipos de funciones. Las definidas por el usaurio o un conjunto predefinido de funciones del sistema.

Funciones definidas por el usuario​

Es posible definir funciones que permiten optimizar la ejecución de un programa.

La sentencia return no es obligatoria al final de la declaración de una función. Solo es requerida cuando la función devuelve un valor numérico.

A continuación se muestra cómo se declara y ejecuta una función.

float c;
....

function userFunction(int varA, float varB)
{
float varC;

...

return varC;
}

....

c = userFunction(4,4.5);

....

Funciones del sistema​

La tabla que sigue describe las funciones que están intregradas al sistemas.

 

FunciónDescripción
delay(ulong time)

Realiza una espera de time milisegundos. 
Si la función se llama fuera de una tarea, cuelga todo el script durante el tiempo especificado. 
Si la función se llama desde una tarea, la función solo bloquea la tarea, y continúa ejecutando las demás tareas.

Ejemplo:

// Detiene el script por 1 segundo
delay(1000);

 

delay_loop(ulong time)

Al igual que la funcion delay, realiza una espera de time milisegundos pero a diferencia de aquella, la espera es medida desde la llamada inmediatamente anterior de la función.
Solo se debe usar dentro de tasks, y es recomendable en tasks que deban repetirse periódicamente cada cierto tiempo exacto.

Ejemplo:

task
{
    delay_loop(1000);
    // Este código se ejecuta exactamente cada 1 segundo independientemente
    // de lo que demore su ejecución.
}

 

sleep(ulong time)

Hace que el RTU-X pase a modo bajo consumo por time milisegundos.
Durante ese tiempo las salidas digitales mantienen su estado y el conteo de pulsos sigue funcionando, 
pero el script se detiene.
Cuando vuelve del modo bajo consumo, el script continúa su ejecución desde la línea donde se llamo a la función.

Ejemplo:

sleep(10000); // Paso a modo de bajo consumo por 10 segundos

 

reset()

Reinicia el RTU-X.
Al reiniciarlo, el script comienza desde el principio. 
Las variables que no se inicialicen al comienzo del script, quedarán con el valor que tenían antes del reset. 
Las variables que se inicialicen al comienzo del script, se inicializarán nuevamente, salvo en casos particulares 
(ver static y shared).

Ejemplo:

reset();

 

set_green_led(uint mode)

Esta función es válida solo en el caso que el led verde esté configurado para ser controlado desde el script.
Fija el modo de funcionamiento de acuerdo a las constantes definidas con prefijo LED_:
LED_ON | LED_OFF | LED_BLINK_FAST | LED_BLINK_SLOW | LED_BLIP
Para más información ver la sección [LEDs](/rtu-x/input-output#configuración-leds).

Ejemplo:

set_green_led(LED_ON);

 

set_red_led(uint mode)

Esta función es válida solo en el caso que el led rojo esté configurado para ser controlado desde el script.
Fija el modo de funcionamiento de acuerdo a las constantes definidas con prefijo LED_:
LED_ON | LED_OFF | LED_BLINK_FAST | LED_BLINK_SLOW | LED_BLIP 
Para más información ver la sección [LEDs](/rtu-x/input-output#configuración-leds).

Ejemplo:

set_red_led(LED_OFF);

 

set_output(uint output, uint value)

Enciende o apaga la salida digital output dependiendo de value (value puede valer 1 o 0).

Ejemplo:

set_output(0,1); // Enciende la salida digital 0
set_output(3,0); // Apaga la salida digital 3

 

int = get_output(uint output)

Devuelve el valor (0 o 1) de la salida output.

Ejemplo:

output0 = get_output(0); // Obtengo el valor de la salida digital 0

 

int = get_input(uint input)

Devuelve el valor (0 o 1) de la entrada input.

Ejemplo:

input0 = get_input(0); // Obtengo el valor de la entrada digital 0

 

set_power(uint value)

Apaga o enciende la salida de alimentación dependiendo de value.
value puede valer una a las constantes definidas con prefijo POWER_:
POWER_12V | POWER_24V | POWER_OFF
Para más información ver la sección [Salida de 12V/24V](/rtu-x/input-output#salida-de-12v24v).

Ejemplo:

set_power(POWER_12V);

 

log(telemetry/attribute value, ...)

Guarda las variables especificadas en el log. Para ello deben ser de tipo telemetry o attribute
Llamar a la función pasando varias variables garantiza que todas se registran en el log con la misma hora.
Para más información ver la sección [Log](/rtu-x/log)

Ejemplo:

log(temperatura, motor);

 

report(telemetry/attribute value, ...)

Guarda las variables especificadas en una lista en RAM para enviar por MQTT. 
Para ello deben ser de tipo telemetry o attribute
Llamar a la función pasando varias variables garantiza que todas se envían con la misma hora.
Para más información ver la sección [Log](/rtu-x/log)

Ejemplo:

report(temperatura, humedad);

 

log_on_change(telemetry/attribute value)

Guarda las variable especificada en el log solamente cuando la variable cambia. La variable debe ser de tipo telemetry o attribute

Ejemplo:

log_on_change(estado);

 

report_on_change(telemetry/attribute value)

Guarda la variable especificada en el log de RAM para enviar por MQTT solamente cuando la variable cambia. La variable debe ser de tipo telemetry o attribute

Ejemplo:

report_on_change(estado);

 

ulong = set_timeout(ulong timeout)Configura un timer para hacer timeout en timeout milisegundos.
Devuelve un valor ulong configurado para utilizar luego en la función check_timeout.
check_timeout(ulong timer)

Devuelve 1 si pasó el tiempo configurado con la función set_timeout o 0 si aún no pasó.

Ejemplo:

// Se configura timer para que el timeout se de a los 5 segundos.
timer = set_timeout(5000); 

while(1)
{
    if (check_timeout(timer))
    {
        // Ingresa a este if si pasaron los 5 segundos
    }
}

 

send_sms(
  uint phone_index,
  uint message_index,
  long/float param1,
  long/float param2)

Envía un SMS al número configurado en el índice phone_index con el mensaje configurado en el índice message_index.
 

Los mensajes salientes pueden incluir hasta 2 parámetros numéricos en cualquier lugar del mensaje. 
 

Para insertar una variable entera (int o long) deberá escribir %li (para representarlo en formato decimal)  o %lX (para representarlo en formato hexadecimal). Si se trata de una variable float, deberá escribir %f. 


Opcionalmente, en caso que se desee controlar la cantidad de decimales luego de la coma, puede escribir %.xf, reemplazando x por la cantidad de decimales deseados. Por ejemplo, %.2f.

Ejemplo:

send_sms(0, 0, 45, 85);

 

float = flow(
  bool value,
  float liters_per_pulse,
  ulong debounce)
La función calcula el caudal de agua a partir de los pulsos de un caudalímetro. 
Se debe llamar pasando en value el valor de la entrada de pulsos, en liters_per_pulse la cantidad de litros entre pulsos del caudalímetro y un tiempo debounce en milisegundos para filtrar rebotes y ruido en el caudalímetro. El resultado se expresa en litros por segundo.
float = filter(
  float value,
  uint size,
  uint average,
  ulong timeout)

Esta función implementa un filtro de mediana y promedio.  El RTU-X dispone de 8 filtros idénticos que se pueden utilizar simultáneamente. 

El parámetro value es el nuevo valor a ingresar en el filtro.  El parámetro size fija el tamaño del filtro. Es decir, la cantidad de valores que se almacenan dentro del filtro, con un máximo de 30.  El parámetro average establece la cantidad de valores dentro del filtro que se usan para calcular el promedio. El resto de los valores se descartan.

El parámetro timeout usa para borrar el buffer del filtro automáticamente si pasantimeout milisegundos sin que la función sea llamada. Si no se desea usar esta funcionalidad, se puede pasar -1 como parámetro. 

La función implementa una ventana deslizante con size valores y en cada llamado los ordena y se queda solamente con average valores centrales y les calcula el promedio, descartando "size - average" valores de los extremos.

Durante las primeras size llamadas a la función, mientras el buffer aún no está completo, la función devuelve directamente el valor ingresado sin ningún procesamiento.

Ejemplo:

voltage = filter(ain[0], 12, 5, 1000);

 

int = wait(
  bool condition,
  ulong timeout)

La función espera a que se cumpla condition o transcurran timeout milisegundos (lo que suceda primero).
Si la función termina porque se cumple la condición, devuelve 1.
Si la función termina porque se da el timeout, devuelve 0.
Si la función se llama fuera de una tarea, cuelga todo el script hasta terminar.
Si la función se llama desde una tarea, la función solo bloquea la tarea, y continúa ejecutando las demás tareas.

Ejemplo:

// Espero hasta que no haya error modbus o pasen 30 segundos.
result = wait(slave_error.0 == 0, 30000)

if (result == 0)
    // Si el wait terminó por timeout ejecuto esta línea.

 

scale(
  float value,
  float x0,
  float y0,
  float x1,
  float y1)

Realiza una interpolación lineal de value a la recta que pasa por [(x0,y0);(x1,y1)].

Ejemplo:

// Escalado de un sensor de temperatura de 4-20mA a 0-100ºC
temperature = scale(ain[0], 4000, 0, 20000, 100);

 

float = pid(
  float value,
  float set_point,
  float kp,
  float ki,
  float kd)

Implementa un control PID, donde value es el valor actual de salida de la plata o proceso a controlar. set_point es el valor de referencia y kp, ki y kd son las constantes proporcional, integral y derivada respectivamente. La función devuelve la señal de control que entra a la planta controlada.


El RTU-X puede implementar hasta 4 controles PID simultáneos.

Ejemplo:

// Variador de frecuencia para ajustar caudal
frequency = pid(flow, flow_set_point, 1.1, 0.5, 0.02);

 

bool = alarm(
  bool condition,
  ulong timeout_start,
  ulong timeout_end)
Permite implementar una alarma con retardo de comienzo y fin. 
Si condition se cumple por más de timeout_start milisegundos, se pone en estado de alarma. 
Si condition deja de cumplirse por más de timeout_end milisegundos, finaliza el estado de alarma. 
La función siempre devuelve 0 o 1 si se encuentra en estado de alarma o no.
int = timer(
TIMER_TON/TIMER_TOFF/TIMER_TP type,
int in,
ulong pt)

Implementa un temporizador estilo IEC 61131-3. El parámetro type selecciona el comportamiento: TIMER_TON (retardo a la conexión), TIMER_TOFF (retardo a la desconexión) o TIMER_TP (pulso de duración fija).

TIMER_TON: la salida se activa recién cuando in permanece en 1 durante pt milisegundos ininterrumpidos. Si in vuelve a 0 antes de cumplirse ese tiempo, la cuenta se reinicia y la salida permanece en 0.

TIMER_TOFF: la salida sigue a in inmediatamente al activarse, pero al desactivarse in permanece en 1 durante pt milisegundos adicionales antes de bajar a 0.

TIMER_TP: cada flanco ascendente de in dispara un pulso de pt milisegundos en la salida, no re-disparable mientras el pulso está en curso.

El RTU-X dispone de 16 timers simultáneos (TIMER_TON, TIMER_TOFF y TIMER_TP comparten el mismo pool de 16 instancias). El estado de los timers no sobrevive un deep sleep.

El tiempo transcurrido de cada instancia se expone en la variable de sistema timer_et[16], útil para telemetría o debug.

Ejemplo:

// Retardo a la conexión: activa la salida 5 segundos después de que la entrada 1 se pone en 1
pump_on = timer(TIMER_TON, get_input(1), 5000);

bool = interval(
  ulong value,
  ulong start,
  ulong end)
Verifica si value se encuentra dentro del intervalo entre start y end.
Si start <= end, entonces simplemente verifica que start <= value < end, y devuelve 1 si se cumple o 0 si no.
Si start > end, entonces verifica que value >= start o value < end, 
y devuelve 1 si se cumple cualquiera de las dos condiciones o 0 si no.
ulong = sunrise(
  ulong day,
  ulong month,
  ulong year,
  float latitude,
  float longitude)
Por medio de un reloj astronómico interno,  devuelve el segundo del día en el que saldrá el sol
en función de la fecha (day, month, year) y la posición (latitude, longitude). 
Devuelve como ulong el instante en segundos del día en hora local. 
El segundo actual se puede calcular como: actual = hours * 3600 + minutes * 60 + seconds; 
En combinación con la función interval y sunset, se puede saber fácilmente si es de día o de noche.
ulong = sunset(
  ulong day,
  ulong month,
  ulong year,
  float latitude,
  float longitude)
Por medio de un reloj astronómico interno,  devuelve el segundo del día en el que se ocultará el sol
en función de la fecha (day, month, year) y la posición (latitude, longitude). 
Devuelve como ulong el instante en segundos del día en hora local. 
El segundo actual se puede calcular como: actual = hours * 3600 + minutes * 60 + seconds; 
En combinación con la función interval y surise, se puede saber fácilmente si es de día o de noche.
pow(float x,float y)Devuelve el resultado de elevar x a la y.
log_e(float x)Devuelve el logaritmo base e de x.
log_10(float x)Devuelve el logaritmo base 10 de x.
cos(float x)Devuelve el coseno de x. Con x en radianes.
acos(float x)Devuelve el arco-coseno de x en radianes.
sin(float x)Devuelve el seno de x. Con x en radianes.
asin(float x)Devuelve el arcoseno de x en radianes.
tan(float x)Devuelve la tangente de x. Con x en radianes.
atan(float x)Devuelve el arcotangente de x en radianes.
sqrt(float x)Devuelve la raíz cuadrada de x.
abs(float x)Devuelve el valor absoluto de x.