package org.wso2.devicemgt.raspberry.agent;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* Created by ace on 7/24/15.
*/
public class MQTTRecieverUtil implements MqttCallback {
private static final Log log = LogFactory.getLog(MQTTRecieverUtil.class);
private MqttClient client;
private String clientId;
private MqttConnectOptions options;
private String subscribeTopic;
private String clientWillTopic;
// topic needs to be set from outside
private String controlQueueEndpoint;
protected MQTTRecieverUtil(String owner, String deviceType, String controlQueueEndpoint,
String subscribeTopic) {
this.clientId = owner + ":" + deviceType;
this.subscribeTopic = subscribeTopic;
this.clientWillTopic = deviceType + File.separator + "disconnection";
this.controlQueueEndpoint = controlQueueEndpoint;
this.initSubscriber(controlQueueEndpoint);
}
private void initSubscriber(String controlQueueEndpoint) {
try {
client = new MqttClient(controlQueueEndpoint, clientId, null);
log.info("MQTT subscriber was created with ClientID : " + clientId);
} catch (MqttException ex) {
String errorMsg = "MQTT Client Error\n" + "\tReason: " + ex.getReasonCode() +
"\n\tMessage: " + ex.getMessage() + "\n\tLocalMsg: " +
ex.getLocalizedMessage() + "\n\tCause: " + ex.getCause() +
"\n\tException: " + ex;
log.error(errorMsg);
}
options = new MqttConnectOptions();
options.setCleanSession(false);
options.setWill(clientWillTopic, "connection crashed".getBytes(StandardCharsets.UTF_8), 2, true);
client.setCallback(this);
}
/**
* @return the whether subscriber is connected to queue
*/
private boolean isConnected() {
return client.isConnected();
}
public void subscribe() throws Exception {
try {
client.connect(options);
log.info("Subscriber connected to queue at: " + controlQueueEndpoint);
} catch (MqttSecurityException ex) {
String errorMsg = "MQTT Security Exception when connecting to queue\n" + "\tReason: " +
ex.getReasonCode() + "\n\tMessage: " + ex.getMessage() +
"\n\tLocalMsg: " + ex.getLocalizedMessage() + "\n\tCause: " +
ex.getCause() + "\n\tException: " + ex; //throw
if (log.isDebugEnabled()) {
log.debug(errorMsg);
}
throw new Exception(errorMsg, ex);
} catch (MqttException ex) {
String errorMsg = "MQTT Exception when connecting to queue\n" + "\tReason: " +
ex.getReasonCode() + "\n\tMessage: " + ex.getMessage() +
"\n\tLocalMsg: " + ex.getLocalizedMessage() + "\n\tCause: " +
ex.getCause() + "\n\tException: " + ex; //throw
if (log.isDebugEnabled()) {
log.debug(errorMsg);
}
throw new Exception(errorMsg, ex);
}
try {
client.subscribe(subscribeTopic, 0);
log.info("Subscribed with client id: " + clientId);
log.info("Subscribed to topic: " + subscribeTopic);
} catch (MqttException ex) {
String errorMsg = "MQTT Exception when trying to subscribe to topic: " +
subscribeTopic + "\n\tReason: " + ex.getReasonCode() +
"\n\tMessage: " + ex.getMessage() + "\n\tLocalMsg: " +
ex.getLocalizedMessage() + "\n\tCause: " + ex.getCause() +
"\n\tException: " + ex;
if (log.isDebugEnabled()) {
log.debug(errorMsg);
}
}
}
@Override public void connectionLost(Throwable arg0) {
log.warn("Lost Connection for client: " + this.clientId + " to " + controlQueueEndpoint);
Thread subscriberDaemon = new Thread() {
public void run() {
while (true) {
if (!isConnected()) {
if (log.isDebugEnabled()) {
log.debug("Subscriber reconnecting to queue........");
}
try {
subscribe();
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Could not reconnect and subscribe to ControlQueue.");
}
}
} else {
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
log.error("An Interrupted Exception in Subscriber thread.");
}
}
}
};
subscriberDaemon.setDaemon(true);
subscriberDaemon.start();
}
@Override public void deliveryComplete(IMqttDeliveryToken arg0) {
log.info("Message for client " + this.clientId + "delivered successfully.");
}
@Override public void messageArrived(final String topic, final MqttMessage message) {
Thread subscriberThread = new Thread() {
public void run() {
postMessageArrived(topic, message);
}
};
subscriberThread.start();
}
/*
This method is used for post processing of a message.
*/
protected void postMessageArrived(String topic, MqttMessage message){
AgentConstants agentConstants = new AgentConstants();
System.out.println("Topic : "+topic+ " Message : "+message);
String fileLocation = agentConstants.prop.getProperty("execution.plan.file.location");
writeToFile(new String(message.getPayload()),fileLocation);
}
private boolean writeToFile(String policy,String fileLocation){
File file = new File(fileLocation);
try (FileOutputStream fop = new FileOutputStream(file)) {
// if file doesn't exists, then create it
if (!file.exists()) {
file.createNewFile();
}
// get the content in bytes
byte[] contentInBytes = policy.getBytes();
fop.write(contentInBytes);
fop.flush();
fop.close();
System.out.println("Done");
AgentInitializer.setUpdated(true);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}