Weiter zum Inhalt
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Hell
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dunkel
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Visualisierung
  4. Bayrol Webportal

NEWS

  • wichtiges UPDATE für controller 7.2.2 im stable
    HomoranH
    Homoran
    9
    1
    699

  • Neues YouTube-Video: Visualisierung im Devices-Adapter
    BluefoxB
    Bluefox
    16
    1
    3.1k

  • Neuer ioBroker-Blog online: Monatsrückblick März/April 2026
    BluefoxB
    Bluefox
    8
    1
    3.1k

Bayrol Webportal

Geplant Angeheftet Gesperrt Verschoben Visualisierung
105 Beiträge 16 Kommentatoren 23.6k Aufrufe 15 Beobachtet
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • H Habedere

    Hallo,
    hat jemand schon mal die Abfrage lokal über die iP versucht?
    Versuche auch meine Bayrol Relax Power (ohne Umwege) in iObroker zu bekommen.

    Mfg

    Q Offline
    Q Offline
    qwertz
    schrieb am zuletzt editiert von
    #90

    @habedere Ich habe die Bayrol automatic ph/cl. Ich wüsste nicht, dass die eine lokale API hat. Deine Bayrol Relax Power ist jedoch ein gänzlich anderes Gerät.

    H 1 Antwort Letzte Antwort
    0
    • Q qwertz

      @habedere Ich habe die Bayrol automatic ph/cl. Ich wüsste nicht, dass die eine lokale API hat. Deine Bayrol Relax Power ist jedoch ein gänzlich anderes Gerät.

      H Offline
      H Offline
      Habedere
      schrieb am zuletzt editiert von
      #91

      @qwertz
      Wusste ich auch nicht - klappt aber…

      844d6355-bd36-4f96-8bc2-0f97194a5608-image.png

      Q 1 Antwort Letzte Antwort
      0
      • H Habedere

        @qwertz
        Wusste ich auch nicht - klappt aber…

        844d6355-bd36-4f96-8bc2-0f97194a5608-image.png

        Q Offline
        Q Offline
        qwertz
        schrieb am zuletzt editiert von
        #92

        @habedere wie ist denn die url dieser seite ?

        OliverIOO Q H 3 Antworten Letzte Antwort
        0
        • Q qwertz

          @habedere wie ist denn die url dieser seite ?

          OliverIOO Offline
          OliverIOO Offline
          OliverIO
          schrieb am zuletzt editiert von
          #93

          @qwertz

          https://www.bayrol-poolaccess.de

          Meine Adapter und Widgets
          TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
          Links im Profil

          1 Antwort Letzte Antwort
          0
          • Q qwertz

            @habedere wie ist denn die url dieser seite ?

            Q Offline
            Q Offline
            qwertz
            schrieb am zuletzt editiert von
            #94

            @qwertz Ich bezog mich auf die lokale API, die Habedere als Screenshot gezeigt hat.

            1 Antwort Letzte Antwort
            0
            • Q qwertz

              @habedere wie ist denn die url dieser seite ?

              H Offline
              H Offline
              Habedere
              schrieb am zuletzt editiert von
              #95

              @qwertz
              Einfach nur die IP im Heimnetz eingeben

              H 1 Antwort Letzte Antwort
              0
              • H Habedere

                @qwertz
                Einfach nur die IP im Heimnetz eingeben

                H Offline
                H Offline
                Habedere
                schrieb am zuletzt editiert von
                #96

                @habedere
                Zur Info - hab die Werte jetzt mit dem Parser ausgelesen.

                d12bb99f-3dc8-4ba4-ae37-4abc7d16fe50-image.png

                J 1 Antwort Letzte Antwort
                0
                • H Habedere

                  @habedere
                  Zur Info - hab die Werte jetzt mit dem Parser ausgelesen.

                  d12bb99f-3dc8-4ba4-ae37-4abc7d16fe50-image.png

                  J Offline
                  J Offline
                  james4711
                  schrieb am zuletzt editiert von
                  #97

                  @habedere
                  Hast du das als Alternative für das WebPortal-Skript verwendet?
                  Für meine Automatic Salt 7 bekomme ich immer Zugriffsfehler:
                  2025-04-23 17:18:17.820 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                  2025-04-23 17:18:17.821 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                  2025-04-23 17:18:20.855 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                  2025-04-23 17:18:20.856 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                  2025-04-23 17:18:23.930 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                  2025-04-23 17:18:23.931 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                  2025-04-23 17:18:26.797 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                  2025-04-23 17:18:26.798 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80

                  OliverIOO 1 Antwort Letzte Antwort
                  0
                  • J james4711

                    @habedere
                    Hast du das als Alternative für das WebPortal-Skript verwendet?
                    Für meine Automatic Salt 7 bekomme ich immer Zugriffsfehler:
                    2025-04-23 17:18:17.820 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                    2025-04-23 17:18:17.821 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                    2025-04-23 17:18:20.855 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                    2025-04-23 17:18:20.856 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                    2025-04-23 17:18:23.930 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                    2025-04-23 17:18:23.931 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                    2025-04-23 17:18:26.797 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80
                    2025-04-23 17:18:26.798 - info: parser.0 (11135) Cannot read link "http://xxx.xxx.xxx.xxx/": Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:80

                    OliverIOO Offline
                    OliverIOO Offline
                    OliverIO
                    schrieb am zuletzt editiert von OliverIO
                    #98

                    @james4711

                    lässt sich die seite im browser aufrufen?
                    muss man sich dort zuvor einloggen(am besten mal im inkognito modus prüfen)?

                    der parser adapter hat nur beschränkte möglichkeiten sich wo einzuloggen

                    die fehlermeldung bedeutet das er die verbindung abgelehnt hat. die adresse ist zwar generell erreichbar, aber entweder stimmt was mit dem port oder der anfrage art nicht

                    Meine Adapter und Widgets
                    TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                    Links im Profil

                    M 1 Antwort Letzte Antwort
                    0
                    • OliverIOO OliverIO

                      @james4711

                      lässt sich die seite im browser aufrufen?
                      muss man sich dort zuvor einloggen(am besten mal im inkognito modus prüfen)?

                      der parser adapter hat nur beschränkte möglichkeiten sich wo einzuloggen

                      die fehlermeldung bedeutet das er die verbindung abgelehnt hat. die adresse ist zwar generell erreichbar, aber entweder stimmt was mit dem port oder der anfrage art nicht

                      M Offline
                      M Offline
                      mameier1234
                      schrieb am zuletzt editiert von
                      #99

                      Falls sich jemand wundert... aktuell kommen keine Daten. Ist bei Bayrol bekannt und sie arbeiten an einer Lösung.

                      Grüße,

                      Martin

                      M 1 Antwort Letzte Antwort
                      1
                      • M mameier1234

                        Falls sich jemand wundert... aktuell kommen keine Daten. Ist bei Bayrol bekannt und sie arbeiten an einer Lösung.

                        M Offline
                        M Offline
                        mameier1234
                        schrieb am zuletzt editiert von
                        #100

                        Wenn man sich auf der Bayrol-poolaccess Seite anmeldet, dann kommt ein Hinweise, dass es aktuell zu Kommunikationsproblemen kommt.

                        Wenn man dies mit "nicht mehr anzeigen" quitiert, dann geht auch das Script wieder :-)

                        Grüße,

                        Martin

                        1 Antwort Letzte Antwort
                        1
                        • R Offline
                          R Offline
                          radi71
                          schrieb am zuletzt editiert von
                          #101

                          Also ich habe mal ein lauffähiges javascript für den iobroker erstellt.

                          Was ich ausgeklammert habe ist die Temp, da ich keinen Sensor dran habe, aber PH + Redox wird zuverlässig ausgelesen.

                          User + PW eintragen und die cid rausfinden (im Browser einmal anmelden dann F12 und dann steht da in der Konsole die cid

                          d59be455-6a5e-4638-b2b4-5b118ddfbe45-image.jpeg

                          ich lese nur zwischen 9 und 21 Uhr aus, alle 10 Min, da sonst meine Umwälzpumpe eh nicht läuft.
                          Um keine falschen Werte anzuzeigen setze ich sie auf null wenn die Pumpe nicht läuft, aber das ist noch nicht 100%.

                          Also hier das Script:

                          const https = require('https');
                          const { URL } = require('url');
                          
                          // ioBroker JavaScript-Adapter-Instanz
                          const JS_INSTANCE = 'javascript.0';
                          
                          // Zugangsdaten
                          const USER = 'xxx';
                          const PASS = 'xxx';
                          
                          // Bayrol Controller-ID
                          const CID = 'xxxxx';
                          
                          const BASE = 'https://www.bayrol-poolaccess.de/webview';
                          
                          const LOGIN_URL = `${BASE}/m/login.php`;
                          const PLANTS_M_URL = `${BASE}/m/plants.php`;
                          const DATA_URL = `${BASE}/getdata.php?cid=${CID}`;
                          
                          // ioBroker States
                          const STATE_PH = `${JS_INSTANCE}.bayrol.ph`;
                          const STATE_REDOX = `${JS_INSTANCE}.bayrol.redox`;
                          const STATE_LAST_UPDATE = `${JS_INSTANCE}.bayrol.lastUpdate`;
                          const STATE_CONNECTED = `${JS_INSTANCE}.bayrol.connected`;
                          const STATE_PUMP_RUNNING = `${JS_INSTANCE}.bayrol.pumpRunning`;
                          const STATE_VALUES_VALID = `${JS_INSTANCE}.bayrol.valuesValid`;
                          
                          let cookies = {};
                          let loggedIn = false;
                          let pollRunning = false;
                          
                          function ensureObjects() {
                              setObject(STATE_PH, {
                                  type: 'state',
                                  common: {
                                      name: 'Bayrol pH',
                                      type: 'number',
                                      role: 'value.ph',
                                      unit: 'pH',
                                      read: true,
                                      write: false
                                  },
                                  native: {}
                              });
                          
                              setObject(STATE_REDOX, {
                                  type: 'state',
                                  common: {
                                      name: 'Bayrol Redox',
                                      type: 'number',
                                      role: 'value',
                                      unit: 'mV',
                                      read: true,
                                      write: false
                                  },
                                  native: {}
                              });
                          
                              setObject(STATE_LAST_UPDATE, {
                                  type: 'state',
                                  common: {
                                      name: 'Bayrol letzte Aktualisierung',
                                      type: 'string',
                                      role: 'date',
                                      read: true,
                                      write: false
                                  },
                                  native: {}
                              });
                          
                              setObject(STATE_CONNECTED, {
                                  type: 'state',
                                  common: {
                                      name: 'Bayrol verbunden',
                                      type: 'boolean',
                                      role: 'indicator.connected',
                                      read: true,
                                      write: false
                                  },
                                  native: {}
                              });
                          
                              setObject(STATE_PUMP_RUNNING, {
                                  type: 'state',
                                  common: {
                                      name: 'Bayrol Umwälzpumpe läuft',
                                      type: 'boolean',
                                      role: 'indicator',
                                      read: true,
                                      write: false
                                  },
                                  native: {}
                              });
                          
                              setObject(STATE_VALUES_VALID, {
                                  type: 'state',
                                  common: {
                                      name: 'Bayrol Messwerte gültig',
                                      type: 'boolean',
                                      role: 'indicator',
                                      read: true,
                                      write: false
                                  },
                                  native: {}
                              });
                          }
                          
                          function saveCookies(setCookieHeaders) {
                              if (!setCookieHeaders) return;
                          
                              if (!Array.isArray(setCookieHeaders)) {
                                  setCookieHeaders = [setCookieHeaders];
                              }
                          
                              setCookieHeaders.forEach(cookie => {
                                  const firstPart = cookie.split(';')[0];
                                  const eq = firstPart.indexOf('=');
                          
                                  if (eq > 0) {
                                      const name = firstPart.substring(0, eq).trim();
                                      const value = firstPart.substring(eq + 1).trim();
                                      cookies[name] = value;
                                  }
                              });
                          }
                          
                          function getCookieHeader() {
                              return Object.entries(cookies)
                                  .map(([name, value]) => `${name}=${value}`)
                                  .join('; ');
                          }
                          
                          function getAttr(tag, attrName) {
                              const regex = new RegExp(attrName + '\\s*=\\s*["\\\']([^"\\\']*)["\\\']', 'i');
                              const match = tag.match(regex);
                              return match ? match[1] : '';
                          }
                          
                          function request(method, url, body, extraHeaders = {}) {
                              return new Promise((resolve, reject) => {
                                  const u = new URL(url);
                          
                                  const headers = {
                                      'User-Agent': 'Mozilla/5.0',
                                      'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                                      'Accept-Language': 'de-DE,de;q=0.9,en;q=0.8',
                                      ...extraHeaders
                                  };
                          
                                  const cookieHeader = getCookieHeader();
                          
                                  if (cookieHeader) {
                                      headers['Cookie'] = cookieHeader;
                                  }
                          
                                  let payload = null;
                          
                                  if (body !== undefined && body !== null) {
                                      payload = String(body);
                                      headers['Content-Length'] = Buffer.byteLength(payload);
                                  }
                          
                                  const options = {
                                      protocol: u.protocol,
                                      hostname: u.hostname,
                                      port: u.port || 443,
                                      path: u.pathname + u.search,
                                      method,
                                      headers
                                  };
                          
                                  const req = https.request(options, res => {
                                      const chunks = [];
                          
                                      saveCookies(res.headers['set-cookie']);
                          
                                      res.on('data', chunk => chunks.push(chunk));
                          
                                      res.on('end', () => {
                                          resolve({
                                              statusCode: res.statusCode,
                                              headers: res.headers,
                                              body: Buffer.concat(chunks).toString('utf8')
                                          });
                                      });
                                  });
                          
                                  req.on('error', reject);
                          
                                  req.setTimeout(15000, () => {
                                      req.destroy(new Error('Timeout'));
                                  });
                          
                                  if (payload) {
                                      req.write(payload);
                                  }
                          
                                  req.end();
                              });
                          }
                          
                          async function requestFollow(method, url, body, headers = {}) {
                              let currentMethod = method;
                              let currentUrl = url;
                              let currentBody = body;
                              let currentHeaders = headers;
                          
                              for (let i = 0; i < 5; i++) {
                                  const res = await request(currentMethod, currentUrl, currentBody, currentHeaders);
                          
                                  if (![301, 302, 303, 307, 308].includes(res.statusCode) || !res.headers.location) {
                                      return res;
                                  }
                          
                                  const oldUrl = currentUrl;
                                  const nextUrl = new URL(res.headers.location, currentUrl).toString();
                          
                                  if (res.statusCode === 307 || res.statusCode === 308) {
                                      currentUrl = nextUrl;
                                  } else {
                                      currentMethod = 'GET';
                                      currentUrl = nextUrl;
                                      currentBody = null;
                                      currentHeaders = {
                                          'Referer': oldUrl
                                      };
                                  }
                              }
                          
                              throw new Error('Zu viele Redirects');
                          }
                          
                          function parseLoginForm(html) {
                              const form = {};
                              const inputTags = html.match(/<input\b[^>]*>/gi) || [];
                          
                              let usernameSet = false;
                              let passwordSet = false;
                          
                              inputTags.forEach(tag => {
                                  const name = getAttr(tag, 'name');
                                  const type = (getAttr(tag, 'type') || 'text').toLowerCase();
                                  const value = getAttr(tag, 'value');
                          
                                  if (!name) return;
                          
                                  form[name] = value || '';
                          
                                  if (!usernameSet && (
                                      type === 'email' ||
                                      type === 'text' ||
                                      /user|mail|email|login|benutzer/i.test(name)
                                  )) {
                                      form[name] = USER;
                                      usernameSet = true;
                                  }
                          
                                  if (!passwordSet && (
                                      type === 'password' ||
                                      /pass|pwd|kennwort/i.test(name)
                                  )) {
                                      form[name] = PASS;
                                      passwordSet = true;
                                  }
                              });
                          
                              if (!usernameSet) {
                                  form.username = USER;
                              }
                          
                              if (!passwordSet) {
                                  form.password = PASS;
                              }
                          
                              if (form.autologin !== undefined) {
                                  form.autologin = 'on';
                              }
                          
                              const formMatch = html.match(/<form\b[^>]*action\s*=\s*["']([^"']+)["']/i);
                          
                              const action = formMatch
                                  ? new URL(formMatch[1], LOGIN_URL).toString()
                                  : `${BASE}/m/login.php?r=reg`;
                          
                              return {
                                  action,
                                  form
                              };
                          }
                          
                          function formEncode(obj) {
                              return Object.entries(obj)
                                  .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
                                  .join('&');
                          }
                          
                          function cleanHtmlText(value) {
                              return String(value || '')
                                  .replace(/<script[\s\S]*?<\/script>/gi, '')
                                  .replace(/<style[\s\S]*?<\/style>/gi, '')
                                  .replace(/<[^>]*>/g, '')
                                  .replace(/&nbsp;/g, ' ')
                                  .replace(/&#160;/g, ' ')
                                  .replace(/&deg;/g, '°')
                                  .replace(/&auml;/g, 'ä')
                                  .replace(/&ouml;/g, 'ö')
                                  .replace(/&uuml;/g, 'ü')
                                  .replace(/&Auml;/g, 'Ä')
                                  .replace(/&Ouml;/g, 'Ö')
                                  .replace(/&Uuml;/g, 'Ü')
                                  .replace(/&szlig;/g, 'ß')
                                  .replace(/&amp;/g, '&')
                                  .replace(/\s+/g, ' ')
                                  .trim();
                          }
                          
                          function parseNumber(value) {
                              const text = cleanHtmlText(value)
                                  .replace(',', '.')
                                  .replace(/[^\d.+-]/g, '');
                          
                              const number = parseFloat(text);
                          
                              return Number.isFinite(number) ? number : null;
                          }
                          
                          function labelToKey(label) {
                              const l = cleanHtmlText(label)
                                  .replace(/\[[^\]]*\]/g, '')
                                  .replace(/\./g, '')
                                  .trim()
                                  .toLowerCase();
                          
                              if (l === 'ph' || l.includes('ph')) {
                                  return 'ph';
                              }
                          
                              if (l.includes('redox') || l.includes('orp') || l.includes('mv')) {
                                  return 'redox';
                              }
                          
                              return null;
                          }
                          
                          function hasCssClass(html, className) {
                              const regex = new RegExp('class\\s*=\\s*["\\\'][^"\\\']*\\b' + className + '\\b[^"\\\']*["\\\']', 'i');
                              return regex.test(String(html || ''));
                          }
                          
                          function parsePumpRunning(html) {
                              const source = String(html || '');
                          
                              if (hasCssClass(source, 'gstat_ok')) {
                                  return true;
                              }
                          
                              if (
                                  hasCssClass(source, 'gstat_nok') ||
                                  hasCssClass(source, 'gstat_error') ||
                                  hasCssClass(source, 'gstat_err') ||
                                  hasCssClass(source, 'gstat_alarm') ||
                                  hasCssClass(source, 'gstat_off')
                              ) {
                                  return false;
                              }
                          
                              const match = source.match(/class\s*=\s*["'][^"']*\bgstat_[^"']*["']/i);
                          
                              if (match) {
                                  log('Bayrol: Unbekannte Statusklasse gefunden: ' + match[0], 'warn');
                              } else {
                                  log('Bayrol: Keine gstat-Statusklasse gefunden', 'warn');
                              }
                          
                              return false;
                          }
                          
                          function parseValues(html) {
                              const source = String(html || '');
                              const values = {};
                          
                              const boxRegex = /<div\b[^>]*class\s*=\s*["'][^"']*tab_box[^"']*["'][^>]*>([\s\S]*?)(?=<div\b[^>]*class\s*=\s*["'][^"']*tab_box|<div\b[^>]*class\s*=\s*["'][^"']*gapp_ase|<\/body>|$)/gi;
                          
                              let boxMatch;
                          
                              while ((boxMatch = boxRegex.exec(source)) !== null) {
                                  const boxHtml = boxMatch[1];
                          
                                  const spanMatch = boxHtml.match(/<span\b[^>]*>([\s\S]*?)<\/span>/i);
                                  const h1Match = boxHtml.match(/<h1\b[^>]*>([\s\S]*?)<\/h1>/i);
                          
                                  if (!spanMatch || !h1Match) {
                                      continue;
                                  }
                          
                                  const label = cleanHtmlText(spanMatch[1]);
                                  const number = parseNumber(h1Match[1]);
                                  const key = labelToKey(label);
                          
                                  if (key && number !== null) {
                                      values[key] = Number(number);
                                  }
                              }
                          
                              const spanH1Regex = /<span\b[^>]*>([\s\S]*?)<\/span>[\s\S]{0,400}?<h1\b[^>]*>([\s\S]*?)<\/h1>/gi;
                          
                              let spanH1Match;
                          
                              while ((spanH1Match = spanH1Regex.exec(source)) !== null) {
                                  const label = cleanHtmlText(spanH1Match[1]);
                                  const number = parseNumber(spanH1Match[2]);
                                  const key = labelToKey(label);
                          
                                  if (key && number !== null) {
                                      values[key] = Number(number);
                                  }
                              }
                          
                              if (values.ph === undefined) {
                                  const phFallback = source.match(/pH\s*(?:\[[^\]]*\])?[\s\S]{0,500}?<h1[^>]*>\s*([0-9]+(?:[.,][0-9]+)?)\s*<\/h1>/i);
                          
                                  if (phFallback) {
                                      values.ph = Number(parseFloat(phFallback[1].replace(',', '.')));
                                  }
                              }
                          
                              if (values.redox === undefined) {
                                  const redoxFallback = source.match(/Redox\s*(?:\[[^\]]*\])?[\s\S]{0,500}?<h1[^>]*>\s*([0-9]+(?:[.,][0-9]+)?)\s*<\/h1>/i);
                          
                                  if (redoxFallback) {
                                      values.redox = Number(parseFloat(redoxFallback[1].replace(',', '.')));
                                  }
                              }
                          
                              if (values.redox !== undefined && values.redox < 100) {
                                  log('Bayrol: Redox-Wert unplausibel verworfen: ' + values.redox, 'warn');
                                  delete values.redox;
                              }
                          
                              return values;
                          }
                          
                          async function login() {
                              cookies = {};
                          
                              log('Bayrol: Loginseite abrufen ...');
                          
                              const loginPage = await requestFollow('GET', LOGIN_URL, null);
                              const parsed = parseLoginForm(loginPage.body);
                          
                              log(`Bayrol: Login-Action: ${parsed.action}`);
                          
                              const loginBody = formEncode(parsed.form);
                          
                              const loginRes = await requestFollow('POST', parsed.action, loginBody, {
                                  'Content-Type': 'application/x-www-form-urlencoded',
                                  'Referer': LOGIN_URL
                              });
                          
                              const body = String(loginRes.body);
                          
                              if (
                                  body.includes('Fehler') ||
                                  body.includes('Zeit abgelaufen') ||
                                  body.includes('Captcha')
                              ) {
                                  throw new Error('Bayrol Login fehlgeschlagen');
                              }
                          
                              loggedIn = true;
                              log('Bayrol: Login erfolgreich');
                          }
                          
                          async function pollBayrol() {
                              if (pollRunning) {
                                  log('Bayrol: Abruf läuft noch, überspringe diesen Durchlauf', 'warn');
                                  return;
                              }
                          
                              pollRunning = true;
                          
                              try {
                                  if (!loggedIn) {
                                      await login();
                                  }
                          
                                  const res = await requestFollow('GET', DATA_URL, null, {
                                      'Referer': PLANTS_M_URL
                                  });
                          
                                  const html = String(res.body);
                          
                                  if (html.includes('Anmeldung') && html.includes('Passwort')) {
                                      loggedIn = false;
                                      throw new Error('Session abgelaufen, Login wird beim nächsten Lauf erneuert');
                                  }
                          
                                  const pumpRunning = parsePumpRunning(html);
                                  const values = parseValues(html);
                          
                                  setState(STATE_CONNECTED, true, true);
                                  setState(STATE_PUMP_RUNNING, pumpRunning, true);
                                  setState(STATE_LAST_UPDATE, new Date().toISOString(), true);
                          
                                  log(`Bayrol: Antwort Status ${res.statusCode}, Länge ${html.length}, Pumpe ${pumpRunning}, Werte ${JSON.stringify(values)}`);
                          
                                  if (!pumpRunning) {
                                      setState(STATE_PH, null, true);
                                      setState(STATE_REDOX, null, true);
                                      setState(STATE_VALUES_VALID, false, true);
                          
                                      log('Bayrol: Pumpe läuft nicht. pH und Redox wurden auf null gesetzt.', 'warn');
                                      return;
                                  }
                          
                                  if (values.ph === undefined && values.redox === undefined) {
                                      loggedIn = false;
                                      setState(STATE_CONNECTED, false, true);
                                      setState(STATE_VALUES_VALID, false, true);
                                      setState(STATE_PH, null, true);
                                      setState(STATE_REDOX, null, true);
                          
                                      log('Bayrol: Keine pH-/Redox-Werte gefunden. Werte wurden auf null gesetzt. HTML-Auszug: ' + html.substring(0, 1500), 'warn');
                                      return;
                                  }
                          
                                  if (values.ph !== undefined) {
                                      setState(STATE_PH, Number(values.ph), true);
                                  } else {
                                      setState(STATE_PH, null, true);
                                  }
                          
                                  if (values.redox !== undefined) {
                                      setState(STATE_REDOX, Number(values.redox), true);
                                  } else {
                                      setState(STATE_REDOX, null, true);
                                  }
                          
                                  setState(STATE_VALUES_VALID, true, true);
                          
                                  log('Bayrol: Werte aktualisiert: ' + JSON.stringify(values));
                          
                              } catch (err) {
                                  loggedIn = false;
                                  setState(STATE_CONNECTED, false, true);
                                  setState(STATE_VALUES_VALID, false, true);
                                  setState(STATE_PH, null, true);
                                  setState(STATE_REDOX, null, true);
                          
                                  log('Bayrol Fehler: ' + err.message, 'warn');
                              } finally {
                                  pollRunning = false;
                              }
                          }
                          
                          function isWithinPollWindow() {
                              const now = new Date();
                              const hour = now.getHours();
                              const minute = now.getMinutes();
                          
                              // 09:00 bis 21:00 inklusive
                              if (hour < 9) return false;
                              if (hour > 21) return false;
                              if (hour === 21 && minute > 0) return false;
                          
                              return true;
                          }
                          
                          function pollBayrolIfInWindow() {
                              if (!isWithinPollWindow()) {
                                  log('Bayrol: Außerhalb des Abfragezeitraums 09:00–21:00, kein Abruf.');
                                  return;
                              }
                          
                              pollBayrol();
                          }
                          
                          // Objekte sauber definieren
                          ensureObjects();
                          
                          // Beim Skriptstart nur abrufen, wenn innerhalb des Zeitfensters
                          setTimeout(pollBayrolIfInWindow, 3000);
                          
                          // alle 10 Minuten von 09:00 bis 20:50
                          schedule('*/10 9-20 * * *', pollBayrol);
                          
                          // zusätzlich exakt um 21:00
                          schedule('0 21 * * *', pollBayrol);
                          
                          OliverIOO 1 Antwort Letzte Antwort
                          0
                          • R radi71

                            Also ich habe mal ein lauffähiges javascript für den iobroker erstellt.

                            Was ich ausgeklammert habe ist die Temp, da ich keinen Sensor dran habe, aber PH + Redox wird zuverlässig ausgelesen.

                            User + PW eintragen und die cid rausfinden (im Browser einmal anmelden dann F12 und dann steht da in der Konsole die cid

                            d59be455-6a5e-4638-b2b4-5b118ddfbe45-image.jpeg

                            ich lese nur zwischen 9 und 21 Uhr aus, alle 10 Min, da sonst meine Umwälzpumpe eh nicht läuft.
                            Um keine falschen Werte anzuzeigen setze ich sie auf null wenn die Pumpe nicht läuft, aber das ist noch nicht 100%.

                            Also hier das Script:

                            const https = require('https');
                            const { URL } = require('url');
                            
                            // ioBroker JavaScript-Adapter-Instanz
                            const JS_INSTANCE = 'javascript.0';
                            
                            // Zugangsdaten
                            const USER = 'xxx';
                            const PASS = 'xxx';
                            
                            // Bayrol Controller-ID
                            const CID = 'xxxxx';
                            
                            const BASE = 'https://www.bayrol-poolaccess.de/webview';
                            
                            const LOGIN_URL = `${BASE}/m/login.php`;
                            const PLANTS_M_URL = `${BASE}/m/plants.php`;
                            const DATA_URL = `${BASE}/getdata.php?cid=${CID}`;
                            
                            // ioBroker States
                            const STATE_PH = `${JS_INSTANCE}.bayrol.ph`;
                            const STATE_REDOX = `${JS_INSTANCE}.bayrol.redox`;
                            const STATE_LAST_UPDATE = `${JS_INSTANCE}.bayrol.lastUpdate`;
                            const STATE_CONNECTED = `${JS_INSTANCE}.bayrol.connected`;
                            const STATE_PUMP_RUNNING = `${JS_INSTANCE}.bayrol.pumpRunning`;
                            const STATE_VALUES_VALID = `${JS_INSTANCE}.bayrol.valuesValid`;
                            
                            let cookies = {};
                            let loggedIn = false;
                            let pollRunning = false;
                            
                            function ensureObjects() {
                                setObject(STATE_PH, {
                                    type: 'state',
                                    common: {
                                        name: 'Bayrol pH',
                                        type: 'number',
                                        role: 'value.ph',
                                        unit: 'pH',
                                        read: true,
                                        write: false
                                    },
                                    native: {}
                                });
                            
                                setObject(STATE_REDOX, {
                                    type: 'state',
                                    common: {
                                        name: 'Bayrol Redox',
                                        type: 'number',
                                        role: 'value',
                                        unit: 'mV',
                                        read: true,
                                        write: false
                                    },
                                    native: {}
                                });
                            
                                setObject(STATE_LAST_UPDATE, {
                                    type: 'state',
                                    common: {
                                        name: 'Bayrol letzte Aktualisierung',
                                        type: 'string',
                                        role: 'date',
                                        read: true,
                                        write: false
                                    },
                                    native: {}
                                });
                            
                                setObject(STATE_CONNECTED, {
                                    type: 'state',
                                    common: {
                                        name: 'Bayrol verbunden',
                                        type: 'boolean',
                                        role: 'indicator.connected',
                                        read: true,
                                        write: false
                                    },
                                    native: {}
                                });
                            
                                setObject(STATE_PUMP_RUNNING, {
                                    type: 'state',
                                    common: {
                                        name: 'Bayrol Umwälzpumpe läuft',
                                        type: 'boolean',
                                        role: 'indicator',
                                        read: true,
                                        write: false
                                    },
                                    native: {}
                                });
                            
                                setObject(STATE_VALUES_VALID, {
                                    type: 'state',
                                    common: {
                                        name: 'Bayrol Messwerte gültig',
                                        type: 'boolean',
                                        role: 'indicator',
                                        read: true,
                                        write: false
                                    },
                                    native: {}
                                });
                            }
                            
                            function saveCookies(setCookieHeaders) {
                                if (!setCookieHeaders) return;
                            
                                if (!Array.isArray(setCookieHeaders)) {
                                    setCookieHeaders = [setCookieHeaders];
                                }
                            
                                setCookieHeaders.forEach(cookie => {
                                    const firstPart = cookie.split(';')[0];
                                    const eq = firstPart.indexOf('=');
                            
                                    if (eq > 0) {
                                        const name = firstPart.substring(0, eq).trim();
                                        const value = firstPart.substring(eq + 1).trim();
                                        cookies[name] = value;
                                    }
                                });
                            }
                            
                            function getCookieHeader() {
                                return Object.entries(cookies)
                                    .map(([name, value]) => `${name}=${value}`)
                                    .join('; ');
                            }
                            
                            function getAttr(tag, attrName) {
                                const regex = new RegExp(attrName + '\\s*=\\s*["\\\']([^"\\\']*)["\\\']', 'i');
                                const match = tag.match(regex);
                                return match ? match[1] : '';
                            }
                            
                            function request(method, url, body, extraHeaders = {}) {
                                return new Promise((resolve, reject) => {
                                    const u = new URL(url);
                            
                                    const headers = {
                                        'User-Agent': 'Mozilla/5.0',
                                        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                                        'Accept-Language': 'de-DE,de;q=0.9,en;q=0.8',
                                        ...extraHeaders
                                    };
                            
                                    const cookieHeader = getCookieHeader();
                            
                                    if (cookieHeader) {
                                        headers['Cookie'] = cookieHeader;
                                    }
                            
                                    let payload = null;
                            
                                    if (body !== undefined && body !== null) {
                                        payload = String(body);
                                        headers['Content-Length'] = Buffer.byteLength(payload);
                                    }
                            
                                    const options = {
                                        protocol: u.protocol,
                                        hostname: u.hostname,
                                        port: u.port || 443,
                                        path: u.pathname + u.search,
                                        method,
                                        headers
                                    };
                            
                                    const req = https.request(options, res => {
                                        const chunks = [];
                            
                                        saveCookies(res.headers['set-cookie']);
                            
                                        res.on('data', chunk => chunks.push(chunk));
                            
                                        res.on('end', () => {
                                            resolve({
                                                statusCode: res.statusCode,
                                                headers: res.headers,
                                                body: Buffer.concat(chunks).toString('utf8')
                                            });
                                        });
                                    });
                            
                                    req.on('error', reject);
                            
                                    req.setTimeout(15000, () => {
                                        req.destroy(new Error('Timeout'));
                                    });
                            
                                    if (payload) {
                                        req.write(payload);
                                    }
                            
                                    req.end();
                                });
                            }
                            
                            async function requestFollow(method, url, body, headers = {}) {
                                let currentMethod = method;
                                let currentUrl = url;
                                let currentBody = body;
                                let currentHeaders = headers;
                            
                                for (let i = 0; i < 5; i++) {
                                    const res = await request(currentMethod, currentUrl, currentBody, currentHeaders);
                            
                                    if (![301, 302, 303, 307, 308].includes(res.statusCode) || !res.headers.location) {
                                        return res;
                                    }
                            
                                    const oldUrl = currentUrl;
                                    const nextUrl = new URL(res.headers.location, currentUrl).toString();
                            
                                    if (res.statusCode === 307 || res.statusCode === 308) {
                                        currentUrl = nextUrl;
                                    } else {
                                        currentMethod = 'GET';
                                        currentUrl = nextUrl;
                                        currentBody = null;
                                        currentHeaders = {
                                            'Referer': oldUrl
                                        };
                                    }
                                }
                            
                                throw new Error('Zu viele Redirects');
                            }
                            
                            function parseLoginForm(html) {
                                const form = {};
                                const inputTags = html.match(/<input\b[^>]*>/gi) || [];
                            
                                let usernameSet = false;
                                let passwordSet = false;
                            
                                inputTags.forEach(tag => {
                                    const name = getAttr(tag, 'name');
                                    const type = (getAttr(tag, 'type') || 'text').toLowerCase();
                                    const value = getAttr(tag, 'value');
                            
                                    if (!name) return;
                            
                                    form[name] = value || '';
                            
                                    if (!usernameSet && (
                                        type === 'email' ||
                                        type === 'text' ||
                                        /user|mail|email|login|benutzer/i.test(name)
                                    )) {
                                        form[name] = USER;
                                        usernameSet = true;
                                    }
                            
                                    if (!passwordSet && (
                                        type === 'password' ||
                                        /pass|pwd|kennwort/i.test(name)
                                    )) {
                                        form[name] = PASS;
                                        passwordSet = true;
                                    }
                                });
                            
                                if (!usernameSet) {
                                    form.username = USER;
                                }
                            
                                if (!passwordSet) {
                                    form.password = PASS;
                                }
                            
                                if (form.autologin !== undefined) {
                                    form.autologin = 'on';
                                }
                            
                                const formMatch = html.match(/<form\b[^>]*action\s*=\s*["']([^"']+)["']/i);
                            
                                const action = formMatch
                                    ? new URL(formMatch[1], LOGIN_URL).toString()
                                    : `${BASE}/m/login.php?r=reg`;
                            
                                return {
                                    action,
                                    form
                                };
                            }
                            
                            function formEncode(obj) {
                                return Object.entries(obj)
                                    .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
                                    .join('&');
                            }
                            
                            function cleanHtmlText(value) {
                                return String(value || '')
                                    .replace(/<script[\s\S]*?<\/script>/gi, '')
                                    .replace(/<style[\s\S]*?<\/style>/gi, '')
                                    .replace(/<[^>]*>/g, '')
                                    .replace(/&nbsp;/g, ' ')
                                    .replace(/&#160;/g, ' ')
                                    .replace(/&deg;/g, '°')
                                    .replace(/&auml;/g, 'ä')
                                    .replace(/&ouml;/g, 'ö')
                                    .replace(/&uuml;/g, 'ü')
                                    .replace(/&Auml;/g, 'Ä')
                                    .replace(/&Ouml;/g, 'Ö')
                                    .replace(/&Uuml;/g, 'Ü')
                                    .replace(/&szlig;/g, 'ß')
                                    .replace(/&amp;/g, '&')
                                    .replace(/\s+/g, ' ')
                                    .trim();
                            }
                            
                            function parseNumber(value) {
                                const text = cleanHtmlText(value)
                                    .replace(',', '.')
                                    .replace(/[^\d.+-]/g, '');
                            
                                const number = parseFloat(text);
                            
                                return Number.isFinite(number) ? number : null;
                            }
                            
                            function labelToKey(label) {
                                const l = cleanHtmlText(label)
                                    .replace(/\[[^\]]*\]/g, '')
                                    .replace(/\./g, '')
                                    .trim()
                                    .toLowerCase();
                            
                                if (l === 'ph' || l.includes('ph')) {
                                    return 'ph';
                                }
                            
                                if (l.includes('redox') || l.includes('orp') || l.includes('mv')) {
                                    return 'redox';
                                }
                            
                                return null;
                            }
                            
                            function hasCssClass(html, className) {
                                const regex = new RegExp('class\\s*=\\s*["\\\'][^"\\\']*\\b' + className + '\\b[^"\\\']*["\\\']', 'i');
                                return regex.test(String(html || ''));
                            }
                            
                            function parsePumpRunning(html) {
                                const source = String(html || '');
                            
                                if (hasCssClass(source, 'gstat_ok')) {
                                    return true;
                                }
                            
                                if (
                                    hasCssClass(source, 'gstat_nok') ||
                                    hasCssClass(source, 'gstat_error') ||
                                    hasCssClass(source, 'gstat_err') ||
                                    hasCssClass(source, 'gstat_alarm') ||
                                    hasCssClass(source, 'gstat_off')
                                ) {
                                    return false;
                                }
                            
                                const match = source.match(/class\s*=\s*["'][^"']*\bgstat_[^"']*["']/i);
                            
                                if (match) {
                                    log('Bayrol: Unbekannte Statusklasse gefunden: ' + match[0], 'warn');
                                } else {
                                    log('Bayrol: Keine gstat-Statusklasse gefunden', 'warn');
                                }
                            
                                return false;
                            }
                            
                            function parseValues(html) {
                                const source = String(html || '');
                                const values = {};
                            
                                const boxRegex = /<div\b[^>]*class\s*=\s*["'][^"']*tab_box[^"']*["'][^>]*>([\s\S]*?)(?=<div\b[^>]*class\s*=\s*["'][^"']*tab_box|<div\b[^>]*class\s*=\s*["'][^"']*gapp_ase|<\/body>|$)/gi;
                            
                                let boxMatch;
                            
                                while ((boxMatch = boxRegex.exec(source)) !== null) {
                                    const boxHtml = boxMatch[1];
                            
                                    const spanMatch = boxHtml.match(/<span\b[^>]*>([\s\S]*?)<\/span>/i);
                                    const h1Match = boxHtml.match(/<h1\b[^>]*>([\s\S]*?)<\/h1>/i);
                            
                                    if (!spanMatch || !h1Match) {
                                        continue;
                                    }
                            
                                    const label = cleanHtmlText(spanMatch[1]);
                                    const number = parseNumber(h1Match[1]);
                                    const key = labelToKey(label);
                            
                                    if (key && number !== null) {
                                        values[key] = Number(number);
                                    }
                                }
                            
                                const spanH1Regex = /<span\b[^>]*>([\s\S]*?)<\/span>[\s\S]{0,400}?<h1\b[^>]*>([\s\S]*?)<\/h1>/gi;
                            
                                let spanH1Match;
                            
                                while ((spanH1Match = spanH1Regex.exec(source)) !== null) {
                                    const label = cleanHtmlText(spanH1Match[1]);
                                    const number = parseNumber(spanH1Match[2]);
                                    const key = labelToKey(label);
                            
                                    if (key && number !== null) {
                                        values[key] = Number(number);
                                    }
                                }
                            
                                if (values.ph === undefined) {
                                    const phFallback = source.match(/pH\s*(?:\[[^\]]*\])?[\s\S]{0,500}?<h1[^>]*>\s*([0-9]+(?:[.,][0-9]+)?)\s*<\/h1>/i);
                            
                                    if (phFallback) {
                                        values.ph = Number(parseFloat(phFallback[1].replace(',', '.')));
                                    }
                                }
                            
                                if (values.redox === undefined) {
                                    const redoxFallback = source.match(/Redox\s*(?:\[[^\]]*\])?[\s\S]{0,500}?<h1[^>]*>\s*([0-9]+(?:[.,][0-9]+)?)\s*<\/h1>/i);
                            
                                    if (redoxFallback) {
                                        values.redox = Number(parseFloat(redoxFallback[1].replace(',', '.')));
                                    }
                                }
                            
                                if (values.redox !== undefined && values.redox < 100) {
                                    log('Bayrol: Redox-Wert unplausibel verworfen: ' + values.redox, 'warn');
                                    delete values.redox;
                                }
                            
                                return values;
                            }
                            
                            async function login() {
                                cookies = {};
                            
                                log('Bayrol: Loginseite abrufen ...');
                            
                                const loginPage = await requestFollow('GET', LOGIN_URL, null);
                                const parsed = parseLoginForm(loginPage.body);
                            
                                log(`Bayrol: Login-Action: ${parsed.action}`);
                            
                                const loginBody = formEncode(parsed.form);
                            
                                const loginRes = await requestFollow('POST', parsed.action, loginBody, {
                                    'Content-Type': 'application/x-www-form-urlencoded',
                                    'Referer': LOGIN_URL
                                });
                            
                                const body = String(loginRes.body);
                            
                                if (
                                    body.includes('Fehler') ||
                                    body.includes('Zeit abgelaufen') ||
                                    body.includes('Captcha')
                                ) {
                                    throw new Error('Bayrol Login fehlgeschlagen');
                                }
                            
                                loggedIn = true;
                                log('Bayrol: Login erfolgreich');
                            }
                            
                            async function pollBayrol() {
                                if (pollRunning) {
                                    log('Bayrol: Abruf läuft noch, überspringe diesen Durchlauf', 'warn');
                                    return;
                                }
                            
                                pollRunning = true;
                            
                                try {
                                    if (!loggedIn) {
                                        await login();
                                    }
                            
                                    const res = await requestFollow('GET', DATA_URL, null, {
                                        'Referer': PLANTS_M_URL
                                    });
                            
                                    const html = String(res.body);
                            
                                    if (html.includes('Anmeldung') && html.includes('Passwort')) {
                                        loggedIn = false;
                                        throw new Error('Session abgelaufen, Login wird beim nächsten Lauf erneuert');
                                    }
                            
                                    const pumpRunning = parsePumpRunning(html);
                                    const values = parseValues(html);
                            
                                    setState(STATE_CONNECTED, true, true);
                                    setState(STATE_PUMP_RUNNING, pumpRunning, true);
                                    setState(STATE_LAST_UPDATE, new Date().toISOString(), true);
                            
                                    log(`Bayrol: Antwort Status ${res.statusCode}, Länge ${html.length}, Pumpe ${pumpRunning}, Werte ${JSON.stringify(values)}`);
                            
                                    if (!pumpRunning) {
                                        setState(STATE_PH, null, true);
                                        setState(STATE_REDOX, null, true);
                                        setState(STATE_VALUES_VALID, false, true);
                            
                                        log('Bayrol: Pumpe läuft nicht. pH und Redox wurden auf null gesetzt.', 'warn');
                                        return;
                                    }
                            
                                    if (values.ph === undefined && values.redox === undefined) {
                                        loggedIn = false;
                                        setState(STATE_CONNECTED, false, true);
                                        setState(STATE_VALUES_VALID, false, true);
                                        setState(STATE_PH, null, true);
                                        setState(STATE_REDOX, null, true);
                            
                                        log('Bayrol: Keine pH-/Redox-Werte gefunden. Werte wurden auf null gesetzt. HTML-Auszug: ' + html.substring(0, 1500), 'warn');
                                        return;
                                    }
                            
                                    if (values.ph !== undefined) {
                                        setState(STATE_PH, Number(values.ph), true);
                                    } else {
                                        setState(STATE_PH, null, true);
                                    }
                            
                                    if (values.redox !== undefined) {
                                        setState(STATE_REDOX, Number(values.redox), true);
                                    } else {
                                        setState(STATE_REDOX, null, true);
                                    }
                            
                                    setState(STATE_VALUES_VALID, true, true);
                            
                                    log('Bayrol: Werte aktualisiert: ' + JSON.stringify(values));
                            
                                } catch (err) {
                                    loggedIn = false;
                                    setState(STATE_CONNECTED, false, true);
                                    setState(STATE_VALUES_VALID, false, true);
                                    setState(STATE_PH, null, true);
                                    setState(STATE_REDOX, null, true);
                            
                                    log('Bayrol Fehler: ' + err.message, 'warn');
                                } finally {
                                    pollRunning = false;
                                }
                            }
                            
                            function isWithinPollWindow() {
                                const now = new Date();
                                const hour = now.getHours();
                                const minute = now.getMinutes();
                            
                                // 09:00 bis 21:00 inklusive
                                if (hour < 9) return false;
                                if (hour > 21) return false;
                                if (hour === 21 && minute > 0) return false;
                            
                                return true;
                            }
                            
                            function pollBayrolIfInWindow() {
                                if (!isWithinPollWindow()) {
                                    log('Bayrol: Außerhalb des Abfragezeitraums 09:00–21:00, kein Abruf.');
                                    return;
                                }
                            
                                pollBayrol();
                            }
                            
                            // Objekte sauber definieren
                            ensureObjects();
                            
                            // Beim Skriptstart nur abrufen, wenn innerhalb des Zeitfensters
                            setTimeout(pollBayrolIfInWindow, 3000);
                            
                            // alle 10 Minuten von 09:00 bis 20:50
                            schedule('*/10 9-20 * * *', pollBayrol);
                            
                            // zusätzlich exakt um 21:00
                            schedule('0 21 * * *', pollBayrol);
                            
                            OliverIOO Offline
                            OliverIOO Offline
                            OliverIO
                            schrieb am zuletzt editiert von OliverIO
                            #102

                            @radi71

                            nochmal eines?
                            was war das problem am letzen?
                            bzw was ist der vorteil von diesem?

                            Meine Adapter und Widgets
                            TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                            Links im Profil

                            R 1 Antwort Letzte Antwort
                            0
                            • OliverIOO OliverIO

                              @radi71

                              nochmal eines?
                              was war das problem am letzen?
                              bzw was ist der vorteil von diesem?

                              R Offline
                              R Offline
                              radi71
                              schrieb am zuletzt editiert von radi71
                              #103

                              @OliverIO das andere hat bei mir nicht funktioniert, bzw. vielleicht hatte ich auch nicht den letzten Stand gefunden

                              OliverIOO 1 Antwort Letzte Antwort
                              0
                              • R radi71

                                @OliverIO das andere hat bei mir nicht funktioniert, bzw. vielleicht hatte ich auch nicht den letzten Stand gefunden

                                OliverIOO Offline
                                OliverIOO Offline
                                OliverIO
                                schrieb am zuletzt editiert von
                                #104

                                @radi71
                                kein Problem.
                                Das skript war nicht für mich.
                                Allerdings spaltet sich nun die Entwicklungsmöglichkeit nun auf 2 Skripte auf.
                                Besser wäre gewesen das vorhandene Skript zu verbessern.
                                Es gab auch Hinweise darauf, das es wohl verschiedene Geräte gibt, evtl solltest du noch dazuschreiben für welches Gerät exakt dein Skript nun funktioniert

                                Meine Adapter und Widgets
                                TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                                Links im Profil

                                1 Antwort Letzte Antwort
                                0
                                • K Offline
                                  K Offline
                                  Kopfii
                                  schrieb am zuletzt editiert von Kopfii
                                  #105

                                  Hallo zusammen,

                                  ist wem bekannt ob man die Kanisterfüllstandüberwachung auch auslesen und dann verwerten kann ?
                                  (Für die Bayrol Automatic ph/cl)

                                  Viele Grüße

                                  1 Antwort Letzte Antwort
                                  0

                                  Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.

                                  Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.

                                  Mit deinem Input könnte dieser Beitrag noch besser werden 💗

                                  Registrieren Anmelden
                                  Antworten
                                  • In einem neuen Thema antworten
                                  Anmelden zum Antworten
                                  • Älteste zuerst
                                  • Neuste zuerst
                                  • Meiste Stimmen


                                  Support us

                                  ioBroker
                                  Community Adapters
                                  Donate

                                  519

                                  Online

                                  33.0k

                                  Benutzer

                                  83.3k

                                  Themen

                                  1.3m

                                  Beiträge
                                  Community
                                  Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                  ioBroker Community 2014-2026
                                  logo
                                  • Anmelden

                                  • Du hast noch kein Konto? Registrieren

                                  • Anmelden oder registrieren, um zu suchen
                                  • Erster Beitrag
                                    Letzter Beitrag
                                  0
                                  • Home
                                  • Aktuell
                                  • Tags
                                  • Ungelesen 0
                                  • Kategorien
                                  • Unreplied
                                  • Beliebt
                                  • GitHub
                                  • Docu
                                  • Hilfe