Navigation

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

    NEWS

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

    • Neues Video über Aliase, virtuelle Geräte und Kategorien

    • Wir empfehlen: Node.js 22.x

    • Profile
    • Following 0
    • Followers 0
    • Topics 27
    • Posts 286
    • Best 23
    • Groups 2

    Lucifor1976

    @Lucifor1976

    24
    Reputation
    47
    Profile views
    286
    Posts
    0
    Followers
    0
    Following
    Joined Last Online
    Website www.do4fbi.de Location Heinsberg Age 49

    Lucifor1976 Follow
    Pro Starter

    Best posts made by Lucifor1976

    • RE: Welcher Intel Nuc / HP Elitedesk

      Ich kann und möchte auch meinen Senf dazugeben.

      Ich fahre eine ganz andere Mentalität und meine Einstellung zu Servern ist eher konvervativ und vor allem Old-School.
      Das hat aber auch seinen Grund. Ich komme nicht aus der Windows Welt. Ich bin seit meiner Jugend Linuxer und Mac Nutzer.
      Ich betreibe seit Jahrzehnten Linux Server vor allem auf Debian. Das ist also in keinster Weise Neuland für mich.
      Jede Hardware hat Ihre Eigenarten, siehe IR Lese/Schreibkopf für einen Stromzähler, da hab ich mal fünf Minuten an meinen Fähigkeiten gezweifelt. (Bis er lief).
      Aber ich benötige keine Werkzeuge um einen Debian Server in Minuten zu backuppen und wiederherzustellen. Und zwar vollständig. Auch Snapschots sind drin, dazu brauchts keine Werkzeuge, sondern ein wenig (ok ich gebe zu ausgeprägte Kenntnisse) der Shell unter einem Linux und deren Funktionsweise. Auch die Notwendigkeit einer Virtualisierung erschließt sich mir nicht. Ich denke seit Wochen darüber nach und habe viel dazu gelesen. Aber zu der Erkenntnis das das notwendig ist bin ich nicht gekommen.
      Ich bin ein ein Freund von autarken Systemen, ich gebe einem angemessenen System eine angemesse Aufgabe.
      Der sogenannte "Single Point of Failure" ist für mich der Worst Case und auf jeden Fall zu vermeiden. ICh werde also neimals einem System die komplette Kontrolle überlassen. Mein NAS ist ein NAS und kein Docker, schön das es das kann, aber das ist meiner Meinung nach nicht der Sinn des NAS, es heisst schließlich auch Network attached Storage und nicht Network attached Allroundsystem.
      Beduetet für mich persönlich schlicht das auf dem NAS kein Docker und kein ioBroker was zu suchen haben, ebenso aber auch das ich einem Despro keine NAS Aufgaben gebe. Sehr wohl aber das ein NAS ein Datenbankserver sein kann und ein Deskpro eben ein ioBroker. Aber deswegen Virtuallisiere ich nicht, werd ich auch nicht.
      Der Deskpro bekommt zwei SSd´s die Im Raid 1 Verbund unter Debian meinen ioBroker samt aller Instanzen, Grafana, Wetterstation und ähnlichem hosten darf.
      Proxmox und Derivate sind gut für Anwender die Windows gewohnt sind und sich nicht wirklich um den Unterbau scheren wollen. Das ist ja auch OK, aber eben nichts für mich. Das Argument schnelle Backups, schnelle Wiederherstellung ect zählen für mich nicht, da sowas Linux von sich aus kann, man nur wissen wo und wie. Stichtort ist hier SMB und dd, mehr brauchts eigentlich nicht. Der ganze Spaß ist gard mal eine Kommandozeile lang. Inklusive zip und Tar. Wem die vier Befehle jetzt nichts sagen ist mit Proxmox deutlich besser drann das gebe ich zu, es trifft auf mich aber nunmal nicht zu. Für mich ist eine Virtualisierungsunterbau nur Recourcenverschwendung.
      Ich will niemandem zu nahe treten, aber das ist meine Meinung

      posted in Hardware
      Lucifor1976
      Lucifor1976
    • RE: [Guide] Zwangsumstellung auf Smartmeter: Freut Euch drauf!

      @Homoran Der Sensor ist nach Augenmaß justiert, soweit dies möglich ist. Der Magnet der dabei ist ist etwas mager. USB Anschluss zeigt nach unten. (das ganze mit ein wenig Tape besser fixiert)

      Die Einstellungen im Adapter sehen so aus: (Entnommen aus der Anleitung von @klassisch

      Bildschirmfoto 2020-11-24 um 15.24.58.png

      Die Objekte im iobroker sehen so aus.:

      Bildschirmfoto 2020-11-24 um 15.24.38.png

      Der Zähler seöbst steht auf Info und es rotieren die Standard Angaben da ich noch keine PIN habe.

      Der Adapter steht auf gelb.

      Ein sudo cat /dev/ttyUSB0 ergibt nichts
      Ein sudo cat /dev/ttAMA0 ergibt nichts
      Ein xxd /dev/ttyUSB0 ergibt nichts
      Ein xxd /dev/ttyAMA0 ergibt nichts

      Ich bin jetzt definitv ratlos 😕

      Edit zu guter letzt noch ein Log im Debug Mode.

      Bildschirmfoto 2020-11-24 um 15.33.31.png

      Edit1:
      Ein "sudo dmesg | grep tty" ergibt ja schon mal etwas ...
      [ 0.896371] 3f201000.serial: ttyAMA0 at MMIO 0x3f201000 (irq = 81, base_baud = 0) is a PL011 rev2

      Also da isser wohl...

      Edit2:
      So läuft.. Ein wenig Doku zu dem Sensor wäre schon toll gewesen.
      Ein gepflegtes "stty -F /dev/ttyUSB0 9600 -parity - cstopb" hat den Sensor zur Arbeit bewegt.

      Herzlichen Dank an alle 🙂

      posted in Praktische Anwendungen (Showcase)
      Lucifor1976
      Lucifor1976
    • Script: HP-ILO 4 Abfrage Temperaturen und FanSpeed

      Hallo zusammen,

      ich nutzte lange den HP-ILO Adapter um meine beiden Server auszulesen.
      Der Adapter wird leider nicht weiter geplegt (letze Änderung vor 5 Jahren).

      Ich habe nun dazu ein Javascript erstellt, welches das gleiche tut.
      Für diejenigen die den Adapter ebenfalls vermissen vielleicht eine Alternative.
      Einfach in Javascript reinkopieren und im iobroker Axiox istallieren. Ohne Axios wird das Script nicht funktionieren.

      Script:

      outdated
      

      Axios installieren:
      auf iobroker per ssh einloggen

      per

      cd /opt/iobroker/node_modules/iobroker.javascript
      

      ins richtige Verzeichnis welchseln und dann per:

      sudo npm install axios
      

      Axios installieren, danach javascript neu starten:

      iobroker restart javascript
      

      Danach das Script starten.
      fertig

      Gruß
      Lucifor

      Künftige Änderungen hier:

      https://github.com/Lucifor1976/HP-ILO
      

      Update: 29.06.2025 12:30

      Das Script ruft nun alle verfügbaren Daten aus dem Server ab.
      Voraussetzung ist ILO 4 Version 2.81 (also die letzte die mit der Service DVD kam)
      Das Script speichert BEnutzername und Kennwort im Klartext, das muss dir bewusst sein!

      Erfolgreich abgerufen wird:
      BIOS
      Physische DISKS
      FANS
      FIRMWARE
      NETWORK
      POWER (Consumption only)
      RAID Konfiguration
      SMART
      SYSTEM
      TEMPERATUREN

      Update: Bei überschreiten von 70 Grad der CPU´s oder bei Ausfall eines PSU wird ein Telegram abgesetzt und eine Alexa Ansage getätigt. (Abschaltbar)

      https://github.com/Lucifor1976/HP-ILO
      

      posted in JavaScript
      Lucifor1976
      Lucifor1976
    • RE: Welcher Intel Nuc / HP Elitedesk

      @lemuba
      Hi, der wäre optisch auch schöner als ein NUC. Leider ist er nicht lieferbar, weder bei Saturn, noch bei MM. Amazon hat Ihn wohl aber auch für 399,-- ohne irgendwelche Rabatte. Aber auch erst in Wochen lieferbar. Ich frag mich grad was mit Amazon los ist, egal nach was mach schaut alles ist erst in Wochen oder gar Monaten lieferbar.

      Allerdings nicht zu vergessen. Die Konfig beinhaltet 8GB RAM und 250 GB SSD bei einem i5 9500.
      Der NUC wäre mit einem i5 10210, 16GB RAM und 500GB SSD für schlappe 35 Takken mehr.
      (NUC 317,-- bei MF, 500GB SSD (M2 Crucial) bei Amazon fürn 50i und 2x8 GB RAM (2666) für 61 Euro (MF).

      posted in Hardware
      Lucifor1976
      Lucifor1976
    • RE: VIS von Sigi234

      Respekt! Die VIS wird immer besser uns ausgereifter! Es macht Spaß sich bei Dir Inspiration zu holen 🙂

      Hat schon jemand versucht Apple Podcasts per iobroker auf einer Alexa abzuspielen?

      posted in Praktische Anwendungen (Showcase)
      Lucifor1976
      Lucifor1976
    • RE: Ständig Beachball auf allen Geräten?

      @cbrocker sagte in Ständig Beachball auf allen Geräten?:

      @lucifor1976 Hey, hattest du bei dem Problem Erfolg mit der 5.5.3? Läuft die VIS bei dir nun richtig?
      Ich habe das gleiche Problem seit Umstieg von Rasp Pi auf Proxmox mit der VIS
      Gib mir bitte mal ein Feedback

      Grüße Christoph

      Hallöchen, es ist etwas besser geworden, aber nicht weg.
      Auf meinen FireHD Geräten nervt das grad extrem, denn immer genau dann wenn man etwas schalten will kommt der Beachball. Dann darf man erstmal einen Reload machen (In Fully auch nicht grade schnell).

      Ich versuche gerade etwas Last vom System zu nehmen, indem ich die Influx schon auf meine Diskstation ausgelagert habe, ist aber noch Paralellbetrieb.

      Was machen die Leute die "nur" einen Raspberry nutzen, läuft da garnichts mehr?

      An den Einstellungen liegt es jedenfalls nicht, denn egal was eingestellt ist, es ändert sich nichts.

      posted in ioBroker Allgemein
      Lucifor1976
      Lucifor1976
    • RE: Welcher Intel Nuc / HP Elitedesk

      @lemuba
      Einer von denen ist es geworden, aber nicht von Kleinanzeigen 🙂
      Bin ich ja mal gespannt was da kommt.. Speicher kann ich nachrüsten und die SSD wird erstmal reichen.

      posted in Hardware
      Lucifor1976
      Lucifor1976
    • RE: Gosund Smart Plug EP2 - noch zu retten?

      Ich möchjte hier einfach mal Mut machen 🙂

      Ich habe heute 4 Gosund EP2 erfolgreich auf Tasmota gebracht (OTA) und Tuya-Convert auf einem Raspberry 3b.

      Danach lief das Update auf Tasmota 12. einwandfrei durch 🙂

      1. Bei Gosund das Update auf 1.0.6 anfordern und ausführen lassen (hat einen Tag gedauert)
      2. Taster auf der Stecksode 5 Sek. drücken
      3. Tuya-Convert Flash Vorgang starten
      4. Hoffen und Bangen
      5. Handy W-Lan mit dem Tasmota-xxxx WLan verbinden.
      6. Acesspoint Daten eingeben, Hostname konfigurieren
      7. Neustart abwarten
      8. Template im EP2 konfigurieren
      9. Update auf Tasmota 12. per Tasmota Admin oder Tool der Wahl.
      10. Freuen 🙂
      11. Mail an Gosund mit der Bitte solche Sperren sein zu lassen, Tasmota nativ anzubieten und deutlich mehr Absatz durch Verkäufe generieren. (ich habs gemacht).
      posted in Microcontroller
      Lucifor1976
      Lucifor1976
    • RE: Ständig Beachball auf allen Geräten?

      @cbrocker sagte in Ständig Beachball auf allen Geräten?:

      @lucifor1976 stimmt genau.
      Ja, den Verbindungsfehler habe ich damit wegbekommen.

      Mich irritiert, daß ich im Rasp Pi gar kein Häkchen im Webadapter aktiv hatte und da lief es wie geschmiert.

      Mal eine doofe Idee. Haken raus und ausprobieren ob der Beachball wieder auftaucht..
      Wäre nur blöd, wenn man dann ständig den Haken setzen muss um den Editor nutzen zu können.
      (Mein Vorschlag damals die Autosafe Funktion im Editor als Option zu machen, wurde ja leider komplett ignoriert. Das kann einem ganz schön die Visualisierung versauen)

      posted in ioBroker Allgemein
      Lucifor1976
      Lucifor1976
    • RE: Welcher Intel Nuc / HP Elitedesk

      @klassisch
      Ja genau eigentlich ist es genau das. Aber das ist ebenfalls genau das wozu ich mich die letzten 25 Jahre gezwungen habe, eben nicht auf ein Backup zurückzugreifen, sondern tatsächlich den Fehler zu suchen und zu beheben.
      Ich komme aus der Branche, wenn ein Kunde zu mir kommt und raushaut: "Ich hab hier so eine seltsame Fehlermeldung und meine Webseite ist nicht mehr erreichbar" und man fragt gibts es Backups, kommt in der Regel "Nein" (kostet ja zusätzlich Geld (Dienst)) und man dann auf die Seite geht, oder auf den SQL Server und dieser begrüßt dich mit einem freudigen:

      ERROR xxxx: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
      

      und du weisst nich was zu tun ist, haste ein Problem. (Gerne werden Passwörter zur DB "aktualisiert" aber nicht gleich überall wo es nötig gewesen wäre.. und schwupps nix geht mehr.

      posted in Hardware
      Lucifor1976
      Lucifor1976

    Latest posts made by Lucifor1976

    • RE: Adapter Klipper-Moonraker

      Ich war so frei und habe eine Scriptversion gebsatelt.
      Die Dezimaldaten werden direkt konvertiert sodas direkt lesbare Datenpunkte entstehen.
      Das ganze kann als Script in iobroker verwendet werden.
      Einfach Moonraker ip anpassen, ggf Alexa ID anpassen.
      Der Code darf gerne ganz oder Teilweise für den Adapter genutzt werden.

      // ======== CONFIG ========
      const MOONRAKER_HOST = "192.168.1.160";
      const MOONRAKER_PORT = 7125;
      const BASE = `http://${MOONRAKER_HOST}:${MOONRAKER_PORT}`;
      const POLL_MS = 10_000;
      
      // Ablagepfad in ioBroker
      const ROOT = "javascript.0.moonraker.Kossel";
      
      // Optional: Testfunktion (Alexa-Ansage jede Minute)
      const ENABLE_TEST_SPEAK = false; // ← bei Bedarf auf true
      const ALEXA_SPEAK_DP = "alexa2.0.Echo-Devices.IDANPASSEN.Commands.speak"; // Deine Echo-ID einsetzen
      const TEST_MESSAGE = "Moonraker Script Test läuft.";
      
      // ======== HELFER ========
      
      // HTTP GET (Node.js Core)
      function httpGet(url, timeout = 5000) {
       return new Promise((resolve, reject) => {
         const http = require("http");
         const req = http.get(url, (res) => {
           if (res.statusCode < 200 || res.statusCode >= 300) {
             reject(new Error(`HTTP ${res.statusCode} for ${url}`));
             res.resume();
             return;
           }
           let data = "";
           res.setEncoding("utf8");
           res.on("data", (chunk) => (data += chunk));
           res.on("end", () => {
             try {
               resolve(JSON.parse(data));
             } catch (e) {
               reject(new Error(`JSON parse error for ${url}: ${e.message}`));
             }
           });
         });
         req.on("error", reject);
         req.setTimeout(timeout, () => {
           req.destroy(new Error(`Timeout after ${timeout}ms for ${url}`));
         });
       });
      }
      
      // State-Helper
      async function ensureState(id, def) {
       if (!existsState(id)) {
         await createStateAsync(id, def, { role: def.common?.role || "state" });
       }
      }
      async function writeNum(id, val, unit = "", role = "value") {
       await ensureState(id, {
         type: "number",
         read: true,
         write: false,
         def: 0,
         name: id.split(".").slice(-1)[0],
         role,
         unit
       });
       setState(id, { val: Number(val), ack: true });
      }
      async function writeStr(id, val, role = "text") {
       await ensureState(id, {
         type: "string",
         read: true,
         write: false,
         def: "",
         name: id.split(".").slice(-1)[0],
         role
       });
       setState(id, { val: String(val ?? ""), ack: true });
      }
      async function writeBool(id, val, role = "indicator") {
       await ensureState(id, {
         type: "boolean",
         read: true,
         write: false,
         def: false,
         name: id.split(".").slice(-1)[0],
         role
       });
       setState(id, { val: !!val, ack: true });
      }
      
      // Formatierungen / Konvertierungen
      function toPercent01(v) {
       if (v == null || isNaN(v)) return null;
       return Math.round(Number(v) * 1000) / 10; // 1 Nachkommastelle
      }
      function toHMS(seconds) {
       if (seconds == null || isNaN(seconds)) return "";
       const s = Math.max(0, Math.floor(seconds));
       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 round1(v) {
       if (v == null || isNaN(v)) return null;
       return Math.round(Number(v) * 10) / 10;
      }
      
      // Dynamik-Cache für Objekte (Fans, Temp-Sensoren, etc.)
      let discovered = {
       fans: [],
       tempSensors: [],
       hasHeaterBed: false,
       hasExtruder: false,
       hasDisplayStatus: false,
       hasGcodeMove: false,
       hasVirtualSd: false,
       hasToolhead: false,
       hasPrintStats: false,
       lastDiscoveryTs: 0
      };
      
      async function discoverObjects() {
       try {
         const list = await httpGet(`${BASE}/printer/objects/list`);
         const raw = list?.result?.objects;
      
         let names = [];
         if (Array.isArray(raw)) {
           names = raw
             .map((o) => (typeof o === "string" ? o : (o && o.name) ? String(o.name) : ""))
             .filter((n) => typeof n === "string" && n.length > 0);
         } else if (raw && typeof raw === "object") {
           names = Object.keys(raw);
         } else {
           names = [];
         }
      
         const isStr = (n) => typeof n === "string" && n.length > 0;
      
         discovered.fans = names.filter((n) =>
           isStr(n) && (n.startsWith("fan") || n.startsWith("heater_fan") || n.startsWith("controller_fan") || n.startsWith("fan_generic"))
         );
      
         discovered.tempSensors = names.filter((n) =>
           isStr(n) && (n.startsWith("temperature_sensor") || n.startsWith("temperature_fan") || n.startsWith("bme280") || n.startsWith("htu21d") || n.startsWith("lm75"))
         );
      
         discovered.hasHeaterBed = names.includes("heater_bed");
         discovered.hasExtruder = names.includes("extruder");
         discovered.hasDisplayStatus = names.includes("display_status");
         discovered.hasGcodeMove = names.includes("gcode_move");
         discovered.hasVirtualSd = names.includes("virtual_sdcard");
         discovered.hasToolhead = names.includes("toolhead");
         discovered.hasPrintStats = names.includes("print_stats");
      
         discovered.lastDiscoveryTs = Date.now();
         await writeStr(`${ROOT}.meta.last_discovery`, new Date().toISOString());
         await writeNum(`${ROOT}.meta.discovered.fans_count`, discovered.fans.length, "", "value");
         await writeNum(`${ROOT}.meta.discovered.temp_sensors_count`, discovered.tempSensors.length, "", "value");
       } catch (e) {
         log(`Moonraker discovery error: ${e.message}`, "warn");
       }
      }
      
      function buildQueryParams() {
       const objs = ["print_stats"];
       if (discovered.hasHeaterBed) objs.push("heater_bed");
       if (discovered.hasExtruder) objs.push("extruder");
       if (discovered.hasDisplayStatus) objs.push("display_status");
       if (discovered.hasGcodeMove) objs.push("gcode_move");
       if (discovered.hasVirtualSd) objs.push("virtual_sdcard");
       if (discovered.hasToolhead) objs.push("toolhead");
       if (discovered.hasPrintStats) objs.push("print_stats");
      
       objs.push(...discovered.fans);
       objs.push(...discovered.tempSensors);
      
       const q = objs.map(encodeURIComponent).join("&");
       return `${BASE}/printer/objects/query?${q}`;
      }
      
      // ======== REST DES POLLERS (pollOnce, Startup, Timer, etc.) ========
      
      // Alexa-Ansage Tracking (Doppelansagen vermeiden)
      let lastPrintState = "";
      let lastAnnouncedFile = "";
      let lastAnnouncedTs = 0;
      const ANNOUNCE_COOLDOWN_MS = 5 * 60 * 1000; // 5 Minuten
      
      async function pollOnce() {
       try {
         
         // 1) Basisinfos
         const [serverInfo, printerInfo] = await Promise.all([
           httpGet(`${BASE}/server/info`),
           httpGet(`${BASE}/printer/info`)
         ]);
      
         const s = serverInfo?.result || {};
         await writeStr(`${ROOT}.server.version`, s.version || "");
         await writeStr(`${ROOT}.server.klippy_state`, s.klippy_state || "");
         await writeStr(`${ROOT}.server.hostname`, s.hostname || "");
         await writeStr(`${ROOT}.server.websocket_address`, s.websocket_address || "");
      
         const p = printerInfo?.result || {};
         await writeStr(`${ROOT}.printer.state`, p.state || "unknown");
         await writeBool(`${ROOT}.printer.ready`, p.state === "ready", "indicator.reachable");
      
         // 2) Objekte ggf. alle 5 Min neu entdecken
         if (Date.now() - discovered.lastDiscoveryTs > 5 * 60 * 1000 || discovered.lastDiscoveryTs === 0) {
           await discoverObjects();
         }
      
         // 3) Printer Objects abfragen
         const queryUrl = buildQueryParams();
         const q = await httpGet(queryUrl);
         const res = q?.result?.status || {};
      
         // ---- print_stats ----
         let currentFilename = "";
         let layerInfo = { current: null, total: null };
         let metaFromFile = { layer_height: null, object_height: null };
      
         if (res.print_stats) {
           const ps = res.print_stats;
           await writeStr(`${ROOT}.print_stats.state`, ps.state || "");
           await writeStr(`${ROOT}.print_stats.filename`, ps.filename || "");
           await writeStr(`${ROOT}.print_stats.message`, ps.message || "");
      
           currentFilename = ps.filename || "";
      
      // === Alexa-Ansage bei Fertigstellung ===
      try {
       let shouldAnnounce = false;
       if ((ps.state || "") === "complete") {
         if (currentFilename) {
           if (currentFilename !== lastAnnouncedFile) {
             shouldAnnounce = true;
             lastAnnouncedFile = currentFilename;
           }
         } else if (lastPrintState !== "complete" && (Date.now() - lastAnnouncedTs) > ANNOUNCE_COOLDOWN_MS) {
           shouldAnnounce = true;
         }
       }
       if (shouldAnnounce) {
         const msg = currentFilename ? `Druckauftrag abgeschlossen: ${currentFilename}.` : "Der 3D Druck ist fertig.";
         setState(ALEXA_SPEAK_DP, { val: msg, ack: false }); // nutzt deinen Alexa-Datenpunkt
         lastAnnouncedTs = Date.now();
         await writeStr(`${ROOT}.meta.last_completed_file`, currentFilename || "");
         await writeStr(`${ROOT}.meta.last_announcement`, new Date().toISOString());
       }
       lastPrintState = ps.state || "";
      } catch (e) {
       log("Alexa-Fertig-Ansage fehlgeschlagen: " + e.message, "warn");
      }
           
           if (ps.total_duration != null) await writeStr(`${ROOT}.print_stats.total_duration_hms`, toHMS(ps.total_duration), "time");
           if (ps.print_duration != null) await writeStr(`${ROOT}.print_stats.print_duration_hms`, toHMS(ps.print_duration), "time");
           if (ps.filament_used != null) {
             const m = Math.round((Number(ps.filament_used) || 0) / 10) / 100; // mm → m
             await writeNum(`${ROOT}.print_stats.filament_used_m`, m, "m", "value.length");
           }
           if (ps.progress != null) {
             await writeNum(`${ROOT}.print_stats.progress_percent`, toPercent01(ps.progress), "%", "value.percent");
           }
           // Layer bevorzugt aus print_stats.info (nur vorhanden, wenn Slicer SET_PRINT_STATS_INFO mitschreibt)
           const info = ps.info || {};
           if (info.current_layer != null) layerInfo.current = Number(info.current_layer);
           if (info.total_layer != null) layerInfo.total = Number(info.total_layer);
         }
      
         // ---- toolhead (für Z→Layer-Fallback) ----
         let zPos = null;
         if (res.toolhead) {
           const th = res.toolhead;
           if (Array.isArray(th.position)) {
             const [x, y, z] = th.position;
             zPos = (z != null ? Number(z) : null);
             await writeNum(`${ROOT}.toolhead.x`, round1(x), "mm", "value.length");
             await writeNum(`${ROOT}.toolhead.y`, round1(y), "mm", "value.length");
             await writeNum(`${ROOT}.toolhead.z`, round1(z), "mm", "value.length");
           }
           if (th.max_velocity != null) await writeNum(`${ROOT}.toolhead.max_velocity`, round1(th.max_velocity), "mm/s", "value.speed");
           if (th.max_accel != null) await writeNum(`${ROOT}.toolhead.max_accel`, round1(th.max_accel), "mm/s²", "value.acceleration");
           if (th.homing_origin && Array.isArray(th.homing_origin)) {
             const [hx, hy, hz] = th.homing_origin;
             await writeNum(`${ROOT}.toolhead.homing_origin.x`, round1(hx), "mm", "value.length");
             await writeNum(`${ROOT}.toolhead.homing_origin.y`, round1(hy), "mm", "value.length");
             await writeNum(`${ROOT}.toolhead.homing_origin.z`, round1(hz), "mm", "value.length");
           }
           if (th.print_time != null) await writeStr(`${ROOT}.toolhead.print_time_hms`, toHMS(th.print_time), "time");
         }
      
         // ---- gcode_move ----
         if (res.gcode_move) {
           const gm = res.gcode_move;
           if (gm.speed != null) await writeNum(`${ROOT}.gcode_move.speed`, round1(gm.speed), "mm/s", "value.speed");
           if (gm.speed_factor != null) await writeNum(`${ROOT}.gcode_move.speed_factor_percent`, toPercent01(gm.speed_factor), "%", "value.percent");
           if (gm.extrude_factor != null) await writeNum(`${ROOT}.gcode_move.extrude_factor_percent`, toPercent01(gm.extrude_factor), "%", "value.percent");
           if (Array.isArray(gm.gcode_position)) {
             const [x, y, z, e] = gm.gcode_position;
             await writeNum(`${ROOT}.gcode_move.gcode_x`, round1(x), "mm", "value.length");
             await writeNum(`${ROOT}.gcode_move.gcode_y`, round1(y), "mm", "value.length");
             await writeNum(`${ROOT}.gcode_move.gcode_z`, round1(z), "mm", "value.length");
             await writeNum(`${ROOT}.gcode_move.gcode_e`, round1(e), "mm", "value.length");
           }
         }
      
         // ---- heater_bed ----
         if (res.heater_bed) {
           const hb = res.heater_bed;
           if (hb.temperature != null) await writeNum(`${ROOT}.heater_bed.temperature`, round1(hb.temperature), "°C", "value.temperature");
           if (hb.target != null) await writeNum(`${ROOT}.heater_bed.target`, round1(hb.target), "°C", "value.temperature");
           if (hb.power != null) await writeNum(`${ROOT}.heater_bed.power_percent`, toPercent01(hb.power), "%", "value.percent");
         }
      
         // ---- extruder ----
         if (res.extruder) {
           const ex = res.extruder;
           if (ex.temperature != null) await writeNum(`${ROOT}.extruder.temperature`, round1(ex.temperature), "°C", "value.temperature");
           if (ex.target != null) await writeNum(`${ROOT}.extruder.target`, round1(ex.target), "°C", "value.temperature");
           if (ex.power != null) await writeNum(`${ROOT}.extruder.power_percent`, toPercent01(ex.power), "%", "value.percent");
           if (ex.pressure_advance != null) await writeNum(`${ROOT}.extruder.pressure_advance`, round1(ex.pressure_advance), "", "value");
           if (ex.smooth_time != null) await writeNum(`${ROOT}.extruder.smooth_time`, round1(ex.smooth_time), "s", "value.interval");
         }
      
         // ---- virtual_sdcard ----
         if (res.virtual_sdcard) {
           const vsd = res.virtual_sdcard;
           if (vsd.progress != null) await writeNum(`${ROOT}.virtual_sdcard.progress_percent`, toPercent01(vsd.progress), "%", "value.percent");
           if (vsd.file_position != null) await writeNum(`${ROOT}.virtual_sdcard.file_position`, Number(vsd.file_position), "B", "value");
         }
      
         // ---- display_status ----
         if (res.display_status) {
           const ds = res.display_status;
           await writeStr(`${ROOT}.display_status.message`, ds.message || "");
           if (ds.progress != null) await writeNum(`${ROOT}.display_status.progress_percent`, toPercent01(ds.progress), "%", "value.percent");
         }
      
         // ---- Fans ----
         for (const f of discovered.fans) {
           const key = f;
           const safeKey = key.replace(/\s+/g, "_");
           const obj = res[key];
           if (!obj) continue;
           if (obj.speed != null) await writeNum(`${ROOT}.fans.${safeKey}.speed_percent`, toPercent01(obj.speed), "%", "value.percent");
           if (obj.rpm != null) await writeNum(`${ROOT}.fans.${safeKey}.rpm`, Number(obj.rpm), "rpm", "value");
         }
      
         // ---- Temperatur-Sensoren ----
         for (const t of discovered.tempSensors) {
           const key = t;
           const safeKey = key.replace(/\s+/g, "_");
           const obj = res[key];
           if (!obj) continue;
           if (obj.temperature != null) await writeNum(`${ROOT}.temp_sensors.${safeKey}.temperature`, round1(obj.temperature), "°C", "value.temperature");
           if (obj.speed != null) await writeNum(`${ROOT}.temp_sensors.${safeKey}.speed_percent`, toPercent01(obj.speed), "%", "value.percent");
         }
      
         // ---- Datei-Metadaten (Layer-Fallback) ----
         if ((layerInfo.total == null || layerInfo.current == null) && currentFilename) {
           try {
             const meta = await httpGet(`${BASE}/server/files/metadata?filename=${encodeURIComponent(currentFilename)}`);
             const md = meta?.result || {};
             const lh = md?.layer_height ?? md?.slicer?.layer_height ?? null;
             const oh = md?.object_height ?? md?.metadata?.object_height ?? null;
             if (lh != null) metaFromFile.layer_height = Number(lh);
             if (oh != null) metaFromFile.object_height = Number(oh);
      
             if (metaFromFile.layer_height != null) await writeNum(`${ROOT}.file.meta.layer_height_mm`, round1(metaFromFile.layer_height), "mm", "value.length");
             if (metaFromFile.object_height != null) await writeNum(`${ROOT}.file.meta.object_height_mm`, round1(metaFromFile.object_height), "mm", "value.length");
      
             if (layerInfo.total == null && metaFromFile.layer_height && metaFromFile.object_height) {
               layerInfo.total = Math.max(1, Math.round(metaFromFile.object_height / metaFromFile.layer_height));
             }
             if (layerInfo.current == null && metaFromFile.layer_height && zPos != null) {
               layerInfo.current = Math.max(0, Math.min(layerInfo.total || 999999, Math.floor(zPos / metaFromFile.layer_height)));
             }
           } catch (e) {
             // nicht kritisch
           }
         }
      
         // ---- Layer in Datenpunkte schreiben ----
         if (layerInfo.current != null) await writeNum(`${ROOT}.layers.current`, layerInfo.current, "", "value");
         if (layerInfo.total != null)   await writeNum(`${ROOT}.layers.total`,   layerInfo.total,   "", "value");
         if (layerInfo.current != null && layerInfo.total != null && layerInfo.total > 0) {
           const pct = Math.round((layerInfo.current / layerInfo.total) * 1000) / 10;
           await writeNum(`${ROOT}.layers.progress_percent`, pct, "%", "value.percent");
         }
      
         await writeStr(`${ROOT}.meta.last_update`, new Date().toISOString(), "date");
         await writeBool(`${ROOT}.meta.ok`, true, "indicator.working");
       } catch (e) {
         await writeBool(`${ROOT}.meta.ok`, false, "indicator.working");
         await writeStr(`${ROOT}.meta.error`, e.message || String(e));
         log(`Moonraker poll error: ${e.message}`, "warn");
       }
      }
      
      // ======== STARTUP ========
      (async () => {
       await ensureState(`${ROOT}.meta.ok`, { type: "boolean", def: false, read: true, write: false, role: "indicator.working" });
       await discoverObjects();
       pollOnce();
      })();
      
      // Intervall
      let pollTimer = setInterval(pollOnce, POLL_MS);
      
      // ======== OPTIONALE TESTFUNKTION (Alexa) ========
      let testTimer = null;
      if (ENABLE_TEST_SPEAK) {
       testTimer = setInterval(() => {
         try {
           setState(ALEXA_SPEAK_DP, { val: TEST_MESSAGE, ack: false });
         } catch (e) {
           log("Alexa-Testansage fehlgeschlagen: " + e.message, "warn");
         }
       }, 60_000);
      }
      

      iScreen Shoter - Firefox - 250816165523.jpg

      posted in ioBroker Allgemein
      Lucifor1976
      Lucifor1976
    • RE: Adapter Klipper-Moonraker

      Sehr schön das sich jemand um Klipper kümmert 🙂

      Gerade zwei Instanzen installiert.

      Was mir direkt auffällt:

      Progress stimmt nicht mit Klipper überein Klipper= 35% Adapter = 44%? Wobei der Progress /100 angezeigt wird?
      (klipper-moonraker.0.display_status.progress)

      Verbrauchtes Filament stimmt nicht mit Klipper überein, Klipper= 1m Adapter 1,2m
      (klipper-moonraker.0.print_stats.total_duration)

      Der Gerade gedruckte Layer wird nicht übertragen. (Null)
      (klipper-moonraker.0.print_stats.info.current_layer)
      Ebenfalls für Total Layer
      (klipper-moonraker.0.print_stats.info.total_layer)

      Ansonsten saubere Arbeit 🙂 und Danke dafür.

      posted in ioBroker Allgemein
      Lucifor1976
      Lucifor1976
    • RE: Upgrade von Debian 12 'Bookworm' auf Debian 13 'Trixie'

      @thomas-braun

      Super, danke.

      Magst sowas bei Zeiten auch für das Upgrade Proxmox 8.x auf 9 machen?
      liebguck

      posted in Pflege des Betriebssystems
      Lucifor1976
      Lucifor1976
    • VIS 2 Falsche Einstellung oder Bug?

      Hallo zusammen,

      Im Editor gibt es ja die Möglichkeit die Auflösung einzustellen.
      Ebenfalls gibt es einen "schwarzen Hintergrund" auf dem sich Widgets ect. einfach verschieben lassen.
      Ausserhalb dieses "schwarzen Hintergrundes" geht das allerding nicht mehr so einfach, mit der Maus etwas zu verschieben fast unmöglich, Positionierung geht dann nur noch über die Tastatur (Pfeiltasten).
      Da ich gerade an einer VIS für meinen Computer arbeite und das eine 4K Vis werden soll, ist das natürlich etwas schwierig.
      Kann man nun das Feld worin einwandfrei gearbeitet werden kann vergrößern?
      Danke euch für Tipps 🙂

      Bildschirmfoto 2025-08-06 um 13.45.55.png

      posted in Visualisierung
      Lucifor1976
      Lucifor1976
    • RE: Smartlock empfehlungen Pro/Contra

      @michael-schmitt

      Weiß ich jetzt nich .. 🙂
      Ich würde stand heute eher zu dem Aquara dentieren.

      Fernöffnung benötige ich nicht, und lässt sich Nuki nun als Feature extra bezahlen..

      Diese Funktion habe ich aber vollständig deaktiviert und die Nutzung innerhalb der Familie streng verboten.
      Es ist nämlich leider schon das ein oder andere mal passiert das diese Funktion aus versehen über die Watches der Familie getriggert wurde. Einmal waren wir dabei 100km entfernt und die Haustüre stand ne Stunde lang offen. (Laut Log im Nuki Adapter fernöffnung durch Benutzer...)
      Seit dem hab ich das deaktiviert.

      posted in Hardware
      Lucifor1976
      Lucifor1976
    • RE: Smartlock empfehlungen Pro/Contra

      @michael-schmitt

      Wir haben ein Nuki, kurz ich würd es nicht nochmal kaufen.

      Lang:
      Geht problemlos in iobroker
      Geschwindigkeit OK
      Lautstärke = deutlich zu laut
      Handy App = ja
      Fingerprint Sensor = ja, extra zu erwerben

      Unser Nuki hat damals gute 280 Euro gekostet und wurde mit einer Bridge und einem Magnetsensor geliefert.
      Der Magnet soll dem Schloss Sagen wo sich inentwa die Türe befindet.
      Ein paar Wochen vor Erscheinen des Nuki 3 erschien für unser Nuki 2 ein Firmwareupdate und zufällig hat sich ein Bug eingeschlcihen der den Sensor unbrauchbar machte, der Bug ist bis heute nicht wieder gefixt.
      Ein schelm wer böses dabei denkt. Die Lautstärke des Schlosses ist deutlich zu laut.
      Das Schloss braucht ewig lang um zu reagieren, egal ob über die app oder meine Uhr. (Iphone 16 pro/ Watch Ultra2)
      Der "Firmwarebug" und der damit zerschossenene (eher einfach deaktivierte) Magnetsensor, sorgt bei mir jedoch für eine "red Flag" bei Nuki, kommt nicht nochmal in die Tüte.

      posted in Hardware
      Lucifor1976
      Lucifor1976
    • RE: Script: HP-ILO 4 Abfrage Temperaturen und FanSpeed

      @david-g
      Sehr gut.. 🙂
      Mach die Änderung bitte auch auf Githup 🙂
      Wenn Deine Version nicht ILO5 V2.95 ist bitte ein neues js File. Dito für ILO 4, langsam herantasten.. 🙂
      Am Wochenende schau ich mal ob ich etwas aus Disk und Raid herausgekitzelt bekomme..
      Hab heute und morgen keine Zeit..

      posted in JavaScript
      Lucifor1976
      Lucifor1976
    • RE: Script: HP-ILO 4 Abfrage Temperaturen und FanSpeed

      @david-g

      Schau mal auf hithup, ich habe ein Script für ILO5 hinzugefügt, teste das mal.
      Wie gesagt im Blindflug.

      posted in JavaScript
      Lucifor1976
      Lucifor1976
    • RE: Script: HP-ILO 4 Abfrage Temperaturen und FanSpeed

      @david-g

      Jetzt bin ich verwirrt, hast du die Fehler im Log bei der Maschine wo es aber geht?

      Weil: Die Reference zu ILO 4 2.61 sagt das Raid und Disk nicht über die API ausgelesen werden können.
      (Das steht auch so im Log (erfolgreich gelesen, aber keine links gefunden bei Raid und Disks)
      Die Fehler im Log rühren nicht vom Script her, die sehen anders aus, ich vermute axios?

      Noch eine Frage, läuft das Script in einer iobroker Umgebung? Diese wird erwartet, das ist kein Shell Script.
      Das Script erwartet die Javascript Engine von iobroker.

      Etwas weiter unten im Log steht was von ILO5?

      Ich kann ein Script für ILO 5 bauen, aber nur im Blindflug, da ich keine Maschine mit ILO 5 habe.
      Geht sicherlich, dauert aber lang .. ständig logs und Scripte hin und her...

      posted in JavaScript
      Lucifor1976
      Lucifor1976
    • RE: Script: HP-ILO 4 Abfrage Temperaturen und FanSpeed

      @david-g

      Ohh das ist ein ML, ich habe nur DL, somit kann ich mit der letzen ILO wohl auch nicht aushelfen.
      Ich sehe gerade für einen ist 2.82 verfügbar.. Ne das tu ich mir jetzt aber nicht an.

      Sieht so aus als wäre das Script dann für dich nicht geeignet..

      posted in JavaScript
      Lucifor1976
      Lucifor1976
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo