I already got a rule for setting the status on based on temperature
and setpoint
- any improvements I can make?
configuration: {}
triggers:
- id: "1"
configuration:
groupName: Radiators_Setpoints
type: core.GroupStateChangeTrigger
- id: "2"
configuration:
groupName: Radiators_Actual_Temps
type: core.GroupStateChangeTrigger
conditions: []
actions:
- inputs: {}
id: "3"
configuration:
type: application/javascript
script: >-
function getRadiator(itemName) {
var radiator = items.getItem(itemName, true);
if (!radiator) return [null, null];
var metadata = radiator.getMetadata('thermostat') ?? radiator.getMetadata('heating') ?? radiator.getMetadata('cooling');
if (!metadata) return [radiator, null];
if (metadata.value?.trim().length > 0) return getRadiator(metadata.value);
return [radiator, metadata];
}
function handleItem(itemName) {
const MEASUREMENT_MARGIN = 0.1; // Number.EPSILON is too small
var name, setpointItemName, setpointItem, setpoitMetadata, actualTempItem, actualTempItemName, actualTempMetadata, requestItem, requestItemName, requestMetadata;
if (itemName.endsWith('_Setpoint_Temperature')) {
name = itemName.slice(0, -"_Setpoint_Temperature".length);
setpointItemName = itemName;
[setpointItem, setpoitMetadata] = getRadiator(setpointItemName);
actualTempItemName = setpoitMetadata?.configuration?.actualTempItem ?? `${name}_Actual_Temp`;
[actualTempItem, actualTempMetadata] = getRadiator(actualTempItemName);
requestItemName = setpoitMetadata?.configuration?.requestItem ?? `${name}_Requests`;
[requestItem, requestMetadata] = getRadiator(requestItemName);
} else if (itemName.endsWith('_Actual_Temp')) {
name = itemName.slice(0, -"_Actual_Temp".length);
actualTempItemName = itemName;
[actualTempItem, actualTempMetadata] = getRadiator(actualTempItemName);
setpointItemName = actualTempMetadata?.configuration?.setpointItem ?? `${name}_Setpoint_Temperature`;
[setpointItem, setpoitMetadata] = getRadiator(setpointItemName);
requestItemName = actualTempMetadata?.configuration?.requestItem ?? `${name}_Requests`;
[requestItem, requestMetadata] = getRadiator(requestItemName);
} else {
var [radiator, metadata] = getRadiator(itemName);
setpointItemName = metadata.configuration.actualTempItem ? metadata.configuration.actualTempItem : itemName;
[setpointItem, setpoitMetadata] = metadata.configuration.setpointItem ? getRadiator(setpointItemName) : [radiator, metadata];
actualTempItemName = metadata.configuration.setpointItem ? metadata.configuration.setpointItem : itemName;
[actualTempItem, actualTempMetadata] = metadata.configuration.actualTempItem ? getRadiator(actualTempItemName) : [radiator, metadata];
requestItemName = metadata.configuration.requestItem ? metadata.configuration.requestItem : itemName;
[requestItem, requestMetadata] = metadata.configuration.requestItem ? getRadiator(requestItemName) : [radiator, metadata];
}
if (!actualTempItem) {
console.error(`Radiator '${name}' cannot determine actual temp item`, { actualTempItemName, setpointItemName, requestItemName, metadata: actualTempMetadata });
return;
}
if (!setpointItem) {
console.error(`Radiator '${name}' cannot determine setpoint item`, { actualTempItemName, setpointItemName, requestItemName, metadata: setpoitMetadata });
return;
}
if (!requestItem) {
console.error(`Radiator '${name}' cannot determine request item`, { actualTempItemName, setpointItemName, requestItemName, metadata: requestMetadata });
return;
}
var temperature = actualTempItem.numericState;
var setpoint = setpointItem.numericState;
switch (requestItem.state) {
case 'none':
if (temperature > setpoint) {
console.info(`Radiator '${name}' changing from '${requestItem.state}' to 'cool' as ${temperature} > ${setpoint}`);
requestItem.sendCommandIfDifferent("cool");
} else if (temperature < setpoint) {
console.info(`Radiator '${name}' changing from '${requestItem.state}' to 'heat' as ${temperature} < ${setpoint}`);
requestItem.sendCommandIfDifferent("heat");
} else {
console.info(`Radiator '${name}' not changing`);
requestItem.sendCommandIfDifferent("none");
}
break;
case 'cool':
if (temperature >= (setpoint - MEASUREMENT_MARGIN) && temperature <= (setpoint + MEASUREMENT_MARGIN)) {
console.info(`Radiator '${name}' changing from '${requestItem.state}' to 'none' as ${temperature} == ${setpoint}`);
requestItem.sendCommandIfDifferent("none");
} else if (temperature < setpoint) {
console.info(`Radiator '${name}' changing from '${requestItem.state}' to 'heat' as ${temperature} < ${setpoint}`);
requestItem.sendCommandIfDifferent("heat");
} else {
console.info(`Radiator '${name}' not changing`);
requestItem.sendCommandIfDifferent("cool");
}
break;
case 'heat':
if (temperature >= (setpoint - MEASUREMENT_MARGIN) && temperature <= (setpoint + MEASUREMENT_MARGIN)) {
console.info(`Radiator '${name}' changing from '${requestItem.state}' to 'none' as ${temperature} == ${setpoint}`);
requestItem.sendCommandIfDifferent("none");
} else if (temperature > setpoint) {
console.info(`Radiator '${name}' changing from '${requestItem.state}' to 'cool' as ${temperature} > ${setpoint}`);
requestItem.sendCommandIfDifferent("cool");
} else {
console.info(`Radiator '${name}' not changing`);
requestItem.sendCommandIfDifferent("heat");
}
break;
}
}
if (this.event.itemName?.trim()?.length > 0) {
handleItem(this.event.itemName);
} else {
for (var item of items.getItem('Radiators_Actual_Temps')?.descendents ?? []) {
console.info(`Manual trigger for '${item.name}'`);
handleItem(item.name);
}
for (var item of items.getItem('Radiators_Setpoints')?.descendents ?? []) {
console.info(`Manual trigger for '${item.name}'`);
handleItem(item.name);
}
}
type: script.ScriptAction
Also quick question - why do the buttons for specific code fences use PHP and not the corresponding language like yaml?