示例#1
0
  /**
   * Publish data to the IBM Internet of Things Foundation.<br>
   * This method allows QoS to be passed as an argument
   *
   * @param event Name of the dataset under which to publish the data
   * @param data Object to be added to the payload as the dataset
   * @param qos Quality of Service - should be 0, 1 or 2
   * @return Whether the send was successful.
   */
  public boolean publishEvent(String event, Object data, int qos) {
    if (!isConnected()) {
      return false;
    }
    final String METHOD = "publishEvent(2)";
    JsonObject payload = new JsonObject();

    String timestamp = ISO8601_DATE_FORMAT.format(new Date());
    payload.addProperty("ts", timestamp);

    JsonElement dataElement = gson.toJsonTree(data);
    payload.add("d", dataElement);

    String topic = "iot-2/evt/" + event + "/fmt/json";

    LoggerUtility.fine(CLASS_NAME, METHOD, "Topic   = " + topic);
    LoggerUtility.fine(CLASS_NAME, METHOD, "Payload = " + payload.toString());

    MqttMessage msg = new MqttMessage(payload.toString().getBytes(Charset.forName("UTF-8")));
    msg.setQos(qos);
    msg.setRetained(false);

    try {
      mqttAsyncClient.publish(topic, msg).waitForCompletion();
    } catch (MqttPersistenceException e) {
      e.printStackTrace();
      return false;
    } catch (MqttException e) {
      e.printStackTrace();
      return false;
    }
    return true;
  }
示例#2
0
  private void setDeviceData(DeviceData deviceData) throws Exception {
    final String METHOD = "setDeviceData";
    if (deviceData == null) {
      LoggerUtility.log(
          Level.FINE,
          CLASS_NAME,
          METHOD,
          "Could not create Managed Client " + "without DeviceInformations !");
      throw new Exception("Could not create Managed Client without DeviceInformations !");
    }
    String typeId = deviceData.getTypeId();
    String deviceId = deviceData.getDeviceId();

    if (typeId == null || deviceId == null) {
      LoggerUtility.log(
          Level.FINE,
          CLASS_NAME,
          METHOD,
          "Could not create Managed Client " + "without Device Type or Device ID!");
      throw new Exception(
          "Could not create Managed Client without Device Type or Device ID!, "
              + "Please specify the same in DeviceData");
    }
    this.deviceData = deviceData;
  }
示例#3
0
  @Override
  public void messageArrived(String topic, MqttMessage message) throws Exception {
    final String METHOD = "messageArrived";
    if (topic.equals(ServerTopic.RESPONSE.getName())) {
      LoggerUtility.log(
          Level.FINE,
          CLASS_NAME,
          METHOD,
          "Received response from IoT Foundation, topic (" + topic + ")");

      String responsePayload = new String(message.getPayload(), "UTF-8");
      JsonObject jsonResponse = new JsonParser().parse(responsePayload).getAsJsonObject();
      try {
        String reqId = jsonResponse.get("reqId").getAsString();
        LoggerUtility.fine(CLASS_NAME, METHOD, "reqId (" + reqId + "): " + jsonResponse.toString());
        MqttMessage sentMsg = requests.remove(reqId);
        if (sentMsg != null) {
          queue.put(jsonResponse);
        }
      } catch (Exception e) {
        if (jsonResponse.get("reqId") == null) {
          LoggerUtility.warn(
              CLASS_NAME,
              METHOD,
              "The response " + "does not contain 'reqId' field (" + responsePayload + ")");
        } else {
          LoggerUtility.log(Level.SEVERE, CLASS_NAME, METHOD, "Unexpected exception", e);
        }
      }
    } else {
      LoggerUtility.warn(CLASS_NAME, METHOD, "Unknown topic (" + topic + ")");
    }
  }
示例#4
0
  /**
   * Constructor that creates a ManagedDevice object, but does not connect to IBM IoT Foundation
   * connect yet
   *
   * @param options List of options to connect to IBM IoT Foundation Connect
   * @param deviceData The Device Model
   * @throws Exception If the essential parameters are not set
   */
  public ManagedDevice(Properties options, DeviceData deviceData) throws Exception {
    super(options);
    final String METHOD = "constructor";
    if (deviceData == null) {
      LoggerUtility.log(
          Level.FINE,
          CLASS_NAME,
          METHOD,
          "Could not create Managed Client " + "without DeviceInformations !");
      throw new Exception("Could not create Managed Client without DeviceInformations !");
    }
    String typeId = this.getDeviceType();
    String deviceId = this.getDeviceId();

    if (typeId == null || deviceId == null) {
      LoggerUtility.log(
          Level.FINE,
          CLASS_NAME,
          METHOD,
          "Could not create Managed Client " + "without Device Type or Device ID !");
      throw new Exception(
          "Could not create Managed Client without Device Type or Device ID!, "
              + "Please specify the same in properties");
    }
    deviceData.setTypeId(typeId);
    deviceData.setDeviceId(deviceId);
    this.deviceData = deviceData;
  }
示例#5
0
 /**
  * UnSubscribe the library from the given topics
  *
  * <p>This method is used by the library to unsubscribe each of the topic where IBM IoT Foundation
  * will send the DM requests
  *
  * @param topics topics to be unsubscribed
  * @throws MqttException
  */
 public void unsubscribe(String[] topics) throws MqttException {
   final String METHOD = "unsubscribe#2";
   LoggerUtility.fine(CLASS_NAME, METHOD, "Topics(" + topics + ")");
   if (isConnected()) {
     if (mqttAsyncClient != null) {
       mqttAsyncClient.unsubscribe(topics);
     } else if (mqttClient != null) {
       mqttClient.unsubscribe(topics);
     }
   } else {
     LoggerUtility.warn(
         CLASS_NAME,
         METHOD,
         "Will not unsubscribe from topics(" + topics + ") because MQTT client is not connected.");
   }
 }
示例#6
0
  /**
   * Moves the device from managed state to unmanaged state
   *
   * <p>A device uses this request when it no longer needs to be managed. This means IoTF will no
   * longer send new device management requests to this device and device management requests from
   * this device will be rejected apart from a Manage device request
   *
   * @return True if the unmanage command is successful
   * @throws MqttException
   */
  public boolean unmanage() throws MqttException {

    final String METHOD = "unmanage";
    boolean success = false;
    DeviceTopic topic = DeviceTopic.UNMANAGE;

    JsonObject jsonPayload = new JsonObject();
    JsonObject jsonResponse = sendAndWait(topic, jsonPayload, REGISTER_TIMEOUT_VALUE);
    if (jsonResponse != null
        && jsonResponse.get("rc").getAsInt() == ResponseCode.DM_SUCCESS.getCode()) {
      success = true;
    }

    terminate();
    DMListener.stop(this);
    DMRequestHandler.clearRequestHandlers(this);
    this.deviceData.terminateHandlers();
    this.supportsDeviceActions = false;
    this.supportsFirmwareActions = false;

    if (responseSubscription != null) {
      this.unsubscribe(this.responseSubscription);
      responseSubscription = null;
    }

    LoggerUtility.log(Level.FINE, CLASS_NAME, METHOD, "Success (" + success + ")");
    if (success) {
      bManaged = false;
    }
    return success;
  }
示例#7
0
 /**
  * Subscribe the given listeners to the given topics
  *
  * <p>This method is used by the library to subscribe to each of the topic where IBM IoT
  * Foundation will send the DM requests
  *
  * @param topics List of topics to be subscribed
  * @param qos Quality of Service for the subscription
  * @param listeners The list of IMqttMessageListeners for the given topics
  * @throws MqttException
  */
 public void subscribe(String[] topics, int[] qos, IMqttMessageListener[] listeners)
     throws MqttException {
   final String METHOD = "subscribe#2";
   LoggerUtility.fine(CLASS_NAME, METHOD, "Topics(" + topics + ")");
   if (isConnected()) {
     if (mqttAsyncClient != null) {
       mqttAsyncClient.subscribe(topics, qos, listeners);
     } else if (mqttClient != null) {
       mqttClient.subscribe(topics, qos, listeners);
     }
   } else {
     LoggerUtility.warn(
         CLASS_NAME,
         METHOD,
         "Will not subscribe to topics(" + topics + ") because MQTT client is not connected.");
   }
 }
示例#8
0
 /**
  * Subscribe the given listener to the given topic
  *
  * <p>This method is used by the library to subscribe to each of the topic where IBM IoT
  * Foundation will send the DM requests
  *
  * @param topic topic to be subscribed
  * @param qos Quality of Service for the subscription
  * @param listener The IMqttMessageListener for the given topic
  * @throws MqttException
  */
 public void subscribe(ServerTopic topic, int qos, IMqttMessageListener listener)
     throws MqttException {
   final String METHOD = "subscribe";
   LoggerUtility.fine(CLASS_NAME, METHOD, "Topic(" + topic + ")");
   if (isConnected()) {
     if (mqttAsyncClient != null) {
       mqttAsyncClient.subscribe(topic.getName(), qos, listener);
     } else if (mqttClient != null) {
       mqttClient.subscribe(topic.getName(), qos, listener);
     }
   } else {
     LoggerUtility.warn(
         CLASS_NAME,
         METHOD,
         "Will not subscribe to topic(" + topic + ") because MQTT client is not connected.");
   }
 }
示例#9
0
 /**
  * This method just connects to the IBM Internet of Things Foundation, Device needs to make a call
  * to manage() to participate in Device Management activities.
  *
  * <p>This method does nothing if the device is already connected
  */
 public void connect() {
   final String METHOD = "connect";
   if (this.isConnected()) {
     LoggerUtility.log(Level.WARNING, CLASS_NAME, METHOD, "Device is already connected");
     return;
   }
   super.connect();
 }
示例#10
0
  private boolean registerDevice(long lifetime) {
    final String METHOD = "registerDevice";
    boolean success = false;
    String organization = getOrgId();
    if (organization == null || ("quickstart").equals(organization)) {
      LoggerUtility.log(
          Level.SEVERE,
          CLASS_NAME,
          METHOD,
          "Unable to create ManagedClient instance.  "
              + "QuickStart devices do not support device management");

      throw new RuntimeException(
          "Unable to create ManagedClient instance.  "
              + "QuickStart devices do not support device management");
    }
    try {
      success = this.manage(lifetime);
      if (success) {
        LoggerUtility.log(Level.INFO, CLASS_NAME, METHOD, "Device is connected as managed device");
      } else {
        LoggerUtility.log(
            Level.WARNING, CLASS_NAME, METHOD, "Device is failed to connect as managed device");
      }
    } catch (MqttException ex) {
      LoggerUtility.log(
          Level.SEVERE,
          CLASS_NAME,
          METHOD,
          "Connecting the device as managed device "
              + "operation is Failed, Exception: "
              + ex.getMessage());

      RuntimeException e =
          new RuntimeException(
              "Connecting the device as managed device "
                  + "operation is Failed, Exception: "
                  + ex.getMessage());
      e.initCause(ex);
      throw e;
    }
    return success;
  }
示例#11
0
 @Override
 public void run() {
   final String METHOD = "run";
   running = true;
   LoggerUtility.log(Level.FINE, CLASS_NAME, METHOD, "Running...");
   while (running) {
     try {
       JsonObject o = publishQueue.take();
       if (o.equals(dummy)) {
         LoggerUtility.log(Level.FINE, CLASS_NAME, METHOD, "It is time to quit.");
       } else {
         publish(o);
       }
     } catch (Exception e) {
       LoggerUtility.log(Level.SEVERE, CLASS_NAME, METHOD, e.toString());
       e.printStackTrace();
       running = false;
     }
   }
   LoggerUtility.log(Level.FINE, CLASS_NAME, METHOD, "Exiting...");
 }
