Commit 0819f496 authored by ToSe's avatar ToSe
Browse files

initial commit

parent 51d94cf9
initial commit
\ No newline at end of file
# openhab jsr223 helper for javascript
First at this point spezial thanks @lewie for his work and share of helper librarays.
Now i have extended this one and want also share this. Perhaps someone will find it usefull.
#### Here is a complete example of all new helper:
```
var timeOfDay_preset = {
"morning_start": "6:00", // morning_start is nessesary for time of day
"night_start": "22:00", // night_start is nessesary for time of day
"bed_start": "00:00", // bed_start is nessesary for time of day
"astro_calc": "00:01",
}
JSRule({
name: "RNTs - example",
description: "example",
triggers: aggregateTrigger([
TimerTrigger("0 0/15 * 1/1 * ? *"), // single cron trigger
ChangedEventTriggerGroup("gExampleGroup1"), // trigger when single item in group changed
ItemCommandTriggerGroup("gExampleGroup2"), // trigger when single item in group received command
generateCronTriggerSet(timeOfDay_preset), // multiple cron trigger generated from var timeOfDay_preset
ItemStateChangeTrigger("exampleSwitch","","ON") // single item change trigger
]),
execute:
```
----
**aggregateTrigger(ArrayOfTriggers)**
In the JSRule template the key trigger except a single array with various sort of triggers. But it's not possible to use nested arrays with nested triggers.
Here the parameter is also an array. In difference one can hand over arrays of trigger or single trigger and the function will return a single array of triggers.
**ItemCommandTriggerGroup(groupName)**
param: group of item
return: single ItemCommandTrigger array of items what are member of group in param
**ChangedEventTriggerGroup(groupName)**
param: group of item
return: single ChangedEventTrigger array of items what are member of group in param
**generateCronTriggerSet(triggerPreset)**
param: dataset with trigger times in the follwoing format - hour:minute
return: array of single cron trigger
example of dataset: var example_timeSet = {
"trigger1": "23:10",
"nightStart": "23:04",
"bedTime": "23:02",
}
one can define as much as nessesary trigger times
the key is for human readability but it must be unique
In the example of time of day https://community.openhab.org/t/migrating-dsl-rules-to-jsr223-javascript-with-a-case-example/73352, @Confectrician thanks for sharing, one can see the benefit of this datastructure. It's exist one place (var timeOfDay_preset) of relevant times.
```
var timeOfDay_preset = {
"morning_start": "6:00", // morning_start is nessesary for time of day
"night_start": "22:00", // night_start is nessesary for time of day
"bed_start": "00:00", // bed_start is nessesary for time of day
"astro_calc": "00:01",
}
JSRule({
name: "Time of day",
description: "Calculates the time of day, depending on several triggers",
triggers: aggregateTrigger([
ChannelEventTrigger("astro:sun:home:rise#event", "START", "astroSunriseTrigger"),
ChannelEventTrigger("astro:sun:home:set#event", "START", "astroSunsetTrigger"),
ChannelEventTrigger("astro:sun:minus90:set#event", "START", "astroSunsetDelayTrigger"),
generateCronTriggerSet(timeOfDay_preset),
ItemStateChangeTrigger("Helper_JSR223_SystemIsStarted","","ON") // trigger for system startup witch helper
]),
...
//logInfo("Calculating time of day...")
// Calculate the times for the static times
var tMorning = timeOfDay_preset["morning_start"].split(':')
var tNight = timeOfDay_preset["night_start"].split(':')
var tBed = timeOfDay_preset["bed_start"].split(':')
var morning_start = new Date().setHours(tMorning[0], tMorning[1], 0, 0) // .setHours(Hour, Minute, Second, Millisecond)
var night_start = new Date().setHours(tNight[0], tNight[1], 0, 0)
var bed_start = new Date().setHours(tBed[0], tBed[1], 0, 0)
```
**hint:** Abouve you see only the relevant part for generateCronTriggerSet not the complete rule.
----
**checkItemExist(item.name)**
param: item name
return: item then exist or null
```
context.checkItemExist = function(it) {
try {
//print("################## "+ir.getItem(it));
return (typeof it === 'string' || it instanceof String) ? ir.getItem(it) : it;
}catch(err) {
return null;
}
};
```
This function is append in the file helper.js. It's almost identical to getItem(item.name). The only difference is, you will not get an error in the log when the item not exist. So i find it a little bit cleaner to check if items exist.
/**
* Copyright (c) 2018 by Helmut Lehmeyer.
*
* @author Helmut Lehmeyer
*/
'use strict';
se.importPreset("RuleSupport");
se.importPreset("RuleSimple");
se.importPreset("RuleFactories");
se.importPreset("default");
var OPENHAB_CONF = Java.type("java.lang.System").getenv("OPENHAB_CONF"); // most this is /etc/openhab2
//var OPENHAB_CONF = Java.type("java.lang.System").getenv("/etc/openhab2"); // most this is /etc/openhab2
load(OPENHAB_CONF+'/automation/jsr223/jslib/helper.js');
load(OPENHAB_CONF+'/automation/jsr223/jslib/triggersAndConditions.js');
//https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/api.html
//var StSimpleRule = Java.type("org.eclipse.smarthome.automation.module.script.rulesupport.shared.simple.SimpleRule");
//var StSimpleRuleExt = new StSimpleRule();
//var ExtendedSimpleRule = Java.extend(SimpleRule, {
// setUID: function(i) {
// //print("Run in separate thread");
// this.uid = i;
// }
//});
//var Thread = Java.type("java.lang.Thread");
//var th = new Thread(new MyRun());
//if(RuleBuilder == undefined)var RuleBuilder = Java.type("org.eclipse.smarthome.automation.core.util.RuleBuilder");
/*
if(RuleBuilder == undefined)var RuleBuilder = Java.type("org.eclipse.smarthome.automation.core.util.RuleBuilder");
In future better do it by org.eclipse.smarthome.automation.core.util.RuleBuilder like in
org.eclipse.smarthome.automation.core.dto.RuleDTOMapper Don't know
return RuleBuilder.create(ruleDto.uid)
.withActions(ActionDTOMapper.mapDto(ruleDto.actions))
.withConditions(ConditionDTOMapper.mapDto(ruleDto.conditions))
.withTriggers(TriggerDTOMapper.mapDto(ruleDto.triggers))
.withConfiguration(new Configuration(ruleDto.configuration))
.withConfigurationDescriptions(ConfigDescriptionDTOMapper.map(ruleDto.configDescriptions))
.withTemplateUID(ruleDto.templateUID)
.withVisibility(ruleDto.visibility)
.withTags(ruleDto.tags)
.withName(ruleDto.name)
.withDescription(ruleDto.description).build();
// UNTESTED UNTESTED UNTESTED
//Simplifies spelling for rules.
(function(context) {
'use strict';
context.JSRuleNew = function(obj) {
//logInfo("################ JSRule Line: "+__LINE__+" #################");
//2. OR second option, to add Rules in rulefile. Is not needed.
var triggers = obj.triggers ? obj.triggers : obj.getEventTrigger();
return RuleBuilder.create( obj.uid ? obj.uid : uuid.randomUUID()+me.replace(/[^\w]/g, "-"))
.withActions( obj.actions ? obj.actions : null)
.withConditions( obj.conditions ? obj.conditions : null)
.withTriggers( triggers && triggers.length > 0 ? triggers : null)
.withConfiguration(new Configuration(ruleDto.configuration))
.withConfigurationDescriptions( obj.configurationDescription ? [obj.configurationDescription] : null)
.withTemplateUID( obj.templateUID ? obj.templateUID : null)
.withVisibility( obj.visibility ? obj.visibility : null)
.withTags( obj.tags ? obj.tags : null)
.withName( obj.name ? obj.name : null)
.withDescription(obj.description ? obj.description : null)
.build();
};
})(this);
// UNTESTED UNTESTED UNTESTED
*/
//Simplifies spelling for rules.
(function (context) {
'use strict';
context.JSRule = function (obj, line) {
try{
var ruid = uuid.randomUUID() + "-" + obj.name.replace(/[^\w]/g, "-");
//logInfo("################ JSRule Line: "+__LINE__+" ################# ruid:" + ruid);
//var rule = new SimpleRule({ setUID: function(i) { uid = i; } })
var rule = new SimpleRule(){
execute: obj.execute //DOES THIS WORK? AND IF YES, WHY? => execute is found in implemented SimpleRuleActionHandler
};
var triggers = obj.triggers ? obj.triggers : obj.getEventTrigger();
rule.setTemplateUID(ruid);
if (obj.description) {
rule.setDescription(obj.description);
}
if (obj.name) {
rule.setName(obj.name);
}
//1. Register rule here
if (triggers && triggers.length > 0) {
rule.setTriggers(triggers);
automationManager.addRule(rule);
}
//2. OR second option, to add Rules in rulefile. Is not needed.
return rule;
}catch(err) {
context.logError("JSRule " + __LINE__ + ". obj: '" + obj + "' Error:" + err);
}
return null;
},
//TODO like in org.eclipse.smarthome.automation.core.dto.RuleDTOMapper
// or org.eclipse.smarthome.automation.sample.extension.java.internal.WelcomeHomeRulesProvider
//Missing SimpleRuleActionHandler!!
context.JSRuleNew = function (obj) {
//logInfo("################ JSRule Line: "+__LINE__+" #################");
//2. OR second option, to add Rules in rulefile. Is not needed.
var rname = obj.name ? obj.name.replace(/[^\w]/g, "-") : "nameless-generic";
var ruid = obj.uid ? obj.uid : uuid.randomUUID() + "-" + rname;
var triggers = obj.triggers ? obj.triggers : obj.getEventTrigger();
return RuleBuilder.create(ruid)
.withActions(obj.execute ? [obj.execute] : null)
//.withConditions(obj.conditions ? obj.conditions : [])
.withTriggers(triggers && triggers.length > 0 ? triggers : null)
.withConfiguration(new Configuration(obj.configuration))
.withConfigurationDescriptions(obj.configurationDescription ? [obj.configurationDescription] : null)
.withTemplateUID(obj.templateUID ? obj.templateUID : ruid)
.withVisibility(obj.visibility ? obj.visibility : null)
.withTags(obj.tags ? obj.tags : null)
.withName(obj.name ? obj.name : null)
.withDescription(obj.description ? obj.description : null)
.build();
}
}) (this);
/**
* Copyright (c) 2018 by Helmut Lehmeyer.
*
* @author Helmut Lehmeyer
*/
'use strict';
var PersistenceExtensions = Java.type("org.eclipse.smarthome.model.persistence.extensions.PersistenceExtensions");
//Simplifies spelling for rules.
(function(context) {
'use strict';
context.PersistenceExtensions = PersistenceExtensions;
context.pe = PersistenceExtensions;
context.persistExt = function(type, it, serviceId) {
try {
//var item = context.getItem(it);
//return (serviceId == undefined) ? context.pe[type+""](item) : context.pe[type+""](item, serviceId);
return (serviceId == undefined) ? context[type+""](it) : context[type+""](it, serviceId);
}catch(err) {
context.logError("persistExt " + type +" "+__LINE__, err);
}
return null;
};
//void persist(Item item, String serviceId)
//void persist(Item item)
context.persist = function(it, serviceId) {
try {
var item = context.getItem(it);
(serviceId == undefined) ? context.pe.persist(item) : context.pe.persist(item, serviceId);
}catch(err) {
context.logError("persist "+__LINE__, err);
}
};
//
//HistoricItem historicState(Item item, AbstractInstant timestamp)
//HistoricItem historicState(Item item, AbstractInstant timestamp, String serviceId)
context.historicState = function(it, timestamp, serviceId) {
try {
var item = context.getItem(it);
return (serviceId == undefined) ? context.pe.historicState(item, timestamp).state : context.pe.historicState(item, timestamp, serviceId).state;
}catch(err) {
context.logError("historicState "+__LINE__, err);
}
return null;
};
//
//Boolean changedSince(Item item, AbstractInstant timestamp)
//Boolean changedSince(Item item, AbstractInstant timestamp, String serviceId)
context.changedSince = function(it, timestamp, serviceId) {
try {
var item = context.getItem(it);
return (serviceId == undefined) ? context.pe.changedSince(item, timestamp) : context.pe.changedSince(item, timestamp, serviceId);
}catch(err) {
context.logError("changedSince "+__LINE__, err);
}
return null;
};
//
//Boolean updatedSince(Item item, AbstractInstant timestamp)
//Boolean updatedSince(Item item, AbstractInstant timestamp, String serviceId)
context.updatedSince = function(it, timestamp, serviceId) {
try {
var item = context.getItem(it);
return (serviceId == undefined) ? context.pe.updatedSince(item, timestamp) : context.pe.updatedSince(item, timestamp, serviceId);
}catch(err) {
context.logError("updatedSince "+__LINE__, err);
}
return null;
};
//
//HistoricItem maximumSince(Item item, AbstractInstant timestamp)
//HistoricItem maximumSince(final Item item, AbstractInstant timestamp, String serviceId)
context.maximumSince = function(it, timestamp, serviceId) {
try {
var item = context.getItem(it);
return (serviceId == undefined) ? context.pe.maximumSince(item, timestamp).state : context.pe.maximumSince(item, timestamp, serviceId).state;
}catch(err) {
context.logError("maximumSince "+__LINE__, err);
}
return null;
};
//
//HistoricItem minimumSince(Item item, AbstractInstant timestamp)
//HistoricItem minimumSince(final Item item, AbstractInstant timestamp, String serviceId)
context.minimumSince = function(it, timestamp, serviceId) {
try {
var item = context.getItem(it);
return (serviceId == undefined) ? context.pe.minimumSince(item, timestamp).state : context.pe.minimumSince(item, timestamp, serviceId).state;
}catch(err) {
context.logError("minimumSince "+__LINE__, err);
}
return null;
};
//
//DecimalType averageSince(Item item, AbstractInstant timestamp)
//DecimalType averageSince(Item item, AbstractInstant timestamp, String serviceId)
context.averageSince = function(it, timestamp, serviceId) {
try {
var item = context.getItem(it);
return (serviceId == undefined) ? context.pe.averageSince(item, timestamp) : context.pe.averageSince(item, timestamp, serviceId);
}catch(err) {
context.logError("averageSince "+__LINE__, err);
}
return null;
};
//
//DecimalType sumSince(Item item, AbstractInstant timestamp)
//DecimalType sumSince(Item item, AbstractInstant timestamp, String serviceId)
context.sumSince = function(it, timestamp, serviceId) {
try {
var item = context.getItem(it);
return (serviceId == undefined) ? context.pe.sumSince(item, timestamp) : context.pe.sumSince(item, timestamp, serviceId);
}catch(err) {
context.logError("sumSince "+__LINE__, err);
}
return null;
};
//
//AbstractInstant lastUpdate(Item item)
//AbstractInstant lastUpdate(Item item, String serviceId)
context.lastUpdate = function(it, serviceId) {
try {
var item = context.getItem(it);
return (serviceId == undefined) ? context.pe.lastUpdate(item) : context.pe.lastUpdate(item, serviceId);
}catch(err) {
context.logError("lastUpdate "+__LINE__, err);
}
return null;
};
//
//DecimalType deltaSince(Item item, AbstractInstant timestamp)
//DecimalType deltaSince(Item item, AbstractInstant timestamp, String serviceId)
context.deltaSince = function(it, timestamp, serviceId) {
try {
var item = context.getItem(it);
return (serviceId == undefined) ? context.pe.deltaSince(item, timestamp) : context.pe.deltaSince(item, timestamp, serviceId);
}catch(err) {
context.logError("deltaSince "+__LINE__, err);
}
return null;
};
//
//DecimalType evolutionRate(Item item, AbstractInstant timestamp)
//DecimalType evolutionRate(Item item, AbstractInstant timestamp, String serviceId)
context.evolutionRate = function(it, timestamp, serviceId) {
try {
var item = context.getItem(it);
return (serviceId == undefined) ? context.pe.evolutionRate(item, timestamp) : context.pe.evolutionRate(item, timestamp, serviceId);
}catch(err) {
context.logError("evolutionRate "+__LINE__, err);
}
return null;
};
//
//HistoricItem previousState(Item item)
//HistoricItem previousState(Item item, boolean skipEqual)
//HistoricItem previousState(Item item, boolean skipEqual, String serviceId)
context.previousState = function(it, skipEqual, serviceId) {
try {
skipEqual = skipEqual == undefined ? false : skipEqual;
var item = context.getItem(it);
return (serviceId == undefined) ? context.pe.previousState(item, skipEqual).state : context.pe.previousState(item, skipEqual, serviceId).state;
}catch(err) {
context.logError("previousState "+__LINE__, err);
}
return null;
};
})(this);
\ No newline at end of file
// trigger helper
// version 0.2
// ToSe
//
// to do's:
//
//
// param: group of item
// return: single ItemCommandTrigger array of items what are member of group in param
//
var ItemCommandTriggerGroup = function(groupName) {
var trigger = [];
getItem(groupName).getAllMembers().forEach(function(key) {
trigger.push(ItemCommandTrigger(key.getName()));
})
return trigger;
}
// param: group of item
// return: single ChangedEventTrigger array of items what are member of group in param
//
var ChangedEventTriggerGroup = function(groupName) {
var trigger = [];
getItem(groupName).getAllMembers().forEach(function(key) {
trigger.push(ChangedEventTrigger(key.getName()));
})
return trigger;
}
// param: dataset with trigger times in the follwoing format - hour:minute
//
// example of dataset: var example_timeSet = {
// "trigger1": "23:10",
// "nightStart": "23:04",
// "bedTime": "23:02",
// }
// one can define as much as nessesary trigger times
// the key is for human readability but it must be unique
//
var generateCronTriggerSet = function(triggerPreset) {
var cronTrigger = []
var triggerPresetKeys = Object.keys(triggerPreset)
if (triggerPresetKeys.length != 0 ) {
var triggerSet = []
triggerPresetKeys.forEach(function(key) { triggerSet.push(triggerPreset[key]) })
triggerSet.sort() // nessesary, else earlyer triggers will not resolved at first run
triggerSet.forEach(function(tS) {
var singleTrigger = tS.split(':')
// construct the cron expression
cronTrigger.push(TimerTrigger('0 ' + singleTrigger[1] + ' ' + singleTrigger[0] + ' * * ? *'))
})
}
return cronTrigger
}
// param: array of trigger
// each entry can be an array of triggers oder a sinle trigger
// return: single array of triggers
//
var aggregateTrigger = function(triggerArray) {
var trigger = []
if (triggerArray.length > 0) {
triggerArray.forEach(function(singleTrigger) {
if (Array.isArray(singleTrigger)) { // it's dosen't work the i push a complete array to trigger, so i must iterate over the array of triggers to add
singleTrigger.forEach(function(sTr) { trigger.push(sTr) })
} else {
trigger.push(singleTrigger)
}
})
}
return trigger
}
// trigger helper
// version 0.2
// ToSe
//
// to do's:
//
//
// param: group of item
// return: single ItemCommandTrigger array of items what are member of group in param
//
var ItemCommandTriggerGroup = function(groupName) {
var trigger = [];
getItem(groupName).getAllMembers().forEach(function(key) {
trigger.push(ItemCommandTrigger(key.getName()));
})
return trigger;
}
// param: group of item
// return: single ChangedEventTrigger array of items what are member of group in param
//
var ChangedEventTriggerGroup = function(groupName) {
var trigger = [];
getItem(groupName).getAllMembers().forEach(function(key) {
trigger.push(ChangedEventTrigger(key.getName()));
})
return trigger;
}
// param: dataset with trigger times in the follwoing format - hour:minute
//
// example of dataset: var example_timeSet = {
// "trigger1": "23:10",
// "nightStart": "23:04",
// "bedTime": "23:02",
// }
// one can define as much as nessesary trigger times
// the key is for human readability but it must be unique
//
var generateCronTriggerSet = function(triggerPreset) {
var cronTrigger = []
var triggerPresetKeys = Object.keys(triggerPreset)
if (triggerPresetKeys.length != 0 ) {
var triggerSet = []
triggerPresetKeys.forEach(function(key) { triggerSet.push(triggerPreset[key]) })
triggerSet.sort() // nessesary, else earlyer triggers will not resolved at first run
triggerSet.forEach(function(tS) {
var singleTrigger = tS.split(':')
// construct the cron expression
cronTrigger.push(TimerTrigger('0 ' + singleTrigger[1] + ' ' + singleTrigger[0] + ' * * ? *'))
})
}
return cronTrigger
}
// param: array of trigger
// each entry can be an array of triggers oder a sinle trigger
// return: single array of triggers
//
var aggregateTrigger = function(triggerArray) {
var trigger = []
if (triggerArray.length > 0) {
triggerArray.forEach(function(singleTrigger) {
if (Array.isArray(singleTrigger)) { // it's dosen't work the i push a complete array to trigger, so i must iterate over the array of triggers to add
singleTrigger.forEach(function(sTr) { trigger.push(sTr) })
} else {
trigger.push(singleTrigger)
}
})
}
return trigger
}
This diff is collapsed.
/**
* Copyright (c) 2018 by Helmut Lehmeyer.
*
* @author Helmut Lehmeyer
*/
'use strict';
se.importPreset("RuleSupport");
se.importPreset("RuleFactories");
// Get Triggers and Conditions module output
// http://localhost:8080/rest/module-types
// Examles:
// see: org.eclipse.smarthome.automation.sample.extension.java.internal.WelcomeHomeRulesProvider.createLightsRule()
if(HashSet == undefined)var HashSet = Java.type("java.util.HashSet");
if(Visibility ==