NEWS
IoBroker mit Warema WMS Web Control
-
@bender275 jap genau der gibt es auch für 255€ der ist noch nicht im latest aber bald
https://forum.iobroker.net/topic/45197/test-warema-wms-webcontroller-v0-0-1 -
@tombox
Puh, dann brauche ich ja noch den Stick für 50€...
Kann man das dann selbst alles (evtl. mit dem WMS Studio) anlernen, oder brauche ich Warema oder den Monteur dazu?Hat jemand nen Screenshot, wie die Werte von der Wetterstation dargestellt werden?
-
@bender275 kann selber angelernt werden gibt Videos. Keine Ahnung ob die Werte von einer Wetter Station übertragen
-
Hallo, hat jemand den WebSocket (warema-wms-venetian-blinds-ws-api) für Node.js im Einsatz? Ich würde diesen gerne nutzen, ohne iobroker zu installieren. Mein Warema WMS Stick wird korrekt erkannt. Die Daten wie PANID, Serial, wmsKey oder Channel sind vorhanden.
Hat jemand ein konkretes Beispiel für mich, wie ich z.B. mit CURL den Socket (Webservice) ansprechen kann, um Kommandos wie up, down, stop oder status zu senden/empfangen?
Auch würde gerne den Socket als Dienst auf einer Linux Maschine laufen lassen. Die Dokumentation der API ist sehr ausführlich, aber leider reichen meine Kenntnisse nicht aus, um ein praktisches Beispiel mittels CURL aufzusetzen.
Vielen Dank für nützliche Hinweise.
-
Hi.
Erstmal danke an alle die sich hier die Mühe machen und Laien wie mich unterstützen
Dann auch großes Dankeschön an alle die am Skript gearbeitet haben um Warema unter iobroker zum Laufen zu bringen. Hat die ganze Zeit tadellos funktioniert! Leider habe ich nun mein System auf die neuste Version gebracht und daher unbemerkt auch serialport V10 installiert.
Da die Version 10 ja "Breaking Changes" hat funktioniert das Skript nun nicht mehr
"Serialport is not a constructor"
Hat jemand ähnliche Probleme gehabt und vllt. schon das Skipt modifiziert? Ich kriege es leider nicht hin...btw -> Der Adapter für das Webcontrol Pro ist klasse, auch dafür vielen Dank! Leider kann ich damit nicht die Daten von meiner Wetterstation auslesen. Bringt mir also nicht sonderlich viel.
-
@schmoke ich stand gerade vor dem gleichen Problem. Nach Studie der Änderungsdoku von Serialport und meinen rudimentären Programmierkenntnissen in Javascript, habe ich es bei mir zum Laufen bekommen. Folgende Änderungen sind vorzunehmen:
var SerialPort = require('serialport');
ersetzen durch:
const {SerialPort} = require('serialport'); const {ReadlineParser} = require('@serialport/parser-readline');
const port = new SerialPort(PATH, { baudRate: 125000, parity: 'none', dataBits: 8, stopBits: 1, autoOpen: false, });
ersetzen durch
const port = new SerialPort({path:PATH, baudRate: 125000, autoOpen: false});
const parser = port.pipe(new SerialPort.parsers.Readline({delimiter: '}'}));
durch
const parser = port.pipe(new ReadlineParser({delimiter: '}'}));
Danach sollte es wieder funktionieren. Bei mir ist PATH als
const PATH = '/dev/ttyUSB0';
definiert.
An dieser Stelle vielen Dank an @willjoha und @Pman. Durch die beiden konnte ich erst iobroker in Kombination mit der wms Steuerung einsetzen. Super Job!
Henry
-
@henry9843
Es funktioniert!
Vielen Dank!!!!!!!!
Ihr rettet mir mein Wochenende! -
Habe das Update nun auch hinter mir und hinterlasse hier nochmal meine aktuelle Version des Skripts.
//updated for serialport 10.x const { SerialPort } = require('serialport'); const { ReadlineParser } = require('@serialport/parser-readline') const namespace = '0_userdata.0.Custom.WMS'; log('namespace: ' + namespace); //config const PATH = "/dev/ttyWMS"; const CHANNEL = 17; const PANID = "FFFF"; //inclusion mode: FFFF const KEY = "00112233445566778899AABBCCDDEEFF"; //inclusion mode: "00112233445566778899AABBCCDDEEFF" var positionInterval = 60; //how often current position is requested (seconds) var scanInterval = 10; //how often to scan for devices (seconds) var scanDevicesMax = 3; //stop scanning after discovering all devices //listPorts(); //uncomment to list all available serial ports /* do not edit below! */ //globals var knownDevices = {}; //stores known devices var lastData = ''; //contains last packet var writeQueue = []; //stores data to be sent to serial port var timers = {}; /* open serial port and setup parser */ function init() { //scan initially timers.scanInit = setTimeout(function () { wmsScan(); }, 5000); //scan again every scanInterval seconds timers.scan = setInterval(function () { wmsScan(); }, scanInterval * 1000); } //connect to serial port const port = new SerialPort({ path: PATH, baudRate: 125000, parity: 'none', dataBits: 8, stopBits: 1, autoOpen: false, }); //create parser with '}' as delemiter const parser = port.pipe(new ReadlineParser({ delimiter: '}' })) // handle serial port errors port.on('error', function () { log('serial port error!', 'warn'); closePort().then((msg) => { log(msg, 'info'); }).catch((err) => { log(err, 'warn'); }); }); //parse incomming packets parser.on('data', parseData); //open serial port portOpen().then((msg) => { log(msg); writeAndWaitFor('{G}', 'gWMS USB-Stick', true).then((line) => { return writeAndWaitFor('{V}', 'v', true); }).then((line) => { log('Stick Version: ' + line); return writeAndWaitFor(encodeWMS('setKey', {key: KEY}), 'a', true); }).then((line) => { return writeAndWaitFor(encodeWMS('switchChannel', { channel: CHANNEL, panId: PANID }), 'a', true); }).then((line) => { return writeAndWaitFor(encodeWMS('switchChannelRequest', { panId: PANID }), 'a', true); }).then((line) => { init(); }).catch((err) => { log(err, 'warn'); closePort().then((msg) => { log(msg, 'info'); }).catch((err) => { log(err, 'warn'); }); }); }).catch((err) => { log(err, 'warn'); }); /* serialport helper functions */ //opens port with promise function portOpen() { return new Promise((resolve, reject) => { port.open((err) => { err ? reject(err) : resolve('port opened'); }) }); } //close port if open function closePort() { return new Promise((resolve, reject) => { log('closing open serial ports', 'info'); clearInterval(timers.scan); if (port && port.isOpen) { // close connection port.close(() => { resolve('port closed') }); } else { reject('no port was opened'); } }); } //on script stop close port onStop(() => { clearInterval(timers.scan); //@todo clear all timers; closePort().then((msg) => { log(msg, 'info'); }).catch((err) => { log(err, 'warn'); }); }, 2000); //handle incomming data function parseData(data) { //trim data data = wmsTrim(data); //do nothing, if packet is received twice if (lastData === data) return lastData = data; log('received message: ' + data, 'debug'); //decode data into object var obj = decodeWMS(data); log('received: ' + JSON.stringify(obj), 'debug'); //process object setTimeout( () => processWMS(obj), 10); } //list available serial ports function listPorts() { SerialPort.list().then((ports) => { log('Serial Ports: ' + JSON.stringify(ports)); }).catch((err) => { log('error listing ports: ' + JSON.stringify(err)); }); } //write to serial port and wait for answer function writeAndWaitFor(data, expect, rejectOnTimeout, timeout) { return new Promise((resolve, reject) => { if (isNaN(timeout)) timeout = 5000; let listener = (line) => { log('listener received message: "' + wmsTrim(line) + '" / expected: "' + expect + '"', 'debug'); if (wmsTrim(line).substr(0, expect.length) === expect) { log('received expected answer: ' + expect, 'debug'); parser.removeListener('data', listener); resolve(wmsTrim(line)); } else { log('received unexpected answer (still waiting): ' + wmsTrim(line).substr(0, expect.length) + '!=' + expect, 'debug'); } }; parser.on('data', listener); enqueue(data); //remove listener after 5 seconds setTimeout(() => { parser.removeListener('data', listener); rejectOnTimeout ? reject(expect) : resolve(false); }, timeout); }); } var portReady = true; var sendInterval; function enqueue(data) { if (typeof data === 'string'){ writeQueue.push(data); } clearInterval(sendInterval); sendInterval = setInterval(sendData, 50); } function sendData() { if (writeQueue.length === 0 && portReady) { clearInterval(sendInterval); return; } if (portReady) { portReady = false; var sendData = writeQueue.shift(); log('sending ' + sendData, 'debug'); port.write(sendData); port.drain((err) => { portReady = true; }); } } /* WMS helper functions */ //trim wms string function wmsTrim(data) { return data.trim().substr(1); } //decode wms strings into an object function decodeWMS(packet) { var obj = {}; switch (packet.substr(0, 1)) { case 'g': obj.type = 'stickType'; obj.payload = {name: packet.substr(1)}; break; case 'v': obj.type = 'stickVersion'; obj.payload = {version: packet.substr(1)}; break; case 'f': obj.type = 'error'; break; case 'a': obj.type = 'ack'; break; case 'r': obj.type = 'message'; obj.payload = decodeWMSMessage(packet.substr(1)); break; default: obj.type = 'unknown'; obj.payload = packet.substr(1); } return obj; } //decode wms messages into an object function decodeWMSMessage(message) { var obj = {}; obj.src = message.substr(0, 6); var type = message.substr(6, 4); var payload = message.substr(10); switch (type) { case '5018': obj.type = 'joinNetworkRequest'; obj.messagePayload = { panId: payload.substr(0, 4), networkKey: payload.substr(4, 32).match(/../g).reverse().join(""), unknown: payload.substr(36, 2), channel: parseInt(payload.substr(38, 2), 16) }; break; case '5060': obj.type = 'switchChannelRequest'; obj.messagePayload = { panId: payload.substr(0, 4), deviceType: payload.substr(4, 2), channel: parseInt(payload.substr(6, 2), 16) }; break; case '50AC': obj.type = 'ack'; obj.messagePayload = { unknown: payload.substr(0, 4) }; break; case '7020': obj.type = 'scanRequest'; obj.messagePayload = { panId: payload.substr(0, 4), deviceType: payload.substr(4, 2) }; break; case '7021': obj.type = 'scanResponse'; obj.messagePayload = { panId: payload.substr(0, 4), deviceType: payload.substr(4, 2), //63: wetterstation, 06: webcontrol, 02: stick/software, 20: zwischenstecker, 00: Handsender unknown: payload.substr(6) //optional }; break; case '7080': obj.type = 'weatherBroadcast'; obj.messagePayload = { unknown_1: payload.substr(0, 2), wind: parseInt(payload.substr(2, 2), 16), lumen: payload.substr(4, 2) === '00' ? parseInt(payload.substr(12, 2), 16) * 2 : parseInt(payload.substr(4, 2), 16) * parseInt(payload.substr(12, 2), 16) * 2, unknown_2: payload.substr(6, 6), unknown_3: payload.substr(14, 2), rain: payload.substr(16, 2) === 'C8', temp: parseInt(payload.substr(18, 2), 16) / 2 - 35, unknown_4: payload.substr(20) }; break; case '7050': obj.type = 'beckonRequest'; break; case '7070': obj.type = 'controlRequest'; obj.messagePayload = { unknown: payload.substr(0, 2), position: parseInt(payload.substr(2, 2), 16) / 2, angle: parseInt(payload.substr(4, 2), 16) - 127, valance_1: payload.substr(6, 2), valance_2: payload.substr(8, 2) }; break; case '7071': obj.type = 'controlResponse'; obj.messagePayload = payload; break; case '8010': obj.type = 'parameterGetRequest'; obj.messagePayload = { parameter: payload.substr(0) //01000005: position, 26000046: clock timer settings, 0C000006: auto modes & limits }; break; case '8011': obj.type = 'parameterGetResponse'; obj.messagePayload = { parameter: payload.substr(0, 8) }; switch (obj.messagePayload.parameter) { case '01000003': //position case '01000005': //position obj.messagePayload.type = 'position'; obj.messagePayload.position = parseInt(payload.substr(8, 2), 16) / 2; obj.messagePayload.angle = parseInt(payload.substr(10, 2), 16) - 127; obj.messagePayload.valance_1 = payload.substr(12, 2); obj.messagePayload.valance_2 = payload.substr(14, 2); break; case '0C000006': //auto modes & limits obj.messagePayload.type = 'autoSettings'; obj.messagePayload.wind = parseInt(payload.substr(8, 2), 16); obj.messagePayload.rain = parseInt(payload.substr(10, 2), 16); obj.messagePayload.sun = parseInt(payload.substr(12, 2), 16); obj.messagePayload.dusk = parseInt(payload.substr(14, 2), 16); obj.messagePayload.op = parseInt(payload.substr(16, 2), 16); break; case '26000046': obj.messagePayload.type = 'clock'; obj.messagePayload.unknown = payload.substr(8); break; default: obj.messagePayload.type = 'unknown'; obj.messagePayload.unknown = payload.substr(8); } break; case '8020': obj.type = 'parameterSetRequest'; obj.messagePayload = { parameter: payload.substr(0, 8) }; switch (obj.messagePayload.parameter) { case '0B080009': obj.messagePayload.type = 'clock'; obj.messagePayload.year = parseInt(payload.substr(8, 2), 16); obj.messagePayload.month = parseInt(payload.substr(10, 2), 16); obj.messagePayload.day = parseInt(payload.substr(12, 2), 16); obj.messagePayload.hour = parseInt(payload.substr(14, 2), 16); obj.messagePayload.minute = parseInt(payload.substr(16, 2), 16); obj.messagePayload.second = parseInt(payload.substr(18, 2), 16); obj.messagePayload.day_of_week = parseInt(payload.substr(20, 2), 16); obj.messagePayload.unknown = payload.substr(22); break; default: obj.messagePayload.type = 'unknown'; obj.messagePayload.unknown = payload.substr(8); } break; default: obj.type = 'unknown'; obj.messagePayload = payload; } return obj; } //create wms strings function encodeWMS(type, parameter) { log('encoding: ' + type + ' with parameters ' + JSON.stringify(parameter), 'debug'); if (!parameter) parameter = {}; switch (type) { case 'setKey': if (!parameter.key) return false; return '{K401' + parameter.key + '}'; break; case 'setScanMode': if (isNaN(parameter.channel) || !parameter.panId) return false; return '{M#' + parameter.channel + parameter.panId.match(/../g).reverse().join("") + '}'; break; case 'switchChannel': if (isNaN(parameter.channel) || !parameter.panId) return false; return '{M%' + parameter.channel + parameter.panId + '}'; break; case 'ack': if (!parameter.dst) return false; return '{R21' + parameter.dst + '50AC}'; break; case 'switchChannelRequest': //channel 17 fixed if (!parameter.panId) return false; return '{R04FFFFFF5060' + parameter.panId + '021100}'; // dst or FFFFFF??? break; case 'scanRequest': return '{R04FFFFFF7020' + parameter.panId + '02}'; break; case 'scanResponse': if (!parameter.panId || !parameter.dst || !parameter.deviceType) return false; return '{R01' + parameter.dst + '7021' + parameter.panId + parameter.deviceType + (parameter.payload ? parameter.payload : '') + '}'; //fixed to deviceType 02 for now break; case 'beckonRequest': if (!parameter.dst) return false; return '{R06' + parameter.dst + '7050}'; break; case 'controlRequest': if (!parameter.dst || isNaN(parameter.position) || isNaN(parameter.angle)) return false; return '{R06' + parameter.dst + '7070' + '03' + ('0' + (Math.min(Math.max(parameter.position, 0), 100) * 2).toString(16)).substr(-2).toUpperCase() + ('0' + (Math.min(Math.max(parameter.angle, 0), 90) + 127).toString(16)).substr(-2).toUpperCase() + 'FFFF}'; //no idea how valance works break; case 'parameterGetRequest': if (!parameter.dst || !parameter.parameter) return false; return '{R06' + parameter.dst + '8010' + parameter.parameter + '}'; break; case 'parameterGetRequestPosition': if (!parameter.dst) return false; return '{R06' + parameter.dst + '8010' + '01000005}'; break; case 'parameterGetRequestClock': if (!parameter.dst) return false; return '{R06' + parameter.dst + '8010' + '26000046}'; break; case 'parameterGetRequestAutoSettings': if (!parameter.dst) return false; return '{R06' + parameter.dst + '8010' + '0C000006}'; break; case 'parameterSetRequestAutoSettings': if (!parameter.dst || !parameter.parameter || isNaN(parameter.wind) || isNaN(parameter.rain) || isNaN(parameter.sun) || isNaN(parameter.dusk)) return false; return '{R06' + parameter.dst + '8020' + '0D000004' + ('0' + Math.min(Math.max(parameter.wind, 0), 9).toString(16)).substr(-2).toUpperCase() + ('0' + Math.min(Math.max(parameter.rain, 0), 9).toString(16)).substr(-2).toUpperCase() + ('0' + Math.min(Math.max(parameter.sun, 0), 9).toString(16)).substr(-2).toUpperCase() + ('0' + Math.min(Math.max(parameter.dusk, 0), 9).toString(16)).substr(-2).toUpperCase() + (parameter.op ? '01' : '00') + '}'; break; case 'parameterSetRequestAutoAll': if (!parameter.dst) return false; return '{R06' + parameter.dst + '8020' + '0D040001' + (parameter.op ? '01' : '00') + '}'; break; default: //unkown message type return false; break; } } //process packets function processWMS(obj) { //log(JSON.stringify(obj)); if (obj.type !== 'message') return; switch (obj.payload.type) { case 'switchChannelRequest': log('received switchChannelRequest, switching channel to ' + obj.payload.messagePayload.channel, 'debug'); writeAndWaitFor(encodeWMS('switchChannel', { channel: obj.payload.messagePayload.channel, panId: PANID }), 'a'); break; case 'scanRequest': // send scanResponse log('received scanRequest, sending scanResponse', 'debug'); writeAndWaitFor(encodeWMS('scanResponse', {dst: obj.payload.src, panId: PANID, deviceType: '20', payload: '8FFF03000000000000000000000201010000000000000000'}), 'a'); break; case 'joinNetworkRequest': log('received joinNetworkRequest:', 'debug'); log('KEY: ' + obj.payload.messagePayload.networkKey); log('CHANNEL: ' + obj.payload.messagePayload.channel); log('PANID: ' + obj.payload.messagePayload.panId); writeAndWaitFor(encodeWMS('ack', {dst: obj.payload.src}), 'a'); break; case 'scanResponse': log('received scanResponse', 'debug'); log('TYPE: ' + obj.payload.messagePayload.deviceType, 'debug'); log('SNR:' + obj.payload.src, 'debug'); if (obj.payload.messagePayload.deviceType === '20') { let src = '' + obj.payload.src.trim(); if (knownDevices[src] === true) { //log('skipping device: ' + src); return; }; knownDevices[src] = true; log('device type 20 found: ' + src); scanDevicesMax--; if (scanDevicesMax === 0) { clearInterval(timers.scan); log ('stop scanning for devices'); } //log('creating state: ' + namespace + '.Raffstore.' + src + '.position'); createState(namespace + '.Raffstore.' + src + '.position', 0, { type: 'number', min: 0, max: 100, unit: '%' }); //log('creating state: ' + namespace + '.Raffstore.' + src + '.angle'); createState(namespace + '.Raffstore.' + src + '.angle', 0, { type: 'number', min: 0, max: 90, unit: '°' }, function () { var deviceId = namespace + '.Raffstore.' + src; on({id: deviceId + '.position', change: 'ne', ack: false}, function (obj) { //send parameter writeAndWaitFor( encodeWMS('controlRequest', { dst: src, position: obj.state.val, angle: getState(deviceId + '.angle').val }), 'r' + src + '7071' ).then(() => { clearInterval(timers[deviceId + 'parameterGetRequestPosition']); var lastValueAngle = -1; var lastValuePosition = -1; var noChange = 0; writeAndWaitFor(encodeWMS('parameterGetRequestPosition', {dst: src}), 'a'); timers[deviceId + 'parameterGetRequestPosition'] = setInterval(function () { //get parameter periodically until no change is detected log(getState(deviceId + '.position').val + ':' + lastValuePosition + ' | ' + getState(deviceId + '.angle').val + ':' + lastValueAngle, 'info') if (getState(deviceId + '.position').val === lastValuePosition && getState(deviceId + '.angle').val === lastValueAngle) { noChange++; if (noChange === 2) { clearInterval(timers[deviceId + 'parameterGetRequestPosition']); } } else { noChange = 0; } lastValuePosition = getState(deviceId + '.position').val; lastValueAngle = getState(deviceId + '.angle').val; writeAndWaitFor(encodeWMS('parameterGetRequestPosition', {dst: src}), 'a'); }, 5000 + Math.random() * 1000); //setState(deviceId + '.position', getState(deviceId + '.position').val, true); }); }); on({id: deviceId + '.angle', change: 'ne', ack: false}, function (obj) { //send parameter writeAndWaitFor(encodeWMS('controlRequest', { dst: src, position: getState(deviceId + '.position').val, angle: obj.state.val }), 'r' + src + '7071' ).then(() => { clearInterval(timers[deviceId + 'parameterGetRequestPosition']); var lastValueAngle = -1; var lastValuePosition = -1; var noChange = 0; writeAndWaitFor(encodeWMS('parameterGetRequestPosition', {dst: src}), 'a'); timers[deviceId + 'parameterGetRequestPosition'] = setInterval(function () { //get parameter periodically until no change is detected log(getState(deviceId + '.position').val + ':' + lastValuePosition + ' | ' + getState(deviceId + '.angle').val + ':' + lastValueAngle, 'info'); if (getState(deviceId + '.position').val === lastValuePosition && getState(deviceId + '.angle').val === lastValueAngle) { noChange++; if (noChange === 2) { clearInterval(timers[deviceId + 'parameterGetRequestPosition']); } } else { noChange = 0; } lastValuePosition = getState(deviceId + '.position').val; lastValueAngle = getState(deviceId + '.angle').val; writeAndWaitFor(encodeWMS('parameterGetRequestPosition', {dst: src}), 'a'); }, 3500 + Math.random() * 1000); //setState(deviceId + '.angle', getState(deviceId + '.angle').val, true); }); }); setTimeout(function () { //get parameter once writeAndWaitFor(encodeWMS('parameterGetRequestPosition', {dst: src}), 'a'); }, 5000 + Math.random() * 5000); setInterval(function () { //get parameter periodicaly writeAndWaitFor(encodeWMS('parameterGetRequestPosition', {dst: src}), 'a'); }, positionInterval * 1000 + Math.random() * 5000); }); } break; case 'parameterGetResponse': log('received parameterGetResponse', 'debug'); switch (obj.payload.messagePayload.type) { case 'position': setStateDelayed(namespace + '.Raffstore.' + obj.payload.src + '.position', obj.payload.messagePayload.position, true, 100, true); setStateDelayed(namespace + '.Raffstore.' + obj.payload.src + '.angle', obj.payload.messagePayload.angle, true, 100, true); default: break; } break; case 'weatherBroadcast': log('received weatherBroadcast', 'debug'); let src = '' + obj.payload.src.trim(); createState(namespace + '.Wetter.' + src + '.temp', 0, { type: 'number', unit: '°C', write: false }, function () { setStateDelayed(namespace + '.Wetter.' + src + '.temp', obj.payload.messagePayload.temp, true, 100, true); }); createState(namespace + '.Wetter.' + src + '.wind', 0, { type: 'number', min: 0, unit: 'm/s', write: false }, function () { setStateDelayed(namespace + '.Wetter.' + src + '.wind', obj.payload.messagePayload.wind, true, 100, true); }); createState(namespace + '.Wetter.' + src + '.lux', 0, { type: 'number', min: 0, unit: 'lux', write: false }, function () { setStateDelayed(namespace + '.Wetter.' + src + '.lux', obj.payload.messagePayload.lumen, true, 100, true); }); createState(namespace + '.Wetter.' + src + '.rain', false, { type: 'boolean', write: false }, function () { setStateDelayed(namespace + '.Wetter.' + src + '.rain', obj.payload.messagePayload.rain, true, 100, true); }); break; case 'beckonRequest': writeAndWaitFor(encodeWMS('ack', {dst: obj.payload.src}), 'a'); break; case 'controlRequest': writeAndWaitFor(encodeWMS('ack', {dst: obj.payload.src}), 'a'); break; default: break; } } //scan for devices function wmsScan() { log('scanning for devices'); writeAndWaitFor(encodeWMS('scanRequest', {panId: PANID}), 'a'); }
-
Hallo zusammen,
Vielen Dank euch allen für's Reverse-Engineering, Coding und Testing!
Wer von euch hat schonmal über den WMS-Stick die Wetterdaten aus einer Wetterstation ausgelesen? Welche genaue Wetterstation verwendet ihr da?
Klappt das mit der WMS Wetterstation eco oder plus oder welche sollte ich am Besten anschaffen?Vielen Dank und viele Grüße,
Toby -
Hello, is the maintaner of warema-wms-venetian-blinds on NPM reading this thread? While I know I can see it and reverse-engineer it from the node_modules folder, Is it possible for this person to put the code on GitHub, so that we can collaborate on it?
I have Warema blinds and a weather station at home, as well as the WMS stick and a webcontrol pro, and I became fairly proficient with WMS Studio, so I can help test the integrations and provide bugfixes!
-
@marco-santarelli sagte in IoBroker mit Warema WMS Web Control:
Hello, is the maintaner of warema-wms-venetian-blinds on NPM reading this thread? While I know I can see it and reverse-engineer it from the node_modules folder, Is it possible for this person to put the code on GitHub, so that we can collaborate on it?
I have Warema blinds and a weather station at home, as well as the WMS stick and a webcontrol pro, and I became fairly proficient with WMS Studio, so I can help test the integrations and provide bugfixes!
Hi Marco, did you get any response? I am also interested in further development.
-
@marc-berg No response, i reverse-engineered the code from the npm package and modified it myself. You can see how I use it at https://github.com/santam85/addon-warema-wms/tree/main
-
Yes, that's how I did it too. A fork of your repo and some customisations for my devices. I'm happy with that now.
-
Had been using Tombox' adapter working with the Webcontrol pro for a while. However it suddenly stopped working some time ago. Does someone still have it running with pro?