Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. ioBroker Allgemein
    4. IoBroker mit Warema WMS Web Control

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    IoBroker mit Warema WMS Web Control

    This topic has been deleted. Only users with topic management privileges can see it.
    • T
      tombox @Bender275 last edited by

      @bender275 Meine Empfehlung ist das die WebControl zu verkaufen und gegen eine WebControl Pro zu tauschen aber zum neu programmieren brauchst du dein WMS Stick. Für die Pro gibt es dann ein Adapter

      B 1 Reply Last reply Reply Quote 0
      • B
        Bender275 @tombox last edited by Bender275

        @tombox Ich habe noch gar keine Web Control - d.h. ich brauche die WebControl Pro und den Stick?
        Ist das die hier?
        https://www.ams-elektro.com/Installationsmaterial/Sonstiges-Installationsmaterial/Tor-Rollladenantriebe-Pumpen-Ventilatoren/Zubehoer-fuer-Tor-Rollladenantriebe/Warema-WMS-WebControl-pro-2020920::2135778.html?MODsid=aqarmdqdap0i1banptufro7vjk

        Wie würde der Adapter heißen? Ich finde gerade nix mit WMS oder Warema.

        T 1 Reply Last reply Reply Quote 0
        • T
          tombox @Bender275 last edited by

          @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

          B 1 Reply Last reply Reply Quote 0
          • B
            Bender275 @tombox last edited by

            @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?

            T 1 Reply Last reply Reply Quote 0
            • T
              tombox @Bender275 last edited by

              @bender275 kann selber angelernt werden gibt Videos. Keine Ahnung ob die Werte von einer Wetter Station übertragen

              1 Reply Last reply Reply Quote 0
              • 9
                9ukj88 @radiorichter last edited by

                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. 🙂

                1 Reply Last reply Reply Quote 0
                • S
                  Schmoke last edited by

                  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.

                  H 1 Reply Last reply Reply Quote 0
                  • H
                    Henry9843 @Schmoke last edited by Henry9843

                    @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

                    S 1 Reply Last reply Reply Quote 0
                    • S
                      Schmoke @Henry9843 last edited by

                      @henry9843
                      Es funktioniert!
                      Vielen Dank!!!!!!!!
                      Ihr rettet mir mein Wochenende!

                      1 Reply Last reply Reply Quote 0
                      • P
                        Pman last edited by

                        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');   
                        }
                        
                        
                        
                        1 Reply Last reply Reply Quote 0
                        • T
                          Toby 1 last edited by

                          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

                          1 Reply Last reply Reply Quote 0
                          • Marco Santarelli
                            Marco Santarelli last edited by Marco Santarelli

                            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!

                            1 Reply Last reply Reply Quote 0
                            • Marc Berg
                              Marc Berg Most Active last edited by

                              @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.

                              Marco Santarelli 1 Reply Last reply Reply Quote 0
                              • Marco Santarelli
                                Marco Santarelli @Marc Berg last edited by

                                @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

                                Marc Berg 1 Reply Last reply Reply Quote 0
                                • Marc Berg
                                  Marc Berg Most Active @Marco Santarelli last edited by

                                  @marco-santarelli

                                  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.

                                  https://github.com/Marc-Berg/wms2mqtt

                                  P 1 Reply Last reply Reply Quote 0
                                  • T
                                    tweefo last edited by

                                    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?

                                    1 Reply Last reply Reply Quote 0
                                    • P
                                      PatrickR @Marc Berg last edited by

                                      @marc-berg
                                      Entschuldige bitte mein Anfängerfrage

                                      Dein "wms2mqtt" auf Github, sollte dies auch auf HA laufen?
                                      Ich frage, weil ich die Fehlermeldung beim hinzufügen erhalte, dass es kein gültiges Repository wäre,
                                      was ggf. an der fehlenden "repository.json" liegt.

                                      Danke schon mal
                                      Patrick

                                      Marc Berg 1 Reply Last reply Reply Quote 0
                                      • Marc Berg
                                        Marc Berg Most Active @PatrickR last edited by

                                        @patrickr sagte in IoBroker mit Warema WMS Web Control:

                                        Dein "wms2mqtt" auf Github, sollte dies auch auf HA laufen?

                                        Mein Ziel war es, das Image um meine zusätzlichen Gerätetypen zu erweitern und unter einer Docker Umgebung laufen zu lassen. Deshalb habe ich alle HA-Funktionalitäten entfernt, um den Code schlank zu halten.

                                        Wenn dir die Geräte reichen, die @Marco-Santarelli drin hat, solltest du sein Image nehmen.

                                        P 1 Reply Last reply Reply Quote 0
                                        • P
                                          PatrickR @Marc Berg last edited by PatrickR

                                          @marc-berg
                                          Danke für Deine schnelle RM.

                                          Ich hab auch 63, 2A, daher bin ich auf Dein Resp gestossen.

                                          Hab gerade erst die Chat-Funktion gefunden (what a shame)
                                          Ich chatte Dich mal an, vermutlich interessiert meine Frage die wenigsten da HA.

                                          Patrick

                                          Marc Berg 1 Reply Last reply Reply Quote 0
                                          • Marc Berg
                                            Marc Berg Most Active @PatrickR last edited by

                                            @patrickr sagte in IoBroker mit Warema WMS Web Control:

                                            vermutlich interessiert meine Frage die wenigsten da HA.

                                            Um ganz ehrlich zu sein: Mich interessiert HA auch nicht. Deshalb kann ich diesbezüglich auch keinen Support leisten.

                                            Wenn du dir selbst was zusammenstricken möchtest, dann musst du neben der index.js auch die Module unter addon-warema-wms/warema-bridge/srv/warema-wms-venetian-blinds anpassen, denn diese übernehmen die eigentliche Kommunikation mit dem WMS Netzwerk. Wegen der von mir entfernen HA-Funktionalität kannst du die Dateien aber nicht 1:1 ersetzen.

                                            P 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            Support us

                                            ioBroker
                                            Community Adapters
                                            Donate
                                            FAQ Cloud / IOT
                                            HowTo: Node.js-Update
                                            HowTo: Backup/Restore
                                            Downloads
                                            BLOG

                                            906
                                            Online

                                            31.7k
                                            Users

                                            79.7k
                                            Topics

                                            1.3m
                                            Posts

                                            26
                                            121
                                            27487
                                            Loading More Posts
                                            • Oldest to Newest
                                            • Newest to Oldest
                                            • Most Votes
                                            Reply
                                            • Reply as topic
                                            Log in to reply
                                            Community
                                            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                                            The ioBroker Community 2014-2023
                                            logo