Hi,
ich habe mir ein Script gebastelt mit JS-Adapter. Das funktioniert sehr gut und man kann darüber einfach Schalter in Homekit anlegen und z.b. die Garage öffnen. Läuft hier seit über einem Jahr einwandfrei. Ab und zu muss der Adapater/Host neu gestartet werden, weil der Host aus irgendwelchen Gründen dann den Client nicht mehr kennt.
Datenpunkte anlegen
Dann braucht ihr nur noch ein kleines Script, dass die Werte open, close, stop, lighton, lightoff in den dp_cmd schreibt.
DeviceName muss so sein, wie Eure Garage in Eurer App heißt!!
Wie gesagt, läuft hier sehr zuverlässig.
// wenns nicht geht - IP-Adresse Garage prüfen
// Benötigt mqtt -wenns nicht geht - IP-Adresse Garage prüfen
//
//
var net = require('net');
var dp_door = "0_userdata.0.Garage.Garage_Status_Tor"; //door state
var dp_light = "0_userdata.0.Garage.Garage_Status_Licht"; //light state
var dp_cmd = "0_userdata.0.Garage.Garage_Command2"; //Befehlsdatenpunkt: Mögliche Werte: open, close, stop, lighton, lightoff. Nach Beschreiben wird der Datenpunkt wieder auf leer gesetzt
var deviceName = "GARAGENNAME";
var host = "IP_ADRESSE";
var port = 2785;
// random client, weil nach Stromausfall das Script nicht mehr lief, erst als anderer Client angegeben wurde.
let x = Math.floor((Math.random() * 30) + 1);
var client=x.toString; // Client mit übergeben
function startClient() {
client = new net.Socket(); // Erzeugen eines neuen Verbindungsobjekts
client.connect(port, host, function() { // Gerät über host:port anwählen und Verbindung erzeugen
console.log('cliend started');
});
client.on('data', function(data) { // Wenn daten ankommen, dann verarbeiten
console.log('client received: ' + data + " for device: " + deviceName);
var dataS = data.toString().trim(); // Datenbuffer in lesbaren Text umwandeln
switch(dataS) { // je nach rückgabewert unterschiedliche Bearbeitung
case "S;"+deviceName+";open": // wenn open
setState(dp_door,"open",false); // dann Datenpunkt setzen
setState(dp_door,"open",true); // dann Datenpunkt setzen
// Garagentür ebenfalls öffnen
setState('alias.0.Garage.Garagentuer'/*Garagentuer auf zu*/, true)
console.log("Script Garage: "+dataS,"info");
break;
case "S;"+deviceName+";closed":
setState(dp_door,"closed",false);
setState(dp_door,"closed",true);
// Garagentür ebenfalls schließen
setState('alias.0.Garage.Garagentuer'/*Garagentuer auf zu*/, false)
console.log("Script Garage: "+dataS,"info");
break;
case "S;"+deviceName+";opening":
setState(dp_door,"opening",false);
setState(dp_door,"opening",true);
console.log("Script Garage: "+dataS,"info");
break;
case "S;"+deviceName+";closing":
setState(dp_door,"closing",false);
setState(dp_door,"closing",true);
console.log("Script Garage: "+dataS,"info");
break;
case "S;"+deviceName+";lightOn":
setState(dp_light,"lightOn",false);
setState(dp_light,"lightOn",true);
console.log("Script Garage: "+dataS,"info");
break;
case "S;"+deviceName+";lightOff":
setState(dp_light,"lightOff",false);
setState(dp_light,"lightOff",true);
console.log("Script Garage: "+dataS,"info");
break;
}
});
client.on("error",(err)=>{ // wenn ein Fehler entsteht
console.log("client error " + err.toString());
});
client.on("timeout",()=>{ // wenn timeout entsteht
console.log("client timeout");
});
}
function sendMessage(host, port, message) {
return new Promise((resolve, reject) => { // Funktion ist asynchron, daher Rückgabe promise
if (!client) {
console.log("No Client available :"+x);
resolve("Error");
return;
}
client.write(message);
resolve("OK");
});
}
onStop (function(){
/* do something when script is stopped */
if (client) {
console.log('client ended ');
client.end();
}
}, 1000);
startClient();
on(dp_cmd, function (obj) { // trigger wenn datenpunkt beschrieben wird
var cmd;
if (obj.state.ack || !obj.state.ack) { // aber nur wenn es sich um einen unbestätigten wert handelt
cmd = String(obj.state.val).toLowerCase(); // Datenpunktinhalt in Kleinbuchstaben umwandeln
console.log('execute command: ' + cmd);
switch(cmd) { // je nach Datenpunktinhalt verschiedene Befehle
case "open": // wenn open
sendMessage(host, port, "C;"+deviceName+";open"); // dann richtigen Befehl an Gerät senden
break;
case "close":
sendMessage(host, port, "C;"+deviceName+";close");
break;
case "stop":
sendMessage(host, port, "C;"+deviceName+";stop");
break;
case "lighton":
sendMessage(host, port, "C;"+deviceName+";lightOn");
break;
case "lightoff":
sendMessage(host, port, "C;"+deviceName+";lightOff");
break;
}
setState(obj.id, {val: "", ack: false}); // datenpunkt auf leer als bestätigt setzen
}
});