示例#12
0
 /**
  * Publish the Device management response to IBm IoT Foundation
  *
  * <p>This method is used by the library to respond to each of the Device Management commands from
  * IBM IoT Foundation
  *
  * @param topic Topic where the response to be published
  * @param payload the Payload
  * @param qos The Quality Of Service
  * @throws MqttException
  */
 public void publish(DeviceTopic topic, JsonObject payload, int qos) throws MqttException {
   final String METHOD = "publish3";
   JsonObject jsonPubMsg = new JsonObject();
   jsonPubMsg.addProperty("topic", topic.getName());
   jsonPubMsg.add("qos", new JsonPrimitive(qos));
   jsonPubMsg.add("payload", payload);
   publishQueue.add(jsonPubMsg);
   LoggerUtility.log(
       Level.FINE,
       CLASS_NAME,
       METHOD,
       ": Queued Topic(" + topic + ") qos=" + qos + " payload (" + payload.toString() + ")");
 }
示例#13
0
  /**
   * This method reconnects when the connection is lost due to n/w interruption and this method is
   * called only when the connection is established originally by the library code.
   *
   * <p>This method does the following activities, 1. Checks whether the device was in a managed
   * state before disconnecting 2. Calculates the lifetime that we need to send in the manage
   * request,
   */
  @Override
  protected void reconnect() {
    String METHOD = "reconnect";

    IMqttDeliveryToken[] tokens = this.mqttAsyncClient.getPendingDeliveryTokens();
    super.connect();

    responseSubscription = null;
    if (this.isConnected() && this.bManaged == true) {
      long lifetime = 0;
      if (dormantTime != null) {
        Date currentTime = new Date();
        lifetime = (dormantTime.getTime() - currentTime.getTime()) / 1000;
        if (lifetime < 0) {
          lifetime = 0;
        }
      }
      try {

        LoggerUtility.log(Level.FINE, CLASS_NAME, METHOD, "lifetime (" + lifetime + ")");
        this.manage(lifetime);

        if (tokens != null) {
          LoggerUtility.log(Level.FINE, CLASS_NAME, METHOD, "Republishing messages start");
          for (int i = 0; i < tokens.length; i++) {
            try {
              MqttMessage msg = tokens[i].getMessage();
              this.mqttAsyncClient.publish(tokens[i].getTopics()[0], msg);
            } catch (MqttException e) {
              e.printStackTrace();
            }
          }
          LoggerUtility.log(Level.FINE, CLASS_NAME, METHOD, "Republishing messages End");
        }
      } catch (MqttException e) {
        e.printStackTrace();
      }
    }
  }
示例#14
0
 private void publish(JsonObject jsonPubMsg) throws MqttException, UnsupportedEncodingException {
   final String METHOD = "publish1";
   String topic = jsonPubMsg.get("topic").getAsString();
   int qos = jsonPubMsg.get("qos").getAsInt();
   JsonObject payload = jsonPubMsg.getAsJsonObject("payload");
   LoggerUtility.log(
       Level.FINE,
       CLASS_NAME,
       METHOD,
       ": Topic(" + topic + ") qos=" + qos + " payload (" + payload.toString() + ")");
   MqttMessage message = new MqttMessage();
   message.setPayload(payload.toString().getBytes("UTF-8"));
   message.setQos(qos);
   publish(DeviceTopic.get(topic), message);
 }
示例#15
0
 /** The Device client does not currently support subscriptions. */
 public void messageArrived(String topic, MqttMessage msg) throws Exception {
   final String METHOD = "messageArrived";
   if (commandCallback != null) {
     /* Only check whether the message is a command if a callback
      * has been defined, otherwise it is a waste of time
      * as without a callback there is nothing to process the generated
      * command.
      */
     Matcher matcher = COMMAND_PATTERN.matcher(topic);
     if (matcher.matches()) {
       String command = matcher.group(1);
       String format = matcher.group(2);
       Command cmd = new Command(command, format, msg);
       LoggerUtility.fine(CLASS_NAME, METHOD, "Event received: " + cmd.toString());
       commandCallback.processCommand(cmd);
     }
   }
 }
