Skip to content

Visualisierung

Hilfe zu Visualisierungen

9.4k Themen 104.1k Beiträge

NEWS

  • hqwidgets - odometer

    vis
    25
    0 Stimmen
    25 Beiträge
    2k Aufrufe
    HomoranH
    @OliverIO sagte in dev-server mit vis1 widget Unterstützung: habe blöderweise zum widget in diesem thread angefangen ich schiebs dann rüber DANKE natürlich auch an @ainu9yem
  • Kein Input möglich (Android)

    Verschoben Ungelöst
    12
    0 Stimmen
    12 Beiträge
    2k Aufrufe
    M
    Hat hier jemand eine Lösung mittlerweile? Würde gerne das Keyboard Widget nehmen, aber ich habe auch das Problem, dass sich das Keypad UND die Android Tastartur öffnet. Außerdem springt das Pad auf eine andere View um, auch wenn ich keine default gesetzt habe ... - Habe die View nochmal auf Default gesetzt und danach wieder nicht. Danach springt er jetzt nicht mehr - trotzdem öffnen beide Keyboards
  • Vis2 WoMo Dashboard

    1
    12
    1 Stimmen
    1 Beiträge
    87 Aufrufe
    Niemand hat geantwortet
  • iQontrol - Kachel nur als Anzeige ob etwas an oder aus ist?

    1
    0 Stimmen
    1 Beiträge
    41 Aufrufe
    Niemand hat geantwortet
  • Hilfe zu Material-Design View Dialog

    11
    5
    0 Stimmen
    11 Beiträge
    879 Aufrufe
    L
    Ich habe lange herumprobiert und des Rätsels Lösung gefunden. Dieses RELATIVE fehlte in den Dialog Views: [image: 1772004618145-1c3cb739-63e1-4255-830f-0794c3fa3871-image.png] [image: 1772007890411-wetter_view.gif] Hier das fertige Projekt 2026-02-25-Wetter2.zip
  • VIS(1): Ein PopUp für mehrere Lampen

    3
    0 Stimmen
    3 Beiträge
    123 Aufrufe
    S
    Hallo, vielen Dank. Muss ich mir mal in Ruhe durschauen
  • Zeigt her eure iQontrol Visualisierung

    iqontrol
    354
    2 Stimmen
    354 Beiträge
    99k Aufrufe
    M
    Moin zusammen, die regnerischen Tage habe ich damit verbracht, mein iQontrol (mal wieder) umzugestalten. Hier mein neues Menü (ich habe nur zwei Unterseiten, die Animation ist als GIF etwas träge… 🥴): [image: 1771760384828-screenrecording_02-22-2026-12-34-35_1.gif] Haben sich eure Dashboards verändert?
  • VIS-2 Material Widgets Signalbilder

    16
    0 Stimmen
    16 Beiträge
    1k Aufrufe
    R
    Hi zusammen, ist der Bug behoben worden? Bei den Widgets Universal & Multi aus "vis-iventwo" und universal aus "iventwo-design" sind weiterhin "nur" 3 Signalbilder möglich, obwohl zB 4 ausgewählt wurden
  • Reolink über go2rtc in VIS einbinden

    23
    1
    0 Stimmen
    23 Beiträge
    244 Aufrufe
    inviI
    Hallo Hans. http://Meine IP:1984/stream.html?src=Hauseingang-1&mode=webrtc läuft mit W-Lan auf einem Echo Show 8 ohne ruckeln. Grüße invi
  • Iqontrol - wie bindet man ein iframe ein?

    3
    0 Stimmen
    3 Beiträge
    62 Aufrufe
    JLegJ
    @weimaraner für eine "Digitaluhr" braucht's keinen iframe - ich habe z.B. ein "Widget" genommen, und bei "background_html" einen eigenen Datenpunkt vom Typ "string" eingetragen. Dazu läuft dann ein Script, das bei mir alle 10min bissel HTML in diesen Datenpunkt schreibt...
  • Lovelace: "Unknown request for /lovelace/default_view"

    7
    0 Stimmen
    7 Beiträge
    82 Aufrufe
    David G.D
    @Rico-Sander Aber warum denkst du ist das der korrekte link? Steht das wirklich unter link auf der Seite wie in meinem Screenshot? [image: 1771325850400-1000061304.jpg] da könnte man zum testen ja mal default_view rein schreiben.
  • iobroker Visu App - Lädt immer via pro.cloud

    5
    9
    0 Stimmen
    5 Beiträge
    115 Aufrufe
    CyberraphC
    @bahnuhr Jap, der admin mit Passwort ist überflüssig. Hab ich schon gelernt, aber bislang nicht raus getan. Jetzt hab ich es mal überall raus getan. Aber abseits davon: Auch nochmal bei meinem anderen Handy, wo alles sauber läuft herumprobiert. Die SSID "FRITZ!Box 7530 UO" mal anders eingegeben. Und zack, dann wird über .pro verbunden. Geb ich sie korrekt ein, läuft es korrekt offline / direkt über das lokale Netzwerk. Bleibt mir ein Rätsel, warum es auf einmal beim anderen Handy nicht mehr funktioniert (obwohl nix geändert wurde). Es trat auf einmal auf nach vermutlich einem Stromausfall -> Serverneustart zuletzt. Aber warum sich da auf einmal was querstellt. Naja ich belasse es mal dabei -> ohne .pro das andere Handy zu belassen, damit es lokal sich verbindet.
  • iQontrol Größe der Geräte-Kacheln anpassen ?

    1
    3
    0 Stimmen
    1 Beiträge
    55 Aufrufe
    Niemand hat geantwortet
  • Support Adapter Energiefluss-erweitert v0.7.7

    Verschoben vis
    5k
    9
    20 Stimmen
    5k Beiträge
    6m Aufrufe
    hotspot_2H
    Hallo zusammen, kurze Frage zur Animation der Elemente oder der Funktion "Elemente nach Wert füllen": Kann man die Animation beim Start irgendwie deaktivieren so das der Wert sofort korrekt angezeigt wird?
  • Widget import klappt nicht in VIS-2

    8
    0 Stimmen
    8 Beiträge
    110 Aufrufe
    OliverIOO
    @Longbow So wie es aussieht, ist das eine Gruppe. D.h. es besteht aus mehreren einzelnen Widgets. Versuche mal in vis1 die Gruppe aufzulösen und dir anzuschauen, welche einzelnen Widgets es sind. Eventuell liegt es auch an der Gruppe, dass es nicht in vis2 zu importieren geht, dann ebenfalls die umgruppierten Widgets markieren, exportieren, und dann noch mal probieren. Dann kannst du in der Kompatibilitätsliste nachschauen, ob es da drin steht. Gegebenfalls musst du es in vis2 selber nachbauen, das dürfte nicht so schwer sein.
  • LovelaceUI Wettervorhersage -> wie weather Endität erzeugen?

    Verschoben
    3
    4
    0 Stimmen
    3 Beiträge
    68 Aufrufe
    AtifanA
    Ah sorry bin im falschen Forum gelandet, war keine Absicht. Kannst du das ins deutsche Forum verschieben? Wenn nicht kopiere ich alles neu und lösche hier.
  • Vis2 Tabs Widget - Tab per URL anspringen

    9
    0 Stimmen
    9 Beiträge
    103 Aufrufe
    M
    @Sesamstrasse Einfach ist relativ. DPs anlegen und den Code in Skripte austauschen. DPs in ioBroker anlegen mit dem Skript Beispiele für DP setzen sind ausgeklammert, da die Werte angepasst werden müssen ioBroker javascript -> DPs anlegen // ************************ // VIS2TabControl v1.0.0 // Copyright ©MCU // ************************ // ioBroker javascript.0 - DPs für VIS2 Tabs anlegen const DP_MAIN = '0_userdata.0.vis2' const DP_TAB_EVENT = DP_MAIN + ".tabEvent"; // Client -> ioBroker const DP_TAB_CMD = DP_MAIN + ".tabCmd"; // ioBroker -> Client const DP_DEVICE_MAP = DP_MAIN + ".deviceMap"; // clientId -> clientName createState(DP_TAB_CMD, '', {name: 'VIS2 Tab Command',type: 'string', role:'', def: '', read: true, write: true, desc: ''}); createState(DP_TAB_EVENT, '', {name: 'VIS2 Tab Event',type: 'string', role:'', def: '', read: true, write: true, desc: ''}); createState(DP_DEVICE_MAP, '', {name: 'VIS2 Client Map',type: 'string', role:'', def: '', read: true, write: true, desc: ''}); // DEVICE_MAP - Aufbau /* { "d787264857bc0d13c393d37336f43dc9": "PC", "d7282dhf83hf832f944mhn4345n345n3": "Tablet" } */ // Beispiele /* setState(DP_TAB_CMD, JSON.stringify({ cmdId: `${Date.now()}-${Math.random().toString(16).slice(2)}`, target: ["d787264857bc0d13c393d37336f43dc9"], view: "datum", tab: "Licht", force: true }), false); */ // Wenn eine Zuordnung im Device_MAP vorhanden ist, kann man auch die Name nutzen /* setState(DP_TAB_CMD, JSON.stringify({ cmdId: `${Date.now()}-${Math.random().toString(16).slice(2)}`, target: ["PC"], view: "datum", tab: 2, force: true }), false); */ Script in VIS2 unter Skripte austauschen Script für VIS-2 Skripte /******************************************************************** * VIS-2 Global Script: Tabs steuern + Sync + Multi-Client Commands * * Fixes: * - Commands funktionieren mehrfach (Dedup nur über cmdId, wenn vorhanden) * - force:true klickt Tab auch wenn bereits selektiert * - periodisches resubscribe gegen verlorene Subscriptions ********************************************************************/ // =================== KONFIG =================== const DEBUG = false; // Tabs-Widget ID (aus deinem DOM) const TABS_WIDGET_ID = "w000016"; // URL Parameter const URL_PARAM_TAB = "tab"; // ?main&tab=Licht#datum // Datenpunkte (string) const DP_TAB_EVENT = "0_userdata.0.vis2.tabEvent"; // Client -> ioBroker const DP_TAB_CMD = "0_userdata.0.vis2.tabCmd"; // ioBroker -> Client const DP_DEVICE_MAP = "0_userdata.0.vis2.deviceMap"; // ioBroker -> Client (DeviceId -> Name) // Index-Format const INDEX_ONE_BASED = true; // true => 1..N, false => 0..N-1 // History const USE_PUSHSTATE = false; // false = replaceState (empfohlen) // Timing const OBSERVE_TIMEOUT_MS = 15000; // Re-Subscribe (gegen „geht nur einmal“) const RESUBSCRIBE_EVERY_MS = 30000; // localStorage Keys const LS_KEYS = { deviceId: "vis2.deviceId", deviceName: "vis2.deviceName", }; // ============================================== // =================== Helpers =================== function dlog(...a) { if (DEBUG) console.log("[VIS2Tabs]", ...a); } function getVis() { return (typeof window !== "undefined" && (window.vis || window.VIS)) || (typeof vis !== "undefined" ? vis : null); } let suppressUntil = 0; function suppress(ms = 350) { suppressUntil = Date.now() + ms; } function isSuppressed() { return Date.now() < suppressUntil; } function norm(s) { return String(s ?? "").trim().toLowerCase(); } function safeJsonParse(s) { try { return JSON.parse(s); } catch { return null; } } function getSearchParams() { return new URLSearchParams(window.location.search); } function getCurrentViewFromHash() { const h = (window.location.hash || "").replace(/^#/, ""); return (h.split("?")[0] || "").trim(); } function gotoView(view) { if (!view) return; const cur = getCurrentViewFromHash(); if (cur === view) return; suppress(600); window.location.hash = `#${view}`; } function getOrCreateDeviceId() { let id = localStorage.getItem(LS_KEYS.deviceId); if (id) return id; const buf = new Uint8Array(16); if (crypto?.getRandomValues) crypto.getRandomValues(buf); else for (let i = 0; i < buf.length; i++) buf[i] = Math.floor(Math.random() * 256); id = Array.from(buf).map(b => b.toString(16).padStart(2, "0")).join(""); localStorage.setItem(LS_KEYS.deviceId, id); return id; } // robustes Lesen aus vis.states Cache (DP oder DP.val / ggf. State-Objekt) function readVisValue(id) { const v = getVis(); if (!v?.states) return null; const candidates = [id + ".val", id]; for (const key of candidates) { try { let val = (v.states.attr && v.states.attr(key)) ?? v.states[key]; if (typeof val === "object" && val && "val" in val) val = val.val; // unwrap if (val !== undefined && val !== null) return val; } catch {} } return null; } function writeVisValue(id, value) { const v = getVis(); if (!v) return false; if (typeof v.setValue === "function") { v.setValue(id, value); return true; } if (v.conn && typeof v.conn.setState === "function") { v.conn.setState(id, value); return true; } return false; } // ============================================== // =================== Device Map =================== function applyDeviceNameFromMap() { const myId = getOrCreateDeviceId(); const raw = readVisValue(DP_DEVICE_MAP); const map = (typeof raw === "string" && raw.trim()) ? safeJsonParse(raw) : null; const name = map && typeof map === "object" ? map[myId] : null; if (name && String(name).trim()) { const n = String(name).trim(); localStorage.setItem(LS_KEYS.deviceName, n); return n; } return (localStorage.getItem(LS_KEYS.deviceName) || "").trim(); } // ============================================== // =================== URL: tab aus Query =================== function getTabParamFromSearch() { return getSearchParams().get(URL_PARAM_TAB) || null; } // NICHT URLSearchParams serialisieren (sonst wird aus ?main -> ?main=) // Wir ersetzen/appendieren nur "&tab=..." function setTabParamInSearch(tabValue) { if (!tabValue) return; const path = window.location.pathname; const hash = window.location.hash || ""; const raw = window.location.search || ""; const current = getTabParamFromSearch(); if (current === tabValue) return; let next = raw; if (/[?&]tab=/.test(next)) { next = next.replace(/([?&]tab=)[^&]*/i, `$1${encodeURIComponent(tabValue)}`); } else { next += (next.includes("?") ? "&" : "?") + `tab=${encodeURIComponent(tabValue)}`; } const newUrl = `${path}${next}${hash}`; suppress(450); if (USE_PUSHSTATE) history.pushState(null, "", newUrl); else history.replaceState(null, "", newUrl); } // ============================================== // =================== Tabs DOM Zugriff =================== function getTabButtons() { const root = document.getElementById(TABS_WIDGET_ID); if (!root) return []; return Array.from(root.querySelectorAll('button[role="tab"]')); } function isSelected(btn) { return ( btn?.getAttribute("aria-selected") === "true" || btn?.classList?.contains("Mui-selected") ); } function getSelectedTab() { const tabs = getTabButtons(); return tabs.find(isSelected) || null; } function getSelectedTabName() { const sel = getSelectedTab(); return sel ? (sel.textContent || "").trim() : ""; } function getSelectedTabIndex() { const tabs = getTabButtons(); const sel = getSelectedTab(); if (!sel) return null; const idx0 = tabs.indexOf(sel); if (idx0 < 0) return null; return INDEX_ONE_BASED ? (idx0 + 1) : idx0; } // force=true: klickt auch wenn schon selected function trySelectTab(tabParam, force = false) { if (tabParam == null) return false; const tabs = getTabButtons(); if (!tabs.length) return false; let target = null; const s = String(tabParam).trim(); if (/^\d+$/.test(s)) { const n = parseInt(s, 10); const idx = (n === 0) ? 0 : (n - 1); target = tabs[idx]; } else { const needle = norm(s); target = tabs.find(b => norm(b.textContent) === needle); } if (!target) return false; if (force || !isSelected(target)) { suppress(450); target.click(); } return true; } function forceSelectTab(tabParam, force = false) { if (trySelectTab(tabParam, force)) return; const obs = new MutationObserver(() => { if (trySelectTab(tabParam, force)) obs.disconnect(); }); obs.observe(document.body, { childList: true, subtree: true }); setTimeout(() => obs.disconnect(), OBSERVE_TIMEOUT_MS); } // ============================================== // =================== TabEvent -> DP =================== let lastSentSig = ""; function sendTabEventToDP() { const idx = getSelectedTabIndex(); const name = getSelectedTabName(); if (idx == null || !name) return; const sig = `${idx}|${name}`; if (sig === lastSentSig) return; lastSentSig = sig; const deviceId = getOrCreateDeviceId(); const deviceName = applyDeviceNameFromMap(); const view = getCurrentViewFromHash(); const payload = { deviceId, deviceName: deviceName || undefined, view: view || undefined, tabIndex: idx, tabName: name, ts: Date.now() }; writeVisValue(DP_TAB_EVENT, JSON.stringify(payload)); } // ============================================== // =================== URL -> Tab (Load/Navi) =================== function applyTabFromUrl() { if (isSuppressed()) return; const tabParam = getTabParamFromSearch(); if (!tabParam) return; forceSelectTab(tabParam, false); } // ============================================== // =================== Tab -> URL (bei Wechsel) =================== let lastWrittenName = ""; function writeUrlFromSelection() { if (isSuppressed()) return; const name = getSelectedTabName(); if (!name) return; if (name === lastWrittenName) return; lastWrittenName = name; setTabParamInSearch(name); } function wireTabHandlers() { const tabs = getTabButtons(); if (!tabs.length) return false; tabs.forEach(btn => { if (btn.__vis2TabWired) return; btn.__vis2TabWired = true; const handler = () => setTimeout(() => { writeUrlFromSelection(); sendTabEventToDP(); }, 0); btn.addEventListener("click", handler); btn.addEventListener("keydown", (e) => { if (e.key === "Enter" || e.key === " " || e.key === "Spacebar") handler(); }); }); return true; } function observeTabChanges() { const root = document.getElementById(TABS_WIDGET_ID); if (!root) return false; const obs = new MutationObserver(() => { wireTabHandlers(); writeUrlFromSelection(); sendTabEventToDP(); }); obs.observe(root, { subtree: true, childList: true, attributes: true, attributeFilter: ["aria-selected", "class"], }); wireTabHandlers(); writeUrlFromSelection(); sendTabEventToDP(); return true; } // ============================================== // =================== Command-DP -> Tab setzen =================== let lastCmdToken = ""; function isTargetForMe(cmd) { const myId = getOrCreateDeviceId(); const myName = applyDeviceNameFromMap(); if (!cmd || cmd.target == null) return false; const t = cmd.target; if (t === "*") return true; if (Array.isArray(t)) { return t.includes(myId) || (myName && t.includes(myName)); } if (typeof t === "string") { return t === myId || (myName && t === myName); } if (typeof t === "object") { if (t.deviceId && t.deviceId === myId) return true; if (t.deviceName && myName && t.deviceName === myName) return true; } return false; } function handleTabCmd(rawVal) { if (rawVal == null) return; // unwrap State-Objekt if (typeof rawVal === "object" && rawVal && "val" in rawVal) { rawVal = rawVal.val; } if (rawVal == null) return; let cmd = null; if (typeof rawVal === "string") { const s = rawVal.trim(); if (!s) return; if (s.startsWith("{") || s.startsWith("[")) cmd = safeJsonParse(s); if (!cmd) cmd = { target: "*", tab: s, ts: Date.now() }; } else if (typeof rawVal === "number") { cmd = { target: "*", tab: rawVal, ts: Date.now() }; } else if (typeof rawVal === "object") { cmd = rawVal; } if (!cmd) return; // Kompatibilität: event-artiges Format akzeptieren if (cmd.target == null && (cmd.deviceId || cmd.deviceName)) { cmd.target = { deviceId: cmd.deviceId, deviceName: cmd.deviceName }; } if (cmd.tab == null) { if (cmd.tabName != null) cmd.tab = cmd.tabName; else if (cmd.tabIndex != null) cmd.tab = cmd.tabIndex; } // ✅ Dedup NUR über cmdId (wenn vorhanden). Ohne cmdId wird NICHT deduped. if (cmd.cmdId != null) { const token = String(cmd.cmdId); if (token === lastCmdToken) return; lastCmdToken = token; } // Zielprüfung applyDeviceNameFromMap(); if (!isTargetForMe(cmd)) return; dlog("CMD accepted:", cmd); if (cmd.view) gotoView(String(cmd.view)); if (cmd.tab != null) forceSelectTab(cmd.tab, !!cmd.force); } // ============================================== // =================== Subscribe/Bind Setup =================== let subscribedIds = new Set(); function subscribeNow(ids) { const v = getVis(); if (!v?.conn?.subscribe) return; try { v.conn.subscribe(ids); ids.forEach(id => subscribedIds.add(id)); dlog("subscribed:", ids); } catch (e) { dlog("subscribe err", e); } } function ensureSubscribeAndBind(ids, onChange) { const v = getVis(); if (!v?.conn?.getStates || !v?.conn?.subscribe || !v?.states?.bind) { return false; } try { v.conn.gettingStates = 0; } catch {} v.conn.getStates(ids, (err, states) => { if (err) dlog("getStates err", err); // subscribe subscribeNow(ids); // cache füllen (hilft je nach Build) try { if (states && typeof v.updateStates === "function") v.updateStates(states); } catch {} ids.forEach(id => { const cb = (e, newVal, oldVal) => onChange(newVal, oldVal, id); // robust: DP und DP.val try { v.states.bind(id + ".val", cb); } catch {} try { v.states.bind(id, cb); } catch {} }); }); return true; } function setupCmdListener() { const ok = ensureSubscribeAndBind([DP_TAB_CMD], (newVal) => { if (isSuppressed()) return; handleTabCmd(newVal); }); if (ok) return true; // Fallback Polling let last = null; const timer = setInterval(() => { try { let v = readVisValue(DP_TAB_CMD); if (typeof v === "object" && v && "val" in v) v = v.val; if (v != null && v !== last) { last = v; if (!isSuppressed()) handleTabCmd(v); } } catch {} }, 500); window.addEventListener("beforeunload", () => clearInterval(timer)); return true; } function setupDeviceMapListener() { const ok = ensureSubscribeAndBind([DP_DEVICE_MAP], () => { if (isSuppressed()) return; const n = applyDeviceNameFromMap(); dlog("deviceName updated:", n); }); applyDeviceNameFromMap(); return ok; } function startPeriodicResubscribe() { setInterval(() => { // immer wieder subscribe, falls VIS2 nach Reconnect „vergisst“ subscribeNow([DP_TAB_CMD, DP_DEVICE_MAP]); }, RESUBSCRIBE_EVERY_MS); } // ============================================== // =================== Init =================== (function init() { const id = getOrCreateDeviceId(); dlog("deviceId:", id); const n = applyDeviceNameFromMap(); dlog("deviceName:", n); applyTabFromUrl(); if (!observeTabChanges()) { const obs = new MutationObserver(() => { if (observeTabChanges()) obs.disconnect(); }); obs.observe(document.body, { childList: true, subtree: true }); setTimeout(() => obs.disconnect(), OBSERVE_TIMEOUT_MS); } setupCmdListener(); setupDeviceMapListener(); startPeriodicResubscribe(); window.addEventListener("popstate", applyTabFromUrl); })(); [image: 1770574125750-vis2-tabcontrol.gif]
  • VIS-2 binding operation json

    10
    1
    0 Stimmen
    10 Beiträge
    124 Aufrufe
    M
    @Cyberraph Offenes Problem zusätzlich https://github.com/ioBroker/ioBroker.vis-2/issues/521
  • Jarvis 3.1.8 - zukünftige Strompreise - Skalierung, Farben

    320
    1
    0 Stimmen
    320 Beiträge
    52k Aufrufe
    M
    @MCU perfekt - funktioniert sofort... da wäre ich nie nie nie drauf gekommen :)
  • Darstellung json-Tipperpreise m

    2
    0 Stimmen
    2 Beiträge
    67 Aufrufe
    M
    @docadams https://github.com/hombach/ioBroker.tibberlink?tab=readme-ov-file#graph-output-configuration

265

Online

32.7k

Benutzer

82.5k

Themen

1.3m

Beiträge