Navigation

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

    NEWS

    • Amazon Alexa - ioBroker Skill läuft aus ?

    • Monatsrückblick – September 2025

    • Neues Video "KI im Smart Home" - ioBroker plus n8n

    V
    • Profile
    • Following 0
    • Followers 0
    • Topics 11
    • Posts 50
    • Best 3
    • Groups 1

    Vippis

    @Vippis

    Starter

    3
    Reputation
    16
    Profile views
    50
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    Vippis Follow
    Starter

    Best posts made by Vippis

    • RE: Tasmota NeoPool per MQTT

      @mickym

      Boah man danke, bin da auf ein YT Video reingefallen ...

      https://www.youtube.com/watch?v=fZmAkQH5kiA

      Hab den Sonoff Adapter gelöscht und den MQTT Adapter installiert und dort kann man dann im Verzeichnis "cmnd" im Expertemodus (!!) eigene Commands anlegen.

      Z.B. NPFiltration mit value "1" schaltet die Pumpe ein.

      Funktioniert einwandfrei!

      posted in Einbindung von Geräten
      V
      Vippis
    • RE: SVG Animation: Regentonne mit animierter Wasserlinie

      Meine vorläufige Lösung nach Recherche:

      <head>
          
      <style>
      
          #container {
            width: 60px;
            height: 70px;
            position: relative;
            left: 50%;
            top: 50%;
            border-radius: 10px;
            /*box-shadow: 0px 0px 2px #000;*/
            transform: translate(-50%,-50%);
          
            overflow: hidden;
          }
          
          .wave-01 {
            position: absolute;
            width: 210%;
            height: 195%;
            left: -50%;
            top: 50%;
            background-color: rgba(0,190,255,0.4);
            border-radius: 60%;
            animation: rotate 3s linear infinite;
          }
      
      </style>
          
      </head>
      
      <body>
          <div id="container">
          <div class="wave-01"></div>
          </div>
      </body>
      
      
      
      

      66d25dc1-8ddb-403c-9912-4d3a608ad5f7-grafik.png

      Den Füllstand passt man dann über den Parameter "top" in "wave-01" an. Das mache ich dann per JS und schreibe den HTML-Code in einen Datenpunkt und binde ihn an das HTML Widget.

      Vorlage:
      https://codepen.io/dhintech/pen/WXKvzX

      posted in Visualisierung
      V
      Vippis
    • RE: "On" Subscripton: Funktionsaufruf mit Parameter

      Ich hab mir unter https://developer.husqvarnagroup.cloud einen frischen API Key erzeugt und bekomme jetzt keinen error 429 mehr

      posted in JavaScript
      V
      Vippis

    Latest posts made by Vippis

    • RE: IOBroker Automatisiertes Deployment

      @Marc-Berg @OliverIO

      Könnt ihr mir sagen wie ich vom mqtt-client username/passwort und host setzen kann?

      Alles bis auf Passwort kann ich so setzen:

      docker exec -u 0 "${MQTT_CID}" iobroker object extend "system.adapter.${MQTT_ADAPTER}" "$(cat <<EOF
      {
        "native": {
          "type": "client",
          "host": "mosquitto",
          "port": 1883,
          "clientId": "${MQTT_CLIENT_ID}",
          "username": "${MQTT_USER}",
          "password": "${MQTT_HASH}",
          "prefix": "",
          "publishAll": false,
          "keepalive": 60,
          "clean": true,
          "qos": 0,
          "retain": false,
          "subscribe": "#",
          "ssl": false
        }
      }
      EOF
      )"
      
      

      Das Problem ist das Passwort, weil der Adapter einen Hash will, den nur die GUI erzeugt

      posted in Skripten / Logik
      V
      Vippis
    • RE: IOBroker Automatisiertes Deployment

      @oliverio

      Ich wollte euch mal ein funktionierendes Skript posten, wie ihr voll automatisiert Skripte in IOBroker importieren könnt.

      Das Skript geht davon aus, dass ihr eure Skripte vorher per Export aus der Skripte GUI exportiert habt (scripts.zip). Das Zip File hat also eine entsprechend vorgegebene Struktur.

      Usage:
      sudo ./script.sh <pfad/zur/zip>

      #!/usr/bin/env bash
      set -uo pipefail
      
      usage() {
        cat <<'USAGE'
      Usage:
        import_iob_scripts_zip_docker.sh <scripts.zip> [--container iobroker] [--instance javascript.0] [--dry-run]
      
      Options:
        --container   ioBroker container name (default: iobroker)
        --instance    JavaScript adapter instance (default: javascript.0)
        --dry-run     Print actions only (no changes)
      USAGE
      }
      
      [[ $# -ge 1 ]] || { usage; exit 1; }
      ZIP="$1"; shift || true
      CONTAINER="iobroker"
      ENGINE_INSTANCE="javascript.0"
      DRY_RUN=0
      while [[ $# -gt 0 ]]; do
        case "$1" in
          --container) CONTAINER="${2:-iobroker}"; shift 2 ;;
          --instance)  ENGINE_INSTANCE="${2:-javascript.0}"; shift 2 ;;
          --dry-run)   DRY_RUN=1; shift ;;
          -h|--help)   usage; exit 0 ;;
          *) echo "Unknown option: $1" >&2; usage; exit 2 ;;
        esac
      done
      
      for bin in docker unzip jq iconv sed; do
        command -v "$bin" >/dev/null 2>&1 || { echo "ERROR: missing $bin"; exit 3; }
      done
      [[ -f "$ZIP" ]] || { echo "ERROR: ZIP not found: $ZIP"; exit 4; }
      docker ps --format '{{.Names}}' | grep -qx "$CONTAINER" || { echo "ERROR: container '$CONTAINER' not running"; exit 5; }
      
      # Ensure jq in container
      if ! docker exec -i "$CONTAINER" sh -lc 'command -v jq >/dev/null'; then
        echo "ERROR: jq fehlt im Container."
        exit 6
      fi
      
      iob(){ docker exec -i "$CONTAINER" iobroker "$@"; }
      
      TMPDIR="$(mktemp -d -t iob-scripts-zip-XXXXXX)"
      trap 'rm -rf "$TMPDIR"' EXIT
      
      echo "==> Entpacke ZIP auf dem Host: $TMPDIR"
      unzip -q "$ZIP" -d "$TMPDIR"
      
      CONTAINER_TMP="/tmp/iob-scripts-import"
      docker exec -i "$CONTAINER" sh -lc "rm -rf '$CONTAINER_TMP' && mkdir -p '$CONTAINER_TMP'" >/dev/null
      
      echo "==> Stoppe Adapter: $ENGINE_INSTANCE"
      [[ $DRY_RUN -eq 1 ]] || iob stop "$ENGINE_INSTANCE"
      
      # Sammle Ordner (_dir.json) und Skripte (*.json ohne _dir.json)
      mapfile -d '' DIR_FILES    < <(find "$TMPDIR" -type f -name '_dir.json' -print0)
      mapfile -d '' SCRIPT_FILES < <(find "$TMPDIR" -type f -name '*.json' -print0 | grep -z -v '_dir.json$')
      
      TOTAL=$(( ${#DIR_FILES[@]} + ${#SCRIPT_FILES[@]} ))
      echo "==> Gefundene Objekte: $TOTAL (Ordner: ${#DIR_FILES[@]}, Skripte: ${#SCRIPT_FILES[@]})"
      [[ $TOTAL -gt 0 ]] || { echo "Keine importierbaren Objekte gefunden."; exit 0; }
      
      # Fortschrittsanzeige
      progress_file="$TMPDIR/progress.count"
      : > "$progress_file"
      
      show_progress() {
        local total=$1
        local width=40
        while true; do
          local done
          done=$(wc -l < "$progress_file")
          [[ $done -gt $total ]] && done=$total
          local filled=$(( done * width / total ))
          local empty=$(( width - filled ))
          printf "\r[%s%s] %d/%d" \
            "$(printf '#%.0s' $(seq 1 $filled))" \
            "$(printf ' %.0s' $(seq 1 $empty))" \
            "$done" "$total"
          [[ $done -ge $total ]] && break
          sleep 0.2
        done
        echo
      }
      show_progress "$TOTAL" &
      PROGRESS_PID=$!
      
      # Import Ordner aus _dir.json (type, common inkl. lokalisierter Namen, native)
      import_dir() {
        local dirjson="$1"
        local obj_id folder_obj
      
        obj_id="$(jq -r '._id' "$dirjson")"
        [[ -n "$obj_id" && "$obj_id" != "null" ]] || return
      
        # Übernehme type/common/native vollständig; system Felder (from, ts, acl) lässt ioBroker selbst setzen
        folder_obj="$(jq -c '{type,common,native}' "$dirjson")"
      
        if [[ $DRY_RUN -eq 1 ]]; then
          echo "[dry-run] Ordner: $obj_id"
        else
          docker exec -i "$CONTAINER" iobroker object set "$obj_id" "$folder_obj"
        fi
        echo 1 >> "$progress_file"
      }
      
      # Import Skriptobjekt + Source
      import_script() {
        local scriptjson="$1"
        local base rel orig_root root_mapped path obj_id script_key
        base="$(basename "$scriptjson")"
        rel="${scriptjson#"$TMPDIR/"}"
        orig_root="${rel%%/*}"
      
        # Mappe lokalisierte Root-Namen
        case "$orig_root" in
          "Allgemeine Skripte (common)") root_mapped="common" ;;
          "Globale Skripte (global)")    root_mapped="global" ;;
          *)                              root_mapped="$orig_root" ;;
        esac
      
        path="${rel#"$orig_root/"}"
        path="${path%.json}"
        path="${path//\//.}"
        obj_id="script.js.$root_mapped.$path"
        script_key="$(echo "$obj_id" | tr '/ ' '__')"
      
        local common_json_host source_txt_host
        common_json_host="$TMPDIR/common_${script_key}.json"
        source_txt_host="$TMPDIR/source_${script_key}.txt"
      
        if jq -er 'type=="object" and has("common") and .common|has("source")' "$scriptjson" >/dev/null 2>&1; then
          local name engineType expert debug verbose enabled
          name="$(jq -r '.common.name // empty' "$scriptjson")"
          [[ -n "$name" && "$name" != "null" ]] || name="${base%.json}"
          engineType="$(jq -r '.common.engineType // "Javascript/Node.js"' "$scriptjson")"
          expert="$(jq -r '.common.expert // false' "$scriptjson")"
          debug="$(jq -r  '.common.debug  // false' "$scriptjson")"
          verbose="$(jq -r '.common.verbose // false' "$scriptjson")"
          enabled="$(jq -r '.common.enabled // false' "$scriptjson")"
      
          jq -c -n --arg name "$name" \
                   --arg engine "system.adapter.$ENGINE_INSTANCE" \
                   --arg engineType "$engineType" \
                   --argjson expert "$expert" \
                   --argjson debug "$debug" \
                   --argjson verbose "$verbose" \
                   --argjson enabled "$enabled" '
            { name:$name, engine:$engine, engineType:$engineType,
              expert:$expert, debug:$debug, verbose:$verbose, enabled:$enabled }' > "$common_json_host"
      
          jq -r '.common.source' "$scriptjson" > "$source_txt_host"
        else
          # Reines Source-JSON: Header entfernen, Defaults setzen
          sed -e '/\/\* -- do not edit following lines - START --/,/-- do not edit previous lines - END --\*\//d' "$scriptjson" > "$source_txt_host"
          jq -c -n --arg name "${base%.json}" \
                   --arg engine "system.adapter.$ENGINE_INSTANCE" \
                   --arg engineType "Javascript/Node.js" '
            { name:$name, engine:$engine, engineType:$engineType,
              expert:false, debug:false, verbose:false, enabled:false }' > "$common_json_host"
        fi
      
        # Encoding säubern
        iconv -f UTF-8 -t UTF-8 -c "$source_txt_host" | tr -d '\000' > "$source_txt_host.clean"
        mv "$source_txt_host.clean" "$source_txt_host"
      
        if [[ $DRY_RUN -eq 1 ]]; then
          echo "[dry-run] Script: $obj_id"
        else
          # Objekt anlegen (idempotent)
          docker exec -i "$CONTAINER" iobroker object set "$obj_id" '{"type":"script","common":{"name":""},"native":{}}' >/dev/null
      
          # common setzen
          docker cp "$common_json_host" "$CONTAINER:$CONTAINER_TMP/common_${script_key}.json" >/dev/null
          docker exec -i "$CONTAINER" sh -lc "C=\$(cat $CONTAINER_TMP/common_${script_key}.json); iobroker object set '$obj_id' \"common=\$C\"" >/dev/null
      
          # source setzen (als JSON-String)
          docker cp "$source_txt_host" "$CONTAINER:$CONTAINER_TMP/source_${script_key}.txt" >/dev/null
          docker exec -i "$CONTAINER" sh -lc "SRC_JSON=\$(jq -Rn --rawfile s '$CONTAINER_TMP/source_${script_key}.txt' '\$s'); iobroker object set '$obj_id' \"common.source=\$SRC_JSON\"" >/dev/null
        fi
      
        echo 1 >> "$progress_file"
      }
      
      export -f import_dir import_script show_progress
      export TMPDIR CONTAINER CONTAINER_TMP ENGINE_INSTANCE progress_file
      
      echo "==> Importiere Ordner (_dir.json) ..."
      printf "%s\n" "${DIR_FILES[@]}" \
        | xargs -P4 -n1 -I{} bash -c 'import_dir "{}"'
      
      echo "==> Importiere Skripte (*.json) ..."
      printf "%s\n" "${SCRIPT_FILES[@]}" \
        | xargs -P4 -n1 -I{} bash -c 'import_script "{}"'
      
      # Fortschrittsanzeige beenden
      wait "$PROGRESS_PID"
      
      echo -e "\n==> Import abgeschlossen: $TOTAL Objekte."
      
      echo "==> Starte Adapter: $ENGINE_INSTANCE"
      [[ $DRY_RUN -eq 1 ]] || iob start "$ENGINE_INSTANCE"
      
      echo "==> Fertig."
      
      posted in Skripten / Logik
      V
      Vippis
    • RE: IOBroker Automatisiertes Deployment

      Wie kann ich die erstellten Javascripts, die ich über die GUI aus einem Quellsystem exportiert habe mit der nativen Funktion, per CLI wieder importieren, so dass sie unter "Scripts" in der Admin GUI erscheinen?

      Wie kann ich einen Usertree unter 0_userdata wieder per CLI importieren?

      posted in Skripten / Logik
      V
      Vippis
    • RE: IOBroker Automatisiertes Deployment

      Für die Installation der NPM Module:

      #!/bin/bash
      log() { echo -e "[INFO] $1"; }
      
      IOBROKER_CID="iobroker"
      IOBROKER_NPM_PACKAGES=("moment" "axios" "influxdb-client" "@influxdata/influxdb-client" "@influxdata/influxdb-client-apis")
      
      # Array in Leerzeichen-getrennten String umwandeln
      libs_string=$(printf "%s " "${IOBROKER_NPM_PACKAGES[@]}")
      libs_string="${libs_string%" "}"   # letztes Leerzeichen entfernen
      
      log "➡️ Setze libraries für javascript.0 auf: ${libs_string}"
      
      docker exec -u 0 "${IOBROKER_CID}" bash -c \
        "iobroker object extend system.adapter.javascript.0 '{\"native\":{\"libraries\":\"${libs_string}\"}}'"
      
      # Danach sicherstellen, dass die Instanz die Pakete kennt
      docker exec -u 0 "${IOBROKER_CID}" bash -c "iobroker upload javascript"
      docker exec -u 0 "${IOBROKER_CID}" bash -c "iobroker restart javascript.0 || true"
      
      
      posted in Skripten / Logik
      V
      Vippis
    • RE: IOBroker Automatisiertes Deployment

      Vielen Dank schonmal @OliverIO und @Marc-Berg

      Die härteste Nuss finde ich fast das Admin PW setzen.

      Im Fall von Docker kann man ja

      docker exec iobroker bash -lc "iobroker user passwd '${IOB_ADMIN_USER}' '${IOB_ADMIN_PASSWORD}'"

      ausführen, aber ich lande immer in einer User-Eingabe das Passwort zu setzen. Geht das nicht per Skript?

      Und die NPM Pakete für den JS Adapter. Habt ihr da auch ein Kommando?

      posted in Skripten / Logik
      V
      Vippis
    • IOBroker Automatisiertes Deployment

      Hallo Community,

      ich bin dabei ein Deployment Skript für IOBroker zu erstellen, um automatisiert Raspberry Pis aufzusetzen mit einem immer gleichen Basissystem.

      Docker compose läuft. Ich brauche Hilfe bei folgenden Deployment per IOB CLI:

      • IOB Admin Passwort automatisiert setzen

      • Welcome Screen überspringen

      • Land/Stadt in Systemeinstellungen setzen (für Javascript astro)

      • Javascript+MQTT-Client Adapter installieren

      • MQTT-Client Instanz mit Username/PW/Host vom MQTT Broker konfigurieren

      • Bestimmte NPM Pakete für Javascript installieren

      • Javascripte aus Backup importieren (aus Dropbox)

      • 0.userdata Baum aus Backup importieren (aus Dropbox)

      • Bestimmte Datenpunkte in 0.userdata mit Infos befüllen, damit die Skripte zum Beispiel InfluxDB Credentials kennen

      Habe zu den meisten Punkten von ChatGPT gefragt, aber der stößt an seine Grenzen.

      Bedanke mich recht herzlich für Eure Hilfe!

      posted in Skripten / Logik
      V
      Vippis
    • RE: CSV Datei über VIS downloaden

      @vippis

      Man muss halt das Node FS Modul nehmen 🙂

      posted in Skripten / Logik
      V
      Vippis
    • RE: CSV Datei über VIS downloaden

      @mickym

      Ah super danke für die Info.

      In der Doku steht:

      The file that looks like '/subfolder/file.txt' will be stored under "/javascript/subfolder/file.txt" and can be accessed over web server with "http://ip:8082/javascript/subfolder/file.txt"

      const fs = require('node:fs');
      writeFile(null, '/subfolder/file.txt', data, (error) => {
          log('file written');
      });
      
      
      posted in Skripten / Logik
      V
      Vippis
    • RE: Skript im VIS-2 Editor funktioniert nur im Editor

      @vippis

      Ich löse einmal auf. All Credits to ChatGPT 😁

      Damit sich das Dropdown Menü wie gewünscht auch in der Runtime Umgebung öffent, musste ich den Code in das HTML Widget in den Script Tag aufnehmen.

      Zusätzlich bestand dann das Problem, dass alle Checkbox Labels als "$undefined:$undefined" angezeigt wurden.

      Das Problem liegt daran, dass mein Browser Firefox anscheinend keine Template Strings im Code unterstützt.

      Ich musste die Variablen dann auf einfache String-Verkettung umstellen, dann funktioniert es.

      const checkboxId = "checkbox-" + bucket + "-" + measurement;
      label.textContent = bucket + ": " + measurement;
      

      Hier das vollständige, lauffähige HTML Widget, falls jemand etwas vergleichbares aufbauen möchte:

      <div id="dropdown-container">
          <!-- Button zum Öffnen des Dropdowns -->
          <button id="dropdown-toggle" class="btn_grafana_style">Messwerte auswählen ▼</button>
          
          <!-- Das Dropdown-Menü, das die Checkboxen enthält -->
          <div id="dropdown-menu" style="display: none; max-height: 70vh; overflow-y: auto; position: absolute; background-color: white; border: 1px solid #ccc; padding: 10px; margin-top: 5px;">
              <!-- Dynamische Inhalte der Checkboxen werden hier eingefügt -->
          </div>
      </div>
      <script>
          // IDs der Datenpunkte
      const sourceDataPoint = "0_userdata.0.Export.Verfügbare_Messwerte"; // JSON mit Messwerten
      const targetDataPoint = "0_userdata.0.Export.Ausgewählte_Messwerte"; // Array für ausgewählte Messwerte
      
      // Dropdown-Elemente
      const dropdownToggle = document.getElementById("dropdown-toggle");
      const dropdownMenu = document.getElementById("dropdown-menu");
      
      // Funktion: Dropdown anzeigen/verstecken
      dropdownToggle.addEventListener("click", (event) => {
          event.stopPropagation(); // Verhindert, dass der Klick das Schließen triggert
          dropdownMenu.style.display = dropdownMenu.style.display === "none" ? "block" : "none";
      });
      
      // Funktion: Schließt das Dropdown, wenn man außerhalb klickt
      document.addEventListener("click", (event) => {
          if (!dropdownMenu.contains(event.target) && event.target !== dropdownToggle) {
              dropdownMenu.style.display = "none";
          }
      });
      
      // Funktion: Verfügbare Messwerte laden und Checkboxen generieren
      function loadMeasurements() {
          vis.conn.getStates(sourceDataPoint, (err, state) => {
              if (err || !state[sourceDataPoint] || !state[sourceDataPoint].val) {
                  console.error("Fehler beim Laden der Messwerte:", err || "Keine Daten gefunden");
                  return;
              }
      
              // JSON-Daten parsen
              const data = JSON.parse(state[sourceDataPoint].val);
              
      
              // Dropdown leeren
              dropdownMenu.innerHTML = "";
      
              // Checkboxen für alle Messwerte generieren
              data.forEach((item) => {
                  const bucket = item.bucket;
                  item.measurements.forEach((measurement) => {
                      const checkboxId = "checkbox-" + bucket + "-" + measurement;
                      const checkboxContainer = document.createElement("div");
                      checkboxContainer.style.marginBottom = "5px";
      
                      const checkbox = document.createElement("input");
                      checkbox.type = "checkbox";
                      checkbox.id = checkboxId;
                      checkbox.dataset.bucket = bucket;
                      checkbox.dataset.measurement = measurement;
      
                      const label = document.createElement("label");
                      label.htmlFor = checkboxId;
                      label.textContent = bucket + ": " + measurement;
      
                      checkboxContainer.appendChild(checkbox);
                      checkboxContainer.appendChild(label);
                      dropdownMenu.appendChild(checkboxContainer);
                  });
              });
              
              // Event-Listener für Änderungen an den Checkboxen hinzufügen
              Array.from(dropdownMenu.querySelectorAll("input[type='checkbox']")).forEach((checkbox) => {
                  checkbox.addEventListener("change", saveSelection);
              });
          });
      }
      
      // Funktion: Auswahl speichern
      function saveSelection() {
          const selectedMeasurements = [];
      
          // Alle ausgewählten Checkboxen sammeln
          Array.from(dropdownMenu.querySelectorAll("input[type='checkbox']:checked")).forEach((checkbox) => {
              selectedMeasurements.push({
                  bucket: checkbox.dataset.bucket,
                  measurement: checkbox.dataset.measurement
              });
          });
      
          // Auswahl als JSON-String in den Ziel-Datenpunkt speichern
          vis.setValue(targetDataPoint, JSON.stringify(selectedMeasurements));
      }
      
      // Messwerte beim Start laden
      loadMeasurements();
      
      // Falls sich die verfügbaren Messwerte ändern, neu laden
      vis.conn.subscribe(sourceDataPoint, (id, state) => {
          if (id === sourceDataPoint && state) {
              loadMeasurements();
          }
      });
      
      </script>
      
      
      posted in Skripten / Logik
      V
      Vippis
    • RE: Skript im VIS-2 Editor funktioniert nur im Editor

      @vippis

      In der Browser Konsole erscheinen auch keine Fehlermeldungen. Anscheinend wird das Skript gar nicht geladen

      posted in Skripten / Logik
      V
      Vippis
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo