package it.uhopper.mqtt.service;
import android.content.Context;
import android.util.Log;
import android.util.Pair;
import org.appcelerator.kroll.KrollFunction;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import it.uhopper.mqtt.MqttModule;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class MqttTask implements Runnable {
static final String TAG = MqttTask.class.getSimpleName();
String ID;
HashMap<String, Integer> topics = new HashMap<String, Integer>();
String host;
Context ctx;
MqttCallbackImplementation callback;
boolean initialized = false;
private MqttClient mqttClient;
MqttConstants.MQTTConnectionStatus connectionStatus;
public MqttTask(Context ctx, String[] TOPICS, int[] qos, MqttCallbackImplementation callback) {
this.callback = callback;
if(TOPICS.length != qos.length) {
Log.w(TAG, "Number of topics and qos does not match ! Using default value");
for (String s : TOPICS) {
this.topics.put(s, 0);
}
}else{
for(int i =0; i< TOPICS.length; i++){
this.topics.put(TOPICS[i], qos[i]);
}
}
this.ctx = ctx;
}
public void run() {
Log.i(TAG, "Starting MQTT THREAD with ID: " + ID);
initialized = false;
try {
ID = MqttConstants.getUniqueID(ctx);
host = MqttConstants.HOST;
// TODO in case of error, maybe retry after N seconds ?
defineConnectionToBroker(host);
Log.i(TAG, "Connecting to broker " + MqttConstants.HOST);
connectToBroker();
Log.i(TAG, "Connected!");
subscribeToTopics();
Log.i(TAG, "Subscribed!");
KrollFunction kf = MqttModule.eventsMap.get("onSuccess");
Object[] arr = {"success : true"};
kf.callAsync(MqttModule.getInstance().getKrollObject(), arr);
} catch (MqttException e) {
Log.e(TAG, "FATAL exception");
KrollFunction kf = MqttModule.eventsMap.get("onError");
Object[] arr = {"success : false"};
kf.callAsync(MqttModule.getInstance().getKrollObject(), arr);
e.printStackTrace();
}
initialized = true;
Log.i(TAG, "++++++++++++++++++++++++End of Command+++++++++++++++++++++");
}
private void defineConnectionToBroker(String host) throws MqttException {
mqttClient = new MqttClient(host, ID, new MemoryPersistence());
mqttClient.setCallback(callback);
connectionStatus = MqttConstants.MQTTConnectionStatus.INITIAL;
}
private void connectToBroker() throws MqttException {
MqttConnectOptions connectOptions = new MqttConnectOptions();
// connectOptions.setKeepAliveInterval(keepAliveSeconds);
connectOptions.setUserName("compose");
connectOptions.setPassword("shines".toCharArray());
mqttClient.connect(connectOptions);
}
private void subscribeToTopics() throws MqttException {
boolean subscribed = false;
if (isAlreadyConnected() == true) {
try {
String topics_arr[] = new String[topics.size()];
int qos_arr[] = new int[topics.size()];
Set<Map.Entry<String, Integer>> pairs = topics.entrySet();
int i = 0;
for(Map.Entry<String, Integer> p : pairs){
topics_arr[i] = p.getKey();
qos_arr[i] = p.getValue();
i++;
}
mqttClient.subscribe(topics_arr, qos_arr);
subscribed = true;
} catch (MqttException e) {
e.printStackTrace();
subscribed = false;
}
if (subscribed == false) {
throw new MqttException(MqttException.REASON_CODE_CLIENT_EXCEPTION);
}
}
}
public boolean publish(String topic, String payload, int qos, boolean retain) {
try {
MqttMessage msg = new MqttMessage();
msg.setPayload(payload.getBytes());
msg.setQos(qos);
msg.setRetained(retain);
mqttClient.publish(topic, msg);
return true;
} catch (Exception e) {
return false;
}
}
public void addSubscription(String str, Integer qos) throws MqttException {
if(qos != topics.put(str,qos) ){// True if str is a new topic or qos is changed
mqttClient.subscribe(str, qos);
}
}
public void removeSubscription(String str) throws MqttException {
if(topics.remove(str)!= null){// True if str was a topic
mqttClient.unsubscribe(str);
}
}
//TODO maybe handle multiple topic un/subscription
public boolean isAlreadyConnected() {
return ((mqttClient != null) && (mqttClient.isConnected() == true));
}
public boolean isInitialized(){
return initialized;
}
public String subscriptions(){
return Arrays.toString(topics.keySet().toArray(new String[topics.size()]));
}
}