Complete examples
Reaction to events
Change value in variable
Detect when the input 9 changes (Variable I9) of the deviceIO. When the input is activated (value 1), activate output 0 (variable O0).
events.addListener({ eventName: 'VariableChange', deviceCode: 'IO', variableCode: 'I9' }, ev => {
if (ev.newValue === 1) {
logger.info('Enable variable O0');
devices.write('IO', 'O0', 1);
} else {
logger.info('Disable output O0');
devices.write('IO', 'O0', 0);
}
});
Timer Events
We have configured on the Virtual Device Memory a variable actual_hour and actual_min that send your updates to screens and other external systems. We have created a one timer to shoot each minute (exact, second 00) with the name minuter:

// For ease to update the device code, We place it in a constant:
const virtualDevCode = 'memory';
events.addListener({
eventName: 'Timer',
timerName: 'Minuter'
},
// We can ignore the Event parameter, since we do not use its values
// for that we create the handler that does not receive any parameter
() => {
const date = new Date(); // We keep the current date and time and time
// And we update both fields
devices.write(virtualDevCode, 'actual_hour', date.getHours());
devices.write(virtualDevCode, 'actual_min', date.getMinutes());
});
Use of GlobalData.
The variable of the GlobalData context allows you to share data between scripts. When all the scripts that have read or written on a field within GlobalData that field is eliminated; That is why it is important to use the GlobalData.RegisterVariable (Variable:String) function at the beginning of a script that may take to access the field.
In this installation the "zone" concept is handled to link variables within the same passenger compartment. It is a concept that the installer has decided, alien to
// In this script we are going to make common initializations.
// By simplifying the example we will only show the map that links the zones
// And the air units that climate each area.
globalData.UEByZone = {
Principal: ['UE_01', 'UE_02'],
Admin: ['UE_03', 'UE_04'],
Salon1: ['UE_05'],
Salon2: ['UE_06', 'UE_07'],
Reception: ['UE_08']
};
//We started the variable Onzones if it has no value, which will save the zones with climate on.
// In this case we will use an JavaScript set, a set is a special list that it does not do
// anything if you try to add the same value twice.
globalData.onZones = globalData.onZones || new Set();
events.addListener((ev) => ev.eventName === 'Timer' && (ev.timerName.startsWith('On') || ev.timerName.startsWith('Off')), (ev) => {
// We detect if the event is on or off
const isOn = ev.timerName.startsWith('On');
// In this case, the zone goes in the name of the event
// After the words "on" or "off"
const zone = ev.timerName.replace('Off', '').replace('On', '');
// We add or eliminate the area of the Set
if(isOn) globalData.onZones.add(zone);
else globalData.onZones.delete(zone);
});
In the following script we will use the Data of Onzones to react depending on whether the area is active or not active:
// Link this script to Onzones and UeByZone, so that the variable does not disappear
// By making changes in previous scripts
globalData.registerVariableUse('onZones');
globalData.registerVariableUse('UEByZone');
// We can define a Arrow function, so that it is more readable to check onzones
const isZoneOn = zone => globalData.onZones.has(zone);
events.addListener({
eventName: 'VariableChange',
deviceCode: virtualDevCode
}, (ev) => {
if (ev.variableCode.startsWith('TempSet')) {
// We know that the variable begins with tempset (length 7) and follows the
// Name of the zone. So we can stay only with the name of the area:
const zoneName = ev.variableCode.substring(7);
// We are only interested in doing this writing if the area is on
if(isZoneOn(zoneName)) {
try {
//we go through all the air units of the area with the new value
globalData.UEByZone[zoneName].forEach(ueCode => {
devices.write(ueCode, 'SET_TSET', ev.newValue);
});
} catch (err) {
// We handle the possible error. You have to keep in mind that this makes
// Stop writing with the first error, we could put the TRY {} around
// of each scripture so that the following yes are carried out
logger.error('Problem in TempSet handler', zoneName, err);
}
}
}
}
Postpone a reaction or action
Act before a change of variable, but postpone it 10 seconds and only execute it once for every 10 seconds:
let timer;
events.addListener({eventName: 'NewVariablesHistoric'}, () => {
// If there is an active timer, we deactivate it and erase the variable
if(timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(() => {
//Code that we want to execute with the event
}, 10 * 1000 /* Settimeout specifies the time in thousandths of a second */);
});
Error handling
Read outdoor temperature variable, if reading fails to use another method consisting of reading an equivalent variable of the specified machine.
const getExternalTemp = machine => {
let externalTemp;
try {
externalTemp = devices.read('Recuperator', 'Exterior_Temperature');
} catch (err) {
logger.error('externalTemp: Could not be read ', err, machine);
}
// If the variable has not been read or has not returned the reading value
if(externalTemp === undefined) {
try {
externalTemp = devices.read(machine, 'EXT_TEMP');
} catch (err) {
logger.error('Alternative reading also failed', err);
}
}
return externalTemp;
}