示例#16
0
 /**
  * A completed deliver does not guarantee that the message is received by the service because
  * devices send messages with Quality of Service (QoS) 0. <br>
  * The message count represents the number of messages that were sent by the device without an
  * error on from the perspective of the device.
  *
  * @param token MQTT delivery token
  */
 public void deliveryComplete(IMqttDeliveryToken token) {
   final String METHOD = "deliveryComplete";
   LoggerUtility.fine(CLASS_NAME, METHOD, "token " + token.getMessageId());
   messageCount++;
 }
示例#17
0
 /**
  * If we lose connection trigger the connect logic to attempt to reconnect to the IBM Internet
  * of Things Foundation.
  *
  * @param exception Throwable which caused the connection to get lost
  */
 public void connectionLost(Throwable exception) {
   final String METHOD = "connectionLost";
   LoggerUtility.info(CLASS_NAME, METHOD, exception.getMessage());
   reconnect();
 }
示例#18
0
  /**
   * Send a device manage request to IoT Foundation
   *
   * <p>A device uses this request to become a managed device. It should be the first device
   * management request sent by the device after connecting to the Internet of Things Foundation. It
   * would be usual for a device management agent to send this whenever is starts or restarts.
   *
   * <p>This method connects the device to IoT Foundation connect if its not connected already
   *
   * @param lifetime The length of time in seconds within which the device must send another Manage
   *     device request. if set to 0, the managed device will not become dormant. When set, the
   *     minimum supported setting is 3600 (1 hour).
   * @return True if successful
   * @throws MqttException
   */
  public boolean manage(long lifetime) throws MqttException {

    final String METHOD = "manage";

    LoggerUtility.log(Level.FINE, CLASS_NAME, METHOD, "lifetime value (" + lifetime + ")");

    boolean success = false;
    DeviceTopic topic = DeviceTopic.MANAGE;

    if (!this.isConnected()) {
      this.connect();
    }

    JsonObject jsonPayload = new JsonObject();
    if (deviceData.getDeviceInfo() != null || deviceData.getMetadata() != null) {

      JsonObject supports = new JsonObject();
      supports.add("deviceActions", new JsonPrimitive(this.supportsDeviceActions));
      supports.add("firmwareActions", new JsonPrimitive(this.supportsFirmwareActions));

      JsonObject data = new JsonObject();
      data.add("supports", supports);
      if (deviceData.getDeviceInfo() != null) {
        data.add("deviceInfo", deviceData.getDeviceInfo().toJsonObject());
      }
      if (deviceData.getMetadata() != null) {
        data.add("metadata", deviceData.getMetadata().getMetadata());
      }
      data.add("lifetime", new JsonPrimitive(lifetime));
      jsonPayload.add("d", data);
    } else {
      LoggerUtility.log(
          Level.SEVERE,
          CLASS_NAME,
          METHOD,
          "Cannot send manage request " + "as either deviceInfo or metadata is not set !!");

      return false;
    }

    JsonObject jsonResponse = sendAndWait(topic, jsonPayload, REGISTER_TIMEOUT_VALUE);
    if (jsonResponse != null
        && jsonResponse.get("rc").getAsInt() == ResponseCode.DM_SUCCESS.getCode()) {
      DMListener.start(this);
      DMRequestHandler.setRequestHandlers(this);
      publishQueue = new LinkedBlockingQueue<JsonObject>();
      Thread t = new Thread(this);
      t.start();
      /*
       * set the dormant time to a local variable, in case if the connection is
       * lost due to n/w interruption, we need to send another manage request
       * with the dormant time as the lifetime
       */
      if (lifetime > 0) {
        Date currentTime = new Date();
        dormantTime = new Date(currentTime.getTime() + (lifetime * 1000));
      }
      success = true;
    }
    LoggerUtility.log(Level.FINE, CLASS_NAME, METHOD, "Success (" + success + ")");

    bManaged = success;
    return success;
  }
