Skip to content

Off Topic

Hier kann über alles geredet werden was sonst nirgendwo hinpasst
3.2k Topics 49.7k Posts

NEWS

Subcategories


  • 91 Topics
    2k Posts
    HomoranH
    @hotspot_2 sagte in Upgrade von Debian 12 'Bookworm' auf Debian 13 'Trixie': Wollte mal nachfragen ob da Handlungsbedarf besteht. ja! https://forum.iobroker.net/post/1324258
  • 256 4k
    256 Topics
    4k Posts
    marcel-drzalM
    habe es gefunden, hatte in Grafana *3.6 nicht als Punkt geschrieben sondern als komma
  • 146 3k
    146 Topics
    3k Posts
    R
    @Marc-Berg sagte in InfluxDB 2.0 - welche Measurement löschen vom Scraper: Ja. Wildcards ("go_*") funktionieren beim Löschen nicht. Also entweder einzeln manuell löschen, oder das Script nutzen, hier müssten alle erwischt werden: Danke!
  • Fragen und Hilfe zur externen SQL Datenbank

    1 5
    1 Topics
    5 Posts
    fuzzy1955F
    Teil 5: Verwenden der SQL-Daten in Diagrammen bzw. im VIS-2 Der Hauptzweck der Datenhistorisierung liegt natürlich in der grafischen bzw. tabellarischen Darstellung, um daraus mögliche Entscheidungen abzuleiten, etwa wo setzte ich beim Börsenstrompreis mein Bezugslimit. Eine einfache Möglichkeit zur grafischen Darstellung bieten die DIAGRAMME. Man wählt als Datenquellen die gewünschten SQL-Historisierungspunkte, stellt noch ein paar Dinge ein und … fertig. [image: 1770367644381-664a0f95-2fc3-48ae-babe-1a8ffafab1ad-image.png] Um das Ganze im VIS-2 anzuzeigen, nimmt man dort das Widget „Basic -IFrame“ und gibt bei Allgemein – Quelle den Link aus den Diagrammen an. [image: 1770367662940-281a33d1-fcdc-49bb-a3d9-c0fb7ea8ecd1-image.png] So kann man sich ein VIS-2-View nur für Diagramme bauen, bei der die gewünschte Art des Diagrammes angetippt wird: [image: 1770367682322-9328d9e4-3448-4e5a-8c92-8eeec3f2b52c-image.png] Die tabellarischen Darstellung im VIS-2 geschieht mit dem Widget „Basic Table“, bei dem man einen separaten Datenpunkt (Table Object ID) mit JSON-Daten befüllt. Dieses Beispiel zeigt Tages-, Monats- und Jahreswerte einer Strombilanz untereinander. [image: 1770367711812-00a9e22f-d74a-43e7-982f-0e35c37db84a-image.png] Die Datenpunkte dazu: { "alias.0.Diagrammdaten.StrombilanzJahre": { "common": { "name": "StrombilanzJahre", "desc": "Manuell erzeugt", "role": "state", "type": "json", "read": true, "write": true, "alias": { "id": "javascript.0.variables.j006" } }, "type": "state", "native": {}, "_id": "alias.0.Diagrammdaten.StrombilanzJahre", "acl": { "object": 1636, "state": 1636, "owner": "system.user.admin", "ownerGroup": "system.group.administrator" }, "val": "", "from": "system.adapter.admin.0", "user": "system.user.admin", "ts": 1768340995710, "ack": false }, "alias.0.Diagrammdaten.StrombilanzMonate": { "common": { "name": "StrombilanzMonate", "desc": "Manuell erzeugt", "role": "state", "type": "json", "read": true, "write": true, "alias": { "id": "javascript.0.variables.j005" } }, "type": "state", "native": {}, "_id": "alias.0.Diagrammdaten.StrombilanzMonate", "acl": { "object": 1636, "state": 1636, "owner": "system.user.admin", "ownerGroup": "system.group.administrator" }, "val": "", "from": "system.adapter.admin.0", "user": "system.user.admin", "ts": 1768340995710, "ack": false }, "alias.0.Diagrammdaten.StrombilanzTage": { "common": { "name": "StrombilanzTage", "desc": "Manuell erzeugt", "role": "state", "type": "json", "read": true, "write": true, "alias": { "id": "javascript.0.variables.j004" } }, "type": "state", "native": {}, "_id": "alias.0.Diagrammdaten.StrombilanzTage", "acl": { "object": 1636, "state": 1636, "owner": "system.user.admin", "ownerGroup": "system.group.administrator" }, "val": "", "from": "system.adapter.admin.0", "user": "system.user.admin", "ts": 1768340995710, "ack": false } } Mit einem Javascript werden die Datenpunkte zeitgesteuert befüllt. strSQL = "SELECT DATE_FORMAT (tag, '%Y-%m-%d') AS Tag, " + "ROUND(SUM(pv) / 1000.0,1) AS PV, " + "ROUND(AVG(akku)) AS Hausakku, " + "ROUND(SUM(haus) / 1000.0,1) AS Haus, " + "ROUND(SUM(eauto) / 1000.0,1) AS eAuto, " + "ROUND(SUM(gen) / 1000.0,1) AS Gen, " + "ROUND(SUM(nots) / 1000.0,1) AS Nots, " + "ROUND(SUM(gesamt) / 1000.0,1) AS gesamt, " + "ROUND(COUNT(autark)) AS autark " + "FROM iobroker.tagesstatistik " + "GROUP BY DATE_FORMAT (tag, '%Y-%m-%d') " + "ORDER BY DATE_FORMAT (tag, '%Y-%m-%d') desc;"; sendTo('sql.0', 'query', strSQL, function (result) { if (result.error) { console.error(result.error); } else { MyTrigger (idStrombilanzTage,JSON.stringify(result.result)); } }); --------------------------- Voila , das war die ganze Zauberei --------------------------- Anregungen, Fragen etc. bitte hier anhängen.
  • 270 Topics
    5k Posts
    teletapiT
    Nabend, ich bräuchte ggf. noch 2 Platinen für die SP112 @premo könntest du dich dahingehend nochmal bei mir melden Gruß HaWe
  • 186 5k
    186 Topics
    5k Posts
    P
    Ich war für Deine Frage hier das erste Mal auf diesem Weg in der Konsole der OpenCCU. Normal nehme ich PuTTY am PC oder Terminal am MacBook. Für "Notfälle" Termius am Tablet. Wobei ich bei der OpenCCU noch keinen Notfall hatte. Da sind es eher Updates der anderen VMs von der Couch aus.
  • Fragen zu Docker-Installationen

    20 245
    20 Topics
    245 Posts
    Q
    @steff2108 Ich habe ein ähnliches Setup wie du. iobroker läuft bei mir im Docker Container (macvlan) auf meiner DS1821+. Als Backup System habe ich eine DS423+ am Laufen. Meine komplette Docker Umgebung habe ich per Portainer Stacks (Compose) eingerichtet. Die persistenten Container Daten repliziere ich einmal täglich per Synology Snapshot Replication auf die DS423+ Sollte meine primäre DS1821+ ausfallen, brauche ich auf der DS423+ nur die Container zu starten und es läuft wieder alles... Beste Grüße
  • 44 559
    44 Topics
    559 Posts
    Thomas BraunT
    @Homoran Ja, Backitup bzw. der ioBroker setzt die ACLs anders, je nach Ursprung. ACHTUNG: Wenn Sie auf einem Eintrag im Dateisystem – egal ob bei einem Verzeichnis oder einer Datei – eine ACL gesetzt haben, dürfen Sie von dem Moment an keine Berechtigungen mehr mit dem Kommando "chmod" ändern. Denn dann ändern Sie nicht mehr die Rechte sondern nur eine ACL-Maske. Diese Maske kann nur Rechte ausfiltern. Sprich: ein Recht, das dort nicht gesetzt ist, kann auch keine Gruppe oder Benutzer erhalten. Aus: https://www.informatik-aktuell.de/betrieb/betriebssysteme/rechte-im-dateisystem-mehr-als-nur-rwx.html
  • Bekomme mount nicht in fsfab

    7
    0 Votes
    7 Posts
    330 Views
    CodierknechtC
    @david-g Habe auch lange daran rumgedoktert und bin zu folgender Lösung gekommen: //192.168.178.5/Docker /mnt/nas cifs x-systemd.automount,x-systemd.requires=network-online.target,file_mode=0666,dir_mode=0777,credentials=/etc/smbcredentials 0 0
  • COMET DECT Thermostat retten

    13
    1
    0 Votes
    13 Posts
    1k Views
    BananaJoeB
    @martinp sagte in COMET DECT Thermostat retten: @bananajoe Da muss man aufpassen, dass man die Dämmung mit einer Sperrbahn gegen den Raum abdichtet, sonst kriecht die Feuchtigkeit in die Dämmung und kondensiert dann durch das Wärmegefälle nach außen am Taupunkt ... öhm, jupp. Folie/Dampfsperre ist da auch hinter
  • Shelly BLU USB Gateway als Beacon? suche USB Beacon

    4
    0 Votes
    4 Posts
    376 Views
    D
    @schmello said in Shelly BLU USB Gateway als Beacon? suche USB Beacon: @dieter_p Muss ich in der App vom Feasycom Stick noch etwas Einstellen? Aktuell läuft soweit ich weiß die feasycom app nicht auf meinem Pixel mit Android 14 bzw. hab schon was länger nicht mehr versucht, von daher alles ausm Gedächtnis. Läuft aber hab keinen Beacon am Mann zum testen. Ich glaube, "irgendwas" war in den beacons die ich gekauft hab bereits konfiguriert und ob das in deinem Stick genauso ist, nicht zu sagen. In jeden Fall würde ich es prüfen, aus Sicherheitsgründen und auch weil es Sinn macht und du dort Sendeintervalle etc ganz genau einstellen kannst. Ebenso unterstützen die Beacons von feasycom verschiedene Typen (ibeacon, Eddystone etc etc.) die dort angelegt werden können. Ungenutztes würde ich sowieso löschen. Ich verwende derzeit noch ESPHome und hab noch nicht Tasmota mit BLE Scanner in Betrieb genommen. Prinzipell das Ganze über iBeacon konfiguriert und ich prüfe mit dem Scanner auf die MAC-Adresse des Beacon. Ablesbar auch mit der feasycom app wenn ein iBeacon konfiguriert ist. Unter Tasmota sehe ich keinen Grund warum es nicht dort genauso gehen sollte. Ein Eindruck zur App, kannst Du hier bekommen: https://www.youtube.com/watch?v=4r0E7_mBHVQ
  • Wie mittels LUXTRONIK-Adapter Wassertemperatur einstellen?

    5
    3
    0 Votes
    5 Posts
    603 Views
    stolly82S
    Hey zusammen, ich habe ein Skript geschrieben, das die Steuerung der Wassertemperatur über MyUplink ermöglicht, da die Luxtronik Weboberfläche (ab Version 3.89.4) keine direkte Option dazu bietet. Der Plan ist, daraus später einen richtigen Adapter zu machen, aber hier ist schon einmal die Skriptversion zum Ausprobieren. Was macht das Skript? Die Luxtronik ab Version 3.89.4 kann MyUplink integrieren, und genau das nutzt dieses Skript aus. Das Skript erlaubt es euch, die Heizung und das Warmwasser über die MyUplink-Cloud zu steuern, und stellt alle Informationen zur Verfügung, die dort abgerufen werden können. Das bedeutet, ihr könnt die Temperatur direkt anpassen, ohne die Einschränkungen der normalen Weboberfläche. Mehr Informationen zu MyUplink findet ihr hier: MyUplink Cloud – Alpha Innotec So probiert ihr das Skript aus: Öffnet den IoBroker > JavaScript Adapter > Neu > JavaScript > Hinzufügen. Fügt das Skript ein. Tragt eure MyUplink-Zugangsdaten ein. Startet das Skript – und schon seid ihr einsatzbereit! Funktionsumfang Heizung & Warmwasser: Ihr könnt die gewünschten Temperaturen einstellen. Informationsabruf: Alle relevanten Daten, die MyUplink zur Verfügung stellt, werden abgerufen und angezeigt. Falls ihr das Skript ausprobiert, würde ich mich sehr über euer Feedback freuen. Viel Spaß damit! // Konfigurationseinstellungen const CONFIG = { email: 'EMAIL@MYMAIL.DE', password: 'GEHEIM', clientId: 'My-Uplink-iOS', clientSecret: '992EFE7C-9CDC-435B-8BA3-2EF8E81BEF14', interval: 30000, // Standardintervall in Millisekunden für wiederkehrende Abfragen intervalFunctions: [ 'getWeatherTileData', 'getAndCreateMenu' ] }; const axios = require('axios'); class MyUplinkAdapter { constructor() { this.token = null; this.userData = {}; // Hier werden die Benutzerdaten gespeichert this.devices = {}; // Hier werden die Gerätedaten gespeichert this.groups = []; // Hier werden die Gruppendaten gespeichert this.failedRequests = []; // Warteschlange für fehlgeschlagene Anfragen log('Konstruktor von MyUplinkAdapter wurde aufgerufen!', 'info'); // Initialisieren des Verbindungsstatus setObject('myUplink.info.connection', { type: 'state', common: { name: 'API-Verbindungsstatus', type: 'boolean', role: 'indicator.connected', read: true, write: false }, native: {} }); setState('myUplink.info.connection', { val: false, ack: true }); } // Authentifizierungsmethode authenticate() { log("Starte Authentifizierung...", 'info'); log(`Authentifizierungsparameter: email=${CONFIG.email}, clientId=${CONFIG.clientId}`, 'debug'); return axios.post('https://internalapi.myuplink.com/v2/users/validate', { email: CONFIG.email, password: CONFIG.password }, { headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Accept-Language': 'de-DE' } }) .then(response => { log("Benutzer validiert. Antwort: " + JSON.stringify(response.data), 'debug'); const validationData = response.data; if (validationData.id) { this.userData = validationData; // Speichert die Benutzerdaten log(`Authentifizierung erfolgreich. Benutzer-ID: ${validationData.id}`, 'info'); setState('myUplink.info.connection', { val: true, ack: true }); // Verbindung erfolgreich return this.getAccessToken(validationData.id); } else { log("Fehlende ID im Validierungsschritt. Antwort: " + JSON.stringify(validationData), 'error'); throw new Error('User validation failed: Missing ID'); } }) .catch(error => { this.handleError(error); setState('myUplink.info.connection', { val: false, ack: true }); // Verbindung fehlgeschlagen throw error; }); } // Methode zum Abrufen des Access Tokens getAccessToken(userId) { log("Abrufen des Access Tokens...", 'info'); log(`Tokenparameter: clientId=${CONFIG.clientId}, userId=${userId}`, 'debug'); return axios.post('https://internalapi.myuplink.com/oauth/token', `password=${encodeURIComponent(CONFIG.password)}&client_secret=${CONFIG.clientSecret}&grant_type=password&client_id=${CONFIG.clientId}&username=${encodeURIComponent(CONFIG.email)}`, { headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'Authorization': `Bearer ${userId}` } } ) .then(response => { log("Token erfolgreich erhalten. Antwort: " + JSON.stringify(response.data), 'debug'); const tokenData = response.data; if (tokenData.access_token) { this.token = tokenData.access_token; log(`Access-Token erfolgreich gespeichert.`, 'info'); return tokenData; } else { log("Fehlender Access-Token in der Antwort: " + JSON.stringify(tokenData), 'error'); throw new Error('Access token not received'); } }) .catch(error => { this.handleError(error); throw error; }); } // Methode zum Speichern der Benutzerdaten saveUserData() { return this.ensureTokenIsValid().then(() => { log("Speichern der Benutzerdaten...", 'info'); const userUrl = 'https://internalapi.myuplink.com/v2/users/me'; log(`Anfrage-URL für Benutzerdaten: ${userUrl}`, 'debug'); return axios.get(userUrl, { headers: { 'Authorization': `Bearer ${this.token}`, 'Accept': 'application/json' } }) .then(response => { log("Benutzerdaten erfolgreich abgerufen. Antwort: " + JSON.stringify(response.data), 'debug'); this.userData = response.data; // Dynamische Erstellung der Datenpunkte in myUplink.users und Setzen der Werte Object.keys(this.userData).forEach(key => { if (typeof this.userData[key] === 'object' && this.userData[key] !== null) { Object.keys(this.userData[key]).forEach(subKey => { const stateId = `myUplink.User.${key}.${subKey}`; setObject(stateId, { type: 'state', common: { name: `${key} ${subKey}`, type: typeof this.userData[key][subKey], read: true, write: false } }); setState(stateId, { val: this.userData[key][subKey], ack: true }); }); } else { const stateId = `myUplink.User.${key}`; setObject(stateId, { type: 'state', common: { name: key, type: typeof this.userData[key], read: true, write: false } }); setState(stateId, { val: this.userData[key], ack: true }); } }); return this.userData; }) .catch(error => { this.handleError(error); throw error; }); }); } // Methode für das Abrufen der Wetterdaten getWeatherTileData() { return this.ensureTokenIsValid().then(() => { const group = this.groups.find(g => g.id); // Nimmt die erste gültige Gruppe aus den gespeicherten Gruppendaten if (!group || !group.id) { log('Keine gültige Group ID gefunden.', 'error'); throw new Error('No valid Group ID found.'); } const groupId = group.id; const fetchWeatherData = () => { log("Abrufen der Wetterdaten...", 'info'); const weatherUrl = `https://internalapi.myuplink.com/v2/groups/${groupId}/weather-tile-data`; log(`Anfrage-URL für Wetterdaten: ${weatherUrl}`, 'debug'); return axios.get(weatherUrl, { headers: { 'Authorization': `Bearer ${this.token}`, 'Accept': 'application/json' } }) .then(response => { log("Wetterdaten erfolgreich abgerufen. Antwort: " + JSON.stringify(response.data), 'debug'); const weatherData = response.data; // Dynamische Erstellung der Datenpunkte in myUplink.Weather und Setzen der Werte const basePath = `myUplink`; Object.keys(weatherData).forEach(key => { if (typeof weatherData[key] === 'object' && weatherData[key] !== null) { if (Array.isArray(weatherData[key])) { weatherData[key].forEach((item, index) => { Object.keys(item).forEach(subKey => { const stateId = `${basePath}.Weather.${key}[${index}].${subKey}`; setObject(stateId, { type: 'state', common: { name: `${key} ${subKey}`, type: typeof item[subKey], read: true, write: false } }); setState(stateId, { val: item[subKey], ack: true }); }); }); } else { Object.keys(weatherData[key]).forEach(subKey => { const stateId = `${basePath}.Weather.${key}.${subKey}`; setObject(stateId, { type: 'state', common: { name: `${key} ${subKey}`, type: typeof weatherData[key][subKey], read: true, write: false } }); setState(stateId, { val: weatherData[key][subKey], ack: true }); }); } } else { const stateId = `${basePath}.Weather.${key}`; setObject(stateId, { type: 'state', common: { name: key, type: typeof weatherData[key], read: true, write: false } }); setState(stateId, { val: weatherData[key], ack: true }); } }); return weatherData; }) .catch(error => { this.handleError(error, fetchWeatherData); }); }; // Erstmaliger Aufruf und Intervall einrichten fetchWeatherData(); setInterval(fetchWeatherData, CONFIG.interval); }); } // Methode zum Sicherstellen, dass der Token noch gültig ist ensureTokenIsValid() { if (!this.token) { log("Token ist nicht vorhanden oder ungültig. Hole neuen Token...", 'warn'); return this.authenticate(); } return Promise.resolve(); } // Methode zum Abrufen der Gruppendaten getGroups() { return this.ensureTokenIsValid().then(() => { log("Abrufen der Gruppendaten...", 'info'); const groupsUrl = 'https://internalapi.myuplink.com/v2/groups/me'; log(`Anfrage-URL für Gruppendaten: ${groupsUrl}`, 'debug'); return axios.get(groupsUrl, { headers: { 'Authorization': `Bearer ${this.token}`, 'Accept': 'application/json' } }) .then(response => { log("Gruppendaten erfolgreich abgerufen. Antwort: " + JSON.stringify(response.data), 'debug'); this.groups = response.data.groups || []; // Speichert die Gruppendaten this.devices = this.groups.flatMap(group => group.devices) || []; // Speichert die Gerätedaten this.createObjectsFromGroupsAndDevices(); return this.groups; }) .catch(error => { this.handleError(error); throw error; }); }); } // Methode zum Erstellen der Baumstruktur in myUplink createObjectsFromGroupsAndDevices() { log("Erstelle Objekte für Gruppen und Geräte...", 'info'); this.groups.forEach(group => { const groupId = group.id; group.devices.forEach(device => { const deviceId = device.id; const groupPath = `myUplink.System.${groupId}.${deviceId}`; // Erstellt das Geräteobjekt innerhalb der Gruppe setObject(groupPath, { type: 'device', common: { name: device.name || 'Unbenanntes Gerät', desc: device.description || '' }, native: device }); }); }); log("Objekterstellung abgeschlossen.", 'info'); } // Methode zum Abrufen der Menüstruktur async getAndCreateMenu(menuId = 0, basePath = `myUplink`) { try { const device = this.groups.flatMap(group => group.devices).find(device => device.id); if (!device || !device.id) { log('Keine gültige Device ID gefunden.', 'error'); throw new Error('No valid Device ID found.'); } const menuUrl = `https://internalapi.myuplink.com/v3/devices/${device.id}/menu/${menuId}`; const response = await axios.get(menuUrl, { headers: { 'Authorization': `Bearer ${this.token}`, 'Accept': 'application/json' } }); const menuData = response.data; if (menuData.rows && menuData.rows.length > 0) { for (const row of menuData.rows) { let name = row.text?.text || `Menü_${row.id}`; name = this.normalizeName(name); // Normalisieren von Umlauten const path = `${basePath}.${name}`; // Falls es ein weiterer Menü-Link ist, rufe das nächste Menü ab if (row.type === 'uilink') { setObject(path, { type: 'channel', common: { name: name, desc: `Menü ID: ${row.id}` }, native: row }); await this.getAndCreateMenu(row.id, path); } // Falls es ein Parameter ist, erstelle das Parameter-Objekt if (row.type === 'uiinfoparameter' || row.type === 'uinumerical' || row.type === 'uidropdown' || row.type === 'uiboolean') { this.createParameterObject(path, row); } } } } catch (error) { this.handleError(error); } } // Methode zum Erstellen eines Parameter-Objekts createParameterObject(path, parameter) { const parameterName = parameter.text?.text || `Parameter_${parameter.parameterId}`; let value = parameter.value?.integerValue ?? parameter.value?.stringValue ?? null; let adjustedValue = value; // Divisor anwenden, falls vorhanden und nur auf den Wert im Objekt selbst if (parameter.metadata?.divisor) { if (typeof value === 'number') { adjustedValue = value / parameter.metadata.divisor; } } // Wert als Text anzeigen, falls enumValues vorhanden sind const states = {}; if (parameter.metadata?.enumValues && parameter.metadata.enumValues.length > 0) { parameter.metadata.enumValues.forEach(ev => { states[ev.value] = ev.text; }); adjustedValue = value; } // Setze den Objekt-Typ je nach Parameter-Typ const commonType = parameter.metadata?.variableType?.toLowerCase() || 'mixed'; const role = parameter.type === 'uiboolean' ? 'switch' : 'text'; setObject(path, { type: 'state', common: { name: parameterName, type: commonType, unit: parameter.metadata?.unit || '', read: true, write: parameter.metadata?.isWritable || false, role: role, states: Object.keys(states).length > 0 ? states : undefined, min: parameter.metadata?.minValue && parameter.metadata.minValue !== 0 ? parameter.metadata.minValue / (parameter.metadata.divisor || 1) : undefined, max: parameter.metadata?.maxValue && parameter.metadata.maxValue !== 0 ? parameter.metadata.maxValue / (parameter.metadata.divisor || 1) : undefined, step: parameter.metadata?.change ? parameter.metadata.change / (parameter.metadata.divisor || 1) : undefined }, native: parameter }); // Setze den Wert des Parameters als Zahl oder Enum-Wert setState(path, { val: typeof adjustedValue === 'number' ? adjustedValue : value, ack: true }); // Lausche auf Änderungen des Werts, um die PUT-Anfrage zu senden if (parameter.metadata?.isWritable) { on({id: path, change: 'ne'}, (obj) => { // 'ne' bedeutet, nur nicht bestätigte Änderungen lauschen if (obj.state.ack) { return; // Wenn die Änderung von der API bestätigt wurde, ignoriere sie } let newValue = obj.state.val; const divisor = parameter.metadata?.divisor || 1; const minValue = typeof parameter.metadata?.minValue !== 'undefined' && parameter.metadata.minValue !== 0 ? parameter.metadata.minValue / divisor : undefined; const maxValue = typeof parameter.metadata?.maxValue !== 'undefined' && parameter.metadata.maxValue !== 0 ? parameter.metadata.maxValue / divisor : undefined; const change = parameter.metadata?.change ? parameter.metadata.change / divisor : undefined; // Werte begrenzen und anpassen if (typeof minValue !== 'undefined' && newValue < minValue) { newValue = minValue; } if (typeof maxValue !== 'undefined' && newValue > maxValue) { newValue = maxValue; } if (typeof change !== 'undefined') { newValue = Math.round(newValue / change) * change; } const adjustedValueForPut = newValue * divisor; let currentPath = path; let menuId = null; while (!menuId && currentPath.includes('.')) { currentPath = currentPath.substring(0, currentPath.lastIndexOf('.')); const currentObject = getObject(currentPath); if (currentObject?.native?.id) { menuId = currentObject.native.id; } } if (menuId) { this.updateParameterValue(menuId, parameter.parameterId, adjustedValueForPut, parameter.metadata?.unit || '', path, newValue); } else { log(`Fehler: Menü-ID für Pfad ${path} nicht gefunden.`, 'error'); } }); } } // Methode zum Normalisieren von Umlauten normalizeName(name) { return name .replace(/ä/g, 'ae') .replace(/ö/g, 'oe') .replace(/ü/g, 'ue') .replace(/ß/g, 'ss') .replace(/[^a-zA-Z0-9]/g, '_'); } // Methode zur Aktualisierung der Parameterwerte (PUT-Call) updateParameterValue(menuId, parameterId, value, unit = "", path, newValue) { const device = this.groups.flatMap(group => group.devices).find(device => device.id); if (!device || !device.id) { log('Keine gültige Device ID gefunden.', 'error'); throw new Error('No valid Device ID found.'); } const updateUrl = `https://internalapi.myuplink.com/v2/devices/${device.id}/menu/${menuId}/rawpoints/${parameterId}`; log(`Sende PUT-Anfrage an URL: ${updateUrl} mit Wert: ${value} und Einheit: ${unit}`, 'info'); return axios.put(updateUrl, { value: value, unit: unit }, { headers: { 'Authorization': `Bearer ${this.token}`, 'Content-Type': 'application/json' } }) .then(response => { log(`Parameter erfolgreich aktualisiert: ${JSON.stringify(response.data)}`, 'debug'); setState(path, { val: newValue, ack: true }); // Bestätigt den Wert im Objekt }) .catch(error => { this.handleError(error, () => this.updateParameterValue(menuId, parameterId, value, unit, path, newValue)); }); } // Fehlerbehandlungs-Methode handleError(error, retryCallback = null) { if (error.response) { log('Fehler-Antwortdaten: ' + JSON.stringify(error.response.data, null, 2), 'error'); log('HTTP-Statuscode: ' + error.response.status, 'error'); if (error.response.status === 401) { log('Token abgelaufen, erneuere den Token...', 'warn'); this.authenticate().then(() => { if (retryCallback) { retryCallback(); } }); } } setState('myUplink.info.connection', { val: false, ack: true }); // Verbindung fehlgeschlagen } } // Beispiel für die Verwendung der MyUplinkAdapter-Klasse (alle Logs als Fehler oder Warnungen) log("Starte die Authentifizierung...", 'info'); const adapter = new MyUplinkAdapter(); adapter.authenticate() .then(() => adapter.getGroups()) .then(groups => { log("Gruppendaten empfangen: " + JSON.stringify(groups), 'debug'); log("Gerätedaten empfangen: " + JSON.stringify(adapter.devices), 'debug'); return adapter.saveUserData(); }) .then(userData => { log("Benutzerdaten gespeichert: " + JSON.stringify(userData), 'info'); return adapter.getWeatherTileData(); }) .then(weatherData => { log("Wetterdaten empfangen: " + JSON.stringify(weatherData), 'info'); }) .then(() => adapter.getAndCreateMenu()) .then(() => { log('Menüstruktur erfolgreich erstellt.', 'info'); }) .then(() => { // Dynamisches Registrieren der Intervall-Funktionen CONFIG.intervalFunctions.forEach(funcName => { if (typeof adapter[funcName] === 'function') { setInterval(() => { adapter[funcName](); }, CONFIG.interval); log(`${funcName} wurde als Intervallfunktion registriert.`, 'info'); } else { log(`Funktion ${funcName} existiert nicht im Adapter.`, 'error'); } }); }) .catch(err => { log('Allgemeiner Fehler: ' + (err.message || "Keine Fehlermeldung verfügbar"), 'error'); }); log("Ende des Skripts erreicht.", 'info');
  • Partitionsgröße automatisch erweitern deaktivieren

    Moved
    16
    0 Votes
    16 Posts
    893 Views
    mickymM
    Nun @ro75 sagte in Partitionsgröße automatisch erweitern deaktivieren: Für was diesen Murks? Nun ich versteh das schon - ich habe meine Partition auch minimal verkleinert, damit die images auf unterschiedliche Fabrikate von SD Karten passen. Installiere Dir parted und resize2fs. Mit parted verkleinere die Partition, anschließend das Dateisystem mit resize2fs anpassen.
  • Yahka Thermostat mit Temperatursensor u. Steckdose erstellen

    Moved
    5
    0 Votes
    5 Posts
    267 Views
    paul53P
    @dody0007 sagte: Die Steckdose soll dann einschalten und wenn die Zieltemp. erreicht ist, wieder ausschalten. Dafür benötigst du einen eigenen Datenpunkt für den Sollwert und einen Zweipunkt-Regler (Skript).
  • Empfehlung 19" Server gesucht

    30
    0 Votes
    30 Posts
    2k Views
    BananaJoeB
    @negalein sagte in Empfehlung 19" Server gesucht: War nur so ein Gedankt, da ich die sehr günstig bekommen hätte. naja, deshalb liegt mein Kauf hier ja auch rum, schön billig sind die ja. Ich habe diese Erfahrung also auch mit Geld erkauft. Ich hatte den in der Testumgebung in der Firma im Einsatz, da ist der Stromverbrauch "egal" bzw. fallen ein paar hundert Watt mehr oder weniger schlicht nicht auf.
  • HM-IP Heizkörperthermostat-Display sehr blass / schwach

    Moved
    7
    0 Votes
    7 Posts
    467 Views
    Samson71S
    @timmss sagte in HM-IP Heizkörperthermostat-Display sehr blass / schwach: @samson71 Das könnte sein ja, wobei die frisch angebaut sind und vor nichtmal einem Jahr bestellt :( Dann wäre ja noch Garantie drauf. Sollte sich der Blickwinkel nicht als Grund zeigen, dann würde ich das direkt reklamieren.
  • Samsung Tab A8 - Akku

    7
    1
    0 Votes
    7 Posts
    358 Views
    NegaleinN
    @samson71 sagte in Samsung Tab A8 - Akku: Die Netzteile meiner 4 Wandtablets werden von Schaltaktoren ein- und ausgeschaltet Hätte ich vor. Muss aber erst Platz finden. Wird wohl hinter dem Tablet eine tiefe UP werden.
  • Roborock S7 einen bestimmten Raum Reinigung anstarten

    1
    0 Votes
    1 Posts
    173 Views
    No one has replied
  • Gesperrter Thread: "Linux bändigen"

    29
    0 Votes
    29 Posts
    1k Views
    K
    @oliverio Bei den Ubuntuusers schaue ich auch zuerst nach, wenn ich mal eine Linux-Frage habe. Dort wird meist sehr gut erklärt - auch anhand von Beispielen. Hat mir i.a. besser geholfen als manpage.
  • Linux-Tipps: USB-Serial und ESP-Programmierung

    2
    2
    1 Votes
    2 Posts
    440 Views
    MartinPM
    Hier noch als Nachtrag eine "sinnvolle" Anwendung von cu, wenn das (fast) fertig programmierte ESP-Device in der Nähe des Proxmox Servers steht. Dann kann man für Feinschliff schön mitlesen, was passiert. USB-Device zu einem "Spiel" Debian--LXC durchreichen, und Kontrollausgaben des ESP32 anzeigen lassen (kommen alle 10 Sekunden) martin@DebianTest:~$ cu -s 115200 -l /dev/ttyACM0 Connected. Difftemp:3.55 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.25 24.75 21.94 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.55 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.25 24.75 21.94 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.55 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.25 24.75 21.87 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.55 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.25 24.69 21.94 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.55 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.25 24.75 21.81 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.55 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.25 24.75 21.94 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.55 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.25 24.81 21.87 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.55 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.25 24.75 21.94 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.55 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.25 24.75 21.94 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.55 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.25 24.75 21.87 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.55 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.25 24.75 21.87 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.54 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.24 24.69 21.94 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.54 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.24 24.75 21.94 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.54 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.24 24.75 21.94 SollT 18.70 WiFi 1 MQTT 1 ok Difftemp:3.54 Hyst:0.15 ventState:0 pwmActual:0 Tmprtrs(22.24 24.75 21.87 SollT 18.70 WiFi 1 MQTT 1 ok
  • Kaco Powador mit RS485 zu MQTT

    Moved
    4
    0 Votes
    4 Posts
    246 Views
    Samson71S
    @hanshiasl sagte in Kaco Powador mit RS485 zu MQTT: Ich beziehe mich hier auf einen älteren Thread: Mir ist sehr wohl bewusst worauf sich das bezieht. Trotzdem kann niemand helfen ohne dedizierte Infos. Insofern ändert das nichts an meiner Antwort. Ich meinte natürlich Screenshots vom entsprechenden ioBroker-Adapter, da ich annahm dass es um ein MQTT-Problem im Zusammenhang mit ioBroker geht. Im Moment schwant mir aber, dass Du ioBroker überhaupt nicht nutzt. Dann hat das hier auch nichts in der Rubrik "ioBroker Allgemein" zu suchen, sondern gehört nach "Off Topic", weil es eben kein ioBroker-Problem ist, bzw. mit diesem nichts zu tun hat. Da helfen dann vermutlich auch weder Log-Einträge von Mosquitto noch vom speziellen Raspi. Der angesprochene User hat auch exakt nur diesen einen Beitrag überhaupt geschrieben und war seit mehr als anderthalb Jahren nicht mehr online. Von daher würde ich mir da eher keine großen Hoffnungen machen.
  • [Gelöst] Problem mit WLAN-Mesh-Netzwerk (Fritzboxen)

    11
    0 Votes
    11 Posts
    961 Views
    H
    @hans_999 said in Problem mit Mesh-Netzwerk (Fritzboxen): Irgendwie schaut es aus, als ob da ein Filter in der Meshverbindung zuschlägt. Aber ich habe nichts in der FB gefunden, was hier falsch parametriert sein könnte. Hat jemand eine Idee, wo ich suchen könnte oder gar Lösung? Mittlerweile hatte ich die Muße einmal die Einstellungen in der FB durchzuprobieren. Den beschriebenen Effekt konnte ich mit folgender Einstellung an der 1. Fritzbox (Master Master) "wegbekommen" WLAN - Sicherheit - Verschlüsselung - Aktive WLAN-Geräte dürfen untereinander kommunizieren erlauben Das gefällt mir zwar nicht so ganz, denn damit kann jedes mobile Gerät im Netz auf die anderen mobilen Geräte zugreifen. Aber im Nachgang klingt es logisch: Die Meshverbindung bindet ein WLAN-Gerät (Mesh-Partner) ein und dem Smartphone wird der Zugriff auf den Mesh-Partner nicht erlaubt. Aber über LAN gab es diese Einschränkung nicht.
  • Ubuntu 24.04 LTS

    11
    1 Votes
    11 Posts
    1k Views
    NegaleinN
    @lobomau sagte in Ubuntu 24.04 LTS: das LXC-Backup bringt dich doch genau dahin wo du vorher warst, also zum Ubuntu 22.04. dachte ich mir. ioB ist kein Problem. Bei einigen muss ich erst forschen, wie da ein Backup&Restore möglich ist.
  • Homekit-controller lässt sich nicht installieren

    Moved
    28
    0 Votes
    28 Posts
    2k Views
    H
    @sirdrinsalot Ich habe leider ebenfalls das Problem unter Windows und wäre für hilfreiche Tipps sehr dankbar! Visual Studio 2017 habe ich auch installiert. Wie passt man die Python Pfade entsprechend an? Dank Dir schon vorab!
  • LinuxTipp: "Mittlere Maustaste" wegkonfigurieren.

    2
    2
    0 Votes
    2 Posts
    209 Views
    MartinPM
    @martinp Heute getestet, funktionert - nach dem Boot ist die mittlere Maustaste unter dem Scrollrad ohne mein Zutun durch das beim Start automatisch ausgeführte Script wegkonfiguriert...
  • Warnung vor dem Linux Mint Upgrade auf 22.0

    2
    0 Votes
    2 Posts
    660 Views
    MartinPM
    So, ein kleines Update - vorher fungierte eine 250 GByte SATA-SSD als Systemplatte, jetzt habe ich kurzentschlossen eine 500 GByte SATA-SSD beim Prime Day geschossen. Mint 22.0 Live USB-Stick gebastelt, Boot-Reihenfolge umgestellt und 22.0 auf der neuen Platte Installiert, Linux Mint 22.0 bootet problemlos, die alte Systemplatte ist soweit unversehrt, dass ich jetzt nach und nach die Daten migrieren kann... Drucker/Scanner läuft, Mails gehen wieder Browser Profil ist migriert, Banking mit Hibiscus geht dank regelmäßiger Backups, ohne dass ich da Daten erneut von der Bank herunter laden musste ... Schrittweise weiter machen - die zweite SSD frisst ja kein Brot ...
  • 2024 noch mit Zigbee starten oder auf Thread setzen?

    10
    0 Votes
    10 Posts
    2k Views
    Jey CeeJ
    @black-falcon87 wirkliche Nachteile wirst du erstmal keine haben. Einzig das Thema Umzug, wenn du dann mal wechselst, könnte man als Nachteil betrachten. Da du dann im ioBroker deine Skripte und Visualisierung anpassen musst weil sich die Datenpunkte ändern. Mit Alias lässt sich das auf ein minimum reduzieren. Das zweite wäre das viele Geräte zum anlernen Zurückgesetzt werden, was bedeutet das du Zigbee Gruppen sofern du welche eingerichtet hast, neu machen musst. Mach dir doch einfach mal Gedanken welche Geräte du so in Zukunft anschaffen möchtest und schau ob die von der Hue Bridge Unterstützt werden. Wenn schon jetzt klar ist das es in naher Zukunft eine andere Lösung braucht, kannst du auch gleich wechseln.
  • iobroker hochverfügbar

    Moved
    82
    1 Votes
    82 Posts
    13k Views
    m1k3f15hM
    @apollon77 So hab ich das noch nie gesehen :) das ist ein guter Ansatz :) mike

714

Online

32.6k

Users

82.3k

Topics

1.3m

Posts