Hallo zusammen,
vielen Dank an loehrj1 und gemuesepudding für die Bereitstellung des Skriptes! Hat mir wirklich sehr geholfen.
Bei dem letzten Stand wurden die aktuellen Zustände nicht richtig abgefragt, da anscheinend die Verwendung der IDs und Bezeichnungen etwas durcheinander geraten ist. Ich habe es nochmal für meine Bedürfnisse angepasst. Die Gruppen habe ich bei mir aktuell nicht benötigt und daher hier erst mal rausgelassen. Mit dieser Version funktioniert zumindest bei mir die Statusabfrage (ist-Wert).
Ich habe außerdem noch eine Stopp-Funktion verwendet, die alle laufenden Aktivitäten anhält.
'use strict' ;
// Netzwerk
const Ip = '192.168.178.43'
const Passwort = '******' // WLAN Passwort
const baseObjectPath = 'javascript.1.Velux.'
var Rollos = [];
class Rollo {
constructor(name, nodeId, isVal, targetVal, group) {
this.name = name;
this.nodeId = nodeId;
this.isVal = isVal;
this.targetVal = targetVal;
}
}
Rollos.push(new Rollo('Eingang' , 0, 100, 100));
Rollos.push(new Rollo('EsszimmerLinks' , 1, 100, 100));
Rollos.push(new Rollo('EsszimmerRechts' , 2, 100, 100));
// // Gruppen. All, SZ, .. are then names of states. Add new properties for more groups
// const groups = {
// All : Object.values(Rollos), // all IDs of shutters
// TODO...
// }
for(let shutter of Rollos) {
createState(baseObjectPath + 'shutter.' + shutter.name + '.soll', 0, { name: 'shutter ' + shutter.name + '.soll', type: 'number', min: 0, max: 100, unit: '%'})
createState(baseObjectPath + 'shutter.' + shutter.name + '.ist' , 0, { name: 'shutter ' + shutter.name + '.ist', type: 'number', min: 0, max: 100, unit: '%'})
}
// for(let key of Object.keys(groups)) {
// createState(baseObjectPath + 'groups.' + key, 0, { name: 'group ' + key, type: 'number', min: 0, max: 100, unit: '%'})
// }
const Up = 0 // Rollo oben
const Down = 0xc800 // Rollo unten
const Stop = 0xD200 // Stopkommando
// Variable
var velux = require('velux-klf200-api')
var Connected = false
let Commands = {}
let shutterNodeIdsAll = Rollos.map(a => a.nodeId);
const MaxNodeIdx = shutterNodeIdsAll.length; // 5 Rollos..
var SessionId = 0
function SetCurrentPos(nodeId, val)
{
var rollo = Rollos.filter(r => {return r.nodeId == nodeId})[0]
if(rollo)
{
rollo.isVal = val;
setState(baseObjectPath + 'shutter.' + rollo.name + '.ist', rollo.isVal, true)
}
}
// Zustand der Rollos holen
function GetState(shuttterIds, sessionId)
{
if (Connected) {
shuttterIds = shuttterIds || shutterNodeIdsAll
log('checking shutters ' + JSON.stringify(shuttterIds), 'debug')
velux.sendCommand({
api: velux.API.GW_STATUS_REQUEST_REQ,
sessionID: sessionId || 0,
indexArrayCount: shuttterIds.length,
indexArray : shuttterIds,
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
if ( (StatusType === 3) &&
(Index >= 0) &&
(Index < MaxNodeIdx))
{
SetCurrentPos(data.index, Current)
}
}
// Callback Ende Job
velux.on('GW_SESSION_FINISHED_NTF', JobFinished);
function JobFinished(data) {
log("EndCmd (" + data.sessionID+')', 'debug')
let sessionKey = 'session_' + data.sessionID
if (typeof Commands[sessionKey] !== 'undefined') {
// get state after job finished
GetState(Commands[sessionKey].shuttterIds, data.sessionID)
delete Commands[sessionKey]
}
}
// Verbindung aufbauen
function ConnectKlf() {
if (! Connected) {
Connected = true;
velux.connect( Ip, {} ).then(()=>{
velux.login( Passwort ).then(()=>{
log("Klf connected!", 'info')
Connected = true
GetState();
})
})
.catch((err)=>{
log('connect error ' + JSON.stringify(err), 'error')
Connected = false
velux.end()
})
}
}
function MoveShutter( shutterIds, Val) {
if ( Connected )
{
return velux.sendCommand({ api: velux.API.GW_COMMAND_SEND_REQ,
sessionID : ++SessionId,
commandOriginator: 1,
priorityLevel: 2,
parameterActive: 1,
functionalParameterMP: {rawValue : Val},
indexArrayCount: shutterIds.length,
indexArray : shutterIds,
priorityLevelLock: false,
}).then((data)=>{
log("StartCmd (" + data.sessionID+')', 'debug')
Commands['session_' + data.sessionID] = {
shuttterIds : shutterIds
}
})
.catch((err)=>{
log(err, 'error')
})
}
}
// 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
log('Connection lost...' +JSON.stringify(err), 'error')
ConnectKlf()
})
});
// Verbinden zu klf200
ConnectKlf()
// Verbindung abbauen und aufraeumen bei Stop
onStop(() => {
Connected = false
log("Disconnect", 'info')
velux.off('GW_STATUS_REQUEST_NTF', Status)
velux.off('GW_SESSION_FINISHED_NTF', JobFinished)
velux.end()
});
on({id: new RegExp(baseObjectPath.replace('.', '\.') + 'shutter\..*\.soll'), change:'any', ack: false}, function (obj) {
let State = Down - Down / 100 * obj.state.val
let shutterName = obj.id.split('.').slice(-2)[0]
let shutterId = Rollos.filter(r => {return r.name == shutterName})[0].nodeId
log('Moving shutter ' + shutterName + '(' + shutterId + ')' + ' to ' + obj.state.val + '%', 'info')
MoveShutter([shutterId], State)
});
on('javascript.1.Velux.Stop', function (obj) {
MoveShutter(shutterNodeIdsAll, Stop);
});