1
0

Rework equipmentMgr

This commit is contained in:
2023-08-26 16:48:49 +02:00
parent 98358d5c09
commit 5aa399d7fe
2 changed files with 262 additions and 268 deletions

View File

@@ -2,25 +2,281 @@ console.loggerName = 'js.equipmentMgr';
console.log('Load equipmentMgr');
const {
equipment,
lib,
timer,
watch
} = require('../utils');
class Equipment {
constructor(equipmentItem) {
// Fetch item if provided equipmentItem is a string
if (typeof equipmentItem === 'string' || equipmentItem instanceof String) {
this.equipmentItem = items[equipmentItem];
} else {
this.equipmentItem = equipmentItem;
}
// Throw error if item is not existing
if (this.equipmentItem === null) {
throw(`Item ${equipmentItem} not existing`);
}
// Throw error if item is not an equipment type
if (this.equipmentItem.semantics.semanticType != 'Equipment') {
throw(`Item ${this.equipmentItem.name} is not an equipment type`);
}
console.info(`Initialization of equipment ${this.equipmentItem.name} with type ${this.constructor.name}`);
// Initialization of properties
this.name = this.equipmentItem.name;
this.watch = new Object();
this.timers = new timer.Timer();
// Check if equipment has state item
if (this.hasProperty('State')) {
this.stateItem = items[this.getPropertyItemName('State')];
this.watch['State'] = new watch.Watch(this.stateItem);
} else {
console.info(`Item ${this.equipmentItem.name} has no state item`)
}
// Check if equipment has LowBat item
if (this.hasProperty('LowBat')) {
this.watch['LowBat'] = new watch.Watch(this.getPropertyItemName('LowBat'));
this.watch['LowBat'].add({
targetState: 'ON',
alertFunc: () => { this.#notifyLowBat(); },
alertRepeat: 'PT23H'
});
}
// Check if equipment has Unreach item
if (this.hasProperty('Unreach')) {
this.watch['Unreach'] = new watch.Watch(this.getPropertyItemName('Unreach'));
this.watch['Unreach'].add({
targetState: 'ON',
alertFunc: () => { this.#notifyUnreach(); },
alertDelay: 'PT15M',
alertRepeat: 'PT1H'
});
}
}
getValue(propertyName, defaultValue = '') {
let valueItemName = this.name + '_' + propertyName;
let returnValue = defaultValue;
if (items[valueItemName] == null) { // Return default value if item is missing
console.warn('Item ' + valueItemName + ' is missing');
} else if (items[valueItemName]['state'] == 'NULL') { // Return default value if item state is null
console.warn('Item ' + valueItemName + ' is unset')
} else { // Return value from item
if (items[valueItemName].quantityState == null && items[valueItemName].numericState == null) {
returnValue = items[valueItemName]['state'];
} else if (items[valueItemName].quantityState == null) {
returnValue = items[valueItemName]['numericState']
} else {
returnValue = items[valueItemName].quantityState;
}
}
console.debug(`Return value for property ${propertyName} for ${this.name}: ${returnValue}`);
return returnValue;
}
getPropertyItemName(propertyName) {
if (this.hasProperty(propertyName)) {
return items[this.name + '_' + propertyName].name;
}
}
hasProperty(propertyName) {
if (items[this.name + '_' + propertyName] == null) {
console.debug(`Eqipment ${this.name} has no property ${propertyName}`)
return false;
}
return true;
}
#notifyLowBat() {
console.warn(`${this.name} has a low battery level.`);
}
#notifyUnreach() {
console.warn(`${this.name} is offline.`);
}
gc() {
console.log('Denitialization of eqipment ' + this.name);
// Delete all watchObjects
for (let watchItem of Object.keys(this.watch)) {
this.watch[watchItem].deleteAll();
}
// Cancel all timers
this.timers.cancelAll();
}
}
class Irrigation extends Equipment {
constructor(equipmentItem) {
super(equipmentItem);
// Initialization of properties
this.valves = new Object();
// Add on/off watch rule
this.watch['State'].add({
targetState: 'ON',
alertFunc: () => { this.#irrigationOn(); },
endAlertFunc: () => { this.#irrigationOff(); },
});
// Fetch irrigation valves and initialize as subequipment
for (let valve of this.equipmentItem.members.filter(item => { return item.tags.includes('IrrigationValve'); } )) {
try {
this.valves[valve.name] = new IrrigationValve(valve);
} catch (error) {
console.error(error);
}
}
}
gc() {
console.info('Deinitialization of irrigation valves for ' + this.name);
// Delete all watchObjects
for (let valve of Object.keys(this.valves)) {
this.valves[valve].gc();
}
// Call function to deinitialize irrigation
super.gc();
}
#irrigationOn() {
console.info(`Irrigation ${this.name} received command on`);
// Fetch valves with AutoMode enabled
let autoValves = Object.keys(this.valves).filter(element => { return this.valves[element].getValue('AutoMode', 'OFF') == 'ON'} );
// Skip if no valves with AutoMode enabled are available
if (autoValves.length == 0) {
console.info('No valves with AutoMode enabled available');
this.stateItem.sendCommandIfDifferent('OFF');
return;
}
let totalDuration = 0;
for (let i = 0; i < autoValves.length; i++) {
let currentValve = autoValves[i];
let nextValve = autoValves[(i + 1)];
let duration = time.toZDT(this.valves[currentValve].getValue('Duration', 'PT30S')).getMillisFromNow();
// calculate start and endtimes for valve
let startTime = time.toZDT(totalDuration)
totalDuration = totalDuration + duration;
let endTime = time.toZDT(totalDuration);
// Set timers for valve
this.valves[currentValve].timers.create(
'autoOn',
startTime,
() => {
this.valves[currentValve].stateItem.sendCommandIfDifferent('ON');
}
);
this.valves[currentValve].timers.create(
'autoOff',
endTime,
() => {
this.valves[currentValve].stateItem.sendCommandIfDifferent('OFF');
}
);
// Stop irrigation after the last valve
if (nextValve == undefined) {
console.log('No further valves with autoMode enabled available');
this.timers.create(
'autoOff',
endTime.plusSeconds(5),
() => {
console.debug(`Switch irrigation ${this.name} to off`)
this.stateItem.sendCommandIfDifferent('OFF');
}
);
}
}
}
#irrigationOff() {
console.info(`Irrigation ${this.name} received command off`);
this.timers.cancel('autoOff')
for (let valve of Object.keys(this.valves)) {
this.valves[valve].timers.cancel('autoOn');
this.valves[valve].timers.cancel('autoOff');
this.valves[valve].stateItem.sendCommandIfDifferent('OFF')
}
}
}
class IrrigationValve extends Equipment {
constructor(equipmentItem) {
super(equipmentItem);
this.watch['State'].add({
targetState: 'ON',
alertFunc: () => { this.stateItem.sendCommand('OFF'); },
alertDelay: 'PT30M'
});
}
}
class TowelRadiator extends Equipment {
constructor(equipmentItem) {
super(equipmentItem);
this.watch['State'].add({
targetState: 'ON',
alertFunc: () => { this.stateItem.sendCommand('OFF'); },
alertDelay: 'PT59M'
});
}
}
class WeatherService extends Equipment {
constructor(equipmentItem) {
super(equipmentItem);
}
}
const eMgr = new Object();
for (let equipmentItem of items.getItems().filter(element => { return (element.semantics.isEquipment == true) && (element.semantics.equipment == null) })) {
// Fetch equipment type
let equipmentType = equipmentItem.tags.filter(element => Object.keys(equipment).includes(element));
if (equipmentType.length > 1) {
equipmentType.splice(equipmentType.indexOf('Equipment'), 1);
// Get equipmentType
var equipmentType = equipmentItem.tags.filter(element => { return !(element == 'Equipment') } );
console.log(equipmentType);
// Set default equipmentType if item does not provide a type
if (equipmentType == '') {
equipmentType = 'Equipment';
}
// Initialize equipment class
try {
eMgr[equipmentItem.name] = new equipment[equipmentType](equipmentItem);
eMgr[equipmentItem.name] = eval(`new ${equipmentType}(equipmentItem)`);
} catch (error) {
console.error(error);
}

View File

@@ -1,262 +0,0 @@
console.loggerName = 'js.equipment';
console.log('Load equipment modules');
class Equipment {
constructor(equipmentItem) {
// Fetch item if provided equipmentItem is a string
if (typeof equipmentItem === 'string' || equipmentItem instanceof String) {
this.equipmentItem = items[equipmentItem];
} else {
this.equipmentItem = equipmentItem;
}
// Throw error if item is not existing
if (this.equipmentItem === null) {
throw(`Item ${equipmentItem} not existing`);
}
// Throw error if item is not an equipment type
if (this.equipmentItem.semantics.semanticType != 'Equipment') {
throw(`Item ${this.equipmentItem.name} is not an equipment type`);
}
console.info(`Initialization of equipment ${this.equipmentItem.name} with type ${this.constructor.name}`);
// Initialization of properties
this.name = this.equipmentItem.name;
this.watch = new Object();
this.timers = new timer.Timer();
// Check if equipment has state item
if (this.hasProperty('State')) {
this.stateItem = items[this.getPropertyItemName('State')];
this.watch['State'] = new watch.Watch(this.stateItem);
} else {
console.info(`Item ${this.equipmentItem.name} has no state item`)
}
// Check if equipment has LowBat item
if (this.hasProperty('LowBat')) {
this.watch['LowBat'] = new watch.Watch(this.getPropertyItemName('LowBat'));
this.watch['LowBat'].add({
targetState: 'ON',
alertFunc: () => { this.#notifyLowBat(); },
alertRepeat: 'PT23H'
});
}
// Check if equipment has Unreach item
if (this.hasProperty('Unreach')) {
this.watch['Unreach'] = new watch.Watch(this.getPropertyItemName('Unreach'));
this.watch['Unreach'].add({
targetState: 'ON',
alertFunc: () => { this.#notifyUnreach(); },
alertDelay: 'PT15M',
alertRepeat: 'PT1H'
});
}
}
getValue(propertyName, defaultValue = '') {
let valueItemName = this.name + '_' + propertyName;
let returnValue = defaultValue;
if (items[valueItemName] == null) { // Return default value if item is missing
console.warn('Item ' + valueItemName + ' is missing');
} else if (items[valueItemName]['state'] == 'NULL') { // Return default value if item state is null
console.warn('Item ' + valueItemName + ' is unset')
} else { // Return value from item
if (items[valueItemName].quantityState == null && items[valueItemName].numericState == null) {
returnValue = items[valueItemName]['state'];
} else if (items[valueItemName].quantityState == null) {
returnValue = items[valueItemName]['numericState']
} else {
returnValue = items[valueItemName].quantityState;
}
}
console.debug(`Return value for property ${propertyName} for ${this.name}: ${returnValue}`);
return returnValue;
}
getPropertyItemName(propertyName) {
if (this.hasProperty(propertyName)) {
return items[this.name + '_' + propertyName].name;
}
}
hasProperty(propertyName) {
if (items[this.name + '_' + propertyName] == null) {
console.debug(`Eqipment ${this.name} has no property ${propertyName}`)
return false;
}
return true;
}
#notifyLowBat() {
console.warn(`${this.name} has a low battery level.`);
}
#notifyUnreach() {
console.warn(`${this.name} is offline.`);
}
gc() {
console.log('Denitialization of eqipment ' + this.name);
// Delete all watchObjects
for (let watchItem of Object.keys(this.watch)) {
this.watch[watchItem].deleteAll();
}
// Cancel all timers
this.timers.cancelAll();
}
}
class Irrigation extends Equipment {
constructor(equipmentItem) {
super(equipmentItem);
// Initialization of properties
this.valves = new Object();
// Add on/off watch rule
this.watch['State'].add({
targetState: 'ON',
alertFunc: () => { this.#irrigationOn(); },
endAlertFunc: () => { this.#irrigationOff(); },
});
// Fetch irrigation valves and initialize as subequipment
for (let valve of this.equipmentItem.members.filter(item => { return item.tags.includes('IrrigationValve'); } )) {
try {
this.valves[valve.name] = new IrrigationValve(valve);
} catch (error) {
console.error(error);
}
}
}
gc() {
console.info('Deinitialization of irrigation valves for ' + this.name);
// Delete all watchObjects
for (let valve of Object.keys(this.valves)) {
this.valves[valve].gc();
}
// Call function to deinitialize irrigation
super.gc();
}
#irrigationOn() {
console.info(`Irrigation ${this.name} received command on`);
// Fetch valves with AutoMode enabled
let autoValves = Object.keys(this.valves).filter(element => { return this.valves[element].getValue('AutoMode', 'OFF') == 'ON'} );
// Skip if no valves with AutoMode enabled are available
if (autoValves.length == 0) {
console.info('No valves with AutoMode enabled available');
this.stateItem.sendCommandIfDifferent('OFF');
return;
}
let totalDuration = 0;
for (let i = 0; i < autoValves.length; i++) {
let currentValve = autoValves[i];
let nextValve = autoValves[(i + 1)];
let duration = time.toZDT(this.valves[currentValve].getValue('Duration', 'PT30S')).getMillisFromNow();
// calculate start and endtimes for valve
let startTime = time.toZDT(totalDuration)
totalDuration = totalDuration + duration;
let endTime = time.toZDT(totalDuration);
// Set timers for valve
this.valves[currentValve].timers.create(
'autoOn',
startTime,
() => {
this.valves[currentValve].stateItem.sendCommandIfDifferent('ON');
}
);
this.valves[currentValve].timers.create(
'autoOff',
endTime,
() => {
this.valves[currentValve].stateItem.sendCommandIfDifferent('OFF');
}
);
// Stop irrigation after the last valve
if (nextValve == undefined) {
console.log('No further valves with autoMode enabled available');
this.timers.create(
'autoOff',
endTime.plusSeconds(5),
() => {
console.debug(`Switch irrigation ${this.name} to off`)
this.stateItem.sendCommandIfDifferent('OFF');
}
);
}
}
}
#irrigationOff() {
console.info(`Irrigation ${this.name} received command off`);
this.timers.cancel('autoOff')
for (let valve of Object.keys(this.valves)) {
this.valves[valve].timers.cancel('autoOn');
this.valves[valve].timers.cancel('autoOff');
this.valves[valve].stateItem.sendCommandIfDifferent('OFF')
}
}
}
class IrrigationValve extends Equipment {
constructor(equipmentItem) {
super(equipmentItem);
this.watch['State'].add({
targetState: 'ON',
alertFunc: () => { this.stateItem.sendCommand('OFF'); },
alertDelay: 'PT30M'
});
}
}
class TowelRadiator extends Equipment {
constructor(equipmentItem) {
super(equipmentItem);
this.watch['State'].add({
targetState: 'ON',
alertFunc: () => { this.stateItem.sendCommand('OFF'); },
alertDelay: 'PT59M'
});
}
}
class WeatherService extends Equipment {
constructor(equipmentItem) {
super(equipmentItem);
}
}
module.exports = {
Equipment,
Irrigation,
IrrigationValve,
TowelRadiator,
WeatherService
};