Nach einigen Änderungen nun umgestellt auf eine Javascript-Klasse, dadurch deutlich leichter zu verwenden und als Vorlage tauglich:
Script für Wechselschaltung mit beliebig vielen Schaltern, Tastern, & Aktoren:
// Ich benutze virtuelle Schalter (Datenpunkte) um z.B. VIS-Seiten aufzubauen, weil ich so
// bei einem Austausch physischer Komponenten (Anderer Hersteller/Name etc.) nicht die
// VIS-Visualisierung und Scripte anpassen muß
//
// Die sonoff-Touch-Schalter schalten die LED's der Touch-Schaltflächen ein, wenn das zugehörige Relais an ist.
// Ich invertiere den Schaltzustand der sonoff-Touch-Schalter, damit die LED der jew. Touch-Schaltfläche
// leuchtet, wenn die zu schaltende Lampe aus ist (so findet man sie im Dunkeln).
// Abspeichern der Javascript-Instanz in Konstante, um in den
// Event-Scubscriptions zu prüfen, woher der Aufruf kommt und
// so Ping/Pong zu vermeiden ( CreditsTo: @paul53 )
const js = 'system.adapter.javascript.' + instance;
class VirtualMultiSwitch {
constructor (idVirtualSwitch='',msDelay=100) {
this.aPowr = new Array(); // zu schaltende Aktoren
this.aNorm = new Array(); // normale Schalter
this.aInvt = new Array(); // zu invertierende Schalter
this.aBttn = new Array(); // auslösende Tatser
this.VirtS = idVirtualSwitch;
this.Counter = 0;
this.Delay = msDelay;
}
incS() { this.Counter +=1; }
decS() { this.Counter -=1; }
addP(Name){ this.aPowr = this.aPowr.concat(Name); }
addN(Name){ this.aNorm = this.aNorm.concat(Name); }
addI(Name){ this.aInvt = this.aInvt.concat(Name); }
addB(Name){ this.aBttn = this.aBttn.concat(Name); }
doSwitchPhysical(obj){
if (this.Counter <= 1){
this.Counter +=1;
setState(this.VirtS,(this.aBttn.indexOf(obj.id )>=0 ? !getState(this.VirtS).val : this.aNorm.indexOf(obj.id)>=0 ? obj.state.val : !obj.state.val));
setTimeout(()=>this.decS(), this.Delay);
}
}
doSwitchVirtual(obj){
if (this.Counter <= 1){
this.Counter +=1;
this.aNorm.forEach(function (TargetId,idx) {setState(TargetId, obj.state.val);});
this.aInvt.forEach(function (TargetId,idx) {setState(TargetId, !obj.state.val);});
this.aPowr.forEach(function (TargetId,idx) {setState(TargetId, obj.state.val);});
setTimeout(()=>this.decS(), this.Delay);
}
}
Start() {
on ({id:this.aNorm, change:"ne", ack: true , fromNe: js}, (obj) =>this.doSwitchPhysical(obj));
on ({id:this.aInvt, change:"ne", ack: true , fromNe: js}, (obj) =>this.doSwitchPhysical(obj));
on ({id:this.aBttn, change:"ne", ack: true , fromNe: js}, (obj) =>this.doSwitchPhysical(obj));
on ({id:this.VirtS, change:"ne" }, (obj) =>this.doSwitchVirtual(obj));
}
Stop() {
unsubscribe(this.aNorm);
unsubscribe(this.aInvt);
unsubscribe(this.aBttn);
unsubscribe(this.VirtS);
}
}
// WechselSchalter01:
var WS01 = new VirtualMultiSwitch('javascript.0.virtualDevice.Schalter.Eins.POWER');
WS01.addP('sonoff.0.Shelly01.Switch.Power' ); // z.B. ein Shelly 1, der die eigentliche Lampe schaltet
WS01.addN('hm-rega.0.1111' ); // HomeMatic, realisiert mit CCU-Systemvariable,
// die in CCU durch Funkschalter getoggelt wird
// und in ioBroker als "hmRega.0.XYZ" auftaucht
WS01.addI('sonoff.0.T1_Touch_01.POWER1' ); // die zu invertierenden Schalter hinzufügen
WS01.addB('hm-rpc.0.ABCDEFGH.1.PRESS_SHORT' ); // ein Hommatic-Funkstaster
WS01.Start();
// WechselSchalter02 (ohne Kommentare viel kürzer)
var WS02 = new VirtualMultiSwitch('javascript.0.virtualDevice.Schalter.Zwei.POWER');
WS02.addP('sonoff.0.Lampe02.POWER' );
WS02.addN('hm-rega.0.2222' );
WS02.addI('sonoff.0.T1_Touch_03.POWER2' );
WS02.Start();
// WechselSchalter03 - schaltet eine ganze Reihe von Aktoren (=Szene)
var WS03 = new VirtualMultiSwitch('javascript.0.virtualDevice.Schalter.Drei.POWER');
WS03.addP('sonoff.0.S4Pro_01.POWER1' );
WS03.addP('sonoff.0.S4Pro_01.POWER2' );
WS03.addP('sonoff.0.S4Pro_01.POWER3' );
WS03.addP('sonoff.0.S4Pro_02.POWER1' );
WS03.addP('sonoff.0.XYZ.POWER' );
WS03.addP('javascript.0.virtualDevice.Schalter.Eins.POWER'); // ja, auch der 1. Virtuelle Schalter wird mitgeschaltet
WS03.addN('hm-rega.0.3333' ); // dafür nur ein auslösender Schalter ...
WS03.Start();
Danke allen Inspirateuren ( insbesondere @Asgothian & @paul53 )!