forked from community/product-iots
parent
7180059df0
commit
568199b507
@ -0,0 +1,152 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>device-mgt-iot-connectedcup</artifactId>
|
||||
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||
<version>1.9.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>org.coffeking.agent</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>1.9.2-SNAPSHOT</version>
|
||||
<name>connected-cup-agent Maven Webapp</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20151123</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.paho</groupId>
|
||||
<artifactId>mqtt-client</artifactId>
|
||||
<version>0.4.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>connected-cup-agent</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>wso2.releases</id>
|
||||
<name>WSO2 internal Repository</name>
|
||||
<url>http://maven.wso2.org/nexus/content/repositories/releases/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>daily</updatePolicy>
|
||||
<checksumPolicy>ignore</checksumPolicy>
|
||||
</releases>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>wso2.snapshots</id>
|
||||
<name>Apache Snapshot Repository</name>
|
||||
<url>http://maven.wso2.org/nexus/content/repositories/snapshots/</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>daily</updatePolicy>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>wso2-nexus</id>
|
||||
<name>WSO2 internal Repository</name>
|
||||
<url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>daily</updatePolicy>
|
||||
<checksumPolicy>ignore</checksumPolicy>
|
||||
</releases>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
|
||||
<repositories>
|
||||
<!-- Before adding ANYTHING in here, please start a discussion on the dev list.
|
||||
Ideally the Axis2 build should only use Maven central (which is available
|
||||
by default) and nothing else. We had troubles with other repositories in
|
||||
the past. Therefore configuring additional repositories here should be
|
||||
considered very carefully. -->
|
||||
<repository>
|
||||
<id>wso2-nexus</id>
|
||||
<name>WSO2 internal Repository</name>
|
||||
<url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>daily</updatePolicy>
|
||||
<checksumPolicy>ignore</checksumPolicy>
|
||||
</releases>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>wso2.releases</id>
|
||||
<name>WSO2 internal Repository</name>
|
||||
<url>http://maven.wso2.org/nexus/content/repositories/releases/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>daily</updatePolicy>
|
||||
<checksumPolicy>ignore</checksumPolicy>
|
||||
</releases>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>wso2.snapshots</id>
|
||||
<name>WSO2 Snapshot Repository</name>
|
||||
<url>http://maven.wso2.org/nexus/content/repositories/snapshots/</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>daily</updatePolicy>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>gcm-server-repository</id>
|
||||
<name>GCM Server repository - GitHub</name>
|
||||
<url>https://github.com/slorber/gcm-server-repository/raw/master/releases/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>wso2-staging</id>
|
||||
<name>WSO2 internal Repository</name>
|
||||
<url>http://maven.wso2.org/nexus/content/repositories/orgwso2carbonapimgt-174/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>daily</updatePolicy>
|
||||
<checksumPolicy>ignore</checksumPolicy>
|
||||
</releases>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
</project>
|
@ -0,0 +1,35 @@
|
||||
package org.coffeeking.agent.datasense;
|
||||
|
||||
import org.coffeeking.agent.transport.TransportHandlerException;
|
||||
import org.coffeeking.agent.transport.mqtt.ConnectedCupMQttTransportHandler;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.StreamCorruptedException;
|
||||
|
||||
public class PushLevel extends HttpServlet {
|
||||
|
||||
private ConnectedCupMQttTransportHandler connectedCupMQttTransportHandler;
|
||||
|
||||
public PushLevel(){
|
||||
connectedCupMQttTransportHandler = ConnectedCupMQttTransportHandler.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String deviceId = req.getParameter("deviceId");
|
||||
String deviceOwner = req.getParameter("deviceOwner");
|
||||
String payload = req.getParameter("payload");
|
||||
|
||||
try {
|
||||
connectedCupMQttTransportHandler.publishToConnectedCup(deviceOwner,deviceId,payload,0,true);
|
||||
} catch (TransportHandlerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package org.coffeeking.agent.datasense;
|
||||
|
||||
import org.coffeeking.agent.transport.TransportHandlerException;
|
||||
import org.coffeeking.agent.transport.mqtt.ConnectedCupMQttTransportHandler;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PushTemperature extends HttpServlet {
|
||||
|
||||
private ConnectedCupMQttTransportHandler connectedCupMQttTransportHandler;
|
||||
|
||||
public PushTemperature(){
|
||||
connectedCupMQttTransportHandler = ConnectedCupMQttTransportHandler.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
String deviceId = req.getParameter("deviceId");
|
||||
String deviceOwner = req.getParameter("deviceOwner");
|
||||
String payload = req.getParameter("payload");
|
||||
|
||||
try {
|
||||
connectedCupMQttTransportHandler.publishToConnectedCup(deviceOwner,deviceId,payload,0,true);
|
||||
} catch (TransportHandlerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.coffeeking.agent.transport;
|
||||
|
||||
/**
|
||||
* This interface consists of the core functionality related to the transport between any device and the server. The
|
||||
* interface is an abstraction, regardless of the underlying protocol used for the transport. Implementation of this
|
||||
* interface by any class that caters a specific protocol (ex: HTTP, XMPP, MQTT, CoAP) would ideally have methods
|
||||
* specific to the protocol used for communication and thees methods that implement the logic related to the devices
|
||||
* using the protocol.
|
||||
*
|
||||
* @param <T> a message type specific to the protocol implemented
|
||||
*/
|
||||
public interface TransportHandler<T> {
|
||||
int DEFAULT_TIMEOUT_INTERVAL = 5000; // millis ~ 10 sec
|
||||
|
||||
void connect();
|
||||
|
||||
boolean isConnected();
|
||||
|
||||
void processIncomingMessage() throws TransportHandlerException;
|
||||
|
||||
void processIncomingMessage(T message) throws TransportHandlerException;
|
||||
|
||||
void processIncomingMessage(T message, String... messageParams) throws TransportHandlerException;
|
||||
|
||||
void publishDeviceData() throws TransportHandlerException;
|
||||
|
||||
void publishDeviceData(T publishData) throws TransportHandlerException;
|
||||
|
||||
void publishDeviceData(String... publishData) throws TransportHandlerException;
|
||||
|
||||
void disconnect();
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.coffeeking.agent.transport;
|
||||
|
||||
public class TransportHandlerException extends Exception {
|
||||
private static final long serialVersionUID = 2736466230451105440L;
|
||||
|
||||
private String errorMessage;
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public TransportHandlerException(String msg, Exception nestedEx) {
|
||||
super(msg, nestedEx);
|
||||
setErrorMessage(msg);
|
||||
}
|
||||
|
||||
public TransportHandlerException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
|
||||
public TransportHandlerException(String msg) {
|
||||
super(msg);
|
||||
setErrorMessage(msg);
|
||||
}
|
||||
|
||||
public TransportHandlerException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TransportHandlerException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
package org.coffeeking.agent.transport.mqtt;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.coffeeking.agent.transport.TransportHandlerException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
public class ConnectedCupMQttTransportHandler extends MQTTTransportHandler {
|
||||
|
||||
private static Log log = LogFactory.getLog(ConnectedCupMQttTransportHandler.class);
|
||||
|
||||
private static String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5);
|
||||
|
||||
private static final String DEVICE_TYPE = "connectedcup";
|
||||
|
||||
private static ConnectedCupMQttTransportHandler connectedCupMQttTransportHandler;
|
||||
|
||||
private static String publishTopic = "wso2" + File.separator + "%s" + File.separator +
|
||||
DEVICE_TYPE + File.separator + "%s" + File.separator
|
||||
+ "connected_publisher";
|
||||
|
||||
protected ConnectedCupMQttTransportHandler() {
|
||||
super(iotServerSubscriber, DEVICE_TYPE, "tcp://localhost:1883", "");
|
||||
}
|
||||
|
||||
private ScheduledFuture<?> dataPushServiceHandler;
|
||||
|
||||
public ScheduledFuture<?> getDataPushServiceHandler() {
|
||||
return dataPushServiceHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
Runnable connect = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
log.info("Trying to connect..");
|
||||
while (!isConnected()) {
|
||||
try {
|
||||
connectToQueue();
|
||||
} catch (TransportHandlerException e) {
|
||||
log.warn("Connection to MQTT Broker at: " +
|
||||
mqttBrokerEndPoint + " failed");
|
||||
|
||||
try {
|
||||
Thread.sleep(timeoutInterval);
|
||||
} catch (InterruptedException ex) {
|
||||
log.error("MQTT-Subscriber: Thread Sleep Interrupt Exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.info("Connected..");
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Thread connectorThread = new Thread(connect);
|
||||
connectorThread.setDaemon(true);
|
||||
connectorThread.start();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processIncomingMessage(MqttMessage message, String... messageParams) {
|
||||
}
|
||||
|
||||
public void publishToConnectedCup(String owner , String deviceId, String payLoad, int qos, boolean retained)
|
||||
throws TransportHandlerException{
|
||||
String topic = String.format(publishTopic,owner,deviceId);
|
||||
publishToQueue(topic, payLoad, qos, retained);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
Runnable stopConnection = new Runnable() {
|
||||
public void run() {
|
||||
while (isConnected()) {
|
||||
try {
|
||||
dataPushServiceHandler.cancel(true);
|
||||
closeConnection();
|
||||
|
||||
} catch (MqttException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.warn("Unable to 'STOP' MQTT connection at broker at: " +
|
||||
mqttBrokerEndPoint);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(timeoutInterval);
|
||||
} catch (InterruptedException e1) {
|
||||
log.error("MQTT-Terminator: Thread Sleep Interrupt Exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread terminatorThread = new Thread(stopConnection);
|
||||
terminatorThread.setDaemon(true);
|
||||
terminatorThread.start();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void publishDeviceData() throws TransportHandlerException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishDeviceData(MqttMessage publishData) throws TransportHandlerException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishDeviceData(String... publishData) throws TransportHandlerException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processIncomingMessage() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processIncomingMessage(MqttMessage message) throws TransportHandlerException {
|
||||
|
||||
}
|
||||
|
||||
public static ConnectedCupMQttTransportHandler getInstance(){
|
||||
if(connectedCupMQttTransportHandler == null){
|
||||
connectedCupMQttTransportHandler = new ConnectedCupMQttTransportHandler();
|
||||
connectedCupMQttTransportHandler.connect();
|
||||
}
|
||||
return connectedCupMQttTransportHandler;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,367 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.coffeeking.agent.transport.mqtt;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.coffeeking.agent.transport.TransportHandler;
|
||||
import org.coffeeking.agent.transport.TransportHandlerException;
|
||||
import org.eclipse.paho.client.mqttv3.*;
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* This is an abstract class that implements the "TransportHandler" interface. The interface is an abstraction for
|
||||
* the core functionality with regards to device-server communication regardless of the Transport protocol. This
|
||||
* specific class contains the HTTP-Transport specific implementations. The class implements utility methods for the
|
||||
* case of a HTTP communication. However, this "abstract class", even-though it implements the "TransportHandler"
|
||||
* interface, does not contain the logic relevant to the interface methods. The specific functionality of the
|
||||
* interface methods are intended to be implemented by the concrete class that extends this abstract class and
|
||||
* utilizes the HTTP specific functionality (ideally a device API writer who would like to communicate to the device
|
||||
* via HTTP Protocol).
|
||||
* <p/>
|
||||
* This class contains the Device-Management specific implementation for all the MQTT functionality. This includes
|
||||
* connecting to a MQTT Broker & subscribing to the appropriate MQTT-topic, action plan upon losing connection or
|
||||
* successfully delivering a message to the broker and processing incoming messages. Makes use of the 'Paho-MQTT'
|
||||
* library provided by Eclipse Org.
|
||||
*/
|
||||
public abstract class MQTTTransportHandler
|
||||
implements MqttCallback, TransportHandler<MqttMessage> {
|
||||
private static final Log log = LogFactory.getLog(MQTTTransportHandler.class);
|
||||
|
||||
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
|
||||
|
||||
private MqttClient client;
|
||||
private String clientId;
|
||||
private MqttConnectOptions options;
|
||||
private String clientWillTopic;
|
||||
|
||||
protected String mqttBrokerEndPoint;
|
||||
protected int timeoutInterval;
|
||||
protected String subscribeTopic;
|
||||
|
||||
/**
|
||||
* Constructor for the MQTTTransportHandler which takes in the owner, type of the device
|
||||
* and the MQTT Broker URL and the topic to subscribe.
|
||||
*
|
||||
* @param deviceOwner the owner of the device.
|
||||
* @param deviceType the CDMF Device-Type of the device.
|
||||
* @param mqttBrokerEndPoint the IP/URL of the MQTT broker endpoint.
|
||||
* @param subscribeTopic the MQTT topic to which the client is to be subscribed
|
||||
*/
|
||||
protected MQTTTransportHandler(String deviceOwner, String deviceType,
|
||||
String mqttBrokerEndPoint,
|
||||
String subscribeTopic) {
|
||||
this.clientId = deviceOwner + ":" + deviceType;
|
||||
this.subscribeTopic = subscribeTopic;
|
||||
this.clientWillTopic = deviceType + File.separator + "disconnection";
|
||||
this.mqttBrokerEndPoint = mqttBrokerEndPoint;
|
||||
this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
|
||||
this.initSubscriber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for the MQTTTransportHandler which takes in the owner, type of the device
|
||||
* and the MQTT Broker URL and the topic to subscribe. Additionally this constructor takes in
|
||||
* the reconnection-time interval between successive attempts to connect to the broker.
|
||||
*
|
||||
* @param deviceOwner the owner of the device.
|
||||
* @param deviceType the CDMF Device-Type of the device.
|
||||
* @param mqttBrokerEndPoint the IP/URL of the MQTT broker endpoint.
|
||||
* @param subscribeTopic the MQTT topic to which the client is to be subscribed
|
||||
* @param intervalInMillis the time interval in MILLI-SECONDS between successive
|
||||
* attempts to connect to the broker.
|
||||
*/
|
||||
protected MQTTTransportHandler(String deviceOwner, String deviceType,
|
||||
String mqttBrokerEndPoint, String subscribeTopic,
|
||||
int intervalInMillis) {
|
||||
this.clientId = deviceOwner + ":" + deviceType;
|
||||
this.subscribeTopic = subscribeTopic;
|
||||
//TODO:: Use constant strings
|
||||
this.clientWillTopic = deviceType + File.separator + "disconnection";
|
||||
this.mqttBrokerEndPoint = mqttBrokerEndPoint;
|
||||
this.timeoutInterval = intervalInMillis;
|
||||
this.initSubscriber();
|
||||
}
|
||||
|
||||
public void setTimeoutInterval(int timeoutInterval) {
|
||||
this.timeoutInterval = timeoutInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the MQTT-Client. Creates a client using the given MQTT-broker endpoint and the
|
||||
* clientId (which is constructed by a concatenation of [deviceOwner]:[deviceType]). Also sets
|
||||
* the client's options parameter with the clientWillTopic (in-case of connection failure) and
|
||||
* other info. Also sets the call-back this current class.
|
||||
*/
|
||||
private void initSubscriber() {
|
||||
try {
|
||||
client = new MqttClient(this.mqttBrokerEndPoint, clientId, null);
|
||||
//TODO:: Need to check for debug
|
||||
log.info("MQTT subscriber was created with ClientID : " + clientId);
|
||||
} catch (MqttException ex) {
|
||||
//TODO:: Remove unnecessary formatting and print exception
|
||||
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);
|
||||
//TODO:: Throw the error out
|
||||
}
|
||||
|
||||
options = new MqttConnectOptions();
|
||||
options.setCleanSession(true);
|
||||
//TODO:: Use constant strings
|
||||
options.setWill(clientWillTopic, "Connection-Lost".getBytes(StandardCharsets.UTF_8), 2,
|
||||
true);
|
||||
client.setCallback(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the connection to the MQTT-Broker persists.
|
||||
*
|
||||
* @return true if the client is connected to the MQTT-Broker, else false.
|
||||
*/
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return client.isConnected();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Connects to the MQTT-Broker and if successfully established connection.
|
||||
*
|
||||
* @throws TransportHandlerException in the event of 'Connecting to' the MQTT broker fails.
|
||||
*/
|
||||
protected void connectToQueue() throws TransportHandlerException {
|
||||
try {
|
||||
client.connect(options);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Subscriber connected to queue at: " + this.mqttBrokerEndPoint);
|
||||
}
|
||||
} 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;
|
||||
//TODO:: Compulsory log of errors and remove formatted error
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(errorMsg);
|
||||
}
|
||||
throw new TransportHandlerException(errorMsg, ex);
|
||||
|
||||
} catch (MqttException ex) {
|
||||
//TODO:: Compulsory log of errors and remove formatted error
|
||||
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;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(errorMsg);
|
||||
}
|
||||
throw new TransportHandlerException(errorMsg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to the MQTT-Topic specific to this MQTT Client. (The MQTT-Topic specific to the
|
||||
* device is taken in as a constructor parameter of this class) .
|
||||
*
|
||||
* @throws TransportHandlerException in the event of 'Subscribing to' the MQTT broker
|
||||
* fails.
|
||||
*/
|
||||
protected void subscribeToQueue() throws TransportHandlerException {
|
||||
try {
|
||||
//TODO:: QoS Level take it from a variable
|
||||
client.subscribe(subscribeTopic, 0);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Subscriber '" + clientId + "' subscribed to topic: " + subscribeTopic);
|
||||
}
|
||||
} catch (MqttException ex) {
|
||||
//TODO:: Compulsory log of errors and remove formatted error
|
||||
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);
|
||||
}
|
||||
|
||||
throw new TransportHandlerException(errorMsg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is used to publish reply-messages for the control signals received.
|
||||
* Invocation of this method calls its overloaded-method with a QoS equal to that of the
|
||||
* default value.
|
||||
*
|
||||
* @param topic the topic to which the reply message is to be published.
|
||||
* @param payLoad the reply-message (payload) of the MQTT publish action.
|
||||
*/
|
||||
protected void publishToQueue(String topic, String payLoad)
|
||||
throws TransportHandlerException {
|
||||
publishToQueue(topic, payLoad, DEFAULT_MQTT_QUALITY_OF_SERVICE, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an overloaded method that publishes MQTT reply-messages for control signals
|
||||
* received form the IoT-Server.
|
||||
*
|
||||
* @param topic the topic to which the reply message is to be published
|
||||
* @param payLoad the reply-message (payload) of the MQTT publish action.
|
||||
* @param qos the Quality-of-Service of the current publish action.
|
||||
* Could be 0(At-most once), 1(At-least once) or 2(Exactly once)
|
||||
*/
|
||||
protected void publishToQueue(String topic, String payLoad, int qos, boolean retained)
|
||||
throws TransportHandlerException {
|
||||
try {
|
||||
client.publish(topic, payLoad.getBytes(StandardCharsets.UTF_8), qos, retained);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Message: " + payLoad + " to MQTT topic [" + topic +
|
||||
"] published successfully");
|
||||
}
|
||||
} 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.info(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void publishToQueue(String topic, MqttMessage message)
|
||||
throws TransportHandlerException {
|
||||
try {
|
||||
client.publish(topic, message);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Message: " + message.toString() + " to MQTT topic [" + topic +
|
||||
"] published successfully");
|
||||
}
|
||||
} catch (MqttException ex) {
|
||||
//TODO:: Compulsory log of errors and remove formatted error
|
||||
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.info(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback method which is triggered once the MQTT client losers its connection to the broker.
|
||||
* Spawns a new thread that executes necessary actions to try and reconnect to the endpoint.
|
||||
*
|
||||
* @param throwable a Throwable Object containing the details as to why the failure occurred.
|
||||
*/
|
||||
@Override
|
||||
public void connectionLost(Throwable throwable) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.warn("Lost Connection for client: " + this.clientId + " to " + this.mqttBrokerEndPoint + "." +
|
||||
"\nThis was due to - " + throwable.getMessage());
|
||||
}
|
||||
|
||||
Thread reconnectThread = new Thread() {
|
||||
public void run() {
|
||||
connect();
|
||||
}
|
||||
};
|
||||
reconnectThread.setDaemon(true);
|
||||
reconnectThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method which is triggered upon receiving a MQTT Message from the broker. Spawns a
|
||||
* new thread that executes any actions to be taken with the received message.
|
||||
*
|
||||
* @param topic the MQTT-Topic to which the received message was published to and the
|
||||
* client was subscribed to.
|
||||
* @param mqttMessage the actual MQTT-Message that was received from the broker.
|
||||
*/
|
||||
@Override
|
||||
public void messageArrived(final String topic, final MqttMessage mqttMessage) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Got an MQTT message '" + mqttMessage.toString() + "' for topic '" + topic + "'.");
|
||||
}
|
||||
|
||||
Thread messageProcessorThread = new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
processIncomingMessage(mqttMessage, topic);
|
||||
} catch (TransportHandlerException e) {
|
||||
log.error("An error occurred when trying to process received MQTT message [" + mqttMessage + "] " +
|
||||
"for topic [" + topic + "].", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
messageProcessorThread.setDaemon(true);
|
||||
messageProcessorThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method which gets triggered upon successful completion of a message delivery to
|
||||
* the broker.
|
||||
*
|
||||
* @param iMqttDeliveryToken the MQTT-DeliveryToken which includes the details about the
|
||||
* specific message delivery.
|
||||
*/
|
||||
@Override
|
||||
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
|
||||
String topic = iMqttDeliveryToken.getTopics()[0];
|
||||
String client = iMqttDeliveryToken.getClient().getClientId();
|
||||
|
||||
try {
|
||||
if (iMqttDeliveryToken.isComplete()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
if (iMqttDeliveryToken.getMessage() != null) {
|
||||
String message = iMqttDeliveryToken.getMessage().toString();
|
||||
log.debug("Message to client [" + client + "] under topic (" + topic +
|
||||
") was delivered successfully with the delivery message: '" + message + "'");
|
||||
} else {
|
||||
log.debug("Message to client [" + client + "] under topic (" + topic +
|
||||
") was delivered successfully.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("FAILED: Delivery of MQTT message to [" + client + "] under topic [" + topic + "] failed.");
|
||||
}
|
||||
} catch (MqttException e) {
|
||||
//TODO:: Throw errors
|
||||
log.error("Error occurred whilst trying to read the message from the MQTT delivery token.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the connection to the MQTT Broker.
|
||||
*/
|
||||
public void closeConnection() throws MqttException {
|
||||
if (client != null && isConnected()) {
|
||||
client.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
version="2.5">
|
||||
<display-name>ConnectedCup-Webapp</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>PushTemperature</servlet-name>
|
||||
<servlet-class>org.coffeeking.agent.datasense.PushTemperature</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>PushTemperature</servlet-name>
|
||||
<url-pattern>/push_temperature</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>PushLevel</servlet-name>
|
||||
<servlet-class>org.coffeeking.agent.datasense.PushLevel</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>PushLevel</servlet-name>
|
||||
<url-pattern>/push_level</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 112 KiB |
@ -0,0 +1,140 @@
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<link rel="stylesheet" href="bootstrap.min.css">
|
||||
<link rel="stylesheet" href="jquery-ui.css">
|
||||
<script src="jquery-1.12.0.min.js"></script>
|
||||
<script src="jquery-ui.js"></script>
|
||||
|
||||
<style>
|
||||
|
||||
.filler {
|
||||
height:200px;
|
||||
background-color:black;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<%
|
||||
String deviceId = request.getParameter("deviceId");
|
||||
if(deviceId != null)request.getSession().setAttribute("deviceId",deviceId);
|
||||
|
||||
String deviceOwner = request.getParameter("deviceOwner");
|
||||
if(deviceOwner != null)request.getSession().setAttribute("deviceOwner",deviceOwner);
|
||||
|
||||
String token = request.getParameter("token");
|
||||
if(token != null)request.getSession().setAttribute("token",token);
|
||||
|
||||
%>
|
||||
<div class="row col-sm-offset-5">
|
||||
<div class="col-md-4" ><h3>Connected Cup</h3></div>
|
||||
</div>
|
||||
<br>
|
||||
</br>
|
||||
|
||||
<div class="row col-sm-offset-2">
|
||||
<div class="col-md-2" >
|
||||
<p>
|
||||
<label for="amount_temp">Temperature: </label>
|
||||
<input type="text" id="amount_temp" readonly style="border:0; color:#f6931f; font-weight:bold;">
|
||||
</p>
|
||||
<div id="temperature_level" style="height:200px; margin: 10%;"></div>
|
||||
</div>
|
||||
<div class="col-md-2" id="objectHolder">
|
||||
<p>
|
||||
<label for="amount">Coffee Level: </label>
|
||||
<input type="text" id="amount" readonly style="border:0; color:#f6931f; font-weight:bold;">
|
||||
</p>
|
||||
<div id="slider-vertical" style="height:200px; margin: 10%;"></div>
|
||||
|
||||
</div>
|
||||
<div class="col-md-4" style="height:200px; ">
|
||||
<div id="filler" class="filler" style="height: 0%; bottom: 0px; position: absolute; width: 100%; ">
|
||||
<img src="coffeecup.png" style="height: 200px; width: 100%; position: absolute; bottom:0px;">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2" >
|
||||
<button id="order-cup">Order Coffee Cup</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="application/javascript">
|
||||
function processCoffeeLevel(min, max){
|
||||
var filler = document.getElementById("filler");
|
||||
$( "#slider-vertical" ).slider({
|
||||
orientation: "vertical",
|
||||
range: "min",
|
||||
min: min,
|
||||
max: max,
|
||||
value: 0,
|
||||
slide: function( event, ui ) {
|
||||
$( "#amount" ).val( ui.value );
|
||||
filler.style.height = map(min, max, 0, 100, ui.value) + "%";
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$( "#amount" ).val( $( "#slider-vertical" ).slider( "value" ) );
|
||||
|
||||
|
||||
}
|
||||
|
||||
function processTemperature(min, max){
|
||||
$( "#temperature_level" ).slider({
|
||||
orientation: "vertical",
|
||||
range: "min",
|
||||
min: min,
|
||||
max: max,
|
||||
value: 0,
|
||||
slide: function( event, ui ) {
|
||||
$( "#amount_temp" ).val( ui.value );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function map(a,b,c,d,N)
|
||||
{
|
||||
return c+((N-a)*(d-c))/(b-a);
|
||||
}
|
||||
|
||||
processCoffeeLevel(0, 100);
|
||||
processTemperature(0,100);
|
||||
|
||||
$("#order-cup").click(function() {
|
||||
|
||||
var deviceId = '<%=request.getSession().getAttribute("deviceId")%>';
|
||||
var deviceOwner = '<%=request.getSession().getAttribute("deviceOwner")%>';
|
||||
var token = '<%=request.getSession().getAttribute("token")%>';
|
||||
var url = "https://localhost:9443/connectedcup/controller/ordercoffee?deviceId=" + deviceId +"&deviceOwner=" +
|
||||
deviceOwner;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: url,
|
||||
headers: {
|
||||
"Authorization" : "Bearer " + token
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function sendData()
|
||||
{
|
||||
var deviceId = '<%=request.getSession().getAttribute("deviceId")%>';
|
||||
var deviceOwner = '<%=request.getSession().getAttribute("deviceOwner")%>';
|
||||
var tempPayload = "temperature:" + $( "#temperature_level" ).slider( "value" );
|
||||
var levelPayload = "coffeelevel:" + $( "#slider-vertical" ).slider( "value" );
|
||||
$.post( "/connected-cup-agent/push_temperature?deviceId=" + deviceId +"&deviceOwner=" + deviceOwner +
|
||||
"&payload=" + tempPayload);
|
||||
$.post( "/connected-cup-agent/push_level?deviceId=" + deviceId +"&deviceOwner=" + deviceOwner +
|
||||
"&payload=" + levelPayload);
|
||||
setTimeout(sendData, 5000);
|
||||
}
|
||||
|
||||
sendData();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue