Unable to get relay status from Domoticz


  • Hardware Contributor

    Starting from relay example and @Boots33 synchronising light switch (https://forum.mysensors.org/topic/6948/synchronising-light-switch) I'm arranging a node with a DS18B20 +relay (simple thermostat).

    My issue is that I cannot receive the relay status from controller (Domoticz). Looking with log parser, seems to me that PAYLOAD is empty.

    This is in effect the log:

    6480 TSF:MSG:SEND,10-10-0-0,s=1,c=2,t=2,pt=0,l=0,sg=1,ft=0,st=OK:
    6496 TSF:MSG:SEND,10-10-0-0,s=1,c=3,t=16,pt=0,l=0,sg=1,ft=0,st=OK:
    6625 TSF:MSG:READ,0-0-10,s=255,c=3,t=17,pt=6,l=25,sg=1:427C42AE0562164806668CEBC26347BE1A113516C9C14F345A
    6723 TSF:MSG:SEND,10-10-0-0,s=1,c=2,t=2,pt=0,l=0,sg=1,ft=0,st=OK:
    9059 TSF:MSG:READ,0-0-10,s=255,c=3,t=17,pt=6,l=25,sg=1:499D2360929A82BB0BB9B0C47873D3E460ADF357B2DECAA3F4
    9153 TSF:MSG:SEND,10-10-0-0,s=0,c=1,t=0,pt=7,l=5,sg=1,ft=0,st=OK:29.5
    180163 TSF:MSG:READ,0-0-10,s=1,c=3,t=16,pt=0,l=0,sg=1:
    180185 TSF:MSG:SEND,10-10-0-0,s=255,c=3,t=17,pt=6,l=25,sg=1,ft=0,st=OK:F62E5E036965BB68EEE8797C8E9F12AA8C935F0C49F4359DFB
    180329 TSF:MSG:READ,0-0-10,s=1,c=1,t=2,pt=0,l=1,sg=1:0
    180428 TSF:MSG:SEND,10-10-0-0,s=1,c=1,t=2,pt=0,l=1,sg=0,ft=0,st=OK:0
    241998 TSF:MSG:READ,0-0-10,s=1,c=3,t=16,pt=0,l=0,sg=1:
    242184 TSF:MSG:READ,0-0-10,s=1,c=1,t=2,pt=0,l=1,sg=1:1
    242284 TSF:MSG:SEND,10-10-0-0,s=1,c=1,t=2,pt=0,l=1,sg=0,ft=0,st=OK:1
    

    And payload seems totally empty.

    Another one thing, neither I read in serial monitor the debug section println

    case C_REQ:                                             // message is a returning request from controller
            Serial.print("Incoming request. The request_state is now: ");
    

    Seems never executed the case "C_REQ".

    If Domoticz sends command to poweron (or poweroff) the relay, all works like a charme. I would simply get the state of relay viewed on Domoticz.

    This is the script (my relay module is powered when PIN goes LOW; for this you see the "inverted" in #define section)

    /**
     * Sketch for a relay + termostat.
     * 
     * In test from 11/08/2017
     * 
     * @version 2.0
     * 
     */
    
    /**
     * DEFINE MYSENSORS SECTION
     */
    #define MY_DEBUG                    // Enable Basic Debug
    //#define MY_DEBUG_VERBOSE_SIGNING    // Enable Signing Debug
    #define MY_RADIO_NRF24
    #define MY_SIGNING_SOFT
    #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7
    #define MY_SIGNING_REQUEST_SIGNATURES
    #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x3B,0xF4,0x61,0xFF,0xFF,0x97,0xB1,0xFF,0xEC}}}
    #define MY_NODE_ID 10               // Default ID
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    #define MY_WITH_LEDS_BLINKING_INVERSE
    #define MY_DEFAULT_ERR_LED_PIN 16
    #define MY_DEFAULT_TX_LED_PIN 17
    #define MY_DEFAULT_RX_LED_PIN 18
    
    /**
     * Include libraries
     */
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    /**
     * Define section.
     * 
     *    // NAME
     */
    #define SKETCH_NAME       "Termostato+Relay"
    #define SKETCH_VERSION    "2.0"
    
        //  PIN
    #define PIN_DS18B20       2
    #define PIN_RELAY         3
    #define PIN_LED_STATUS    19
    
        //  CHILD ID
    #define CHILD_ID_TEMP     0
    #define CHILD_ID_RELAY    1
    
        //  RELAY SECTION
    #define RELAY_ON          0   // if inverted, invert here
    #define RELAY_OFF         1   // if inverted, invert here
    
        //  WAITs TIMES
    #define WAIT_LOOPS        5  // The status led flashes ON 10 ms and OFF 4990 ms == 5000 ms of loop. 5000 * WAIT_LOOPS = number of cycles before new read. 60 == 5 minutes
    #define WAIT_RETURN       1500  //  Milliseconds to wait for returns from gateway
    
    /**
     * Various variable
     */
    bool is_first_loop = true;
    bool request_state;
    bool state = false; // the current state of relay
    bool uplink_available = true;
    unsigned long uplink_check_time;                // holder for uplink checks
    unsigned long uplink_check_period = 30*1000;     // time between checks for uplink in milliseconds
    
    /*
     * One Wire Section
     */
    OneWire oneWire(PIN_DS18B20); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature.
    
    /**
     * Mysensors message
     */
    // Initialize temperature message
    MyMessage msg_temperature(CHILD_ID_TEMP , V_TEMP);
    // Initialize relay message
    MyMessage msg_relay(CHILD_ID_RELAY , V_STATUS);
    
    /**
     * Before class
     */
    void before() {
      // Startup up the OneWire library
      sensors.begin();
    }
    
    /**
     * Presentation.
     * 
     * Presents the child to the controller
     */
    void presentation() {
    
      // send sketch name
      sendSketchInfo(SKETCH_NAME , SKETCH_VERSION);
      // Present all sensors to controller.
      // TEMPERATURE
      present(CHILD_ID_TEMP, S_TEMP);
      // RELAY
      present(CHILD_ID_RELAY , S_BINARY);
      
    }
    
    /**
     * Our Setup
     */
    
    void setup() {
    
      // SETUP LED STATUS
        // Set the LED STATUS as OUTPUT and shutdown it.
      pinMode(PIN_LED_STATUS , OUTPUT);
      digitalWrite(PIN_LED_STATUS , LOW);
    
      // SETUP RELAY
        // Set the RELAY PIN as OUTPUT and LOW
      pinMode(PIN_RELAY , OUTPUT);
      digitalWrite(PIN_RELAY , RELAY_OFF);
    
      // initialize sensors
      sensors.setWaitForConversion(false);
      
    }
    
    
    /**
     * Our loop
     */
    void loop() {
    
      Serial.println("-------------- DEBUG loop() ---------------");
      Serial.print("Value of is_first_loop is ");
      Serial.println(is_first_loop);
      Serial.println("-------------------------------------------");
      
      if ( is_first_loop == true ) {
    
        // request state of relay to the controller;
        getStateFromController();
    
        // set is_first_loop = false;
        is_first_loop = false;
      }
    
      // executed the reading
      loopTemperature();
      
      // light the status led... so wait
      lightLedStatus();
      
    }
    
    /*
     * Get the state of relay from controller.
     * Executed once at first loop.
     * 
     * @since 2.0
     */
    void getStateFromController() {
    
      Serial.println("-------------- DEBUG getStateFromController() ---------------");
    
      
    
      if (request( CHILD_ID_RELAY , V_STATUS)) {       // request the current state of the switch on the controller and check that an ack was received
    
        Serial.print("request( CHILD_ID_RELAY , V_STATUS) value is ");
        Serial.print(request( CHILD_ID_RELAY , V_STATUS));
        Serial.println("Uplink available!");
        wait (WAIT_RETURN);
        Serial.print("Relay in controller is marked as ");
       /*
        * THIS IS FOREVER FALSE == 0 :( 
       */
        Serial.println(request_state);
        if (request_state != state) {      // check that controller is corectly showing the current relay state
            send(msg_relay.set(state), false);  // notify controller of current state
        }
      } else {
        Serial.println("! ERROR uplink is not available!");
        uplink_available = false;               // no uplink established
        uplink_check_time = millis();
      }
    
      Serial.println("-------------------------------------------------------------");
      
    }
    
    /**
     * Loop temperature.
     * Executed inside loop()
     * 
     * @since 2.0
     */
    void loopTemperature() {
    
      // Fetch temperatures from Dallas sensors
      // we need sensors.requestTemperatures() to NO BLOCK THE THREAD!!!
      sensors.requestTemperatures();
      float temperature = readTemperature();
      Serial.println("-------------- DEBUG loopTemperature() ---------------");
      Serial.print("Temperature is now ");
      Serial.println(temperature);
      Serial.println("------------------------------------------------------");
    
      sendTemperatureToController(temperature);
      
    }
    
    /************************************************/
    /****       VARIOUS FUNCTION TO SUPPORT     *****/
    /************************************************/
    
    /**
     * Receive function
     * 
     * @since 2.0
     */
    void receive(const MyMessage &msg_relay) {
    
      Serial.println("-------------- DEBUG receive() ---------------");
      
      if (msg_relay.type == V_STATUS) {                                   // check to see if incoming message is for a switch
        switch (msg_relay.getCommand()) {                                 // message.getCommand will give us the command type of the incomming message
          case C_SET:                                                   //message is a set command  from controller to update relay state
            state = msg_relay.getBool();                                  // get the new state
            digitalWrite(PIN_RELAY, state ? RELAY_ON : RELAY_OFF);      // switch relay to new state
            uplink_available = true;                                     //  uplink established
            Serial.print("Incoming change for sensor:");
            Serial.print(msg_relay.sensor);
            Serial.print(", New status: ");
            Serial.println(msg_relay.getBool());
            break;
          case C_REQ:                                             // message is a returning request from controller
            Serial.print("Incoming request. The request_state is now: ");
            request_state = msg_relay.getBool();                       // update requestState with returning state
            Serial.println(request_state);
            break;
        }
      }
    
      Serial.println("--------------------------------------------");
    }
    
    /**
     * Read the temperature from DS18B20
     * 
     * @since 2.0
     */
    float readTemperature() {
    
      // query conversion time and sleep until conversion completed
      int16_t conversionTime = millisToWaitForConversion(sensors.getResolution());
      wait(conversionTime);
    
      // Read temperatures and send them to controller 
      // Fetch and round temperature to one decimal
      float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(CHILD_ID_TEMP):sensors.getTempFByIndex(CHILD_ID_TEMP)) * 10.)) / 10.;
    
      return temperature;
      
    }
    
    /**
     * Get the millis to wait before reading based on resolution.
     * 
     * @since 2.0
     */
    
    int16_t millisToWaitForConversion(uint8_t bitResolution) {
      switch (bitResolution) {
        case 9:
        return 94;
        case 10:
        return 188;
        case 11:
        return 375;
        default:
        return 750;
      }
    }
    
    /**
     * Send the temperature to controller
     * 
     * @since 2.0
     */
    
    void sendTemperatureToController(float temperature) {
    
      if (temperature != -127.00 && temperature != 85.00) {
    
        send(msg_temperature.setSensor(CHILD_ID_TEMP).set(temperature,1));
        digitalWrite(MY_DEFAULT_ERR_LED_PIN , LOW);
        Serial.println("-------------- DEBUG sendTemperatureToController() ---------------");
        Serial.println("No error on send temperature");
        Serial.println("------------------------------------------------------");
        
      } else {
    
        // light the error led fixed!
        digitalWrite(MY_DEFAULT_ERR_LED_PIN , HIGH);
        Serial.println("-------------- DEBUG sendTemperatureToController() ---------------");
        Serial.println("! ERROR sending temperature");
        Serial.println("------------------------------------------------------");
        
      }
      
    }
    
    /**
     * Light the LED status
     * 
     * @since 2.0
     */
    void lightLedStatus() {
    
      int k = 0;
    
      for ( k = 0; k < WAIT_LOOPS; k++) {
        
        digitalWrite(PIN_LED_STATUS,HIGH);
          wait(10); // 5 * 1000 millisends = 5 seconds;
        digitalWrite(PIN_LED_STATUS,LOW);
          wait(4990);
        
      }
      
    }
    
    /**********************************************/
    /****       VARIOUS FUNCTION TO DEBUG     *****/
    /**********************************************/
    
    /**
     * Test Led status
     * @since 2.0
     */
    void testLed() {
    
      int k = 16;
      for (k = 16; k<20; k++) {
    
        pinMode(k,OUTPUT);
        digitalWrite(k,HIGH);
        wait(50);
        digitalWrite(k,LOW);
        wait(50);
        
      }
      
    }
    

    Thank you for your time.


  • Mod

    Do a debug print of the command you received before you enter the "case"


  • Hardware Contributor

    @gohan

    I did edit the receive function with this:

    void receive(const MyMessage &msg_relay) {
    
      Serial.println("-------------- DEBUG receive() ---------------");
    
      Serial.print("msg_relay.type value is ");
      Serial.println(msg_relay.type);
      Serial.println("------------------------------------------");
      Serial.print("msg_relay.getCommand() value is ");
      Serial.println(msg_relay.getCommand());
      Serial.println("------------------------------------------");
    
      Serial.println("--------------------------------------------");
    }
    

    Receive is NOT called at first start ( I have no debug in monitor). Receive is called only when from DOMOTICZ I poweron or poweroff the relay.

    In effect this is the debug monitor:

    -------------- DEBUG getStateFromController() ---------------
    request( CHILD_ID_RELAY , V_STATUS) value is 1
    Uplink available!
    Relay in controller is marked as 0
    -------------------------------------------------------------
    -------------- DEBUG receive() ---------------
    msg_relay.type value is 2
    ------------------------------------------
    msg_relay.getCommand() value is 1
    ------------------------------------------
    --------------------------------------------
    -------------- DEBUG receive() ---------------
    msg_relay.type value is 2
    ------------------------------------------
    msg_relay.getCommand() value is 1
    ------------------------------------------
    --------------------------------------------
    

    Last two receive() debug called only when I did poweron or poweroff the relay.



  • You could try editing out all the ifs etc in the getStateFromController and only request the state (surrounded by a few serial prints to see which bits execute). If it works in simplest form then you could build up the logic around it to see what is failing

    void getStateFromController() {
    
      Serial.println(" starting GetStateFromController");
      request( CHILD_ID_RELAY , V_STATUS);
      wait (WAIT_RETURN);
     serial.print("Waiting");
    
    }    
    
    

  • Mod

    I still miss the point in asking the status of the relay...


  • Hardware Contributor

    @Ben-Andrewes request return every time "1". This is not the state of relay in Domoticz . The following state from Domoticz is "0", either if in Domoticz relay need to be on or off ....


  • Hardware Contributor

    @gohan to mantain them in sync after a power failure.

    But you did put me on right way. I could simply put the relay off on Arduino start and send off to Domoticz.

    Every 5 minutes I could send the corrent state ti Domoticz (Imagine a gateway Power failure instead).

    In this mode I delegate all logic to Domoticz, when the relay need to be on or off....


  • Mod

    There is the savestate and readstate functions in mysensors in case you need it


  • Hardware Contributor

    @gohan I know, but I would to not use the EEprom and I would also learn and understand where is my error / why cannot get the state... 🙂


  • Mod

    I was just trying to point out that it is a design flaw as the nodes should be as much as indipendent as possible from controller but if you want to play around, have fun


  • Hardware Contributor

    Ok,
    I don't know if it is necessary to open a new post.

    I imagine now it's a problem of Domoticz.

    I did change all my logic. NOw on startup and every X minutes, the node send to the Domoticz the status of relay, to mantain it in sync.

    Errrr...... the status is received but not displayed correctly 😥

    I attach an image to explain better.

    alt text

    Domoticz is last update version, this is the current sketch:

    /**
     * Sketch for a relay + termostat.
     * 
     * In test from 11/08/2017
     * 
     * TERMINARE SE UPLINK NON è DISPONIBILE
     * 
     * @version 2.0
     * 
     */
    
    /**
     * DEFINE MYSENSORS SECTION
     */
    #define MY_DEBUG                    // Enable Basic Debug
    //#define MY_DEBUG_VERBOSE_SIGNING    // Enable Signing Debug
    #define MY_RADIO_NRF24
    #define MY_SIGNING_SOFT
    #define MY_SIGNING_SOFT_RANDOMSEED_PIN 7
    #define MY_SIGNING_REQUEST_SIGNATURES
    #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x3B,0xF4,0x61,0xDF,0x1E,0xFF,0xFF,0xFF,0xEC}}}
    #define MY_NODE_ID 10               // Default ID
    #define MY_DEFAULT_LED_BLINK_PERIOD 300
    #define MY_WITH_LEDS_BLINKING_INVERSE
    #define MY_DEFAULT_ERR_LED_PIN 16
    #define MY_DEFAULT_TX_LED_PIN 17
    #define MY_DEFAULT_RX_LED_PIN 18
    
    /**
     * Include libraries
     */
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DallasTemperature.h>
    #include <OneWire.h>
    
    /**
     * Define section.
     * 
     *    // NAME
     */
    #define SKETCH_NAME       "Termostato+Relay"
    #define SKETCH_VERSION    "3.0"
    
        //  PIN
    #define PIN_DS18B20       2
    #define PIN_RELAY         3
    #define PIN_LED_STATUS    19
    
        //  CHILD ID
    #define CHILD_ID_TEMP     0
    #define CHILD_ID_RELAY    1
    
        //  RELAY SECTION
    #define RELAY_ON          0   // if inverted, invert here
    #define RELAY_OFF         1   // if inverted, invert here
    
        //  WAITs TIMES
    #define WAIT_LOOPS        1  // The status led flashes ON 10 ms and OFF 4990 ms == 5000 ms of loop. 5000 * WAIT_LOOPS = number of cycles before new read. 60 == 5 minutes
    //#define WAIT_RETURN       1500  //  Milliseconds to wait for returns from gateway
    
    
    
    /*
     * One Wire Section
     */
    OneWire oneWire(PIN_DS18B20); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature.
    
    /**
     * Mysensors message
     */
    // Initialize temperature message
    MyMessage msg_temperature(CHILD_ID_TEMP , V_TEMP);
    // Initialize relay message
    MyMessage msg_relay(CHILD_ID_RELAY , V_STATUS);
    
    /**
     * Before class
     */
    void before() {
      // Startup up the OneWire library
      sensors.begin();
    }
    
    /**
     * Presentation.
     * 
     * Presents the child to the controller
     */
    void presentation() {
    
      // send sketch name
      sendSketchInfo(SKETCH_NAME , SKETCH_VERSION);
      // Present all sensors to controller.
      // TEMPERATURE
      present(CHILD_ID_TEMP, S_TEMP);
      // RELAY
      present(CHILD_ID_RELAY , S_BINARY);
      
    }
    
    /**
     * Our Setup
     */
    
    void setup() {
    
      // SETUP LED STATUS
        // Set the LED STATUS as OUTPUT and shutdown it.
      pinMode(PIN_LED_STATUS , OUTPUT);
      digitalWrite(PIN_LED_STATUS , LOW);
    
      // SETUP RELAY
        // Set the RELAY PIN as OUTPUT and LOW
      pinMode(PIN_RELAY , OUTPUT);
      digitalWrite(PIN_RELAY , RELAY_OFF);
    
      // initialize sensors
      sensors.setWaitForConversion(false);
      
    }
    
    
    /**
     * Our loop
     */
    void loop() {
    
      // send the relay state to controller
      sendRelayStateToController();
    
      // executed the reading
      loopTemperature();
      
      // light the status led... so wait
      lightLedStatus();
      
    }
    
    /*
     * Send the state of relay to controller.
     * 
     * @since 3.0
     */
    void sendRelayStateToController() {
    
      Serial.println("-------------- DEBUG sendRelayStateToController() ---------------");
    
      bool current_state = digitalRead(PIN_RELAY);
    
      
    
      if (current_state == 1) {
    
        current_state = RELAY_ON;
        
      } else {
    
        current_state = RELAY_OFF;
        
      }
    
      Serial.print("current_state value is ");
      Serial.println(current_state);
      send(msg_relay.set(current_state) , true);
    
      Serial.println("------------------------------------------------------------");
      
    }
    
    /**
     * Loop temperature.
     * Executed inside loop()
     * 
     * @since 2.0
     */
    void loopTemperature() {
    
      // Fetch temperatures from Dallas sensors
      // we need sensors.requestTemperatures() to NO BLOCK THE THREAD!!!
      sensors.requestTemperatures();
      float temperature = readTemperature();
     
    
      sendTemperatureToController(temperature);
      
    }
    
    /************************************************/
    /****       VARIOUS FUNCTION TO SUPPORT     *****/
    /************************************************/
    
    /**
     * Receive function
     * 
     * @since 2.0
     */
    void receive(const MyMessage &message) {
    
      
    
      if ( !message.isAck() ) {
    
        if ( message.type == V_STATUS) {
      
          if (  message.getCommand() == 1 ) {
      
            bool received_state = message.getBool();
            Serial.print("received_state value is ");
            Serial.println(received_state);
      
            if ( received_state == 1) {
      
              digitalWrite(PIN_RELAY , RELAY_ON);
              
            } else {
      
              digitalWrite(PIN_RELAY , RELAY_OFF);
              
            }
            
          }
          
        }
    
      }
      
     
    
      Serial.println("--------------------------------------------");
    }
    
    /**
     * Read the temperature from DS18B20
     * 
     * @since 2.0
     */
    float readTemperature() {
    
      // query conversion time and sleep until conversion completed
      int16_t conversionTime = millisToWaitForConversion(sensors.getResolution());
      wait(conversionTime);
    
      // Read temperatures and send them to controller 
      // Fetch and round temperature to one decimal
      float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(CHILD_ID_TEMP):sensors.getTempFByIndex(CHILD_ID_TEMP)) * 10.)) / 10.;
    
      return temperature;
      
    }
    
    /**
     * Get the millis to wait before reading based on resolution.
     * 
     * @since 2.0
     */
    
    int16_t millisToWaitForConversion(uint8_t bitResolution) {
      switch (bitResolution) {
        case 9:
        return 94;
        case 10:
        return 188;
        case 11:
        return 375;
        default:
        return 750;
      }
    }
    
    /**
     * Send the temperature to controller
     * 
     * @since 2.0
     */
    
    void sendTemperatureToController(float temperature) {
    
      if (temperature != -127.00 && temperature != 85.00) {
    
        send(msg_temperature.setSensor(CHILD_ID_TEMP).set(temperature,1));
        digitalWrite(MY_DEFAULT_ERR_LED_PIN , LOW);
        //Serial.println("-------------- DEBUG sendTemperatureToController() ---------------");
        //Serial.println("No error on send temperature");
        //Serial.println("------------------------------------------------------");
        
      } else {
    
        // light the error led fixed!
        digitalWrite(MY_DEFAULT_ERR_LED_PIN , HIGH);
        //Serial.println("-------------- DEBUG sendTemperatureToController() ---------------");
        //Serial.println("! ERROR sending temperature");
        //Serial.println("------------------------------------------------------");
        
      }
      
    }
    
    /**
     * Light the LED status
     * 
     * @since 2.0
     */
    void lightLedStatus() {
    
      int k = 0;
    
      for ( k = 0; k < WAIT_LOOPS; k++) {
        
        digitalWrite(PIN_LED_STATUS,HIGH);
          wait(10); // 5 * 1000 millisends = 5 seconds;
        digitalWrite(PIN_LED_STATUS,LOW);
          wait(4990);
        
      }
      
    }
    
    
    

  • Mod

    Is displayed opposite or it is not updated?


  • Hardware Contributor

    @gohan Totally not updated. I did upload just now the @boots33 sketch in synch and it works. So it is my fault... But I cannot find!

    I re-start from fresh (err.. from boots sketch).


Log in to reply
 

Suggested Topics

  • 1
  • 2
  • 1
  • 2
  • 1
  • 3

14
Online

11.4k
Users

11.1k
Topics

112.7k
Posts