/**
   * Constructs an instance of the sample client wrapper
   *
   * @param brokerUrl the url to connect to
   * @param clientId the client id to connect with
   * @param cleanSession clear state at end of connection or not (durable or non-durable
   *     subscriptions)
   * @param quietMode whether debug should be printed to standard out
   * @param userName the username to connect with
   * @param password the password for the user
   * @throws MqttException
   */
  public SampleAsyncWait(
      String brokerUrl,
      String clientId,
      boolean cleanSession,
      boolean quietMode,
      String userName,
      String password)
      throws MqttException {
    this.brokerUrl = brokerUrl;
    this.quietMode = quietMode;
    this.clean = cleanSession;
    this.userName = userName;
    this.password = password;
    // This sample stores in a temporary directory... where messages temporarily
    // stored until the message has been delivered to the server.
    // ..a real application ought to store them somewhere
    // where they are not likely to get deleted or tampered with
    String tmpDir = System.getProperty("java.io.tmpdir");
    MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(tmpDir);

    try {
      // Construct the connection options object that contains connection parameters
      // such as cleanSession and LWT
      conOpt = new MqttConnectOptions();
      conOpt.setCleanSession(clean);
      if (password != null) {
        conOpt.setPassword(this.password.toCharArray());
      }
      if (userName != null) {
        conOpt.setUserName(this.userName);
      }

      // Construct a non-blocking MQTT client instance
      client = new MqttAsyncClient(this.brokerUrl, clientId, dataStore);

      // Set this wrapper as the callback handler
      client.setCallback(this);

    } catch (MqttException e) {
      e.printStackTrace();
      log("Unable to set up client: " + e.toString());
      System.exit(1);
    }
  }
  public static void main(String[] args) {
    clearConsolidation();

    try {
      final MqttAsyncClient mqttClient =
          new MqttAsyncClient(BROKER_URI, MqttClient.generateClientId(), new MemoryPersistence());

      mqttClient.setCallback(
          new MqttCallback() {

            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {

              try {
                // TODO retrieve sensor value and sensor name
                double sensorValue = 0;
                // sensorValue = ...
                String sensorName = null;
                // sensorName = ...

                ConsolidatedValues conso = consolidation.get(sensorName);
                if (conso == null) {
                  conso = new ConsolidatedValues();
                  consolidation.put(sensorName, conso);
                }

                conso.addSample(sensorValue);

                // end of the minute?
                if (System.currentTimeMillis() > nextMinuteTimestamp) {
                  System.out.println("PUBLISH CONSOLIDATION");

                  // TODO publish computed average value

                  clearConsolidation();
                }
              } catch (RuntimeException e) {
                e.printStackTrace();
              }
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
              // not used
            }

            @Override
            public void connectionLost(Throwable cause) {
              System.out.println("Connection lost: " + cause.getLocalizedMessage());
            }
          });
      mqttClient.connect(
          null,
          new IMqttActionListener() {
            @Override
            public void onSuccess(IMqttToken asyncActionToken) {

              // TODO subscribe to live data
            }

            @Override
            public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
              exception.printStackTrace();
            }
          });
    } catch (MqttException e) {
      e.printStackTrace();
    }
  }