示例#19
0
  protected IMqttDeliveryToken publish(DeviceTopic topic, MqttMessage message)
      throws MqttException {
    final String METHOD = "publish";
    IMqttDeliveryToken token = null;
    LoggerUtility.fine(CLASS_NAME, METHOD, "Topic(" + topic + ")");
    while (true) {
      if (isConnected()) {
        try {
          if (this.mqttAsyncClient != null) {
            token = mqttAsyncClient.publish(topic.getName(), message);
          } else if (mqttClient != null) {
            mqttClient.publish(topic.getName(), message);
          }
        } catch (MqttException ex) {
          String payload = null;
          try {
            payload = new String(message.getPayload(), "UTF-8");
          } catch (UnsupportedEncodingException e1) {
          }
          if (this.mqttAsyncClient.isConnected() == false) {
            LoggerUtility.log(
                Level.WARNING,
                CLASS_NAME,
                METHOD,
                " Connection Lost retrying to publish MSG :"
                    + payload
                    + " on topic "
                    + topic
                    + " every 5 seconds");

            // 	wait for 5 seconds and retry
            try {
              Thread.sleep(5 * 1000);
              continue;
            } catch (InterruptedException e) {
            }
          } else {
            throw ex;
          }
        }

        if (isConnected() == false) {
          LoggerUtility.log(
              Level.WARNING,
              CLASS_NAME,
              METHOD,
              "MQTT got disconnected " + "after publish to Topic(" + topic + ")");
        }
        return token;
      } else {
        LoggerUtility.warn(
            CLASS_NAME,
            METHOD,
            ": Will not publish to topic(" + topic + ") because MQTT client is not connected.");
        try {
          Thread.sleep(5 * 1000);
          continue;
        } catch (InterruptedException e) {
        }
      }
    }
  }
示例#20
0
  /**
   * Send the message and waits for the response from IBM IoT Foundation
   *
   * <p>
   *
   * <p>This method is used by the library to send following messages to IBM IoT Foundation
   *
   * <ul class="simple">
   *   <li>Manage
   *   <li>Unmanage
   *   <li>Location update
   *   <li>Diagnostic update/clear
   * </ul>
   *
   * @param topic Topic where the message to be sent
   * @param jsonPayload The message
   * @param timeout How long to wait for the resonse
   * @return response in Json format
   * @throws MqttException
   */
  public JsonObject sendAndWait(DeviceTopic topic, JsonObject jsonPayload, long timeout)
      throws MqttException {

    final String METHOD = "sendAndWait";

    String uuid = UUID.randomUUID().toString();
    jsonPayload.add("reqId", new JsonPrimitive(uuid));

    LoggerUtility.fine(
        CLASS_NAME,
        METHOD,
        "Topic (" + topic + ") payload (" + jsonPayload.toString() + ") reqId (" + uuid + ")");

    if (responseSubscription == null) {
      responseSubscription = ServerTopic.RESPONSE;
      subscribe(responseSubscription, 1, this);
    }

    MqttMessage message = new MqttMessage();
    try {
      message.setPayload(jsonPayload.toString().getBytes("UTF-8"));
    } catch (UnsupportedEncodingException e) {
      LoggerUtility.log(
          Level.SEVERE, CLASS_NAME, METHOD, "Error setting payload for topic: " + topic, e);
      return null;
    }

    message.setQos(1);

    requests.put(uuid, message);

    publish(topic, message);

    JsonObject jsonResponse = null;
    while (jsonResponse == null) {
      try {
        jsonResponse = queue.poll(timeout, TimeUnit.MILLISECONDS);
        if (jsonResponse == null) {
          break;
        }
        if (jsonResponse.get("reqId").getAsString().equals(uuid)) {
          LoggerUtility.fine(
              CLASS_NAME, METHOD, "" + "This response is for me reqId:" + jsonResponse.toString());
          break;
        } else {
          // This response is not for our request, put it back to the queue.
          LoggerUtility.warn(
              CLASS_NAME, METHOD, "This response is NOT for me reqId:" + jsonResponse.toString());
          queue.add(jsonResponse);
          jsonResponse = null;
        }
      } catch (InterruptedException e) {
        break;
      }
    }
    if (jsonResponse == null) {
      LoggerUtility.warn(
          CLASS_NAME, METHOD, "NO RESPONSE from IoTF for request: " + jsonPayload.toString());
      LoggerUtility.warn(CLASS_NAME, METHOD, "Connected(" + isConnected() + ")");
    }
    return jsonResponse;
  }