Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. paulkerl

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

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

    • ioBroker goes Matter ... Matter Adapter in Stable

    P
    • Profile
    • Following 0
    • Followers 0
    • Topics 5
    • Posts 26
    • Best 0
    • Groups 1

    paulkerl

    @paulkerl

    Starter

    0
    Reputation
    14
    Profile views
    26
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    paulkerl Follow
    Starter

    Latest posts made by paulkerl

    • UNIFI API Voucher Skript

      Hallo zusammen,

      ich habe mal GEMINI bemüht mir ein Voucher Skript für die Unifi API zu bauen, das in IOBROKER läuft. Vielleicht kanns wer brauchen.

      Funktionen deines WLAN-Voucher-Generierungs-Skripts

      Dieses ioBroker-Skript ist dein persönlicher Assistent zur automatischen Erstellung und Verwaltung von WLAN-Vouchern für dein UniFi-Netzwerk, direkt aus deiner ioBroker-Steuerungsoberfläche (VIS) heraus.


      Was das Skript macht:

      1. Vorbereitung und Einrichtung:

        • Beim Start sorgt das Skript dafür, dass alle notwendigen "Schalter" und "Anzeigefelder" in ioBroker existieren. Diese findest du unter 0_userdata.0.WIFIVoucher. Dazu gehören Felder, um einzustellen, wie viele Nutzer einen Voucher verwenden dürfen (max_users) und wie lange er gültig ist (valid_days), sowie ein "Start"-Knopf (generate) und ein Feld, das dir den fertigen Code anzeigt (actual_voucher).
      2. WLAN-Voucher generieren:

        • Wenn du in deiner ioBroker-Ansicht den "Start"-Knopf (0_userdata.0.WIFIVoucher.generate) betätigst, tritt das Skript in Aktion.
        • Es liest deine zuvor eingestellten Werte für die maximale Nutzerzahl und die Gültigkeitsdauer aus den entsprechenden Feldern.
        • Mit diesen Informationen sendet das Skript eine verschlüsselte und authentifizierte Anfrage an deine UniFi-Hardware (den UniFi Controller, z.B. deine USG Max). Dies geschieht direkt und sicher, ohne Umwege über externe Programme wie curl.
        • Deine UniFi-Hardware erstellt daraufhin einen neuen WLAN-Voucher.
      3. Voucher-Code anzeigen und formatieren:

        • Sobald der neue Voucher von UniFi generiert wurde, empfängt das Skript den Voucher-Code.
        • Es formatiert diesen Code sofort, sodass er leichter zu lesen ist – beispielsweise wird aus "1234567890" ein "12345-67890".
        • Der so formatierte Code wird dann in deinem ioBroker-Anzeigefeld (0_userdata.0.WIFIVoucher.actual_voucher) dargestellt, sodass du ihn direkt ablesen und weitergeben kannst.
      4. Automatische Code-Anzeige und Zurücksetzung:

        • Nachdem der Voucher-Code angezeigt wurde, startet das Skript einen 5-minütigen Countdown.
        • Während dieser Zeit bleibt der Code sichtbar. Wenn die 5 Minuten abgelaufen sind, wird der angezeigte Voucher-Code automatisch durch eine Reihe von Nullen ("00000-00000") ersetzt. Das sorgt dafür, dass nicht dauerhaft alte Codes sichtbar bleiben und du immer den aktuellen Code im Blick hast.
        • Wichtig: Solltest du einen neuen Voucher generieren, während der alte Code noch angezeigt wird, wird der Countdown sofort zurückgesetzt und ein neuer 5-Minuten-Zeitraum für den neuen Code gestartet. So wird sichergestellt, dass immer der aktuellste Code für 5 Minuten sichtbar ist.
      5. Bereitschaft für den nächsten Voucher:

        • Nachdem der Generierungsprozess abgeschlossen ist (egal ob erfolgreich oder mit einem Problem), setzt das Skript den "Start"-Knopf (0_userdata.0.WIFIVoucher.generate) in ioBroker automatisch wieder auf seine Ausgangsposition zurück. So ist er bereit für die nächste Voucher-Erstellung.
      // Direkte Nutzung des HTTPS-Moduls für API-Anfragen
      const https = require('https');
      
      // --- Konfiguration ---
      // API-Endpunkt für deine UniFi USG MAX und spezifische Site-ID
      const API_URL_BASE = "https://192.168.xxx.xxx/proxy/network/integration/v1/sites/*site-id*";
      // Dein UniFi API-Schlüssel
      const API_KEY = "*API Token*";
      // Fester Name für automatisch generierte Voucher im UniFi Controller
      const VOUCHER_NAME = "autogen";
      
      // --- Datenpunkte definieren ---
      const DP_BASE = "0_userdata.0.WIFIVoucher";
      const DP_GENERATE = DP_BASE + ".generate";       // Boolean: TRUE zum Generieren eines Vouchers
      const DP_ACTUAL_VOUCHER = DP_BASE + ".actual_voucher"; // String: Speichert den generierten Voucher-Code
      const DP_MAX_USERS = DP_BASE + ".max_users";     // Number: Maximale Nutzer pro Voucher
      const DP_VALID_DAYS = DP_BASE + ".valid_days";   // Number: Gültigkeitsdauer in Tagen
      
      // --- Timer-Variable für das automatische Überschreiben ---
      let voucherTimeout = null;
      
      // --- Funktion zum Erstellen oder Aktualisieren von Datenpunkten ---
      async function createDataPoints() {
          log("Prüfe und erstelle Datenpunkte...", "info");
      
          // Datenpunkt zum Triggern der Voucher-Generierung
          await createStateAsync(DP_GENERATE, false, {
              name: "WLAN Voucher generieren",
              desc: "Setzen Sie auf TRUE, um einen neuen WLAN Voucher zu generieren.",
              type: "boolean",
              role: "button",
              read: true,
              write: true
          });
      
          // Datenpunkt zum Speichern des generierten Voucher-Codes
          await createStateAsync(DP_ACTUAL_VOUCHER, "", {
              name: "Aktueller WLAN Voucher Code",
              desc: "Der zuletzt generierte WLAN Voucher Code.",
              type: "string",
              role: "value",
              read: true,
              write: false // Nur lesbar durch VIS, geschrieben vom Skript
          });
      
          // Datenpunkt für die maximale Anzahl der Nutzer pro Voucher
          await createStateAsync(DP_MAX_USERS, 1, { // Standardwert: 1 Nutzer
              name: "Max. Nutzer pro Voucher",
              desc: "Die maximale Anzahl von Geräten, die den Voucher nutzen können (UniFi-Max: 10).",
              type: "number",
              role: "value",
              read: true,
              write: true,
              min: 1,
              max: 10 // Übliches Maximum in UniFi für Guest Limit
          });
      
          // Datenpunkt für die Gültigkeitsdauer in Tagen
          // Beachte: UniFi API hat ein internes Limit für timeLimitMinutes (z.B. 43200 Stunden = 1800 Tage).
          // Ein höherer Wert wird vom Controller wahrscheinlich auf sein internes Maximum begrenzt.
          await createStateAsync(DP_VALID_DAYS, 1, { // Standardwert: 1 Tag
              name: "Gültigkeit des Vouchers (Tage)",
              desc: "Die Gültigkeitsdauer des Vouchers in Tagen (UniFi-Limit beachten).",
              type: "number",
              role: "value",
              read: true,
              write: true,
              min: 1,
              max: 128000 // Maximalwert laut deiner Anforderung
          });
      
          log("Datenpunkte geprüft/erstellt.", "info");
      }
      
      // --- Funktion zum Formatieren des Voucher-Codes (5 Ziffern - 5 Ziffern) ---
      function formatVoucherCode(code) {
          if (typeof code !== 'string' || code.length !== 10) {
              return code; // Gib den Code unverändert zurück, wenn er nicht 10 Ziffern lang ist
          }
          return code.substring(0, 5) + '-' + code.substring(5, 10);
      }
      
      // --- Funktion zum Zurücksetzen des Voucher-Codes nach Timeout ---
      function resetVoucherCode() {
          log("Setze Voucher-Code auf '00000-00000' zurück.", "info");
          setState(DP_ACTUAL_VOUCHER, "00000-00000", true); // Bestätigen, dass der Wert geschrieben wurde
      }
      
      // --- Hauptfunktion zum Generieren eines einzelnen Vouchers ---
      async function generateVoucher() {
          log("Starte Voucher-Generierung...", "info");
      
          // **WICHTIG:** Alten Timer stoppen, falls vorhanden
          if (voucherTimeout) {
              clearTimeout(voucherTimeout);
              log("Vorherigen Voucher-Timeout gestoppt.", "debug");
          }
      
          // Lese die aktuellen Werte aus den Datenpunkten
          const maxUsersState = await getStateAsync(DP_MAX_USERS);
          const validDaysState = await getStateAsync(DP_VALID_DAYS);
      
          // Prüfe, ob die Datenpunkte gültige Werte liefern
          if (!maxUsersState || maxUsersState.val === null || !validDaysState || validDaysState.val === null) {
              log("Fehler: Datenpunkte für max. Nutzer oder Gültigkeit konnten nicht gelesen werden.", "warn");
              setState(DP_GENERATE, false); // Setze Schalter zurück, da keine gültigen Daten
              return;
          }
      
          const maxUsers = maxUsersState.val;
          const validDays = validDaysState.val;
          // Umrechnung von Tagen in Minuten, wie von der UniFi API erwartet
          const timeLimitMinutes = validDays * 24 * 60;
      
          // Erstelle das JSON-Objekt für den POST-Request-Body
          const postDataObj = {
              name: VOUCHER_NAME,
              authorizedGuestLimit: maxUsers,
              timeLimitMinutes: timeLimitMinutes
          };
          const postData = JSON.stringify(postDataObj); // Konvertiere Objekt in JSON-String
      
          // Manuelle URL-Zerlegung für das https-Modul
          const fullUrl = API_URL_BASE + '/hotspot/vouchers';
          const parts = fullUrl.match(/^https?:\/\/([^/:]+)(:\d+)?(.*)$/);
      
          if (!parts) {
              log(`Fehler: Ungültige URL-Formatierung für ${fullUrl}. Bitte URL prüfen.`, "error");
              setState(DP_GENERATE, false);
              return;
          }
      
          const hostname = parts[1];
          const port = parts[2] ? parseInt(parts[2].substring(1)) : 443; // Standard-HTTPS-Port 443
          const path = parts[3];
      
          // Optionen für den HTTPS-Request
          const options = {
              hostname: hostname,
              port: port,
              path: path,
              method: 'POST',
              headers: {
                  'Content-Type': 'application/json',
                  'Content-Length': Buffer.byteLength(postData), // Notwendig für POST-Requests
                  'Accept': 'application/json',
                  'X-API-Key': API_KEY // Dein API-Schlüssel zur Authentifizierung
              },
              rejectUnauthorized: false // Wichtig: Deaktiviert die Zertifikatsprüfung für selbstsignierte UniFi-Zertifikate
          };
      
          log(`Sende HTTP POST-Request an: ${fullUrl}`, "debug");
          log(`Post-Daten: ${postData}`, "debug");
      
          try {
              const responseData = await new Promise((resolve, reject) => {
                  const req = https.request(options, (res) => {
                      let data = '';
      
                      res.on('data', (chunk) => {
                          data += chunk;
                      });
      
                      res.on('end', () => {
                          if (res.statusCode >= 200 && res.statusCode < 300) {
                              resolve(data);
                          } else {
                              reject(new Error(`Server responded with status code ${res.statusCode}: ${data}`));
                          }
                      });
                  });
      
                  req.on('error', (e) => {
                      reject(e);
                  });
      
                  req.write(postData);
                  req.end();
              });
      
              // Verarbeitung der erfolgreichen API-Antwort
              log("API-Antwort erhalten: " + responseData, "debug");
              const result = JSON.parse(responseData);
      
              if (result && Array.isArray(result.vouchers) && result.vouchers.length > 0) {
                  const rawVoucherCode = result.vouchers[0].code;
                  const formattedVoucherCode = formatVoucherCode(rawVoucherCode); // Voucher-Code formatieren
      
                  log(`Neuer Voucher erfolgreich generiert: ${formattedVoucherCode}`, "info");
                  // Speichere den formatierten Code im ioBroker Datenpunkt
                  setState(DP_ACTUAL_VOUCHER, formattedVoucherCode, true); // Bestätigen, dass der Wert geschrieben wurde
      
                  // **Neuer Timer starten**
                  voucherTimeout = setTimeout(resetVoucherCode, 5 * 60 * 1000); // 5 Minuten = 5 * 60 * 1000 ms
                  log("Timeout für Voucher-Rücksetzung gestartet (5 Minuten).", "debug");
      
              } else {
                  log("Unerwartete API-Antwort Struktur bei Voucher-Generierung: " + responseData, "warn");
                  if (result && result.statusCode) {
                      log(`API Fehler-Code: ${result.statusCode}, Nachricht: ${result.message || 'Keine Nachricht'}`, "error");
                  }
              }
      
          } catch (e) {
              log(`Ausnahme beim Generieren des Vouchers: ${e.message}. Stack: ${e.stack}`, "error");
          } finally {
              setState(DP_GENERATE, false, true); // Setzt den Trigger-Datenpunkt immer auf FALSE zurück
          }
      }
      
      // --- Skriptstart und Trigger-Definitionen ---
      
      // Dieser Listener sorgt dafür, dass die Datenpunkte initialisiert werden,
      // wenn das Skript aktiviert oder neu gestartet wird.
      on({ id: "javascript.0.scriptEnabled.script.js." + instance + ".WLAN_Voucher_Generator", change: "ne" }, async function (obj) {
          if (obj.state.val === true) {
              log("Skript gestartet. Datenpunkte werden initialisiert.", "info");
              await createDataPoints();
          }
      });
      
      // Dieser Trigger reagiert auf Änderungen des "generate"-Datenpunkts.
      // Wenn dieser auf TRUE gesetzt wird, startet die Voucher-Generierung.
      on({ id: DP_GENERATE, change: "ne", val: true }, async function (obj) {
          log("Datenpunkt " + DP_GENERATE + " auf TRUE gesetzt. Starte Voucher-Generierung...", "info");
          await generateVoucher();
      });
      
      // Initialer Aufruf zum Erstellen der Datenpunkte beim Skriptstart
      createDataPoints();
      
      posted in JavaScript
      P
      paulkerl
    • RE: Test Tesla-Motors v1.0.0

      @lobomau
      AFAIK hat Tesla die API "abgeschaltet" bzw. eingeschränkt. Zugriff nur noch über ein DEV-Account (für privat ebenfalls kostenlos) möglich.

      Ich würde vermute, dass der Adapter umgestellt werden muss auf Access- & Refreshtoken Zugriff.

      posted in Tester
      P
      paulkerl
    • RE: MQTT nimmt nur ein paar Sekunden Anfragen entgegen

      @samson71
      Wie erwähnt, hat es bis vor ein paar Monaten funktioniert. Da kein PV-Überschuss vorhanden war, habe ich mich erstmal nicht drum gekümmert.

      In meiner Kombination (EVCC, Tinkerforge Warp2 und EnergyManager) scheint 1s Voraussetzung zu sein, da EVCC sonst mledet, dass die Werte im MQTT von der Wallbox veraltet sind. Dies bedeudet, dass ich wohl zwingend auf 1s gehen muss.

      Ich habe heute den MQTT-Adapter in ioBroker deaktiviert und paralell auf dem darunterliegenden Ubuntu Mosquitto installiert. Das scheint nun mit 1s zu funktionieren. Ich beobachte es weiter.

      Leider kann ich nicht sagen, woran es nun genau liegt, dass der MQTT-Adapter nach kurzer Zeit keine Daten mehr bekommt (bei 1s Taktung). Ob sich am Adapter was geändert hat, am OS drunter oder an der FW der Wallbox.

      Vielen Dank für schnellen Antworten.

      Vg Paul

      posted in ioBroker Allgemein
      P
      paulkerl
    • RE: MQTT nimmt nur ein paar Sekunden Anfragen entgegen

      @samson71
      Hallo Markus, du hattest recht. Ich bin auf 3 Sekunden hoch und nun funktioniert es.

      Dennoch bin ich verwundert, da es über ein Jahr so funktioniert hat. Ich vermute, in einem der letzten Updates scheint sich da etwas zu verändert haben. Weißt du da zufälligerweise etwas? Konnte das Change Log nicht finden.

      Da der Wert bei mir für das PV Überschuss laden verantwortlich ist, ist eine geringe Latenz. Natürlich besser. Aber mit 3 Sekunden müsste ich auch leben

      posted in ioBroker Allgemein
      P
      paulkerl
    • RE: MQTT nimmt nur ein paar Sekunden Anfragen entgegen

      @arteck

      Jedes Mal, wenn ich den Adapter neu starte, werden die Werte der Clients aktualisiert. Die Clients senden circa jede Sekunde aktuelle Werte. Nach ein paar Sekunden ist ein Schluss.

      posted in ioBroker Allgemein
      P
      paulkerl
    • MQTT nimmt nur ein paar Sekunden Anfragen entgegen

      Hallo zusammen,
      mein MQTT Broker nimmt nach Adapter-Neustart für ein paar Sekunden Anfragen entgegen und danach nur noch sporadisch (wenn überhaupt). Der Adapter scheint aber wieterhin zu laufen. In den LOGs sehe ich nicht Gegenteiliges. Das Problem besteht schon seit einiger Zeit. Leider kann ich nciht sagen seit wann. Ich speichere die Zustände in REDIS. Kann es ggf damit zusammenhängen? Wäre aber bei mir dann der einzige Adapter der mit REDIS Probleme macht.

      Vielleicht habt ihr eine Idee, woran es klemmen könnte.

      Besten Dank im Vorraus.

      Vg Paul

      posted in ioBroker Allgemein
      P
      paulkerl
    • RE: JSON Graph mit VIS?

      Hallo @haus-automatisierung ,

      betsen Dank für den Tipp. Hat geholfen.
      War ein Denkfehler von mir, dass Material-Design Widgets nicht bei VIS funktionieren.

      Vg Paulkerl

      posted in Visualisierung
      P
      paulkerl
    • JSON Graph mit VIS?

      Guten Morgen in die Runde,

      mit Material (und JARVIS - soweit mir bekannt ist) können gibt es die Möglichkeit JSON Graphs darzustellen.

      Ich selber habe VIS im Einsatz und würde gerne von PVFORCAST den JSON Graph in VIS darstellen.
      Hat mir jemand einen Tipp, wie ich das am besten anstellen kann?

      Vielen lieben Dank.
      VG Paulkerl

      posted in Visualisierung
      P
      paulkerl
    • RE: Test Adapter e3dc-rscp v0.0.x GitHub

      Hallo @arnod ,

      besten Dank für die Info. Dann mache ich mich mal ans Werk :).

      Vg Paulkerl

      posted in Tester
      P
      paulkerl
    • RE: Test Adapter e3dc-rscp v0.0.x GitHub

      Hallo @arnod,

      das Skript kenne ich und verfolge auch den dazugehörigen Thread. Da steckt viel Arbeit drin und deckt mE jeden Usecase ab. Das Gesamtwerk ist mir allerdings "zu groß" für meine Anwendung. Ich möchte alles so schlank als möglich halten.

      Mich würde interessieren, wie Du technisch die SOC-Begrenzung umgestezt hast. Den Teil würde ich gerne in Node-Red bei mir nachbilden.

      Ich bin leider nicht all zu tief im JS-Coding drin und tue mir schwer Deinen Code auseinander zu nehmen um nachzuvollziehen wie Du das technisch umgesetzt hast. Eine schnelle Erklärung würde mir helfen.

      Vielen lieben Dank.
      LG Paulkerl

      posted in Tester
      P
      paulkerl
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo