Skip to content

Ejemplos completos

Reacción a eventos

Cambio de valor en variable

Detectar cuándo la entrada 9 (variable I9) del dispositivo IO. Cuándo la entrada se active (valor 1), activar la salida 0 (variable O0).

events.addListener({ eventName: 'VariableChange', deviceCode: 'IO', variableCode: 'I9' }, ev => {
  if (ev.newValue === 1) {
    logger.info('Activar variable O0');
    devices.write('IO', 'O0', 1);
  } else {
    logger.info('Desactivar salida O0');
    devices.write('IO', 'O0', 0);
  }
});

Eventos temporizador

Hemos configurado en el dispositivo virtual memory una variable hora_actual y min_actual que envían sus actualizaciones a pantallas y otros sistemas externos. Hemos creado un temporizador para dispararse cada minuto (exacto, segundo 00) con el nombre Minuter:

Evento configurado para dispararse con el cambio de minuto

// Por facilidad para actualizar el código de dispositivo,
// lo colocamos en una constante:
const virtualDevCode = 'memory';
events.addListener({
  eventName: 'Timer',
  timerName: 'Minuter'
},
// Podemos ignorar el parámetro event, ya que no usamos sus valores
// Para eso creamos el manejador que no recibe ningún parámetro
() => {
  const date = new Date(); // Guardamos la fecha y hora actual
  // Y actualizamos ambos campos
  devices.write(virtualDevCode, 'hora_actual', date.getHours());
  devices.write(virtualDevCode, 'min_actual', date.getMinutes());
});

Uso de globalData

La variable del contexto globalData permite compartir datos entre scripts. Cuando se eliminan todos los scripts que han leído o escrito sobre un campo dentro de globalData ese campo se elimina; por eso es importante utilizar la función globalData.registerVariableUse(variable: string) al inicio de un script que pueda tardar en acceder al campo.

En esta instalación se maneja el concepto "zona" para vincular variables dentro de un mismo habitáculo. Es un concepto que ha decidido el instalador, ajeno a adquio, pero gracias a la flexibilidad de los scripts se permite manejarlos fácilmente.

// En este script vamos a hacer inicializaciones comunes.
// Por simplificar el ejemplo sólo mostraremos el mapa que vincula las zonas
// y las unidades de aire que climatizan cada zona.
globalData.UEByZone = {
  Principal: ['UE_01', 'UE_02'],
  Administracion: ['UE_03', 'UE_04'],
  Salon1: ['UE_05'],
  Salon2: ['UE_06', 'UE_07'],
  Recepcion: ['UE_08']
};
// Iniciamos la variable onZones si no tiene valor ya, que guardará las zonas
// con clima encendido.
// En este caso utilzaremos un Set de EcmaScript, un set es una lista especial
// que no hace nada si se intenta añadir dos veces el mismo valor.
globalData.onZones = globalData.onZones || new Set();

events.addListener((ev) => ev.eventName === 'Timer' && (ev.timerName.startsWith('Encendido') || ev.timerName.startsWith('Apagado')), (ev) => {
  // Detectamos si el evento es de Encendido o Apagado
  const isOn = ev.timerName.startsWith('Encendido');
  // En este caso, la zona va en el nombre del evento
  // Después de la palabra "Encendido" o "Apagado"
  const zone = ev.timerName.replace('Apagado', '').replace('Encendido', '');
  // Añadimos o eliminamos del Set la zona
  if(isOn) globalData.onZones.add(zone);
  else globalData.onZones.delete(zone);
});

En el siguiente script utilizaremos los datos de onZones para reaccionar dependiendo de si la zona está o no activa:

// Vincula este script a onZones y UEByZone, para que la variable no desaparezca
// al hacer cambios en los scripts anteriores
globalData.registerVariableUse('onZones');
globalData.registerVariableUse('UEByZone');

// Podemos definir una función arrow, para que sea más legible comprobar onZones
const isZoneOn = zone => globalData.onZones.has(zone);

events.addListener({
  eventName: 'VariableChange',
  deviceCode: virtualDevCode
}, (ev) => {
  if (ev.variableCode.startsWith('TempSet')) {
    // Sabemos que la variable empieza por TempSet (longitud 7) y le sigue el
    // nombre de la zona- Así podemos quedarnos solo con el nombre de la zona:
    const zoneName = ev.variableCode.substring(7);

    // Solo nos interesa hacer esta escritura si la zona está encendida
    if(isZoneOn(zoneName)) {
      try {
        //Recorremos todas las unidades de aire de la zona con el nuevo valor
        globalData.UEByZone[zoneName].forEach(ueCode => {
          devices.write(ueCode, 'SET_TSET', ev.newValue);
        });
      } catch (err) {
        // Manejamos el posible error. Hay que tener en cuenta que esto hace eque
        // se pare la escritura con el primer error, podríamos poner el try{} alrededor
        // de cada escritura para que las siguientes sí se realicen
        logger.error('Problem in TempSet handler', zoneName, err);
      }
    }
  }
}

Aplazar una reacción o acción

Actuar ante un cambio de variable, pero aplazarlo 10 segundos y solo ejecutarlo una vez por cada 10 segundos:

let timer;
events.addListener({eventName: 'NewVariablesHistoric'}, () => {
  // Si hay un timer activo, lo desactivamos y borramos la variable
  if(timer) {
    clearTimeout(timer);
    timer = null;
  }
  timer = setTimeout(() => {
    // Código que queremos ejecutar con el evento
  }, 10 * 1000 /* setTimeout especifica el tiempo en milésimas de segundo */);
});

Manejo de errores

Leer variable de temperatura exterior, si falla la lectura utilizar otro método consistente en leer una variable equivalente de la máquina especificada.

const getExternalTemp = maquina => {
  let externalTemp;
  try {
    externalTemp = devices.read('Recuperador', 'Temperatura_exterior');
  } catch (err) {
    logger.error('No se pudo leer externalTemp', err, maquina);
  }
  // Si no se ha logrado leer la variable o no ha devuelto valor la lectura
  if(externalTemp === undefined) {
    try {
    externalTemp = devices.read(maquina, 'EXT_TEMP');
    } catch (err) {
      logger.error('También falló la lectura alternativa', err);
    }
  }
  return externalTemp;
}