Skip to content

Einsteigerfragen

nur für Fragen von Einsteigern / Newbies / Noobs

4.1k Topics 52.1k Posts

NEWS

Subcategories


  • Grundfragen bei Anbindung von SmartHome Geräten

    1k 12k
    1k Topics
    12k Posts
    D
    jooo, jetzt läuft er auch bei mir
  • Grundfragen zur Installation von ioBroker

    642 11k
    642 Topics
    11k Posts
    Michael SchmittM
    @Thomas-Braun sagte in System auf neue SSD - Bitte mal Iob Diag anschauen: Der javascript und der fritzdect wären mir allerdings zu gesprächig, wenn die Frequenz mit der da in das Log geschrieben wird immer so ist. Das von Javascript kommt nur nach dem Neustart des Iobroker so oft. Ansonsten nur wenn ein Sensor nicht erreichbar ist oder wenn er dann reconnectet. Fritzdect ist nur eine Telegrammeldung dass ein Fenster geöffnet wurde und der Heizmodus geändert (kommt ja normal auch nicht so oft)
  • Grundfragen zur Erstellung von automatischen Abläufen

    206 3k
    206 Topics
    3k Posts
    HomoranH
    @decnet sagte in Auswertung von Datenpunkten (Akku einer Solaranlage): Wie kann man das einfach realisieren? z.B. mit einem kleinen Skript/Blockly/Flow.... EDIT: z.B. so: [image: 1774084632296-screenshot_20260321-101612_duckduckgo.jpg] Du legst zwei eigene Datenpunkte für Timestamp und Minimum an, triggerst auf en DP Akku und schreibst die Werte ggf. einmal täglich 23:59 den Wert Minimum nullen
  • Was kann es Einsteigern leichter machen?

    39 320
    39 Topics
    320 Posts
    M
    @schienw Es gibt einen slideshow Adapter. [image: 1774548630949-d03a193e-023c-43b1-8a63-833869059fcc-image.png] Welche Dateitypen sind denn dabei: png, jpg ?
  • HUE in Zigbee einbinden u. über Schalter schalten[Gelöst]

    16
    1
    0 Votes
    16 Posts
    1k Views
    P
    @asgothian hab hier gelesen, dass bei den Daten der "kritischen" Objekte (in meinem Fall also die, die fälschlicherweise auf "Ein" und "Aus" regieren) die Zeile "byON": "-" eingetragen bzw. angepasst werden muss. Hier mal als Beispiel die Objektdaten der Helligkeit: { { "type": "state", "common": { "name": "Wandlampe", "role": "level.brightness", "type": "number", "max": 100, "read": true, "write": true, "alias": { "id": "zigbee.0.00178801083800ea.brightness" }, "custom": { "iot.0": { "smartName": { "smartType": "LIGHT", "byON": "-" } } } }, "_id": "alias.0.Wandlampe.level", "native": {}, "acl": { "object": 1636, "state": 1636, "owner": "system.user.admin", "ownerGroup": "system.group.administrator" }, "from": "system.adapter.admin.0", "user": "system.user.admin", "ts": 1754311640373 } Das scheint zu funktionieren. Mal sehen, ob das dann die dauerhafte Lösung ist und welche neuen Nebenwirkungen auftreten. Gestern hat es ja auch zeitweise "einfach mal so" funktioniert.
  • Z-Wave Schwaiger ZHS 14 zeigt keinen Batterie-Status

    2
    1
    0 Votes
    2 Posts
    88 Views
    arteckA
    @AlCalzone ne idee ?
  • [GELÖST]Node.js update will nicht wie es soll

    40
    1
    0 Votes
    40 Posts
    3k Views
    Thomas BraunT
    @gerhardptl sagte in [GELÖST]Node.js update will nicht wie es soll: ich werde am besten neu anfangen. Richtig... Schnapp die ein frisches Speichermedium, knall da RaspberryOS 13 'Trixie' drauf, wenn das in wenigen Wochen veröffentlicht wurde und zieh dann mit einem Backup der Nutzdaten um. https://forum.iobroker.net/topic/51869/installation-auf-raspi-einfacher-geht-s-nicht
  • Shelly via Cloud einbinden

    13
    2
    0 Votes
    13 Posts
    863 Views
    mcm1957M
    @ramses5333 Danke Da das Script noch das V1Api verwendet hier als Info für User die später drüber stolpern: Shelly hat das Cloud Api V1 ABGEKÜNDIGT und wird es in absehbarer Zeit EINSTELLEN. Der Umstieg auf Api V2 ist von Seite Shelly dringend empfohlen: https://shelly-api-docs.shelly.cloud/cloud-control-api/ danger This API is deprecated and will be removed in the near future. We strongly recommend migrating to the v2.0-beta API, which provides improved functionality and enhanced performance. und auch hier: https://shelly-forum.com/article/174-hinweis-zur-abkündigung-cloud-control-api-v1-wechseln-sie-zu-v2/ Hinweis zur Abkündigung: Cloud Control API V1 – Wechseln Sie zu V2 Wir werden die Cloud Control API V1 in Kürze einstellen. Bitte wechseln Sie zur API V2, um einen unterbrechungsfreien Service und Zugriff auf neue Funktionen zu gewährleisten. ⚡ Mit V2 können Sie eine einzige Statusabfrage für bis zu 10 Geräte erhalten, was die Effizienz und Leistung verbessert.
  • Szenen Adapter: einzele mit DP de-/aktivieren

    16
    1
    0 Votes
    16 Posts
    716 Views
    A
    hier ist meine aktuelle Version für mehrere Rollos und verschiedenen Scenen. Gerne mal drüberschauen ;) Danke für Eure Hilfe, wie immer großartig!!! // Konfiguration für mehrere Rollos const rollos = [ { name: "EG Küche SW", blockDP: "0_userdata.0.RolloStatus.Automatik.EG.Kueche.SW", blockMQTT: [ "alias.0.Rollo.EG.Kueche.SuedWest.CLOSE", "alias.0.Rollo.EG.Kueche.SuedWest.STOP", "alias.0.Rollo.EG.Kueche.SuedWest.OPEN" ], idScene: 'scene.0.Rollo_EG_SW', idSceneMember: 'alias.0.Rollo.EG.Kueche.SW.Position' }, { name: "EG Wohnzimmer Ost", blockDP: "0_userdata.0.RolloStatus.Automatik.EG.WZ.Fenster_SE", blockMQTT: [ "alias.0.Rollo.EG.WZ.Fenster SE.CLOSE", "alias.0.Rollo.EG.WZ.Fenster SE.STOP", "alias.0.Rollo.EG.WZ.Fenster SE.OPEN" ], idScene: 'scene.0.Rollo_EG_E', idSceneMember: 'alias.0.Rollo.EG.WZ.Fenster SE.Position' }, // ...weitere Rollos hier hinzufügen ]; // Initialisierung für alle Rollos bei Skriptstart (async function initAll() { for (const rollo of rollos) { // Automatikstatus auf aktiv setzen setState(rollo.blockDP, true); log(`[Init] Automatikstatus zurückgesetzt: ${rollo.blockDP} für ${rollo.name}`, 'info'); // Szenenmitglied aktivieren await controlDp(rollo.idSceneMember, true, rollo.idScene); log(`[Init] Szenenmitglied ${rollo.idSceneMember} für ${rollo.name} aktiviert`, 'info'); } })(); // Funktion: Automatik blockieren, wenn manuell gefahren wird function setBlock(rollo) { const currentStatus = getState(rollo.blockDP).val; // Wenn bereits gesperrt, keine weitere Aktion if (currentStatus === false) { log(`[Sperre] Automatik für ${rollo.name} ist bereits gesperrt, keine weiteren Aktionen.`, 'info'); return; } // Automatik sperren log(`[Sperre] Manuelle Bedienung für ${rollo.name} erkannt – Automatik wird gesperrt.`, 'warn'); setState(rollo.blockDP, false); log(`[Sperre] ${rollo.blockDP} = false (gesperrt)`, 'info'); log(`Automatik für ${rollo.name} gesperrt bis morgen.`, 'info'); } // Funktion: Szene-Mitglied aktivieren oder deaktivieren async function controlDp(id, enable, sceneId) { log(`[Szene] Lese Szene: ${sceneId}`, 'debug'); const sceneObj = await getObjectAsync(sceneId); if (!sceneObj || !sceneObj.native || !Array.isArray(sceneObj.native.members)) { log(`[Fehler] Szene ${sceneId} ist ungültig oder hat keine Mitglieder.`, 'error'); return; } let found = false; for (let member of sceneObj.native.members) { log(`[Szene] Prüfe Mitglied: ${member.id}`, 'debug'); if (member.id === id) { member.disabled = !enable; found = true; log(`[Szene] → ${id} wurde ${enable ? 'aktiviert' : 'deaktiviert'}.`, 'info'); break; } } if (!found) { log(`[Warnung] Mitglied ${id} nicht in Szene ${sceneId} gefunden.`, 'warn'); } await setObjectAsync(sceneId, sceneObj); log(`[Szene] Szene ${sceneId} wurde aktualisiert.`, 'debug'); } // MQTT-Trigger für alle Rollos einrichten (ack: false beachten!) for (const rollo of rollos) { on({ id: rollo.blockMQTT, ack: false }, async (obj) => { log(`[Trigger] MQTT-Befehl empfangen: ${obj.id} = ${obj.state.val} für ${rollo.name}`, 'debug'); // Manuelle Bedienung erkannt → Automatik sperren setBlock(rollo); await controlDp(rollo.idSceneMember, false, rollo.idScene); }); } // Beispiel-Funktion: Automatik pro Rollo (kann erweitert werden) function automatikFunktion(rollo) { const status = getState(rollo.blockDP).val; log(`[Automatik] Statusprüfung für ${rollo.name}: ${rollo.blockDP} = ${status}`, 'debug'); if (status === false) { log(`Automatik für ${rollo.name} ist gesperrt, kein automatisches Fahren.`, 'warn'); return; } // Hier steht die Automatik-Logik pro Rollo log(`Automatik aktiv: ${rollo.name} fährt automatisch.`, 'info'); } // Zeitgesteuerte Rücksetzung der Sperre täglich um 03:00 Uhr schedule("0 3 * * *", async () => { log("[Reset] Starte tägliche Rücksetzung der Automatik-Sperre um 03:00 Uhr", 'info'); for (const rollo of rollos) { setState(rollo.blockDP, true); log(`[Reset] Sperrstatus zurückgesetzt: ${rollo.blockDP} für ${rollo.name}`, 'info'); await controlDp(rollo.idSceneMember, true, rollo.idScene); } });
  • Alexa Sprachsteuerung in IOB nur noch sehr eingeschränkt

    Locked
    2
    0 Votes
    2 Posts
    350 Views
    apollon77A
    @duffy Du hast mit https://forum.iobroker.net/topic/81618/iobroker-skill-in-alexa-nicht-verfügbar/69 schon den richtigen Thread gefunden. Kein grund für noch einen :-)
  • Iobroker, Alexa, Locales LLM

    1
    0 Votes
    1 Posts
    172 Views
    No one has replied
  • simple.api findet Shelly-Datenpunkte nicht

    5
    0 Votes
    5 Posts
    366 Views
    A
    @arteck said in simple.api findet Shelly-Datenpunkte nicht: ersetze die '#' mit %23 Vielen Dank, ich hab schon den Alias vergeben und das funktioniert prima weil ja auch der Name jetzt schön kurz und einprägsam ist. Ich habe es mal ausprobiert und %23 funktioniert auch!
  • Füllstands-Messung mit Iobroker

    14
    0 Votes
    14 Posts
    1k Views
    wendy2702W
    @mickemup Danke. Werde ich mal testen wenn der aktuelle Ultraschall Sensor nicht vernünftig funktionieren sollte.
  • Resol EL2 - älterer Regler

    Unsolved
    1
    0 Votes
    1 Posts
    89 Views
    No one has replied
  • tvprogram Adapter

    8
    0 Votes
    8 Posts
    510 Views
    OliverIOO
    @gerdternes Ja er funktioniert auch in vis2. Vis2 musste noch um etwas erweitert werden, was eine Weile gedauert hat, aber das Ostseite einiger Zeit ebenfalls erledigt. https://github.com/ioBroker/ioBroker.vis-2/pull/444 Gibts dabei Probleme? Welche?
  • Bewässerung mit Schleife

    9
    0 Votes
    9 Posts
    435 Views
    A
    @paul53 said in Bewässerung mit Schleife: Ich bevorzuge auch die Version mit den Timeouts in einer Funktion. Prima! Nochmals vielen Dank!
  • Playlist von Festplatte

    51
    0 Votes
    51 Posts
    6k Views
    Andre LiebgottA
    @icebear Installation HEOS-Adapter installieren und starten (https://github.com/withstu/ioBroker.heos) HTML-State "0_userdata.0.heos.browse_result_html" als Zeichenkette anlegen (alternativ eigener State, dann in der Konfiguration anpassen) dieses Script im Admin unter Skripte als neues Script hinzufügen. dieses Script starten in der ioBroker-vis ein basic-string(unescaped)-Widget in einem View einfügen, den HTML-State zuweisen View ausführen [image: 1752773658722-datapuunkt.jpg] ------------------- KONFIGURATION ------------------- */ // Ziel-State, in welchem das interpretierte HTML abgelegt wird. Der State muss vorher manuell angelegt worden sein const STATE_BROWSE_RESULT_HTML = '0_userdata.0.heos.browse_result_html'; // play-Befehle werden immer via broadcast an alle Player gesendet, ist dieses nicht gewünscht, so können in dem hier // anzugegebenen State die PIDs der Player angegeben werden, welche die play-Befehle erhalten sollen. Lässt sich // z.B. gut mit dem Widget jqui-container-HTML-View "Setze Objekt-ID" nutzen. // Im State sind die Player-PIDs durch , getrennt angebbar, der State muss vorher manuell angelegt worden sein const STATE_BROWSE_RESULT_PLAYERS = '0_userdata.0.heos.browse_result_player'; // Font und Rahmen-Basisfarbe, bei dunklem Hintergrund durch '255,255,255' ersetzen const HEOS_FONT_COLOR = '0,0,0'; // wenn es sich bei der HEOS Instanz nicht um die 0. handelt, bitte anpassen const HEOS_INSTANCE = '0'; // sollen die Navigationsergebnisse beim Starten des Scripts bereits untersucht werden? const BUILD_HTML_AT_SCRIPTSTART = true; ------------------- Script ------------------- */ const STATE_BROWSE_RESULT = `heos.${HEOS_INSTANCE}.sources.browse_result`; const STATE_COMMAND = `heos.${HEOS_INSTANCE}.command`; const STATE_PLAYERS = `heos.${HEOS_INSTANCE}.players`; function buildHTML( data ) { // sind players angegeben, so wird das globale command-State durch die Player-command-States ersetzt und // "player/" wird aus dem command selbst entfernt function buildOnClick(cmd,cmdState,players,doPatch) { let cmds = [cmdState]; let onClick = ''; // wenn nur ein player angesprochen werden soll, dann command-state auf den des players setzen // und command anpassen 'player\' entfernen if (doPatch && players!='') { cmds = players.split(','); for (let j=0; j<cmds.length; j++ ) cmds[j] = `${STATE_PLAYERS}.${cmds[j]}.command`; cmd = cmd.substr(cmd.indexOf('/',cmd)+1,9999); } for (let j=0; j<cmds.length; j++ ) onClick += `servConn.setState('${cmds[j]}','${cmd}');`; return onClick; } let html = "Sorry, no data!" if(data){ let command = getState(STATE_COMMAND).val; let playerIDs = ''; if (existsState(STATE_BROWSE_RESULT_PLAYERS)) playerIDs = getState(STATE_BROWSE_RESULT_PLAYERS).val; // Playernamen ermitteln let playerNames = 'Alle'; if (playerIDs!='') { let players = playerIDs.split(','); playerNames = ''; for (let i=0; i<players.length; i++) { if (existsState(`${STATE_PLAYERS}.${players[i]}.name`)) playerNames += (playerNames==''?'':', ') + getState(`${STATE_PLAYERS}.${players[i]}.name`).val; } } // subtitle soll Anzahl enthalten let subtitle = ''; if (data.parameter.count) subtitle += `${data.parameter.count} Einträge`; else if (data.payload) subtitle += `${data.payload.length} Einträge`; if (data.parameter.range) subtitle += ` (${data.parameter.range.replace(',','-')})`; if (subtitle!='') subtitle = `<div class="heos-head-subtext">${subtitle}</div>`; // globale Funktionen wie Übersicht/Back/... in der Kopfzeile darstellen let controls={'load_next':{'sym':'&rsaquo;', 'onClick':'' }, 'load_prev':{'sym':'&lsaquo;', 'onClick':'' }, 'play_all': {'sym':'&blacktriangleright;', 'onClick':'' }, 'back': {'sym':'&blacktriangle;', 'onClick':'' }, 'sources': {'sym':'&equals;', 'onClick':'' }, 'getHTML': function(key) { return `<div class="heos-head-btn ${controls[key].onClick!=''?'heos-clickable':''}" ${controls[key].onClick}> ${controls[key].sym} </div>`; } }; for (let i = 0; i < data.payload.length; i++) { let payload = data.payload[i]; if (payload.type=="control" && controls.hasOwnProperty(payload.name)) { let onClick = ''; for (let key in payload.commands) onClick = buildOnClick(payload.commands[key],STATE_COMMAND,playerIDs,key=='play'); controls[payload.name].onClick = `onClick="${onClick}"`; } } // Zeilen des Listview aufbauen let rowsHTML=''; for (let i = 0; i < data.payload.length; i++) { let payload = data.payload[i]; if (payload.type!="control") { for (let key in payload.commands) { let sym = ''; let onClick = buildOnClick(payload.commands[key],STATE_COMMAND,playerIDs,key=='play'); switch (key) { case 'play': sym = '&blacktriangleright;'; break; case 'browse': break; } rowsHTML += `<div class="heos-row" onClick="${onClick}"> <div class="heos-img">${payload.image_url!=''?`<img class="heos-img-fit" src="${payload.image_url}" width="auto" height="100%" alt="">`:'<div class="heos-img-empty"></div>'}</div> <div class="heos-text">${payload.name}</div> <div class="heos-btn">${sym}</div> </div>`; } } } html = ` <style type="text/css"> :root {--heos-font-color:rgba(${HEOS_FONT_COLOR},.9); --heos-border-color:rgba(${HEOS_FONT_COLOR},.05); } .heos-root { position:absolute; height:100%; width:100%; color:var(--heos-font-color); } .heos-head { height:96px; border-bottom:4px solid var(--heos-border-color); } .heos-head-players { font-size:0.7em; opacity:0.66; text-align:right; } .heos-head-img { width:72px; flex:none; height:72px; overflow:hidden; } .heos-head-title { width:100%; overflow:hidden; display:flex; align-items:flex-start; } .heos-head-text {text-align:left;padding-top:0.25em;padding-left:4px;font-size:1.1em;} .heos-head-subtext { font-size:0.66em; opacity:0.66; } .heos-head-btns {width:108px; flex:none; display:flex; flex-wrap:wrap; margin-left:auto;} .heos-head-btns-row {width:100%; display:flex;} .heos-head-btn {width:36px; height:36px; opacity:.2;text-align:center;font-size:2em; } .heos-body { overflow-y:auto; height:calc(100% - 72px); } .heos-img { width:64px; height:100%; overflow:hidden; } .heos-img-fit { width:100%; height:100%; object-fit:contain; } .heos-img-empty:after { content:'\\266A'; font-size:2.5em; opacity:0.2; display:flex; justify-content:center;} .heos-row { width:100%;height:56px;border-bottom:1px solid var(--heos-border-color);padding-top:4px;padding-bottom:4px; display:flex; align-items: center;} .heos-text {width:calc(100% - 112px);text-align:left;padding-left:4px;white-space: nowrap;overflow:hidden;} .heos-btn {width:48px;border-radius: 2px;text-align:center;font-size:2em; border-left:1px solid var(--heos-border-color); } .heos-clickable {opacity:1; } .heos-row:hover, .heos-clickable:hover {background-blend-mode:multiply;background-image: linear-gradient(var(--heos-border-color),var(--heos-border-color)) !important; } [class*="_heos-"] {outline:1px solid rgba(255,0,0,.2); outline-offset:-1px;} </style> <div class="heos-root"> <div class="heos-head"> <div class="heos-head-title"> <div class="heos-head-img">${data.image_url!=''?`<img class="heos-img-fit" src="${data.image_url}" alt="">`:'<div class="heos-img-empty"></div>'}</div> <div class="heos-head-text"> <div style="height:56px; overflow:hidden;"> ${data.name == "sources"?"HEOS Quellen-Übersicht":data.name} </div> ${subtitle} </div> <div class="heos-head-btns"> <div class="heos-head-btns-row"><div class="heos-head-btn"></div>${controls.getHTML('sources')+controls.getHTML('back')}</div> <div class="heos-head-btns-row">${controls.getHTML('load_prev')+controls.getHTML('play_all')+controls.getHTML('load_next')}</div> </div> </div> <div class="heos-head-players">Player: ${playerNames}</div> </div> <div class="heos-body"> ${rowsHTML} </div> </div>`; } setState(STATE_BROWSE_RESULT_HTML, html); }; // browse_result Überwachung on({id: STATE_BROWSE_RESULT, change: 'any'}, function (obj) { let data = JSON.parse(obj.state.val); if(data) buildHTML(data); }); on({id: STATE_BROWSE_RESULT_PLAYERS, change: 'any'}, function (obj) { let data = JSON.parse(getState(STATE_BROWSE_RESULT).val); if(data) buildHTML(data); }); // Sriptstart if (BUILD_HTML_AT_SCRIPTSTART) buildHTML( JSON.parse(getState(STATE_BROWSE_RESULT).val) ); [image: 1752773526043-fehlermeldung.jpg]
  • Modbus Finder 7M.38.8.400.0212 auslesen

    87
    4
    0 Votes
    87 Posts
    13k Views
    HomoranH
    @matis sagte in Modbus Finder 7M.38.8.400.0212 auslesen: Ich hab vier Zähler an einem Konverter in einem modbus frei nach: "meiner ist größer" :joy: ich hab aber 6, und 3 kommen demnächst noch dazu! ja, mit mehreren Zugriffen hast du recht, wobei das auch nicht ohne ist. ich hab die Waveshare (USB) an einem aktiven USB HUB, die Geräte per serial/by-id/ und hab den auch schon einfach umgesteckt, und alles lief wieder. Die Waveshare haben eindeutige IDs im Gegensatz zu billigen Konvertern [image: 1739130696636-20240204_165646.jpg]
  • [gelöst] backup error von influxdb2 remote

    12
    0 Votes
    12 Posts
    828 Views
    T
    @marc-berg oh man danke. das war es. da hätte ich selbst drauf kommen können/müssen
  • Wert von Adapter über MQTT setzen

    8
    0 Votes
    8 Posts
    459 Views
    A
    @marc-berg said in Wert von Adapter über MQTT setzen: enet/TischEsszimmer/Output Funktioniert - gehe davon aus dass es die Leerzeichen oder das fehlende Topic im Client waren ... Besten Dank :-)
  • Türklingel mit Video gesucht

    4
    0 Votes
    4 Posts
    404 Views
    MartinPM
    @andreios Die Datenrate für die Übertragung von Video beißt sich etwas mit der Signalqualität, die man über "Klingeldraht" erreichen kann ... Von Hikvision gibt es "two wire video doorbells" - wenn ich das richtig verstehe reichen die zwei Drähte, um Video und Spannungsversorgung zu gewährleisten. Ob da Klingeldrähte reichen, oder ob es ein definiertes "twisted Pair" sein muss, weiß ich nicht... https://www.amazon.de/-/en/Hikvision-Intercom-Complete-Quality-Control/dp/B0D1XN5ZQP
  • Wassermengenmesser

    22
    0 Votes
    22 Posts
    2k Views
    S
    @master67 Dann spendiere dem Nachbar doch noch ein Bier :beer:
  • benutzerdefinierte Einstellungen bei Obj. geht nicht(mehr)

    5
    1
    0 Votes
    5 Posts
    355 Views
    R
    @feuersturm Ja, na klar. Auch den Admin-Adapter reinstalliert. Werde das wohl auch mit dem History-Adapter machen UPDATE: History-Adapter neu installiert - alles okay - es geht wieder :-)) Danke - auch für den Tipp mit "iob diag" ( kannte ich noch nicht ). Lg
  • Alexa2-Adapter Problem bei Amazon-Anmeldung

    Unsolved
    2
    0 Votes
    2 Posts
    252 Views
    Samson71S
    @reinhard-boehm sagte in Alexa2-Adapter Problem bei Amazon-Anmeldung: bekomme auch den Code per SMS geschickt. https://github.com/Apollon77/ioBroker.alexa2?tab=readme-ov-file#problem-with-cookie-determination-with-sms-based-2fa-flow

278

Online

32.7k

Users

82.6k

Topics

1.3m

Posts