package org.wso2.carbon.device.mgt.iot.agent.kura.firealarm.core.utils.xmpp; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jivesoftware.smack.packet.Message; import org.wso2.carbon.device.mgt.iot.agent.kura.firealarm.core.communication .CommunicationHandlerException; import org.wso2.carbon.device.mgt.iot.agent.kura.firealarm.core.communication.xmpp .XMPPCommunicationHandler; import org.wso2.carbon.device.mgt.iot.agent.kura.firealarm.core.internal.AgentConstants; import org.wso2.carbon.device.mgt.iot.agent.kura.firealarm.core.internal.AgentCoreOperations; import org.wso2.carbon.device.mgt.iot.agent.kura.firealarm.core.internal.AgentManager; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; public class XMPPCommunicationHandlerImpl extends XMPPCommunicationHandler { private static final Log log = LogFactory.getLog(XMPPCommunicationHandlerImpl.class); private static final AgentManager agentManager = AgentManager.getInstance(); private ScheduledExecutorService service = Executors.newScheduledThreadPool(2); private ScheduledFuture<?> dataPushServiceHandler; private ScheduledFuture<?> connectorServiceHandler; private String username; private String password; private String resource; private String xmppAdminJID; private String xmppDeviceJID; public XMPPCommunicationHandlerImpl(String server) { super(server); } public XMPPCommunicationHandlerImpl(String server, int port) { super(server, port); } public XMPPCommunicationHandlerImpl(String server, int port, int timeout) { super(server, port, timeout); } public ScheduledFuture<?> getDataPushServiceHandler() { return dataPushServiceHandler; } @Override public void connect() { username = agentManager.getAgentConfigs().getDeviceId(); password = agentManager.getAgentConfigs().getAuthToken(); resource = agentManager.getAgentConfigs().getDeviceOwner(); xmppDeviceJID = username + "@" + server; xmppAdminJID = AgentConstants.XMPP_ADMIN_ACCOUNT_UNAME + "@" + server; Runnable connect = new Runnable() { public void run() { if (!isConnected()) { try { connectToServer(); loginToServer(username, password, resource); setMessageFilterAndListener(xmppAdminJID, xmppDeviceJID, true); publishDeviceData(agentManager.getAgentConfigs().getDataPushInterval()); } catch (CommunicationHandlerException e) { if (log.isDebugEnabled()) { log.warn(AgentConstants.LOG_APPENDER + "Connection/Login to XMPP server at: " + server + " failed"); } } } } }; connectorServiceHandler = service.scheduleAtFixedRate(connect, 0, timeoutInterval, TimeUnit.MILLISECONDS); } /** * This is an abstract method used for post processing the received XMPP-message. This * method will be implemented as per requirement at the time of creating an object of this * class. * * @param xmppMessage the xmpp message received by the listener. */ @Override public void processIncomingMessage(Message xmppMessage) { String from = xmppMessage.getFrom(); String message = xmppMessage.getBody(); log.info(AgentConstants.LOG_APPENDER + "Received XMPP message [" + message + "] from " + from); String replyMessage; String[] controlSignal = message.toString().split(":"); //message- "<SIGNAL_TYPE>:<SIGNAL_MODE>" format. (ex: "BULB:ON", "TEMPERATURE", "HUMIDITY") switch (controlSignal[0].toUpperCase()) { case AgentConstants.BULB_CONTROL: if (controlSignal.length != 2) { replyMessage = "BULB controls need to be in the form - 'BULB:{ON|OFF}'"; log.warn(replyMessage); sendXMPPMessage(xmppAdminJID, replyMessage, "CONTROL-REPLY"); break; } AgentCoreOperations.changeBulbStatus( controlSignal[1].equals(AgentConstants.CONTROL_ON) ? true : false); log.info(AgentConstants.LOG_APPENDER + "Bulb was switched to state: '" + controlSignal[1] + "'"); break; case AgentConstants.TEMPERATURE_CONTROL: double currentTemperature = agentManager.getTemperature(); String replyTemperature = "The current temperature was read to be: '" + currentTemperature + "C'"; log.info(AgentConstants.LOG_APPENDER + replyTemperature); replyMessage = AgentConstants.TEMPERATURE_CONTROL + ":" + currentTemperature; sendXMPPMessage(xmppAdminJID, replyMessage, "CONTROL-REPLY"); break; case AgentConstants.HUMIDITY_CONTROL: double currentHumidity = agentManager.getHumidity(); String replyHumidity = "The current humidity was read to be: '" + currentHumidity + "%'"; log.info(AgentConstants.LOG_APPENDER + replyHumidity); replyMessage = AgentConstants.HUMIDITY_CONTROL + ":" + currentHumidity; sendXMPPMessage(xmppAdminJID, replyMessage, "CONTROL-REPLY"); break; default: replyMessage = "'" + controlSignal[0] + "' is invalid and not-supported for this device-type"; log.warn(replyMessage); sendXMPPMessage(xmppAdminJID, replyMessage, "CONTROL-ERROR"); break; } } @Override public void publishDeviceData(int publishInterval) { Runnable pushDataRunnable = new Runnable() { @Override public void run() { double currentTemperature = agentManager.getTemperature(); String payLoad = AgentConstants.TEMPERATURE_CONTROL + ":" + currentTemperature; Message xmppMessage = new Message(); xmppMessage.setTo(xmppAdminJID); xmppMessage.setSubject("PUBLISHER"); xmppMessage.setBody(payLoad); xmppMessage.setType(Message.Type.chat); sendXMPPMessage(xmppAdminJID, xmppMessage); log.info(AgentConstants.LOG_APPENDER + "Message: '" + xmppMessage.getBody() + "' sent to XMPP JID [" + xmppAdminJID + "] under subject [" + xmppMessage.getSubject() + "]"); } }; dataPushServiceHandler = service.scheduleAtFixedRate(pushDataRunnable, publishInterval, publishInterval, TimeUnit.SECONDS); } @Override public void disconnect() { Runnable stopConnection = new Runnable() { public void run() { while (isConnected()) { dataPushServiceHandler.cancel(true); connectorServiceHandler.cancel(true); closeConnection(); if (log.isDebugEnabled()) { log.warn(AgentConstants.LOG_APPENDER + "Unable to 'STOP' connection to XMPP server at: " + server); } try { Thread.sleep(timeoutInterval); } catch (InterruptedException e1) { log.error(AgentConstants.LOG_APPENDER + "XMPP-Terminator: Thread Sleep Interrupt Exception"); } } } }; Thread terminatorThread = new Thread(stopConnection); terminatorThread.setDaemon(true); terminatorThread.start(); } @Override public void processIncomingMessage() { } }