Skip to content

Skripten / Logik

Hilfe zu JavaScript, Blockly, TypeScript, Node-RED, Scenes und text2command

16.5k Topics 213.2k Posts

NEWS

Subcategories


  • Hilfe für Skripterstellung mit JavaScript

    2k 49k
    2k Topics
    49k Posts
    P
    @arnod Leider ist das Problem immer noch vorhanden. Welchen Hysteresewert muss ich denn bei mir anpassen, damit ich mein Problem abmindern kann? Ich habe gesehen, dass es mehrere Hysteresewerte im Script gibt.
  • Hilfe für Skripterstellung mit Blockly

    7k 79k
    7k Topics
    79k Posts
    mickemupM
    @IceD112 sagte in Datenpunkte spiegel - wie?: @arteck Damit meine ich: Aktuell lese ich ja gewisse DP im Tado Adapter bei Änderungen aus. Sprich, geht die Luftfeuchtigkeit 1% hoch oder runter, so habe ich jedes mal eine Abfrage des DP in Tado. und doch @oliverio, offenbar ist das lesen eines States ein Call bei Tado. das schreiben wiederum nicht. So hab ich es zumindest gelesen. @arteck wenn ich also nun hingehen würde und würde den Datenpunkt von tado zu userdata "spiegeln" und ich ersetze im Blockly im Trigger den DP von Tado gegen den gespiegelten aus userdata, dann würde das lesen des DP nur lokal laufen und bindet keine Ressourcen in der Tado Cloud. Bist du dir da sicher? Das "Binde" muss ja den Datenpunkt auch "beobachten" und bei Änderung wird dann dein user DP ein Update erhalten. Die Abfrage entsteht ja durch den Tado-Adapter. Ein Trigger auf den DP alleine kann doch eigentlich gar keine Abfrage auslösen. (Der schaut ja auch nur "lokal" ob sich der DP in der TADO Instanz geändert hat.) Oder von wo hast du diese Info?
  • Hilfe für Skripterstellung mit Node-RED

    953 13k
    953 Topics
    13k Posts
    S
    welche Palette hast du installiert, damit du den "AND" Baustein hast?
  • Definizion des Datenpunkts bereits im Skript

    Moved
    15
    0 Votes
    15 Posts
    3k Views
    P
    Klappt super: createState('Nachtruhe', false, false, { name: 'Status Nachtruhe', type: 'boolean', desc: 'Nachtruhe', role: 'switch', smartName: { 'de': 'Nachtruhe' }, custom: { "influxdb.0": { "enabled": true, "changesOnly": true, "debounce": "", "retention": 63072000 // 2 Jahre } } }); Danke! Pix
  • Hilfe zu Werteliste für JavaScript Noobie

    Moved
    2
    0 Votes
    2 Posts
    606 Views
    paul53P
    @Zippolighter: Geht das überhaupt so mit schreiben und lesen aus Werteliste?? Wie müssen dann hierfür die setState und getState Kommandos aussehen. ` An die Zustandstexte der Werteliste kommt man nur per getObject() und setObject() http://forum.iobroker.net/viewtopic.php?f=21&t=6418&p=66212#p66212. @Zippolighter: Oder denke ich viel zu kompliziert und es gibt eine einfachere Variante ` Die einfachere Variante ist ein Array, das mit JSON.stringify() in einen Datenpunkt vom Typ "string" gespeichert und per JSON.parse() wieder ausgelesen wird. Der Index ist dann Tag des Monats - 1.
  • Meine StateMachine

    Moved
    12
    0 Votes
    12 Posts
    4k Views
    frankjokeF
    Eine Möglichkeit wäre: Eine Variable zu erzeugen mittels: variables: { v_temp: ['mysensors.0.100.1_TEMP.V_TEMP', (val,that,st) => that.list[0] ] } und dann beim Event eine Bedingiung anzugeben: activity: {id: "fhem.0.MyHarmony.activity", change: "ne"}, activity_ifTemp: ['activity', (old, that) => that.getVariable('v_temp')<15] Dann wird activity_ifTemp nur ausgeführt wenn die Temperatur <15° ist.
  • [Geloest] Bitte um Hilfe bei Script ccu-> iobroker

    Moved
    25
    0 Votes
    25 Posts
    5k Views
    D
    Hallo Paul, ich nutze nun der Parser-Adapter. Für einen nicht Programmierer nicht so einfach. Ich habe es aber geschafft. Vielen Dank noch einmal für Dein Hilfe. Gesendet von iPad mit Tapatalk
  • Scipt in Vis startet nicht

    Moved
    5
    0 Votes
    5 Posts
    1k Views
    PeoplesP
    Da hast du vollkommen recht :D
  • LOWBAT Medungen Scipt Fehler

    Moved
    2
    0 Votes
    2 Posts
    1k Views
    paul53P
    Das Original Script stammt von http://forum.iobroker.net/viewtopic.php?f=21&t=869&p=10992#p6535. Zeile 10 kann entfallen, da die Anzahl aus der Array-Länge ermittelt werden kann. Zeile 26 sollte geändert werden in: ++moeglicheLOWBAT; // Zählt die Anzahl der vorhandenen Geräte unabhängig vom Status Dann muss auch Zeile 31 geändert werden: log("Anzahl Geräte: " + moeglicheLOWBAT + " # davon LOWBAT erkannt: " + textLOWBAT.length); Um auch noch abzufangen, dass der State zu Datenpunkten, die noch nie etwas empfangen haben, nicht existiert, sollte Zeile 20 ergänzt werden if(getState(id)) { var status = getState(id).val; // Zustand *.LOWBAT abfragen (jedes Element) } Hier das korrigierte Skript: createState('zählenLowbat.möglicheLOWBAT', 0); // wenn benötigt: Anzahl der Geräte mit Batterie createState('zählenLowbat.anzahlLOWBAT', 0); // wenn benötigt: Anzahl der vorhandenen LOWBAT createState('zählenLowbat.textLOWBAT', " "); // Namen LOWBAT, die an sind als Variable unter Javascript.0 anlegen var cacheSelectorLOWBAT = $('channel[state.id=*0.LOWBAT]'); function countLowbat(obj) { // Setzt die Zähler vor dem Durchlauf aller Elemente *.LOWBAT auf 0 var moeglicheLOWBAT = 0; var textLOWBAT = []; if (obj) { log('Auslösender Aktor: ' + obj.id + ': ' + obj.newState.val); // Info im Log, welcher Zustand sich geändert hat } else { log('Ausgelöst bei Timer'); } cacheSelectorLOWBAT.each(function (id, i) { // Schleife für jedes gefundenen Element *0.LOWBAT var status = false; if(getState(id)) { status = getState(id).val; // Zustand *0.LOWBAT abfragen (jedes Element) } var obj = getObject(id); if (status === true) { // wenn Zustand = true, wird das Array erweitert textLOWBAT.push(obj.common.name); // Zu Array hinzufügen } log("Geräte Nr. " + i + ": " + getObject(id).common.name + ": " + status); ++moeglicheLOWBAT; // Zählt die Anzahl der vorhandenen Geräte unabhängig vom Status }); // Schleife ist durchlaufen. Im Log wird der aktuelle Status (Anzahl, davon LOWBAT zutreffend) ausgegeben log("Text: " + textLOWBAT); log("Anzahl Geräte: " + moeglicheLOWBAT + " # davon LOWBAT erkannt: " + textLOWBAT.length); // die ermittelten Werte werden als javascript.0\. Variable in ioBroker gespeichert (z.B. für die Verarbeitung in VIS) setState("zählenLowbat.textLOWBAT", textLOWBAT.join(', ')); // Schreibt die Namen der Geräte mit LOWBAT Meldung setState("zählenLowbat.anzahlLOWBAT", textLOWBAT.length); // Schreibt die aktuelle Anzahl der LOWBAT-Meldungen setState("zählenLowbat.möglicheLOWBAT", moeglicheLOWBAT); // Schreibt die Anzahl der vorhandenen Batterie-Geräte } cacheSelectorLOWBAT.on(function(obj) { // bei Zustandänderung *. LOWBAT in allen Gewerken countLowbat(obj); }); schedule("*/60 * * * *", function () { //oder!! soll entweder ausgelöst werden alle 10 Minuten log("===>Will be triggered every 60 minutes!"); countLowbat(); });
  • Wandthermostat, Heizkörperthermostat und MANU_MODE

    Moved
    3
    0 Votes
    3 Posts
    799 Views
    bentschikB
    Hi Black, Danke für den Hinweis. In der Tat scheint es im damaligen WebUI-Programm auch so gewesen zu sein, dass ich den HT auch auf MANU_MODE stellen musste. Das hatte ich wohl falsch in Erinnerung. Die Original-Programme habe ich schon lange gelöscht, aber ich habe es eben nochmal kurz getestet. Ich muss nun einfach nur die beiden Datenpunkte des HT bei jedem HT mit der selben Funktion "ccontrol" versehen, wie die beiden Datenpunkte des WT. An dem Script muss ich nichts ändern. Mit // Wintermode inactive on({id:"/Wintermode",val:false}, function (obj) { $('state[id=*.MANU_MODE](functions=ccontrol)').each(function (id,i) { log("Summermode: setting "+id+" to off"); setStateDelayed(id,30.5,i*2000); }); }); läuft es dann auch, wie gewünscht, und die HTs gehen auch in MANU_MODE. Danke & beste Grüsse, Ben
  • Offene Fenster ansagen nach Ereignis

    Moved
    2
    0 Votes
    2 Posts
    632 Views
    DutchmanD
    @tobih83: Ist so etwas in einem gewissen Rahmen möglich? Vielen Dank Tobias ` Aber sicher da gibt es auch bereits einige Beispiele im Script subforum. Habe so schnell den Link nicht aber meine das pix und Paul haben bereits einige gepostet Gr Dutch –----------------------- Send from mobile device
  • [Frage] Relais bei überschreiten einer Temperatur schalten

    Moved
    14
    0 Votes
    14 Posts
    5k Views
    O
    hab mich gleich mal rangemacht, habs nach dieser Anleitung gemacht. http://www.iobroker.net/docu/?page_id=5106&lang=de doch :evil: Jetzt kommen diese Fehler: [image: 2717_bildschirmfoto_2017-05-20_um_11.26.02.png] [image: 2717_bildschirmfoto_2017-05-20_um_11.26.24.png]
  • Frage Node- red version Adapter

    Moved
    5
    0 Votes
    5 Posts
    2k Views
    apollon77A
    Fixed!
  • Zugriff auf iobroker Name, Type, Role?

    Moved
    11
    0 Votes
    11 Posts
    5k Views
    S
    danke ;) ich habe den + Button im Object Browser nicht gesehen. Jetzt mit dem link ist alles klar. Großes Kompliment an alle ioBroker Macher! Das ist echt professionell gemacht. Grüße Stefan
  • [Frage] Einfache Zeitschaltuhr über Node-Red

    Moved
    3
    0 Votes
    3 Posts
    9k Views
    rudikxR
    Nach langer Zeit habe ich nun doch eine Lösung für mein Problem gefunden. Wenn es jemanden interessiert wie man eine gewisse Zeit in einen Flow übergeben kann und diese dann entsprechend in einem Timer verarbeiten kann. Der kann sich meinen Lösungsweg gern ansehen. Vielleicht hilft es dem einen oder anderen ;) [image: 29206358fj.jpg]~~![](</s><URL url=)http://up.picr.de/29206358fj.jpg" /> Ich habe es gebraucht um meinen selbstgebauten Sprenklerventilen eine bestimmte Laufzeit zu geben. [image: 29206385qu.jpg]~~![](</s><URL url=)http://up.picr.de/29206385qu.jpg" /> Ist nicht das beste aber erfüllt seinen zweck vollkommen :) ! ```` [ { "id": "c1e423.55be5be", "type": "delay", "z": "6ebec0ea.874cf", "name": "", "pauseType": "delay", "timeout": "5", "timeoutUnits": "minutes", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "x": 737.7430152893066, "y": 294.7970428466797, "wires": [ [ "d06a5682.976518" ] ] }, { "id": "cd2acd2e.37301", "type": "ioBroker in", "z": "6ebec0ea.874cf", "name": "Ventil1_Zyklus", "topic": "admin.0.Eigene_Objekte.Bewaesserung.Ventil1_Zyklus", "payloadType": "value", "onlyack": "", "func": "all", "gap": "", "x": 154.75029754638672, "y": 130.17978191375732, "wires": [ [ "e901079b.805bd8" ] ] }, { "id": "e901079b.805bd8", "type": "switch", "z": "6ebec0ea.874cf", "name": "", "property": "payload", "propertyType": "msg", "rules": [ { "t": "eq", "v": "true", "vt": "str" } ], "checkall": "true", "outputs": 1, "x": 337.7503890991211, "y": 264.14856243133545, "wires": [ [ "e7320bf.f39fcf8", "7ad308a0.d61348" ] ] }, { "id": "e7320bf.f39fcf8", "type": "ioBroker get", "z": "6ebec0ea.874cf", "name": "Laufzeit_SOLL_V1", "topic": "admin.0.Eigene_Objekte.Bewaesserung.Laufzeit_SOLL_V1", "attrname": "payload", "payloadType": "value", "x": 280.75025177001953, "y": 411.343825340271, "wires": [ [ "41fd7a46.5a4ec4" ] ] }, { "id": "41fd7a46.5a4ec4", "type": "switch", "z": "6ebec0ea.874cf", "name": "", "property": "payload", "propertyType": "msg", "rules": [ { "t": "eq", "v": "0", "vt": "str" }, { "t": "eq", "v": "5", "vt": "str" }, { "t": "eq", "v": "10", "vt": "str" }, { "t": "eq", "v": "15", "vt": "str" }, { "t": "eq", "v": "20", "vt": "str" }, { "t": "eq", "v": "25", "vt": "str" }, { "t": "eq", "v": "30", "vt": "str" }, { "t": "eq", "v": "35", "vt": "str" }, { "t": "eq", "v": "40", "vt": "str" } ], "checkall": "true", "outputs": 9, "x": 480.7503204345703, "y": 355.1563529968262, "wires": [ [], [ "c1e423.55be5be" ], [ "26916043.4cb45" ], [ "846aced2.afb23" ], [ "d6da9b2f.5729d8" ], [ "4e92ebfd.e90c44" ], [ "1ff8132e.7bdc5d" ], [ "5e083cf1.f400b4" ], [ "30eee9e7.f45b26" ] ] }, { "id": "bbea0bcc.cd1e68", "type": "ioBroker out", "z": "6ebec0ea.874cf", "name": "Ventil1_Zyklus", "topic": "admin.0.Eigene_Objekte.Bewaesserung.Ventil1_Zyklus", "ack": "false", "autoCreate": "false", "x": 1095.7511825561523, "y": 490.4221124649048, "wires": [] }, { "id": "26916043.4cb45", "type": "delay", "z": "6ebec0ea.874cf", "name": "", "pauseType": "delay", "timeout": "10", "timeoutUnits": "minutes", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "x": 736.758243560791, "y": 330.80480003356934, "wires": [ [ "d06a5682.976518" ] ] }, { "id": "846aced2.afb23", "type": "delay", "z": "6ebec0ea.874cf", "name": "", "pauseType": "delay", "timeout": "15", "timeoutUnits": "minutes", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "x": 717.750431060791, "y": 369.80480003356934, "wires": [ [ "d06a5682.976518" ] ] }, { "id": "d6da9b2f.5729d8", "type": "delay", "z": "6ebec0ea.874cf", "name": "", "pauseType": "delay", "timeout": "20", "timeoutUnits": "minutes", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "x": 694.758243560791, "y": 408.80480003356934, "wires": [ [ "d06a5682.976518" ] ] }, { "id": "4e92ebfd.e90c44", "type": "delay", "z": "6ebec0ea.874cf", "name": "", "pauseType": "delay", "timeout": "25", "timeoutUnits": "minutes", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "x": 672.750431060791, "y": 447.80480003356934, "wires": [ [ "d06a5682.976518" ] ] }, { "id": "1ff8132e.7bdc5d", "type": "delay", "z": "6ebec0ea.874cf", "name": "", "pauseType": "delay", "timeout": "30", "timeoutUnits": "minutes", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "x": 651.750431060791, "y": 486.80480003356934, "wires": [ [ "d06a5682.976518" ] ] }, { "id": "5e083cf1.f400b4", "type": "delay", "z": "6ebec0ea.874cf", "name": "", "pauseType": "delay", "timeout": "35", "timeoutUnits": "minutes", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "x": 629.742618560791, "y": 525.8048000335693, "wires": [ [ "d06a5682.976518" ] ] }, { "id": "30eee9e7.f45b26", "type": "delay", "z": "6ebec0ea.874cf", "name": "", "pauseType": "delay", "timeout": "40", "timeoutUnits": "minutes", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "x": 606.750431060791, "y": 565.8126125335693, "wires": [ [ "d06a5682.976518" ] ] }, { "id": "d06a5682.976518", "type": "change", "z": "6ebec0ea.874cf", "name": "", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "false", "tot": "str" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 1031.742733001709, "y": 281.6251096725464, "wires": [ [ "bbea0bcc.cd1e68", "7e126dd2.a74244" ] ] }, { "id": "10590312.b3865d", "type": "ioBroker out", "z": "6ebec0ea.874cf", "name": "Ventil1_SOLL", "topic": "admin.0.Eigene_Objekte.Bewaesserung.Ventil1_SOLL", "ack": "false", "autoCreate": "false", "x": 753.5001373291016, "y": 190.3334140777588, "wires": [] }, { "id": "7ad308a0.d61348", "type": "delay", "z": "6ebec0ea.874cf", "name": "", "pauseType": "delay", "timeout": "5", "timeoutUnits": "seconds", "rate": "1", "nbRateUnits": "1", "rateUnits": "second", "randomFirst": "1", "randomLast": "5", "randomUnits": "seconds", "drop": false, "x": 559.6667747497559, "y": 190.66672611236572, "wires": [ [ "10590312.b3865d" ] ] }, { "id": "7e126dd2.a74244", "type": "ioBroker out", "z": "6ebec0ea.874cf", "name": "Ventil1_SOLL", "topic": "admin.0.Eigene_Objekte.Bewaesserung.Ventil1_SOLL", "ack": "false", "autoCreate": "false", "x": 1102.6668090820312, "y": 435.66675567626953, "wires": [] }, { "id": "b38c2f80.fb3d2", "type": "comment", "z": "6ebec0ea.874cf", "name": "Ventil1 Einzel Zyklus", "info": "Startet den einzelzyklus für Ventil1\nschaltet nach 5 sec verzögerung das Ventil1 ein\nprüft die eingebegeben Laufzeit aus dem Objekt\nswicht die entsprechnede Zeit zum entsprechenden Timer ;) \nund schaletet dannach wieder alles ab!\n\n", "x": 162.50003051757812, "y": 58.00003623962402, "wires": [] } ]
  • Liste von Geräte IDs die einen bestimmten Status haben

    Moved
    5
    0 Votes
    5 Posts
    2k Views
    C
    Ich habe jetzt einen anderen Weg eingeschlagen und den Code im Link von pix umgebaut. Jetzt habe ich ein JSON: [{"id":"hm-rpc.1.NEQ0891532.13.STATE","displayName":"Wohnzimmer"},{"id":"hm-rpc.1.NEQ0891532.17.STATE","displayName":"Küche"}] Ich überlege, wie ich das jetzt in Vis darstellen könnte. Im Grunde möchte ich eine Liste bauen welche eine Lampe und den Namen darstellt. Die Objekt ID soll gleich gesetzt sein, damit man diese halt auch schalten kann.
  • [Frage] Batterielevel aus Fully Browser weiterverwenden

    Moved
    8
    0 Votes
    8 Posts
    2k Views
    PeoplesP
    die Variante mit PAW klingt sehr interessant, jedoch würde ich gerne "Nur" den Akkustand mit Hilfe von fully auslesen. ... console.log( "Battery Level: " + fully.getBatteryLevel() ); setState("javascript.0.Batteriestatus", fully.getBatterylevel()); // falls string: fully.getBatteryLevel().toFloat(); console.log( "Screen Brightness: " + fully.getScreenBrightness() ); ... Mir erschließt sich nur nicht wie ich bzw. wo ich das o.g. einbinden kann. In Vis selbst, oder in einem sep. script? Weil wenn ich einfach ein Script erstelle mit einem bspw. schedule um das ganze zyklisch abzufragen bekomme ich nur eine Fehlermeldung, da Fully.getBatterylevel nicht vorhanden ist. Oder muss ich in Vis ein bspw. html objekt erstellen welches die daten dann an meinen Datenpunkt übergibt? Grüße
  • [gelöst]Suchfunktion im Java Skript Adapter

    Moved
    3
    0 Votes
    3 Posts
    634 Views
    S
    Danke, das war es. Ich hatte irgendwie den Ficus nicht richtig und es wurde immer nur die google suche geöffnet. Weil ich Strg. F und S probiert hatte. Nachdem ich in das Skript reingeklickt und dann Strg. F gedrückt habe: alles gut. Sorry!
  • Einfaches Script zur Gesamtstromberechung mit Fehler?

    Moved
    4
    1
    0 Votes
    4 Posts
    781 Views
    G
    Danke Paul. Geht jetzt. > Bitte in Zukunft kein Screenshot vom Skript, sondern eine Kopie aus dem JS-Editor-Fenster in Code tags posten. Ja macht sinn
  • 0 Votes
    3 Posts
    843 Views
    rantanplanR
    @lobomau: Wenn man einen Trigger-Eingang Hinzufügt oder Wegnimmt, dann springt der Trigger Block auf "wurde geändert" zurück, wenn man da vorher auf was anderes wie z.B. "wurde aktualisiert" oder "ist wahr" war. Ist das Absicht? Ich denke nicht. Falls sich das einfach ändern lässt, dann wäre es schön. Inzwischen weiß ich es. Aber ich habe mich schon mal totgesucht als nach einer Änderung das Script nicht mehr das tat was es sollte. Das übersieht man zuerst, weil man da ja nichts geändert hat. ` Den Bug habe ich schon bei Trello reingesetzt. Bluefox ist informiert. Grüße
  • (gelöst) Erster Versuch in Blockly

    Moved
    4
    1
    0 Votes
    4 Posts
    1k Views
    rantanplanR
    Prima! Wenn Du weitergekommen bist, setzte bitte ein [Gelöst] in den Betreff Deines ersten Eintrags. Weitere Infos hier http://forum.iobroker.net/viewtopic.php?f=8&t=2451 Grüße
  • KNX Status änderung per Pushover

    Moved
    3
    0 Votes
    3 Posts
    675 Views
    DutchmanD
    Tip: Fang mit blockly an und mach dir ein paar Schaltungen, Wechsel zur Code Sicht und du siehst was blockly für Skripte gebaut hat. So hab ich auch angefangen und manchmal wenn Mal wieder ne Lücke hab Klaue ich von blockly und danach ergänzen mit eigenes script –----------------------- Send from mobile device
  • [Frage] Hilfe für Script

    Moved
    6
    1
    0 Votes
    6 Posts
    879 Views
    eric2905E
    @Xxxvale46xxx: Geht es im Vis oder nur als Programm? ` Stimmt, den "ON_TIME" hatte ich vergessen. Mir ist auf Anhieb kein Widget bekannt, welches mehrere Aktionen nacheinander ausführt (Setze "ON_TIME" auf 30 Sekunden und dann den "STATE" auf True). Da müsste aber über eine Szene oder ein Javascript gehen, welches dann per Button gestartet wird. Gruß, Eric

665

Online

32.6k

Users

82.2k

Topics

1.3m

Posts