Hallo Alex,
ich steuere aktuell 5 Solarroladen (Az..., Sz, Wz...) über dieses Script in Verbindung mit der KLF-200 API.
Die Ansteuerung der einzelnen Rolladen erfolgt über die Logitech Harmony und über Apple Homekit.
Eine kurze Beschreibung der verwendeten Funktionen:
function ConnectKlf()
Aufbau der Vebindung zum KLF200
function Rollo( Num, Val)
Ansteuerung der Rolladen. Num ist NodeId des zu steuernden Rollos. Num entspricht einem Wert zwischen 0 und 0xc700, 0xD200 entspricht dem Wert für Stop
function GetState()
Holt den Öffnungswert aller 5 Rolladen. Verwende ich zyklisch als Idle-Telegramm zur Aufrechterhaltung der Verbindung
function Status(data)
Callbackfunktion zur Auswertung der Öffnungswerte der Rolladen aus data.parameterData[0].parameter (Highbyte) und data.parameterData[0].parameterValue (Lowbyte)
function JobFinished(data)
Callback fuer Ende der Befehlsausfuehrung
onStop(function skriptStop () {....
Beenden des scripts mit Verbindungsabbau und Aufräumen
schedule('/1 * * * ', function () {...
Lebenszeichentelegramm und Statusabfrage jede Minute
*schedule('5 23 * * ', function () {....
Reboot des KLF200 einmal am Tag
Viele Grüße
Jürgen
Hier das Script:
'use strict' ;
// Netzwerk
const Ip = '192.168.178.5'
const Passwort = '0123456789' // WLAN Passwort
// nodeIDs der einzelnen Rollos
const AzWest = 0 // nodeId Arbeitzimmer Fenster Westseite
const AzOst = 1 // nodeId Arbeitzimmer Fenster Ostseite
const SzSued = 2 // nodeId Schlafzimmer Fenster Suedseite
const WzSued = 3 // nodeId Wohnzimmer Fenster Suedseite
const WzNord = 4 // nodeId Wohnzimmer Fenster Nordseite
const MaxNodeIdx = 5; // 5 Rollos..
const Z = ["AzWest","AzOst","Sz","WzSued","WzNord"] // Name fuer Zuugriff azf Statevariable
// Gruppen
const All = 5 // Alles Dachrolladen
const Wz = 6 // Wohnzimmer
const Az = 7 // Arbeitszimmer
const Sz = 2 // Schlafzimmer
const Up = 0 // Rollo oben
const Down = 0xc800 // Rollo unten
const Stop = 0xD200 // Stopkommando
// Variable
var velux = require('velux-klf200-api')
var Connected = false
var SessionId = 1
// Zustand der 5 Rollos holen
function GetState()
{
velux.sendCommand({ api: velux.API.GW_STATUS_REQUEST_REQ,
sessionID: 0,
indexArrayCount: 5,
indexArray : [AzOst, AzWest, SzSued, WzSued, WzNord],
statusType : 3 // Main Info
})
}
// Callback fuer Positionsrueckmeldung
velux.on('GW_STATUS_REQUEST_NTF', Status)
function Status(data)
{
var Target = Math.round(100 - data.targetPosition.value)
var Current = Math.round(100 - data.currentPosition.value) // aktuelle Position
var Time = data.remainingTime // Restlaufzeit
var Index = data.index // Node index
var StatusType = data.statusType // Status Typ "Main Info" = 3 erwartet
// console.log(JSON.stringify(data))
console.log(Z[data.index] + ',Ziel:' +Target + ' Aktuell:' + data.currentPosition.value + ' Restlaufzeit:' + Time)
if ( (StatusType == 3) &&
(Time == 0) &&
(Index >= 0) &&
(Index < MaxNodeIdx))
{
var IdStr = "javascript.0.Var.DG.Dach.Soll." + Z[data.index]
var IdStrIst = "javascript.0.Var.DG.Dach.Ist." + Z[data.index]
setState(IdStr, Current)
setState(IdStrIst, Current)
}
}
// Callback Ende Job
velux.on('GW_SESSION_FINISHED_NTF',JobFinished)
function JobFinished(data){
if ( SessionId == data.sessionID ) // Ende letztes Kommando
{
console.log("EndCmd (" + SessionId+')')
GetState() // bei Befehlsende Position der fenster abfragen
}
}
// Verbindung aufbauen
function ConnectKlf() {
if (! Connected)
{
Connected = true;
velux.connect( Ip, {} )
.then(()=>{
velux.login( Passwort ).then(()=>{
sendMsg("KLF: Connected")
console.log("Klf connected!")
Connected = true
GetState();
})
})
.catch((err)=>{
console.log(err)
Connected = false
velux.end()
})
}
}
// Rollos ansteuern
var Rollos = [0,1,2,3,4]
var Count = 5
function Rollo( Num, Val) {
if ( Connected )
{
if (Num == All)
{
Rollos[0] = WzSued
Rollos[1] = WzNord
Rollos[2] = AzOst
Rollos[3] = AzWest
Rollos[4] = SzSued
Count = 5
}
else if (Num == Wz)
{
Rollos[0] = WzSued
Rollos[1] = WzNord
Count = 2
}
else if (Num == Az)
{
Rollos[0] = AzOst
Rollos[1] = AzWest
Count = 2
}
else
{
Rollos[0] = Num
Count = 1
}
return velux.sendCommand({ api: velux.API.GW_COMMAND_SEND_REQ,
sessionID : ++SessionId,
commandOriginator: 1,
priorityLevel: 2,
parameterActive: 1,
functionalParameterMP: {rawValue : Val},
indexArrayCount: Count,
indexArray : [Rollos[0], Rollos[1], Rollos[2], Rollos[3], Rollos[4]] ,
priorityLevelLock: false,
})
.then((data)=>{
console.log("StartCmd (" + data.sessionID+')')
})
.catch((err)=>{
console.log(err)
})
}
}
// Restart einmal pro Tag um 22 Uhr
schedule('5 20 * * *', function () {
velux.sendCommand({ api: velux.API.GW_REBOOT_REQ})
Connected = false
});
// zyklisches Senden Idle Telegramm und Rolladenstatus holen
schedule('*/1 * * * *', function () {
velux.sendCommand({ api: velux.API.GW_GET_STATE_REQ})
.then((data)=>{
Connected = true
GetState() // Rolladenpostionen holen
})
.catch((err)=>{
Connected = false
sendMsg("KLF: Connection lost")
console.log("Connection lost...")
ConnectKlf()
})
});
// Verbinden zu klf200
ConnectKlf()
// Verbindung abbauen und aufraeumen bei Stop
onStop(function skriptStop () {
Connected = false
console.log("Disconnect")
velux.off('GW_STATUS_REQUEST_NTF', Status)
velux.off('GW_SESSION_FINISHED_NTF',JobFinished)
velux.end()
});
//*******************************************************************************
// Befehle aus Homekit
//*******************************************************************************
on({id: 'javascript.0.Var.DG.Dach.Alle', change: 'ne' }, function (obj) {
var State = Down - Down / 100 * obj.state.val
Rollo(All, State)
});
on({id: 'javascript.0.Var.DG.Dach.Soll.WzSued', change: 'ne'}, function (obj) {
var State = Down - Down / 100 * obj.state.val
Rollo(WzSued, State)
});
on({id: 'javascript.0.Var.DG.Dach.Soll.WzNord', change: 'ne' }, function (obj) {
var State = Down - Down / 100 * obj.state.val
Rollo(WzNord, State)
});
on({id: 'javascript.0.Var.DG.Dach.Soll.AzOst', change: 'ne' }, function (obj) {
var State = Down - Down / 100 * obj.state.val
Rollo(AzOst, State)
});
on({id: 'javascript.0.Var.DG.Dach.Soll.AzWest', change: 'ne' }, function (obj) {
var State = Down - Down / 100 * obj.state.val
Rollo(AzWest, State)
});
on({id: 'javascript.0.Var.DG.Dach.Soll.Sz', change: 'ne' }, function (obj) {
var State = Down - Down / 100 * obj.state.val
Rollo(Sz, State)
});
//*******************************************************************************
// Mapping fuer Logitech Harmony
//*******************************************************************************
// Dach zu
subscribe({id: 'fakeroku.0.Rolladen.keys.Left', val : true, ack :true}, function (obj) {
Rollo(Wz, Down)
});
// Dach auf
subscribe({id: 'fakeroku.0.Rolladen.keys.Down', val : true, ack :true}, function (obj) {
Rollo(Wz, Up)
});
// Dach Stop
subscribe({id: 'fakeroku.0.Rolladen.keys.Info', val : true, ack :true}, function (obj) {
Rollo(Wz, Stop)
});
// Alles zu
subscribe({id: 'fakeroku.0.Rolladen.keys.Home', change :'ne', ack :true}, function (obj) {
Rollo(Wz, Down)
setStateDelayed("hm-rpc.1.OEQ1312460.1.LEVEL", 0, 100, true)
setStateDelayed('hm-rpc.1.KEQ0157348.1.LEVEL', 0, 100, true)
});