backward-compatibilty.js 26.95 KiB
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'); }