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.
    • 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
                          • P
                            PatrickR @Marc Berg last edited by

                            @marc-berg Vielen Dank

                            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

                            815
                            Online

                            31.7k
                            Users

                            79.7k
                            Topics

                            1.3m
                            Posts

                            26
                            121
                            27491
                            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