/* * HostDetailActivity.java * Open Mobile Hub * * Created by Gareth Johnson * Copyright (c) 2014 Beckersweet. All rights reserved. */ package com.beckersweet.opmub; import java.io.File; import org.eclipse.paho.client.mqttv3.MqttCallback; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttDefaultFilePersistence; import org.eclipse.paho.client.mqttv3.MqttDeliveryToken; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.MqttPersistenceException; import org.eclipse.paho.client.mqttv3.MqttTopic; import org.json.JSONArray; import org.json.JSONObject; import android.os.Handler; import android.os.HandlerThread; public class MqttHelper implements MqttCallback { protected static final boolean DEBUG = true; protected static final String DEBUG_TAG = "BeckersweetMqttClient:Helper"; public static final String BROKER_NAME = "broker"; protected static final String THREAD_NAME = DEBUG_TAG; // for handler thread protected static final boolean CLEAN_SESSION = true; public boolean isWaiting; // whether client is waiting for a response private int connectionHandlerReturnCode; // hack for handler return value private File cacheDirectory; // for persistenceFile (below) private Handler connectionHandler; private HandlerThread handlerThread; // background thread that runs client private MqttCallback callback; // for receiving messages from broker private MqttClient client; private MqttConnectOptions connectionOptions; private MqttDefaultFilePersistence persistenceFile; // record of messages private MqttMessage message; // for outgoing messages private MqttTopic brokerTopic; private JSONArray hosts; private String messageString; // String version of outgoing message private String clientTopicName; private UserMessageHelper messenger; public MqttHelper(UserMessageHelper newMessenger, File newCacheDirectory) { messenger = newMessenger; cacheDirectory = newCacheDirectory; isWaiting = false; callback = this; } public int connect(String url, String deviceId) { try { messenger.printDebugMessage("Creating persistence file..."); String directoryPath = cacheDirectory.getAbsolutePath(); persistenceFile = new MqttDefaultFilePersistence(directoryPath); } catch(MqttPersistenceException e) { messenger.showAlert("Problem with persistence file: " + e.getMessage()); e.printStackTrace(); return 1; } messenger.printDebugMessage("Creating handler thread..."); handlerThread = new HandlerThread(THREAD_NAME); handlerThread.start(); messenger.printDebugMessage("Creating connection handler..."); connectionHandler = new Handler(handlerThread.getLooper()); messenger.printDebugMessage("Setting connection options..."); connectionOptions = new MqttConnectOptions(); connectionOptions.setCleanSession(CLEAN_SESSION); try { messenger.printDebugMessage("Creating client..."); client = new MqttClient(url, deviceId, persistenceFile); } catch (MqttException e) { messenger.showAlert("Problem with creating client: " + e.getMessage()); e.printStackTrace(); return 1; } connectionHandlerReturnCode = -1; connectionHandler.post(new Runnable() { @Override public void run() { try { messenger.printDebugMessage("Connecting..."); client.connect(connectionOptions); messenger.printDebugMessage("Connected."); connectionHandlerReturnCode = 0; } catch (MqttException e) { messenger.showAlert("Connection problem: " + e.getMessage()); e.printStackTrace(); connectionHandlerReturnCode = 1; } } }); while (connectionHandlerReturnCode == -1) { // Wait for connection handler thread to finish. } return connectionHandlerReturnCode; } public void disconnect() { connectionHandler.post(new Runnable() { @Override public void run() { try { messenger.printDebugMessage("Disconnecting..."); client.disconnect(); } catch (MqttException e) { messenger.showAlert("Disconnection problem: " + e.getMessage()); e.printStackTrace(); return; } } }); } public boolean isConnected() { if (client != null) return client.isConnected(); return false; } public int sendMessage(String newMessageString) { messageString = newMessageString; connectionHandlerReturnCode = -1; connectionHandler.post(new Runnable() { @Override public void run() { try { client.setCallback(callback); message = new MqttMessage(); message.setPayload(messageString.getBytes()); messenger.printDebugMessage("Publishing message..."); brokerTopic = client.getTopic(BROKER_NAME); brokerTopic.publish(message); } catch (MqttException e) { messenger.showAlert("Publication problem: " + e.getMessage()); e.printStackTrace(); connectionHandlerReturnCode = 1; } } }); while (connectionHandlerReturnCode == -1) { // Wait for connection handler thread to finish. } return connectionHandlerReturnCode; } public void subscribe(String topicFilter) { clientTopicName = topicFilter; isWaiting = true; connectionHandler.post(new Runnable() { @Override public void run() { if (isConnected()) { try { client.setCallback(callback); messenger.printDebugMessage("Subscribing to '" + clientTopicName + "'..."); client.subscribe(clientTopicName); messenger.printDebugMessage("Subscribed. Waiting for " + "response..."); } catch (MqttException e) { messenger.showAlert("Problem with subscription: " + e.getMessage()); e.printStackTrace(); isWaiting = false; } } } }); } @Override public void connectionLost(Throwable cause) { messenger.printDebugMessage("Connection lost: " + cause.getMessage()); } @Override public void deliveryComplete(MqttDeliveryToken token) { messenger.printDebugMessage("Message delivered successfully."); connectionHandlerReturnCode = 0; } @Override public void messageArrived(MqttTopic topic, MqttMessage message) throws MqttException { String incomingMessage = message.toString(); messenger.printDebugMessage("Message received: " + incomingMessage); JSONObject jsonMessage; try { jsonMessage = new JSONObject(incomingMessage); } catch (Exception e) { messenger.printDebugMessage("Incoming message not JSON."); isWaiting = false; return; } try { hosts = new JSONArray(jsonMessage.getString("realHosts")); } catch (Exception e) { messenger.printDebugMessage("Incoming message has no field " + "'realHosts'."); } isWaiting = false; } public JSONArray getHosts() { return hosts; } }