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

Kategorie Mods

Privat

Mods die nur einzelne Kategorien betreuen

Beiträge


  • Klipper --> Telegram --> Snapshot
    NegaleinN Negalein

    wurde mit Hilfe von KI (Perplexity) erstellt

    /**
     * ========================================================
     * 3D-Druck Telegram Snapshot Script
     * ========================================================
     * 
     * Überwacht den Status deines 3D-Druckers und sendet per Telegram
     * regelmäßig Snapshots deiner Drucker-Webcam mit Fortschrittsbalken,
     * Restzeit und Dateinamen.
     * 
     * Version:     2.1 (2026-03-25)
     * Autor:       Christian Wimmer
     * ioBroker:    JavaScript-Adapter
     * 
     * LIZENZ: MIT License
     * 
     * Copyright (c) 2026 Christian Wimmer
     * 
     * Permission is hereby granted, free of charge, to any person obtaining a copy
     * of this software and associated documentation files (the "Software"), to deal
     * in the Software without restriction, including without limitation the rights
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     * copies of the Software, and to permit persons to whom the Software is
     * furnished to do so, subject to the following conditions:
     * 
     * The above copyright notice and this permission notice shall be included in
     * all copies or substantial portions of the Software.
     * 
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     * THE SOFTWARE.
     * 
     * ========================================================
     */
    
    console.log("🖨️ 3D-Druck Telegram Script v2.1 gestartet");
    
    // ==========================
    // KONFIGURATION
    // ==========================
    
    const TELEGRAM_INSTANCE = "telegram.0";
    const CHAT_ID           = DEINE_CHAT_ID;
    
    const DP_STATE     = "0_userdata.0.3DDrucker.Snapmaker_U1.print_stats.state";
    const DP_PROGRESS  = "0_userdata.0.3DDrucker.Snapmaker_U1.virtual_sdcard.progress_percent";
    const DP_FILENAME  = "0_userdata.0.3DDrucker.Snapmaker_U1.print_stats.filename";
    const DP_REMAIN    = "0_userdata.0.3DDrucker.Snapmaker_U1.Restzeit";
    
    const SNAPSHOT_URL = "http://10.0.1.244/webcam/snapshot.jpg";
    const DP_LAST_STEP = "0_userdata.0.3DDrucker.Script.lastStep";
    
    const STEP_SIZE    = 10;
    const SNAP_TIMEOUT = 5000;
    const MAX_STEP     = Math.floor(100 / STEP_SIZE);
    
    // ==========================
    // VARIABLEN
    // ==========================
    
    let printingActive = false;
    let currentFile    = "";
    
    // ==========================
    // INIT STATE
    // ==========================
    
    createState(DP_LAST_STEP, -1, {
        type:  "number",
        read:  true,
        write: true,
        def:   -1
    });
    
    // ==========================
    // HELFER
    // ==========================
    
    function sendTgText(text) {
        if (!text) return;
        sendTo(TELEGRAM_INSTANCE, "send", {
            text,
            chatId: CHAT_ID
        });
    }
    
    function getFileName() {
        const raw = getState(DP_FILENAME)?.val;
        if (!raw || typeof raw !== "string") return "Unbekannt";
    
        const withoutPath = raw.includes("/") ? raw.split("/").pop() : raw;
        return withoutPath.replace(/\.gcode$/i, "");
    }
    
    function formatTime(seconds) {
        const s = Number(seconds);
        if (!Number.isFinite(s) || s <= 0) return "--:--:--";
    
        const h   = Math.floor(s / 3600);
        const m   = Math.floor((s % 3600) / 60);
        const sec = s % 60;
    
        return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:${String(sec).padStart(2, "0")}`;
    }
    
    function getBar(p) {
        const progress = Math.min(Math.max(Number(p) || 0, 0), 100);
        const total    = 20;
        const filled   = Math.round((progress / 100) * total);
        let out        = "";
    
        for (let i = 0; i < total; i++) {
            if (i < filled) {
                if (progress < 30) out += "🟥";
                else if (progress < 70) out += "🟨";
                else out += "🟩";
            } else {
                out += "⬜";
            }
        }
        return out;
    }
    
    function buildCaption(progress) {
        const p      = Math.min(Math.max(Number(progress) || 0, 0), 100);
        const remain = getState(DP_REMAIN)?.val;
    
        return (
    `📸 ${p}%
    ${getBar(p)}
    ⏱️ ${formatTime(remain)}
    📄 ${currentFile || "Unbekannt"}`
        );
    }
    
    // ==========================
    // SNAPSHOT
    // ==========================
    
    function sendSnapshot(progress) {
        const caption = buildCaption(progress);
    
        httpGet(
            SNAPSHOT_URL,
            { responseType: "arraybuffer", timeout: SNAP_TIMEOUT },
            (err, res) => {
                const hasImage = !err && res && res.data && res.data.byteLength > 1000;
    
                if (!hasImage) {
                    sendTgText(caption + "\n⚠️ Kein Bild");
                    return;
                }
    
                const buffer = Buffer.from(new Uint8Array(res.data));
    
                writeFile("0_userdata.0", "snapshot_3d.jpg", buffer, () => {
                    readFile("0_userdata.0", "snapshot_3d.jpg", (error, data) => {
                        if (error || !data) {
                            sendTgText(caption + "\n⚠️ Lesefehler");
                            return;
                        }
    
                        sendTo(TELEGRAM_INSTANCE, "send", {
                            text:   data,
                            type:   "photo",
                            caption,
                            chatId: CHAT_ID
                        });
                    });
                });
            }
        );
    }
    
    // ==========================
    // START / STOP
    // ==========================
    
    on({ id: DP_STATE, change: "ne" }, obj => {
        const state = obj?.state?.val;
    
        if (state === "printing") {
            printingActive = true;
            currentFile    = getFileName();
    
            const p    = Math.floor(Number(getState(DP_PROGRESS)?.val) || 0);
            const step = Math.floor(p / STEP_SIZE);
    
            setState(DP_LAST_STEP, step, true);
    
            sendTgText(`🖨️ Start\n📄 ${currentFile}\n📊 ${p}%`);
    
            setTimeout(() => sendSnapshot(p), 1500);
            return;
        }
    
        const isEndState = state === "complete" || state === "idle" || state === "error";
    
        if (isEndState && printingActive) {
            printingActive = false;
    
            sendTgText(`🏁 Ende\n📄 ${currentFile}\nStatus: ${state}`);
    
            setTimeout(() => sendSnapshot(100), 2000);
    
            setState(DP_LAST_STEP, -1, true);
        }
    });
    
    // ==========================
    // FORTSCHRITT
    // ==========================
    
    on({ id: DP_PROGRESS, change: "ne" }, obj => {
        if (!printingActive) return;
    
        const pRaw = Number(obj?.state?.val) || 0;
        const p    = Math.min(Math.max(Math.floor(pRaw), 0), 100);
    
        let last = Number(getState(DP_LAST_STEP)?.val);
        if (!Number.isFinite(last)) last = -1;
    
        while (p >= (last + 1) * STEP_SIZE && last < MAX_STEP) {
            last++;
            setState(DP_LAST_STEP, last, true);
            sendSnapshot(p);
        }
    });
    
    // ==========================
    // INIT (RESTART)
    // ==========================
    
    setTimeout(() => {
        const state = getState(DP_STATE)?.val;
    
        if (state !== "printing") return;
    
        printingActive = true;
        currentFile    = getFileName();
    
        const p    = Math.floor(Number(getState(DP_PROGRESS)?.val) || 0);
        const step = Math.floor(p / STEP_SIZE);
    
        setState(DP_LAST_STEP, step, true);
    
        sendTgText(`🔄 Restart erkannt\n📄 ${currentFile}\n📊 ${p}%`);
    
        setTimeout(() => sendSnapshot(p), 2000);
    }, 5000);
    
    console.log("🖨️ 3D-Druck Telegram Script v2.1 bereit");
    

    3D-Druck Telegram Snapshot Script

    Dieses Projekt ist ein ioBroker-JavaScript, das den Status deines 3D-Druckers überwacht und per Telegram regelmäßig Snapshots deiner Drucker-Webcam mit Fortschrittsbalken, Restzeit und Dateinamen sendet.


    Features

    • Start-/Ende-Benachrichtigung bei Druckjobs
    • Fortschrittsupdates in konfigurierbaren Schritten (z.B. alle 10 %)
    • Snapshot der Webcam als Foto in Telegram
    • Emoji-Fortschrittsbalken und formatierte Restzeit
    • Robust gegenüber ioBroker-/Adapter-Neustarts (Erkennung laufender Drucke)

    Voraussetzungen

    • ioBroker mit JavaScript-Adapter
    • Telegram-Adapter eingerichtet (Bot + Chat-ID bekannt)
    • 3D-Drucker integriert (z.B. Snapmaker) mit folgenden Datenpunkten:
      • Druckstatus (printing, complete, idle, error)
      • Fortschritt in Prozent
      • Dateiname des Jobs
      • Restzeit (Sekunden oder kompatibel)
    • Webcam-URL, die ein Snapshot-Bild liefert

    Installation

    1. Script anlegen

      • In ioBroker Admin zu „Skripte“ wechseln.
      • Neues Skript im JavaScript-Adapter erstellen.
      • Den kompletten Script-Code aus diesem Repository einfügen.
    2. Konfiguration anpassen

      • Oben im Skript die Konstanten anpassen:
        • TELEGRAM_INSTANCE (z.B. "telegram.0")
        • CHAT_ID (deine Chat-ID)
        • DP_STATE, DP_PROGRESS, DP_FILENAME, DP_REMAIN auf deine Datenpunkte
        • SNAPSHOT_URL auf deine Webcam-Snapshot-URL
        • Optional: STEP_SIZE (z.B. 5 oder 10)
    3. Speichern und aktivieren

      • Skript speichern.
      • Sicherstellen, dass das Skript aktiviert ist.

    Kurzes Tutorial

    1. Telegram-Chat-ID ermitteln

    1. Telegram-Bot im Adapter anlegen und verbinden.
    2. Eine Nachricht an deinen Bot senden.
    3. Im ioBroker-Log oder in den Objekten des Telegram-Adapters nachsehen, welche Chat-ID verwendet wurde.
    4. Diese ID in CHAT_ID im Skript eintragen.

    2. Datenpunkte des Druckers finden

    1. Im ioBroker-Admin unter „Objekte“ nach deinem Drucker-Adapter suchen (z.B. Snapmaker_U1).
    2. Die relevanten Datenpunkte identifizieren:
      • Status (String, z.B. „printing“)
      • Fortschritt (Zahl in Prozent)
      • Dateiname (String)
      • Restzeit (Sekunden)
    3. Die vollständigen Pfade in die Konstanten DP_STATE, DP_PROGRESS, DP_FILENAME, DP_REMAIN im Skript eintragen.

    3. Webcam-Snapshot testen

    1. Die URL aus SNAPSHOT_URL im Browser öffnen.
    2. Wenn ein Bild geladen wird, ist alles gut.
    3. Falls nicht, die richtige Snapshot-URL des Druckers/Webcams ermitteln und im Skript eintragen.

    4. Funktion testen

    1. Einen Druckjob starten.
    2. In Telegram solltest du eine Start-Nachricht mit Fortschritt und kurz danach ein Foto erhalten.
    3. Während des Drucks bekommst du alle STEP_SIZE Prozent ein neues Bild.
    4. Am Ende des Drucks kommt eine End-Nachricht + abschließender Snapshot.

    Konfigurationstipps

    • STEP_SIZE verkleinern (z.B. 5), um häufiger Bilder zu bekommen.
    • SNAP_TIMEOUT erhöhen, wenn deine Webcam regelmäßig länger braucht.
    • Falls du mehrere Drucker hast, kannst du das Skript kopieren und die Datenpunkte/URLs pro Drucker anpassen.

    Lizenz

    Dieses Projekt steht unter der MIT License.

    JavaScript

  • Test Adapter Fronius 2.0.x
    NegaleinN Negalein

    funktioniert jetzt.

    78d2da33-9ad4-44de-9261-abebd082088f-image.jpeg

    Danke

    Tester

  • Test Adapter Fronius 2.0.x
    NegaleinN Negalein

    @Homoran sagte:

    Du nimmst ja auch das Objekt und nicht dessen Wert

    da kommt ein Fehler

    62ade94a-fdc6-49a8-a44a-5b4141104776-image.jpeg

    javascript.0	14:00:37.860	error	getState has been called with id of type "number" but expects a string
    javascript.0	14:00:37.861	error	Error: TypeError: Cannot read properties of undefined (reading 'val')
    javascript.0	14:00:37.861	error	    at Object.<anonymous> (script.js.Fronius.Hausverbrauch:5:153)
    javascript.0	14:00:37.861	error	    at Object.callback (/opt/iobroker/node_modules/iobroker.javascript/src/lib/sandbox.ts:1773:38)
    javascript.0	14:00:37.861	error	    at JavaScript.onStateChange (/opt/iobroker/node_modules/iobroker.javascript/src/main.ts:753:25)
    javascript.0	14:00:37.861	error	    at JavaScript.emit (node:events:519:28)
    javascript.0	14:00:37.861	error	    at Immediate.<anonymous> (/opt/iobroker/node_modules/@iobroker/js-controller-adapter/src/lib/adapter/adapter.ts:11163:53)
    javascript.0	14:00:37.861	error	    at processImmediate (node:internal/timers:484:21)
    javascript.0	14:00:37.861	error	    at process.callbackTrampoline (node:internal/async_hooks:130:17)
    
    Tester

  • Test Adapter Fronius 2.0.x
    NegaleinN Negalein

    @Homoran sagte:

    Bei Änderung Ergebnis in eigenen Datenpunkt schreiben

    habs so versucht.
    Da schreibt er mir (null) in den erstellten DP (number).

    d3750ac6-6a6b-4763-9984-937dd9646f4a-image.jpeg

    50cd8063-c8cf-4453-aa3a-77bade35f5f6-image.jpeg

    {
      "common": {
        "name": "Fronius.Verbrauch",
        "desc": "Manuell erzeugt",
        "role": "state",
        "type": "number",
        "read": true,
        "write": true,
        "def": 0
      },
      "type": "state",
      "native": {},
      "from": "system.adapter.admin.0",
      "user": "system.user.admin",
      "ts": 1776080048723,
      "_id": "0_userdata.0.Fronius.Verbrauch",
      "acl": {
        "object": 1636,
        "state": 1636,
        "owner": "system.user.admin",
        "ownerGroup": "system.group.administrator"
      }
    }
    
    Tester

  • Test Adapter Fronius 2.0.x
    NegaleinN Negalein

    @klassisch sagte:

    Die Differenz zwischen P_Load und P_Grid wird im Haus verbraucht.

    Danke dir

    Also müsste ich den Hausverbrauch dann zB mit Blockly berechnen?
    Du hast nicht zufällig was fertiges? ;)

    Tester

  • Test Adapter Fronius 2.0.x
    NegaleinN Negalein

    Hallo

    Ich komm mit den DP nicht zurecht. Was ist was?!

    Ich bräuchte folgende:

    • PV Erzeugung
    • Netz Bezug
    • Netz Einspeisung
    • Hausverbrauch

    Finde ich die unter fronius.0.inverter.1 oder fronius.0.meter.0 oder doch eher fronius.0.site?

    Wäre super, wenn mir wer weiterhelfen könnte.


    hab gerade das gefunden.
    Würde das passen?

    P_Akku : in die Batterie fließende Leistung
    P_Grid : aus dem Netz bezogene Leistung (für die man zahlen muss).
    P_Load : ins Hausnetz abgegebene Leistung als Summe von P_AC und P_Grid. Anm.: Hieraus lässt sich der Eigenverbrauch des GEN24 ermitteln.
    P_PV : von den Solarmodulen DC-seitig gelieferte Leistung

    Tester

  • X-Sense Adapter
    NegaleinN Negalein

    @arteck sagte:

    @Negalein nein da sind mehr.

    https://github.com/arteck/ioBroker.xsense/wiki/Devices

    Danke dir.

    zu MQTT: wird hier der Status schneller übermittelt?

    Tester

  • X-Sense Adapter
    NegaleinN Negalein

    @Merlin123 sagte:

    Ich hab verschiedene RMs....

    die funktionieren alle mit dem SBS50?

    Lt. XSense ja nur
    193f8e85-3515-44c0-a3a1-91de50d0b730-image.jpeg

    Tester

  • X-Sense Adapter
    NegaleinN Negalein

    @Merlin123 sagte:

    Hat jirgendetwas unter einer Minute gedauert

    rein über Cloud oder MQTT?

    PS: welchen RM nutzt du?

    Tester

  • Liste mit Geräten und deren Auflösung für VIS
    NegaleinN Negalein

    @Longbow sagte:

    welche Auflösung wäre bei einem iPhone 17 Pro Max ?

    testen wie im 1. Beitrag beschrieben

    Visualisierung vis

Mitgliederliste

NegaleinN Negalein
SegwayS Segway
  • 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