An error occurred while loading the file. Please try again.
-
roman.koehler authored
- add persistent scope
71baeaf2
var lWarn = {logln:function (o){}};
var lInfo = {logln:function (o){}};
var lInfoFILE_NAME = "sr-config.log";
lWarn = new Logger(lInfoFILE_NAME);
//lInfo = new Logger(lInfoFILE_NAME);
function storeSubParameter(path, value) {
Property.setProperty('entries/' + path, value);
Property.setFlag('entries/' + path, 'ARCHIVE', true);
}
function getNewIdValue() {
var idValue = 0;
var baseNode = Property.getNode('entries');
if (baseNode == null) {
return idValue;
}
var oArrayNode = baseNode.getChildren();
for ( var iIndex = 0; iIndex < oArrayNode.length; iIndex++) {
var oChildNode = oArrayNode[iIndex];
if (oChildNode.getChild('id') != null) {
if (oChildNode.getChild('id').getValue() != null) {
if (parseInt("" + oChildNode.getChild('id').getValue(), 10) >= idValue) {
idValue = parseInt("" + oChildNode.getChild('id').getValue(), 10) + 1;
}
}
}
}
return idValue;
}
function isPropertyTreeNotCurrent(currentVersionString, compareVersionString) {
var curVersion = currentVersionString.split('.'),
comVersion = compareVersionString.split('.');
for (var i=0; i < curVersion.length; i++) {
if ((i < comVersion.length) &&
(parseInt(curVersion[i], 10) < parseInt(comVersion[i], 10))) {
return true;
}
}
return false;
}
function convertOldTriggers() {
var ndTriggers = Property.getNode('triggers');
if (!ndTriggers) {
return;
}
var triggers = ndTriggers.getChildren();
var i;
for (i = 0; i < triggers.length; ++i) {
var ndOldParams = triggers[i].getChild('params'),
oldParams,
oldTrigger,
oldActions;
if (!ndOldParams) {
lInfo.logln('Error: no old params found to convert on trigger ' + triggers[i].name);
deleteOldTrigger(triggers[i]);
continue;
}
try {
// lInfo.logln('Debug: old params: ' + ndOldParams.getValue());
oldParams = JSON.parse(ndOldParams.getValue());
// lInfo.logln('Debug: old trigger: ' + decodeURIComponent(oldParams.trigger));
oldTrigger = JSON.parse(oldParams.trigger);
// lInfo.logln('Debug: old actions: ' + decodeURIComponent(oldParams.actions));
oldActions = JSON.parse(oldParams.actions);
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
} catch (e) {
lInfo.logln('Deleting old trigger '+ triggers[i].name +': failed to parse');
deleteOldTrigger(triggers[i]);
continue;
}
//
// validity checks
//
if (!oldTrigger
|| isNaN(oldTrigger.scene)
|| isNaN(oldTrigger.zone)
// allowed to be unset in very old versions (< 0.1.4)
|| (oldTrigger.group && isNaN(oldTrigger.group))
) {
// delete invalid triggers
lInfo.logln('Deleting old trigger '+ triggers[i].name +': missing trigger');
deleteOldTrigger(triggers[i]);
continue;
}
if (!validScene(oldTrigger.scene)) {
lInfo.logln('Deleting old trigger '+ triggers[i].name +': scene ' + oldTrigger.scene +' is not supported by this version');
deleteOldTrigger(triggers[i]);
continue;
}
if (!oldActions
|| !oldActions.actions
|| !(oldActions.actions.length > 0)
) {
// delete invalid triggers
lInfo.logln('Deleting old trigger '+ triggers[i].name +': missing actions');
deleteOldTrigger(triggers[i]);
continue;
}
oldActions = oldActions.actions;
//
// Conversions
//
// new params object
var params = {
name: triggers[i].name, // or oldParams.name
disabled: false, // there existed no possibility to disable an action
scene: parseInt(oldTrigger.scene, 10),
zone: parseInt(oldTrigger.zone, 10)
};
// Convert delay
if (oldParams.duration === undefined) {
params.delay = 0;
} else if (isNaN(oldParams.duration)) {
lInfo.logln('Warning: invalid delay on trigger '+ triggers[i].name +', assuming 0');
params.delay = 0;
} else {
params.delay = 60 * parseInt(oldParams.duration, 10);
}
// Convert trigger group
if (isNaN(oldTrigger.group)) {
lInfo.logln('Warning: no trigger group is set on '+ triggers[i].name +': defaulting to group 1 (Lights)');
params.group = 1;
} else {
params.group = parseInt(oldTrigger.group, 10);
}
// Convert old actions
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
params.actions = [];
var a;
for (a = 0; a < oldActions.length; ++a) {
var p = {};
if (isNaN(oldActions[a].zone)
|| (isNaN(oldActions[a].scene) && isNaN(oldActions[a].value))
|| (oldActions[a].group && isNaN(oldActions[a].group))
|| (!isNaN(oldActions[a].value)
&& (oldActions[a].value < 0 || oldActions[a].value > 255))
) {
lInfo.logln('Error: no or invalid action set on trigger '+ triggers[i].name +' action at index '+ a +'. Skipping');
continue;
}
p.zone = parseInt(oldActions[a].zone, 10);
if (oldActions[a].group === undefined) {
lInfo.logln('Warning: no group is set on '+ triggers[i].name +' action at index '+ a +', defaulting to group 1 (Lights)');
p.group = 1;
} else {
p.group = parseInt(oldActions[a].group, 10);
}
if (oldActions[a].scene !== undefined) {
if (!validScene(oldActions[a].scene)) {
lInfo.logln('Warning unsupported scene '
+ oldActions[a].scene +' call from action '+ a
+' on '+ triggers[i].name +': skipping');
continue;
}
p.scene = parseInt(oldActions[a].scene, 10);
} else if (oldActions[a].value !== undefined) {
p.outputValue = parseInt(oldActions[a].value, 10);
}
params.actions.push(p);
}
if (params.actions.length === 0) {
lInfo.logln('Error: no valid actions on trigger '+ triggers[i].name +': deleting');
deleteOldTrigger(triggers[i]);
continue;
}
// store converted trigger
deleteOldTrigger(triggers[i]);
addTrigger(params);
lInfo.logln('Converted trigger '+ params.idname);
}
Property.store();
} // convertOldTriggers
/**
* Check if a scene is supported by this scene responder version
* @param s {Number} Scene id to check
* @return {Boolean} True if supported, false if unsupported
*/
function validScene(s) {
if ((s >= 10 && s <= 16) || (s >= 32 && s <= 63) || s >= 74) {
return false;
}
return true;
}
/**
* Returns an unused unique identifier (id)
* @return {String} A unique string
*/
function getId() {
var ndTriggers = Property.getNode('triggers'),
triggers,
max = 0;
if (ndTriggers) {
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
triggers = ndTriggers.getChildren();
while (ndTriggers.getChild(max.toString())) {
++max;
}
return max.toString();
} else {
return "0";
}
}
/**
* Checks if parameters conform to what is expected
* @param triggerParams {Object} Object to check
* @return {Object} Conform object or null on error
*/
function checkParams(triggerParams) {
if (!triggerParams.name) {
lInfo.logln('Error: trigger has no name');
return null;
}
if (!triggerParams.actions || triggerParams.actions.length === 0) {
lInfo.logln('Error: trigger has no actions');
return null;
}
var actions = [];
var i;
for (i = 0; i < triggerParams.actions.length; ++i) {
var a = triggerParams.actions[i];
if (!a.device && isNaN(a.group)) { // isNan(undefined) === true
lInfo.logln('Error: no or invalid group or device defined as target on action ' + i);
return null;
}
if (a.blink === undefined && a.scene === undefined && a.outputValue === undefined) {
lInfo.logln('Error: no action defined at index ' + i);
return null;
}
if (
(a.scene !== undefined && isNaN(a.scene))
|| (a.group !== undefined && isNaN(a.group))
|| (a.outputValue !== undefined && (
isNaN(a.outputValue) || a.outputValue < 0 || a.outputValue > 255
))
) {
lInfo.logln('Error: invalid action defined at index ' + i);
return null;
}
var action = {};
if (a.zone !== undefined) {
action.zone = parseInt(a.zone, 10);
}
if (a.group !== undefined) {
action.group = parseInt(a.group, 10);
}
if (a.device !== undefined) {
action.device = a.device;
}
if (a.blink) {
action.blink = true;
}
if (a.scene !== undefined) {
action.scene = parseInt(a.scene, 10);
}
if (a.outputValue !== undefined) {
action.outputValue = parseInt(a.outputValue, 10);
}
actions.push(action);
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
}
if (isNaN(triggerParams.delay)) {
lInfo.logln('Warning: invalid delay on action ' + i +' assuming 0');
triggerParams.delay = 0;
}
if (isNaN(triggerParams.scene)
|| isNaN(triggerParams.group)
|| isNaN(triggerParams.zone)
) {
lInfo.logln('Error: invalid trigger on action ' + i);
return null;
}
// create the valid params object
var params = {
name: triggerParams.name,
delay: parseInt(triggerParams.delay, 10),
scene: parseInt(triggerParams.scene, 10),
group: parseInt(triggerParams.group, 10),
zone: parseInt(triggerParams.zone, 10),
disabled: !!triggerParams.disabled,
actions: actions
};
// add id, idname fields if they were supplied
if (triggerParams.id) {
params.id = triggerParams.id;
params.idname = params.id + ' (' + params.name + ')';
}
return params;
} // checkParams
/**
* Updates a node if it exists or creates a new archived property node otherwise
* @param path {String} Relative path
* @param value {String|Boolean|Integer} Value to set
*/
function updateOrCreateNode(path, value) {
var nd = Property.getNode(path);
if (nd) {
nd.setValue(value);
} else {
createNode(path, value);
}
}
/**
* Creates a new archived property node with given value
* @param path {String} Relative path
* @param value {String|Boolean|Integer} Value to set
* @return {Object} The newly created node
*/
function createNode(path, value) {
var nd = new Property(path);
if (value !== undefined) {
nd.setValue(value);
}
nd.setFlag('ARCHIVE', true);
return nd;
}
/**
* Stores _VALID_ parameters into the property tree.
* Use checkParams(params) to validate them first!
* Make sure to call Property.store() after calling this method
* @param params {Object} Object to store
* @return {Object} The trigger node
*/
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
function storeParams(params) {
var triggerPath = 'triggers/' + params.id;
var actionPath = triggerPath + '/actions';
var i, c;
var ndTrigger = Property.getNode(triggerPath) || createNode(triggerPath);
updateOrCreateNode(triggerPath + '/id', params.id);
updateOrCreateNode(triggerPath + '/name', params.name);
updateOrCreateNode(triggerPath + '/delay', params.delay);
updateOrCreateNode(triggerPath + '/disabled', !!params.disabled);
updateOrCreateNode(triggerPath + '/scene', params.scene);
updateOrCreateNode(triggerPath + '/group', params.group);
updateOrCreateNode(triggerPath + '/zone', params.zone);
// actions
var ndActions = ndTrigger.getChild('actions');
if (ndActions) {
// clean out actions, as indices might not match up
ndTrigger.removeChild(ndActions);
}
ndActions = createNode(actionPath);
// populate actions
for (i = 0; i < params.actions.length; ++i) {
var p = actionPath + '/' + i;
createNode(p);
if (params.actions[i].zone !== undefined) {
createNode(p + '/zone', params.actions[i].zone);
}
if (params.actions[i].group !== undefined) {
createNode(p + '/group', params.actions[i].group);
}
if (params.actions[i].device) {
createNode(p + '/device', params.actions[i].device);
}
if (params.actions[i].blink) {
createNode(p + '/blink', true);
}
if (params.actions[i].scene !== undefined) {
createNode(p + '/scene', params.actions[i].scene);
}
if (params.actions[i].outputValue !== undefined) {
createNode(p + '/outputValue', params.actions[i].outputValue);
}
}
return ndTrigger;
} // storeParams
/**
* Add a new trigger
* @param params {Object} The new trigger is created from these parameters
*/
function addTrigger(triggerParams) {
// check triggerParams and set params for serialization
var params = checkParams(triggerParams),
// tmpId is used to communicate the id of the newly created trigger
// to the client. Since there is no way to specify a return value
// for an event, the client will be able to specify a temporary id
// tmpId and poll for that id. When it's created, it'll contain the
// definitive id of the created trigger.
// The client is charged with deleting this node
tmpId;
if (params) {
if (params.id === undefined || params.id.substr(0, 3) === 'tmp') {
if (params.id !== undefined) {
tmpId = params.id;
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
}
params.id = getId();
params.idname = params.id + ' (' + params.name + ')';
}
storeParams(params);
if (tmpId !== undefined) {
var evt = new Event('system-addon-scene-responder.create.' + tmpId, { id: params.id });
evt.raise();
}
Property.store();
}
}
/**
* Deletes an old (and converted but not saved) trigger from the property tree
*/
function deleteOldTrigger(ndTrigger) {
ndTrigger.getParent().removeChild(ndTrigger);
Property.store();
}
function updateData() {
var baseNodes = Property.getNode('triggers');
var fMigrate=false;
lInfo.logln("UpdateDataStart");
if (baseNodes != null) {
fMigrate=true;
var fError=false;
var oBaseArray=baseNodes.getChildren();
for ( var iIndex = 0; iIndex < oBaseArray.length; iIndex++) {
lInfo.logln("found #" + iIndex);
var oNewID=getNewIdValue();
lInfo.logln("using id " + oNewID);
try
{
var oTriggerNode=oBaseArray[iIndex];
var sName = Utf8.encode(unescape(oTriggerNode.getChild('name').getValue()));
lInfo.logln("Name: " + sName);
var fDisabled=oTriggerNode.getChild('disabled').getValue();
lInfo.logln("fDisabled: " + fDisabled);
storeSubParameter(oNewID + '/name', sName);
storeSubParameter(oNewID + '/id', oNewID);
storeSubParameter(oNewID + '/conditions/enabled', (fDisabled == true? false : true));
if (oTriggerNode.getChild('delay')!=null) {
var iDelay=oTriggerNode.getChild('delay').getValue();
lInfo.logln("iDelay: " + iDelay);
storeSubParameter(oNewID + '/delay', iDelay);
}
var triggerScene=oTriggerNode.getChild('scene').getValue();
var triggerGroup=oTriggerNode.getChild('group').getValue();
var triggerZone=oTriggerNode.getChild('zone').getValue();
lInfo.logln("Triggering on : " + triggerZone + " " + triggerGroup + " " + triggerScene);
if (triggerZone == 0) {
lInfo.logln("Trigger-zone is 0 -> setting to -1");
triggerZone = -1;
}
if (triggerScene == 65 || (triggerScene >= 71 && triggerScene <= 73)) {
triggerGroup = 0;
triggerZone = 0;
lInfo.logln("Trigger-scene is Panik, Kommen, Gehen or Klingel -> force setting group and zone to 0");
} else if (triggerScene >= 64) {
triggerGroup = 0;
lInfo.logln("Trigger-scene is apartment scene -> force setting group to 0");
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
}
var sSubpath=oNewID + '/triggers/0/';
storeSubParameter(sSubpath + "type" ,'zone-scene');
storeSubParameter(sSubpath + "zone" , triggerZone);
storeSubParameter(sSubpath + "group" , triggerGroup);
storeSubParameter(sSubpath + "scene" , triggerScene);
storeSubParameter(sSubpath + "dsid" , -1);
var oActionNodes=oTriggerNode.getChild('actions').getChildren();
for (var jIndex=0;jIndex<oActionNodes.length;jIndex++) {
var oActionNode=oActionNodes[jIndex];
if (oActionNode.getChild('device')!=null) {
//device calls
if (oActionNode.getChild('blink')!=null) {
lInfo.logln("Action #" + jIndex + " on : " + oActionNode.getChild('device').getValue() + " blink");
storeSubParameter(oNewID + '/actions/' + jIndex + '/type', 'device-blink');
storeSubParameter(oNewID + '/actions/' + jIndex + '/dsid', oActionNode.getChild('device').getValue());
} else if (oActionNode.getChild('outputValue')!=null) {
lInfo.logln("Action #" + jIndex + " on : " + oActionNode.getChild('device').getValue() + " outvalue " + oActionNode.getChild('outputValue').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/type', 'device-value');
storeSubParameter(oNewID + '/actions/' + jIndex + '/dsid', oActionNode.getChild('device').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/value', oActionNode.getChild('outputValue').getValue());
} else if (oActionNode.getChild('scene')!=null){
lInfo.logln("Action #" + jIndex + " on : " + oActionNode.getChild('device').getValue() + " scene " +oActionNode.getChild('scene').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/type', 'device-scene');
storeSubParameter(oNewID + '/actions/' + jIndex + '/dsid', oActionNode.getChild('device').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/scene', oActionNode.getChild('scene').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/force', false);
}
} else {
// zone calls
if (oActionNode.getChild('blink')!=null) {
lInfo.logln("Action #" + jIndex + " on : " + oActionNode.getChild('zone').getValue() + " " + oActionNode.getChild('group').getValue() + " blink");
storeSubParameter(oNewID + '/actions/' + jIndex + '/type', 'zone-blink');
storeSubParameter(oNewID + '/actions/' + jIndex + '/zone', oActionNode.getChild('zone').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/group', oActionNode.getChild('group').getValue());
} else if (oActionNode.getChild('outputValue')!=null) {
lInfo.logln("Action #" + jIndex + " on : " + oActionNode.getChild('zone').getValue() + " " + oActionNode.getChild('group').getValue() + " outvalue " + oActionNode.getChild('outputValue').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/type', 'zone-value');
storeSubParameter(oNewID + '/actions/' + jIndex + '/zone', oActionNode.getChild('zone').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/group', oActionNode.getChild('group').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/value', oActionNode.getChild('outputValue').getValue());
} else if (oActionNode.getChild('scene')!=null){
lInfo.logln("Action #" + jIndex + " on : " + oActionNode.getChild('zone').getValue() + " " + oActionNode.getChild('group').getValue() + " scene " +oActionNode.getChild('scene').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/type', 'zone-scene');
storeSubParameter(oNewID + '/actions/' + jIndex + '/zone', oActionNode.getChild('zone').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/group', oActionNode.getChild('group').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/scene', oActionNode.getChild('scene').getValue());
storeSubParameter(oNewID + '/actions/' + jIndex + '/force', false);
}
}
}
lInfo.logln("done. Delete old Node " + oTriggerNode.getPath());
baseNodes.removeChild(oTriggerNode);
}
catch (e)
{
lWarn.logln("Fehler beim Datenupgrade " + e);
if (Property.getNode('entries')!=null) {
Property.getNode('entries').removeChild(oNewID);
}
fError=true;
}
}
if (!fError) {
lInfo.logln("All done. Delete old Node");
Property.getNode('/scripts/system-addon-scene-responder').removeChild('triggers');
}
}
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
// patch the "evt" - node to "eventid" if possible
lInfo.logln('Checke nach evt-nodes');
var basePropertyArray = Property.getNode('entries');
if (basePropertyArray!=null) {
var subPropArray = basePropertyArray.getChildren();
for ( var iIndex = 0; iIndex < subPropArray.length; iIndex++) {
lInfo.logln('values found ' + iIndex);
if (subPropArray[iIndex].getChild('triggers')!=null) {
var triggerArray = subPropArray[iIndex].getChild('triggers').getChildren();
if (triggerArray!=null) {
lInfo.logln('trigger found ' + iIndex);
for ( var jIndex = 0; jIndex < triggerArray.length; jIndex++) {
if (triggerArray[jIndex].getChild('type')!=null)
if (triggerArray[jIndex].getChild('type').getValue()=="device-sensor") {
lInfo.logln('trigger sensor found ' + iIndex);
if (triggerArray[jIndex].getChild('evt')!=null) {
var sEVT=triggerArray[jIndex].getChild('evt').getValue();
var sDSID=triggerArray[jIndex].getChild('dsid').getValue();
lInfo.logln('device ' + sDSID + ' ' + sEVT);
var oEventArray=Property.getNode('/apartment/zones/zone0/devices/' + sDSID + '/sensorEvents').getChildren();
if (oEventArray!=null) {
for (var kIndex=0;kIndex<oEventArray.length;kIndex++) {
if (oEventArray[kIndex].getValue()==sEVT) {
lInfo.logln('device found : id ' +oEventArray[kIndex].name);
Property.setProperty(triggerArray[jIndex].getPath()+'/eventid',oEventArray[kIndex].name);
Property.setFlag(triggerArray[jIndex].getPath()+'/eventid','ARCHIVE',true);
triggerArray[jIndex].removeChild('evt');
fMigrate=true;
}
}
}
}
}
}
}
}
}
}
if (fMigrate)
Property.store();
else
lInfo.logln('nothing to update');
}
function updateScope() {
// adding scope variable
var fMigrate=false;
lInfo.logln('Checke nach system-addon-scene-responder - scope');
var basePropertyArray = Property.getNode('entries');
if (basePropertyArray!=null) {
var subPropArray = basePropertyArray.getChildren();
for ( var iIndex = 0; iIndex < subPropArray.length; iIndex++) {
lInfo.logln('values found ' + iIndex);
if (subPropArray[iIndex].getChild('scope')==null) {
fMigrate=true;
Property.setProperty(subPropArray[iIndex].getPath()+'/scope','system-addon-scene-responder');
Property.setFlag(subPropArray[iIndex].getPath()+'/scope','ARCHIVE',true);
}
}
}
if (fMigrate)
Property.store();
else
lInfo.logln('nothing to update - scope');
}
631632633634635636637638639640641642643644645646647648649650651652653654
function updatePersistentScope() {
// adding scope variable
var fMigrate=false;
lInfo.logln('Checke nach system-addon-scene-responder - scope');
var basePropertyArray = Property.getNode('entries');
if (basePropertyArray!=null) {
var subPropArray = basePropertyArray.getChildren();
for ( var iIndex = 0; iIndex < subPropArray.length; iIndex++) {
lInfo.logln('values found ' + iIndex);
if (subPropArray[iIndex].getChild('persistentScope')==null) {
fMigrate=true;
Property.setProperty(subPropArray[iIndex].getPath()+'/persistentScope',true);
Property.setFlag(subPropArray[iIndex].getPath()+'/persistentScope','ARCHIVE',true);
}
}
}
if (fMigrate)
Property.store();
else
lInfo.logln('nothing to update - scope');
}