Merge branch 'master' of /home/amalka/wso2/source/carbon-device-mgt-plugins

fix-test-failure
Amalka Subasinghe 2 years ago
commit 83bfaded86

@ -0,0 +1,237 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>virtual-fire-alarm-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.1.21-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.impl</artifactId>
<name>WSO2 Carbon - IoT Server VirtualFireAlarm Agent</name>
<description>WSO2 Carbon - VirtualFireAlarm Device Agent Implementation</description>
<url>http://wso2.org</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<source>${wso2.maven.compiler.source}</source>
<target>${wso2.maven.compiler.target}</target>
</configuration>
<version>2.3.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>
org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.Bootstrap
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>wso2-firealarm-virtual-agent</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- this is used for inheritance merges -->
<phase>package</phase>
<!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!--Dependency on Log4J - required by IoT Common Component-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!--Dependency on Jetty-Server Library-->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<!--Dependency on MQTT Client Library-->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>${paho.mqtt.version}</version>
</dependency>
<!--Dependencies on XMPP Client Library-->
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
<version>${smack.wso2.version}</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
<version>${smackx.wso2.version}</version>
</dependency>
<!--Dependency on BouncyCastle Library for SCEP-->
<dependency>
<groupId>org.bouncycastle.wso2</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>${bcprov.wso2.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle.wso2</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>${bcpkix.wso2.version}</version>
</dependency>
<!--Dependency on WSO2 JSCEP Orbit-->
<dependency>
<groupId>com.google.code.jscep.wso2</groupId>
<artifactId>jscep</artifactId>
<version>${jscep.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons-lang.version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${common-logging.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io}</version>
</dependency>
<!--Dependency on SLF4J - required by BouncyCastle-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.10</version>
</dependency>
</dependencies>
<repositories>
<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-maven2-repository</id>
<url>http://dist.wso2.org/maven2</url>
</repository>
</repositories>
<properties>
<!-- Java Version Compatibility -->
<wso2.maven.compiler.source>1.7</wso2.maven.compiler.source>
<wso2.maven.compiler.target>1.7</wso2.maven.compiler.target>
<!-- Jetty Server Version -->
<jetty.version>8.1.3.v20120416</jetty.version>
<!-- MQTT Paho Version -->
<paho.mqtt.version>1.0.2</paho.mqtt.version>
<!-- Jivesoftware XMPP Version -->
<smack.wso2.version>3.0.4.wso2v1</smack.wso2.version>
<smackx.wso2.version>3.0.4.wso2v1</smackx.wso2.version>
<!-- BouncyCastle Version -->
<bcprov.wso2.version>1.49.wso2v1</bcprov.wso2.version>
<bcpkix.wso2.version>1.49.wso2v1</bcpkix.wso2.version>
<!-- WSO2 JSCEP Orbit Version -->
<jscep.version>2.0.2.wso2v2</jscep.version>
<!-- Commons Libraries -->
<log4j.version>1.2.17</log4j.version>
<common-logging.version>1.2</common-logging.version>
<commons.io>2.4</commons.io>
<commons-codec.version>1.7</commons-codec.version>
<commons-lang.version>2.6</commons-lang.version>
<!-- SLF4J Version -->
<slf4j.version>1.7.13</slf4j.version>
</properties>
</project>

@ -0,0 +1,36 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
public class Bootstrap {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
System.setProperty("org.apache.commons.logging.simplelog.defaultlog", "info");
System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
System.setProperty("org.apache.commons.logging.simplelog.dateTimeFormat", "HH:mm:ss");
AgentManager.getInstance().init();
}
}

@ -0,0 +1,484 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.http;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.http.HTTPTransportHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ProtocolException;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class FireAlarmHTTPCommunicator extends HTTPTransportHandler {
private static final Log log = LogFactory.getLog(FireAlarmHTTPCommunicator.class);
private ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
private ScheduledFuture<?> dataPushServiceHandler;
private ScheduledFuture<?> connectorServiceHandler;
public FireAlarmHTTPCommunicator() {
super();
}
public FireAlarmHTTPCommunicator(int port) {
super(port);
}
public FireAlarmHTTPCommunicator(int port, int reconnectionInterval) {
super(port, reconnectionInterval);
}
public ScheduledFuture<?> getDataPushServiceHandler() {
return dataPushServiceHandler;
}
public void connect() {
Runnable connect = new Runnable() {
public void run() {
if (!isConnected()) {
try {
processIncomingMessage();
server.start();
registerThisDevice();
publishDeviceData();
log.info("HTTP Server started at port: " + port);
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.warn("Unable to 'START' HTTP server. Will retry after " +
timeoutInterval / 1000 + " seconds.");
}
}
}
}
};
connectorServiceHandler = service.scheduleAtFixedRate(connect, 0, timeoutInterval,
TimeUnit.MILLISECONDS);
}
@Override
public void processIncomingMessage() {
server.setHandler(new AbstractHandler() {
public void handle(String s, Request request, HttpServletRequest
httpServletRequest,
HttpServletResponse httpServletResponse)
throws IOException, ServletException {
httpServletResponse.setContentType("text/html;charset=utf-8");
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
request.setHandled(true);
AgentManager agentManager = AgentManager.getInstance();
String pathContext = request.getPathInfo();
String separator = File.separatorChar=='\\' ? "\\\\" : File.separator ;
if (pathContext.toUpperCase().contains(
separator + AgentConstants.TEMPERATURE_CONTROL)) {
httpServletResponse.getWriter().println(
agentManager.getTemperature());
} else if (pathContext.toUpperCase().contains(
separator + AgentConstants.HUMIDITY_CONTROL)) {
httpServletResponse.getWriter().println(
agentManager.getHumidity());
} else if (pathContext.toUpperCase().contains(
separator + AgentConstants.BULB_CONTROL)) {
String[] pathVariables = pathContext.split(separator);
if (pathVariables.length != 3) {
httpServletResponse.getWriter().println(
"Invalid BULB-control received by the device. Need to be in " +
"'{host}:{port}/BULB/{ON|OFF}' format.");
return;
}
String switchState = pathVariables[2];
if (switchState == null) {
httpServletResponse.getWriter().println(
"Please specify switch-status of the BULB.");
} else {
boolean status = switchState.toUpperCase().equals(
AgentConstants.CONTROL_ON);
agentManager.changeAlarmStatus(status);
httpServletResponse.getWriter().println("Bulb is " + (status ?
AgentConstants.CONTROL_ON : AgentConstants.CONTROL_OFF));
}
} else {
httpServletResponse.getWriter().println(
"Invalid control command received by the device.");
}
}
});
}
@Override
public void publishDeviceData() {
final AgentManager agentManager = AgentManager.getInstance();
int publishInterval = agentManager.getPushInterval();
final String deviceOwner = agentManager.getAgentConfigs().getDeviceOwner();
final String deviceID = agentManager.getAgentConfigs().getDeviceId();
boolean simulationMode = false;
int duration = 2 * 60;
int frequency = 5;
Runnable pushDataRunnable = new Runnable() {
@Override
public void run() {
String pushDataPayload = String.format(AgentConstants.PUSH_DATA_PAYLOAD, deviceOwner,
deviceID, (agentManager.getDeviceIP() + ":" + port),
agentManager.getTemperature());
executeDataPush(pushDataPayload);
}
};
if (!simulationMode) {
dataPushServiceHandler = service.scheduleAtFixedRate(pushDataRunnable, publishInterval,
publishInterval,
TimeUnit.SECONDS);
} else {
String pushDataPayload = String.format(AgentConstants.PUSH_SIMULATION_DATA_PAYLOAD, deviceOwner,
deviceID, (agentManager.getDeviceIP() + ":" + port),
agentManager.getTemperature(), true, duration, frequency);
executeDataPush(pushDataPayload);
}
}
private void executeDataPush(String pushDataPayload) {
AgentManager agentManager = AgentManager.getInstance();
String pushDataEndPointURL = agentManager.getPushDataAPIEP();
HttpURLConnection httpConnection;
int responseCode = -1;
try {
httpConnection = TransportUtils.getHttpConnection(agentManager.getPushDataAPIEP());
httpConnection.setRequestMethod(AgentConstants.HTTP_POST);
httpConnection.setRequestProperty("Authorization",
"Bearer " + agentManager.getAgentConfigs().getAuthToken());
httpConnection.setRequestProperty("Content-Type", AgentConstants.APPLICATION_JSON);
httpConnection.setDoOutput(true);
DataOutputStream dataOutPutWriter = new DataOutputStream(httpConnection.getOutputStream());
dataOutPutWriter.writeBytes(pushDataPayload);
dataOutPutWriter.flush();
dataOutPutWriter.close();
responseCode = httpConnection.getResponseCode();
httpConnection.disconnect();
log.info(AgentConstants.LOG_APPENDER + "Message - '" + pushDataPayload +
"' was published to server at: " + httpConnection.getURL());
} catch (ProtocolException exception) {
String errorMsg =
"Protocol specific error occurred when trying to set method to " +
AgentConstants.HTTP_POST + " for:" + pushDataEndPointURL;
log.error(AgentConstants.LOG_APPENDER + errorMsg);
} catch (IOException exception) {
String errorMsg =
"An IO error occurred whilst trying to get the response code from: " +
pushDataEndPointURL + " for a " + AgentConstants.HTTP_POST + " method.";
log.error(AgentConstants.LOG_APPENDER + errorMsg);
} catch (TransportHandlerException exception) {
log.error(AgentConstants.LOG_APPENDER +
"Error encountered whilst trying to create HTTP-Connection to IoT-Server EP at: " +
pushDataEndPointURL);
}
if (responseCode == HttpStatus.CONFLICT_409 ||
responseCode == HttpStatus.PRECONDITION_FAILED_412) {
log.warn(AgentConstants.LOG_APPENDER +
"DeviceIP is being Re-Registered due to Push-Data failure with response code: " +
responseCode);
registerThisDevice();
} else if (responseCode != HttpStatus.NO_CONTENT_204) {
if (log.isDebugEnabled()) {
log.error(AgentConstants.LOG_APPENDER + "Status Code: " + responseCode +
" encountered whilst trying to Push-Device-Data to IoT Server at: " +
agentManager.getPushDataAPIEP());
}
agentManager.updateAgentStatus(AgentConstants.SERVER_NOT_RESPONDING);
}
if (log.isDebugEnabled()) {
log.debug(AgentConstants.LOG_APPENDER + "Push-Data call with payload - " + pushDataPayload +
", to IoT Server returned status " + responseCode);
}
}
@Override
public void disconnect() {
Runnable stopConnection = new Runnable() {
public void run() {
while (isConnected()) {
try {
dataPushServiceHandler.cancel(true);
connectorServiceHandler.cancel(true);
closeConnection();
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.warn(AgentConstants.LOG_APPENDER + "Unable to 'STOP' HTTP server at port: " + port);
}
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException e1) {
log.error(
AgentConstants.LOG_APPENDER + "HTTP-Termination: Thread Sleep Interrupt Exception");
}
}
}
}
};
Thread terminatorThread = new Thread(stopConnection);
terminatorThread.setDaemon(true);
terminatorThread.start();
}
@Override
public void processIncomingMessage(Object message, String... messageParams) {
}
@Override
public void publishDeviceData(String... publishData) {
}
public void registerThisDevice() {
final AgentManager agentManager = AgentManager.getInstance();
agentManager.updateAgentStatus("Registering...");
final Runnable ipRegistration = new Runnable() {
@Override
public void run() {
while (isConnected()) {
try {
int responseCode = registerDeviceIP(
agentManager.getAgentConfigs().getDeviceOwner(),
agentManager.getAgentConfigs().getDeviceId());
if (responseCode == HttpStatus.OK_200) {
agentManager.updateAgentStatus(AgentConstants.REGISTERED);
break;
} else {
log.error(AgentConstants.LOG_APPENDER +
"Device Registration with IoT Server at:" + " " +
agentManager.getIpRegistrationEP() +
" failed with response - '" + responseCode + ":" +
HttpStatus.getMessage(responseCode) + "'");
agentManager.updateAgentStatus(AgentConstants.RETRYING_TO_REGISTER);
}
} catch (AgentCoreOperationException exception) {
log.error(AgentConstants.LOG_APPENDER +
"Error encountered whilst trying to register the " +
"Device's IP at: " +
agentManager.getIpRegistrationEP() +
".\nCheck whether the network-interface provided is " +
"accurate");
agentManager.updateAgentStatus(AgentConstants.REGISTRATION_FAILED);
}
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException e1) {
log.error(AgentConstants.LOG_APPENDER +
"Device Registration: Thread Sleep Interrupt Exception");
}
}
}
};
Thread ipRegisterThread = new Thread(ipRegistration);
ipRegisterThread.setDaemon(true);
ipRegisterThread.start();
}
/**
* This method calls the "Register-API" of the IoT Server in order to register the device's IP
* against its ID.
*
* @param deviceOwner the owner of the device by whose name the agent was downloaded.
* (Read from configuration file)
* @param deviceID the deviceId that is auto-generated whilst downloading the agent.
* (Read from configuration file)
* @return the status code of the HTTP-Post call to the Register-API of the IoT-Server
* @throws AgentCoreOperationException if any errors occur when an HTTPConnection session is
* created
*/
private int registerDeviceIP(String deviceOwner, String deviceID)
throws AgentCoreOperationException {
int responseCode = -1;
final AgentManager agentManager = AgentManager.getInstance();
String networkInterface = agentManager.getNetworkInterface();
String deviceIPAddress = getDeviceIP(networkInterface);
if (deviceIPAddress == null) {
throw new AgentCoreOperationException(
"An IP address could not be retrieved for the selected network interface - '" +
networkInterface + ".");
}
agentManager.setDeviceIP(deviceIPAddress);
log.info(AgentConstants.LOG_APPENDER + "Device IP Address: " + deviceIPAddress);
String deviceIPRegistrationEP = agentManager.getIpRegistrationEP();
String registerEndpointURLString =
deviceIPRegistrationEP + File.separator + deviceOwner + File.separator + deviceID +
File.separator + deviceIPAddress + File.separator + port;
if (log.isDebugEnabled()) {
log.debug(AgentConstants.LOG_APPENDER + "DeviceIP Registration EndPoint: " +
registerEndpointURLString);
}
HttpURLConnection httpConnection;
try {
httpConnection = TransportUtils.getHttpConnection(registerEndpointURLString);
} catch (TransportHandlerException e) {
String errorMsg =
"Protocol specific error occurred when trying to fetch an HTTPConnection to:" +
" " + registerEndpointURLString;
log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException();
}
try {
httpConnection.setRequestMethod(AgentConstants.HTTP_POST);
httpConnection.setRequestProperty("Authorization", "Bearer " +
agentManager.getAgentConfigs().getAuthToken());
httpConnection.setDoOutput(true);
responseCode = httpConnection.getResponseCode();
} catch (ProtocolException exception) {
String errorMsg = "Protocol specific error occurred when trying to set method to " +
AgentConstants.HTTP_POST + " for:" + registerEndpointURLString;
log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg, exception);
} catch (IOException exception) {
String errorMsg = "An IO error occurred whilst trying to get the response code from:" +
" " + registerEndpointURLString + " for a " + AgentConstants.HTTP_POST + " method.";
log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg, exception);
}
log.info(AgentConstants.LOG_APPENDER + "DeviceIP - " + deviceIPAddress +
", registration with IoT Server at : " +
agentManager.getAgentConfigs().getHTTPS_ServerEndpoint() +
" returned status " +
responseCode);
return responseCode;
}
/*------------------------------------------------------------------------------------------*/
/* Utility methods relevant to creating and sending HTTP requests to the Iot-Server */
/*------------------------------------------------------------------------------------------*/
/**
* This method is used to get the IP of the device in which the agent is run on.
*
* @return the IP Address of the device
* @throws AgentCoreOperationException if any errors occur whilst trying to get the IP address
*/
private String getDeviceIP() throws AgentCoreOperationException {
try {
return Inet4Address.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
String errorMsg = "Error encountered whilst trying to get the device IP address.";
log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
}
/**
* This is an overloaded method that fetches the public IPv4 address of the given network
* interface
*
* @param networkInterfaceName the network-interface of whose IPv4 address is to be retrieved
* @return the IP Address iof the device
* @throws AgentCoreOperationException if any errors occur whilst trying to get details of the
* given network interface
*/
private String getDeviceIP(String networkInterfaceName) throws
AgentCoreOperationException {
String ipAddress = null;
try {
Enumeration<InetAddress> interfaceIPAddresses = NetworkInterface.getByName(
networkInterfaceName).getInetAddresses();
for (; interfaceIPAddresses.hasMoreElements(); ) {
InetAddress ip = interfaceIPAddresses.nextElement();
ipAddress = ip.getHostAddress();
if (log.isDebugEnabled()) {
log.debug(AgentConstants.LOG_APPENDER + "IP Address: " + ipAddress);
}
if (TransportUtils.validateIPv4(ipAddress)) {
return ipAddress;
}
}
} catch (SocketException | NullPointerException exception) {
String errorMsg =
"Error encountered whilst trying to get IP Addresses of the network interface: " +
networkInterfaceName +
".\nPlease check whether the name of the network interface used is correct";
log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg, exception);
}
return ipAddress;
}
}

@ -0,0 +1,293 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.mqtt;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentUtilOperations;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.mqtt.MQTTTransportHandler;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
//TODO:: Lincence header, comments and SPECIFIC class name since its not generic
public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
private static final Log log = LogFactory.getLog(FireAlarmMQTTCommunicator.class);
private ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
private ScheduledFuture<?> dataPushServiceHandler;
private static final String DEFAULT_PASSWORD = "";
public FireAlarmMQTTCommunicator(String deviceOwner, String deviceType,
String mqttBrokerEndPoint, String subscribeTopic) {
super(deviceOwner, deviceType, mqttBrokerEndPoint, subscribeTopic);
}
@SuppressWarnings("unused")
public FireAlarmMQTTCommunicator(String deviceOwner, String deviceType,
String mqttBrokerEndPoint, String subscribeTopic,
int intervalInMillis) {
super(deviceOwner, deviceType, mqttBrokerEndPoint, subscribeTopic, intervalInMillis);
}
public ScheduledFuture<?> getDataPushServiceHandler() {
return dataPushServiceHandler;
}
//TODO:: Terminate logs with a period
//TODO: Need to print exceptions
@Override
public void connect() {
final AgentManager agentManager = AgentManager.getInstance();
Runnable connector = new Runnable() {
public void run() {
while (!isConnected()) {
try {
connectToQueue(agentManager.getAgentConfigs().getAuthToken(), DEFAULT_PASSWORD);
agentManager.updateAgentStatus("Connected to MQTT Queue");
} catch (TransportHandlerException e) {
log.warn(AgentConstants.LOG_APPENDER + "Connection to MQTT Broker at: " + mqttBrokerEndPoint +
" failed.\n Will retry in " + timeoutInterval + " milli-seconds.");
if (e.getCause() != null && e.getCause() instanceof MqttSecurityException) {
refreshOAuthToken((MqttSecurityException) e.getCause());
}
}
try {
if (isConnected()) {
subscribeToQueue();
agentManager.updateAgentStatus("Subscribed to MQTT Queue");
publishDeviceData();
}
} catch (TransportHandlerException e) {
log.warn(AgentConstants.LOG_APPENDER + "Subscription to MQTT Broker at: " +
mqttBrokerEndPoint + " failed");
agentManager.updateAgentStatus("Subscription to broker failed.");
}
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException ex) {
log.error(AgentConstants.LOG_APPENDER + "MQTT: Connect-Thread Sleep Interrupt Exception.");
}
}
}
};
Thread connectorThread = new Thread(connector);
connectorThread.setDaemon(true);
connectorThread.start();
}
private void refreshOAuthToken(final MqttSecurityException exception) {
Runnable tokenRefresher = new Runnable() {
public void run() {
String authenticationMethod = AgentUtilOperations.getAuthenticationMethod();
try {
if (exception.getReasonCode() == MqttSecurityException.REASON_CODE_FAILED_AUTHENTICATION &&
authenticationMethod.equals(AgentConstants.TOKEN_AUTHENTICATION_METHOD)) {
AgentUtilOperations.refreshOAuthToken();
}
} catch (AgentCoreOperationException e1) {
log.error(AgentConstants.LOG_APPENDER + "Token Refresh Attempt Failed. " + e1);
}
}
};
Thread connectorThread = new Thread(tokenRefresher);
connectorThread.setDaemon(true);
connectorThread.start();
}
@Override
public void processIncomingMessage(MqttMessage message, String... messageParams) {
final AgentManager agentManager = AgentManager.getInstance();
String tenantDomain = agentManager.getAgentConfigs().getTenantDomain();
String deviceOwner = agentManager.getAgentConfigs().getDeviceOwner();
String deviceID = agentManager.getAgentConfigs().getDeviceId();
String receivedMessage;
String replyMessage;
String securePayLoad;
try {
receivedMessage = AgentUtilOperations.extractMessageFromPayload(message.toString());
log.info(AgentConstants.LOG_APPENDER + "Message [" + receivedMessage + "] was received");
} catch (AgentCoreOperationException e) {
log.warn(AgentConstants.LOG_APPENDER + "Could not extract message from payload.", e);
return;
}
String[] controlSignal = receivedMessage.split(":");
// message- "<SIGNAL_TYPE>:<SIGNAL_MODE>" format.(ex: "BULB:ON", "TEMPERATURE", "HUMIDITY")
try {
switch (controlSignal[0].toUpperCase()) {
case AgentConstants.BULB_CONTROL:
boolean stateToSwitch = controlSignal[1].equals(AgentConstants.CONTROL_ON);
agentManager.changeAlarmStatus(stateToSwitch);
log.info(AgentConstants.LOG_APPENDER + "Bulb was switched to state: '" + controlSignal[1] + "'");
break;
case AgentConstants.TEMPERATURE_CONTROL:
int currentTemperature = agentManager.getTemperature();
String replyTemperature = "Current temperature was read as: '" + currentTemperature + "C'";
log.info(AgentConstants.LOG_APPENDER + replyTemperature);
String tempPublishTopic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC, tenantDomain, deviceID);
replyMessage = AgentConstants.TEMPERATURE_CONTROL + ":" + currentTemperature;
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
publishToQueue(tempPublishTopic, securePayLoad);
break;
case AgentConstants.HUMIDITY_CONTROL:
int currentHumidity = agentManager.getHumidity();
String replyHumidity = "Current humidity was read as: '" + currentHumidity + "%'";
log.info(AgentConstants.LOG_APPENDER + replyHumidity);
String humidPublishTopic = String.format(
AgentConstants.MQTT_PUBLISH_TOPIC, tenantDomain, deviceID);
replyMessage = AgentConstants.HUMIDITY_CONTROL + ":" + currentHumidity;
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
publishToQueue(humidPublishTopic, securePayLoad);
break;
default:
log.warn(AgentConstants.LOG_APPENDER + "'" + controlSignal[0] +
"' is invalid and not-supported for this device-type");
break;
}
} catch (AgentCoreOperationException e) {
log.warn(AgentConstants.LOG_APPENDER + "Preparing Secure payload failed", e);
} catch (TransportHandlerException e) {
log.error(AgentConstants.LOG_APPENDER +
"MQTT - Publishing, reply message to the MQTT Queue at: " +
agentManager.getAgentConfigs().getMqttBrokerEndpoint() + " failed");
}
}
@Override
public void publishDeviceData() {
final AgentManager agentManager = AgentManager.getInstance();
int publishInterval = agentManager.getPushInterval();
Runnable pushDataRunnable = new Runnable() {
@Override
public void run() {
int currentTemperature = agentManager.getTemperature();
String message = "{\"event\": {\"metaData\": {\"owner\": \"" + AgentManager
.getInstance().getAgentConfigs().getDeviceOwner() + "\",\"deviceId\": \"" + AgentManager
.getInstance().getAgentConfigs().getDeviceId() + "\",\"time\": " +
"0},\"payloadData\": { \"temperature\": " + currentTemperature + "} }}";
try {
String payLoad = AgentUtilOperations.prepareSecurePayLoad(message);
MqttMessage pushMessage = new MqttMessage();
pushMessage.setPayload(payLoad.getBytes(StandardCharsets.UTF_8));
pushMessage.setQos(DEFAULT_MQTT_QUALITY_OF_SERVICE);
pushMessage.setRetained(false);
String topic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC,
agentManager.getAgentConfigs().getTenantDomain(),
agentManager.getAgentConfigs().getDeviceId());
publishToQueue(topic, pushMessage);
log.info(AgentConstants.LOG_APPENDER + "Message: '" + message + "' published to MQTT Queue at [" +
agentManager.getAgentConfigs().getMqttBrokerEndpoint() + "] under topic [" +
topic + "]");
} catch (TransportHandlerException e) {
log.warn(AgentConstants.LOG_APPENDER + "Data Publish attempt to topic - [" +
AgentConstants.MQTT_PUBLISH_TOPIC + "] failed for payload [" + message + "]");
} catch (AgentCoreOperationException e) {
log.warn(AgentConstants.LOG_APPENDER + "Preparing Secure payload failed", e);
}
}
};
dataPushServiceHandler = service.scheduleAtFixedRate(pushDataRunnable, publishInterval, publishInterval,
TimeUnit.SECONDS);
}
@Override
public void disconnect() {
Runnable stopConnection = new Runnable() {
public void run() {
while (isConnected()) {
if (dataPushServiceHandler != null) {
dataPushServiceHandler.cancel(true);
}
try {
closeConnection();
} catch (MqttException e) {
if (log.isDebugEnabled()) {
log.warn(AgentConstants.LOG_APPENDER +
"Unable to 'STOP' MQTT connection at broker at: " +
mqttBrokerEndPoint);
}
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException e1) {
log.error(AgentConstants.LOG_APPENDER +
"MQTT-Terminator: Thread Sleep Interrupt Exception");
}
}
}
}
};
Thread terminatorThread = new Thread(stopConnection);
terminatorThread.setDaemon(true);
terminatorThread.start();
}
@Override
public void processIncomingMessage() {
}
@Override
public void publishDeviceData(String... publishData) {
}
}

@ -0,0 +1,265 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.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.virtualfirealarm.agent.core.AgentConfiguration;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentUtilOperations;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.xmpp.XMPPTransportHandler;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class FireAlarmXMPPCommunicator extends XMPPTransportHandler {
private static final Log log = LogFactory.getLog(FireAlarmXMPPCommunicator.class);
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 FireAlarmXMPPCommunicator(String server) {
super(server);
}
public FireAlarmXMPPCommunicator(String server, int port) {
super(server, port);
}
public FireAlarmXMPPCommunicator(String server, int port, int timeout) {
super(server, port, timeout);
}
public ScheduledFuture<?> getDataPushServiceHandler() {
return dataPushServiceHandler;
}
@Override
public void connect() {
final AgentManager agentManager = AgentManager.getInstance();
username = agentManager.getAgentConfigs().getDeviceId();
password = agentManager.getAgentConfigs().getAuthToken();
xmppDeviceJID = username + "@" + agentManager.getAgentConfigs().getXmppServerName();
xmppAdminJID = agentManager.getAgentConfigs().getServerJID();
Runnable connect = new Runnable() {
public void run() {
if (!isConnected()) {
try {
connectToServer();
} catch (TransportHandlerException e) {
log.warn(AgentConstants.LOG_APPENDER + "Connection to XMPP server at: " + server + " failed");
}
try {
loginToServer(username, password, resource);
agentManager.updateAgentStatus("Connected to XMPP Server");
setMessageFilterAndListener(xmppAdminJID, xmppDeviceJID, true);
publishDeviceData();
} catch (TransportHandlerException e) {
log.warn(AgentConstants.LOG_APPENDER + "Login to XMPP server at: " + server + " failed");
agentManager.updateAgentStatus("No XMPP Account for Device");
}
}
}
};
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... messageParams) {
final AgentManager agentManager = AgentManager.getInstance();
String from = xmppMessage.getFrom();
String message = xmppMessage.getBody();
String receivedMessage;
String replyMessage;
String securePayLoad;
try {
receivedMessage = AgentUtilOperations.extractMessageFromPayload(message);
log.info(AgentConstants.LOG_APPENDER + "Message [" + receivedMessage + "] was received");
} catch (AgentCoreOperationException e) {
log.warn(AgentConstants.LOG_APPENDER + "Could not extract message from payload.", e);
return;
}
String[] controlSignal = receivedMessage.split(":");
//message- "<SIGNAL_TYPE>:<SIGNAL_MODE>" format. (ex: "BULB:ON", "TEMPERATURE", "HUMIDITY")
try {
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);
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
sendXMPPMessage(xmppAdminJID, securePayLoad, "CONTROL-REPLY");
break;
}
agentManager.changeAlarmStatus(controlSignal[1].equals(AgentConstants.CONTROL_ON));
log.info(AgentConstants.LOG_APPENDER + "Bulb was switched to state: '" + controlSignal[1] + "'");
break;
case AgentConstants.TEMPERATURE_CONTROL:
int 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;
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
sendXMPPMessage(xmppAdminJID, securePayLoad, "CONTROL-REPLY");
break;
case AgentConstants.HUMIDITY_CONTROL:
int currentHumidity = agentManager.getHumidity();
String replyHumidity = "The current humidity was read to be: '" + currentHumidity + "%'";
log.info(AgentConstants.LOG_APPENDER + replyHumidity);
replyMessage = AgentConstants.HUMIDITY_CONTROL + ":" + currentHumidity;
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
sendXMPPMessage(xmppAdminJID, securePayLoad, "CONTROL-REPLY");
break;
default:
replyMessage = "'" + controlSignal[0] + "' is invalid and not-supported for this device-type";
log.warn(replyMessage);
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
sendXMPPMessage(xmppAdminJID, securePayLoad, "CONTROL-ERROR");
break;
}
} catch (AgentCoreOperationException e) {
log.warn(AgentConstants.LOG_APPENDER + "Preparing Secure payload failed", e);
}
}
@Override
public void publishDeviceData() {
final AgentManager agentManager = AgentManager.getInstance();
int publishInterval = agentManager.getPushInterval();
Runnable pushDataRunnable = new Runnable() {
@Override
public void run() {
Message xmppMessage = new Message();
try {
int currentTemperature = agentManager.getTemperature();
String message = "{\"event\": {\"metaData\": {\"owner\": \"" + AgentManager
.getInstance().getAgentConfigs().getDeviceOwner() + "\",\"deviceId\": \"" + AgentManager
.getInstance().getAgentConfigs().getDeviceId() + "\",\"time\": " +
"0},\"payloadData\": { \"temperature\": " + currentTemperature + "} }}";
String payLoad = AgentUtilOperations.prepareSecurePayLoad(message);
xmppMessage.setTo(xmppAdminJID);
xmppMessage.setSubject(agentManager.getAgentConfigs().getTenantDomain());
xmppMessage.setBody(payLoad);
xmppMessage.setType(Message.Type.chat);
sendXMPPMessage(xmppAdminJID, xmppMessage);
log.info(AgentConstants.LOG_APPENDER + "Message: '" + message + "' sent to XMPP JID - " +
"[" + xmppAdminJID + "] under subject [" + xmppMessage.getSubject() + "].");
} catch (AgentCoreOperationException e) {
log.warn(AgentConstants.LOG_APPENDER + "Preparing Secure payload failed for XMPP JID - " +
"[" + xmppAdminJID + "] with subject - [" + xmppMessage.getSubject() + "].");
}
}
};
dataPushServiceHandler = service.scheduleAtFixedRate(pushDataRunnable, publishInterval,
publishInterval, TimeUnit.SECONDS);
}
@Override
public void disconnect() {
Runnable stopConnection = new Runnable() {
public void run() {
if (dataPushServiceHandler != null) {
dataPushServiceHandler.cancel(true);
}
if (connectorServiceHandler != null) {
connectorServiceHandler.cancel(true);
}
while (isConnected()) {
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() {
}
@Override
public void publishDeviceData(String... publishData) {
}
}

@ -0,0 +1,164 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
/**
* A Configuration class that holds all the Agent specific details that are read from the
* 'deviceConfig.properties' file. This file is generated by the IoT-Server at the time of
* downloading the device agent from the IoT-Server.
*/
public class AgentConfiguration {
private String tenantDomain;
private String deviceOwner;
private String deviceId;
private String deviceName;
private String HTTPS_ServerEndpoint;
private String HTTP_ServerEndpoint;
private String apimGatewayEndpoint;
private String mqttBrokerEndpoint;
private String xmppServerEndpoint;
private String apiApplicationKey;
private String authToken;
private String refreshToken;
private int dataPushInterval;
private String xmppServerName;
private String serverJID;
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
public String getDeviceOwner() {
return deviceOwner;
}
public void setDeviceOwner(String deviceOwner) {
this.deviceOwner = deviceOwner;
}
public String getDeviceId() {
return deviceId;
}
public String getServerJID() {
return serverJID;
}
public void setServerJID(String serverJID) {
this.serverJID = serverJID;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getHTTPS_ServerEndpoint() {
return HTTPS_ServerEndpoint;
}
public void setHTTPS_ServerEndpoint(String HTTPS_ServerEndpoint) {
this.HTTPS_ServerEndpoint = HTTPS_ServerEndpoint;
}
public String getHTTP_ServerEndpoint() {
return HTTP_ServerEndpoint;
}
public void setHTTP_ServerEndpoint(String HTTP_ServerEndpoint) {
this.HTTP_ServerEndpoint = HTTP_ServerEndpoint;
}
public String getApimGatewayEndpoint() {
return apimGatewayEndpoint;
}
public void setApimGatewayEndpoint(String apimGatewayEndpoint) {
this.apimGatewayEndpoint = apimGatewayEndpoint;
}
public String getMqttBrokerEndpoint() {
return mqttBrokerEndpoint;
}
public void setMqttBrokerEndpoint(String mqttBrokerEndpoint) {
this.mqttBrokerEndpoint = mqttBrokerEndpoint;
}
public String getXmppServerEndpoint() {
return xmppServerEndpoint;
}
public void setXmppServerEndpoint(String xmppServerEndpoint) {
this.xmppServerEndpoint = xmppServerEndpoint;
}
public String getApiApplicationKey() {
return apiApplicationKey;
}
public void setApiApplicationKey(String apiApplicationKey) {
this.apiApplicationKey = apiApplicationKey;
}
public String getAuthToken() {
return authToken;
}
public void setAuthToken(String authToken) {
this.authToken = authToken;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public int getDataPushInterval() {
return dataPushInterval;
}
public void setDataPushInterval(int dataPushInterval) {
this.dataPushInterval = dataPushInterval;
}
public String getXmppServerName() {
return xmppServerName;
}
public void setXmppServerName(String xmppServerName) {
this.xmppServerName = xmppServerName;
}
}

@ -0,0 +1,127 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
public class AgentConstants {
public static final String DEVICE_TYPE = "virtual_firealarm";
public static final String LOG_APPENDER = "AGENT_LOG:: ";
public static final String PROPERTIES_FILE_PATH = "";
public static final int DEFAULT_RETRY_THREAD_INTERVAL = 5000; // time in millis
public static final String TOKEN_AUTHENTICATION_METHOD = "token";
/* ---------------------------------------------------------------------------------------
IoT-Server specific information
--------------------------------------------------------------------------------------- */
public static final String DEVICE_CONTROLLER_API_EP = "/virtual_firealarm/device";
public static final String DEVICE_SCEP_API_EP = "/virtual_firealarm_scep";
public static final String DEVICE_ENROLLMENT_API_EP = "/scep";
public static final String DEVICE_REGISTER_API_EP = "/register";
public static final String DEVICE_PUSH_TEMPERATURE_API_EP = "/temperature";
public static final String PUSH_DATA_PAYLOAD =
"{\"owner\":\"%s\",\"deviceId\":\"%s\",\"reply\":\"%s\",\"value\":\"%s\"}";
public static final String PUSH_SIMULATION_DATA_PAYLOAD =
"{\"owner\":\"%s\",\"deviceId\":\"%s\",\"reply\":\"%s\",\"value\":\"%s\",\"isSimulated\":\"%s\"," +
"\"duration\":\"%s\",\"frequency\":\"%s\"}";
public static final String DEVICE_DETAILS_PAGE_EP = "/devicemgt/device/%s?id=%s";
public static final String DEVICE_ANALYTICS_PAGE_URL =
"/devicemgt/device/virtual_firealarm/analytics?deviceId=%s&deviceName=%s";
/* ---------------------------------------------------------------------------------------
HTTP Connection specific information for communicating with IoT-Server
--------------------------------------------------------------------------------------- */
public static final String HTTP_POST = "POST";
public static final String HTTP_GET = "GET";
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String CONTENT_TYPE_HEADER = "Content-Type";
public static final String APPLICATION_JSON = "application/json";
public static final String X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
public static final String REGISTERED = "Registered";
public static final String NOT_REGISTERED = "Not-Registered";
public static final String REGISTRATION_FAILED = "Registration Failed";
public static final String RETRYING_TO_REGISTER = "Registration Failed. Re-trying..";
public static final String SERVER_NOT_RESPONDING = "Server not responding..";
/* ---------------------------------------------------------------------------------------
MQTT Connection specific information
--------------------------------------------------------------------------------------- */
public static final int DEFAULT_MQTT_RECONNECTION_INTERVAL = 2; // time in seconds
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
public static final String MQTT_SUBSCRIBE_TOPIC = "%s/" + DEVICE_TYPE + "/%s/operation/#";
public static final String MQTT_PUBLISH_TOPIC = "%s/" + DEVICE_TYPE + "/%s/temperature";
/* ---------------------------------------------------------------------------------------
Device/Agent specific properties to be read from the 'deviceConfig.properties' file
--------------------------------------------------------------------------------------- */
public static final String AGENT_PROPERTIES_FILE_NAME = "deviceConfig.properties";
public static final String TENANT_DOMAIN = "tenantDomain";
public static final String DEVICE_OWNER_PROPERTY = "owner";
public static final String DEVICE_ID_PROPERTY = "deviceId";
public static final String SERVER_JID_PROPERTY = "server-jid";
public static final String DEVICE_NAME_PROPERTY = "device-name";
public static final String SERVER_HTTPS_EP_PROPERTY = "https-ep";
public static final String SERVER_HTTP_EP_PROPERTY = "http-ep";
public static final String APIM_GATEWAY_EP_PROPERTY = "apim-ep";
public static final String MQTT_BROKER_EP_PROPERTY = "mqtt-ep";
public static final String XMPP_SERVER_EP_PROPERTY = "xmpp-ep";
public static final String XMPP_SERVER_NAME_PROPERTY = "xmpp-server-name";
public static final String API_APPLICATION_KEY = "application-key";
public static final String AUTH_TOKEN_PROPERTY = "auth-token";
public static final String REFRESH_TOKEN_PROPERTY = "refresh-token";
public static final String NETWORK_INTERFACE_PROPERTY = "network-interface";
public static final String PUSH_INTERVAL_PROPERTY = "push-interval";
/* ---------------------------------------------------------------------------------------
Default values for the Device/Agent specific configurations listed above
--------------------------------------------------------------------------------------- */
public static final String DEFAULT_NETWORK_INTERFACE = "en0";
public static final int DEFAULT_DATA_PUBLISH_INTERVAL = 15; // seconds
public static final String DEFAULT_PROTOCOL = "MQTT";
/* ---------------------------------------------------------------------------------------
Control Signal specific constants to match the request context
--------------------------------------------------------------------------------------- */
public static final String BULB_CONTROL = "BULB";
public static final String TEMPERATURE_CONTROL = "TEMPERATURE";
public static final String POLICY_SIGNAL = "POLICY";
public static final String HUMIDITY_CONTROL = "HUMIDITY";
public static final String CONTROL_ON = "ON";
public static final String CONTROL_OFF = "OFF";
public static final String AUDIO_FILE_NAME = "fireAlarmSound.mid";
/* ---------------------------------------------------------------------------------------
Communication protocol specific Strings
--------------------------------------------------------------------------------------- */
public static final String TCP_PREFIX = "tcp://";
public static final String HTTP_PREFIX = "http://";
public static final String HTTPS_PREFIX = "https://";
public static final String HTTP_PROTOCOL = "HTTP";
public static final String MQTT_PROTOCOL = "MQTT";
public static final String XMPP_PROTOCOL = "XMPP";
public static final String PROTOCOL_PROPERTY = "Protocol";
public static final String HOST_PROPERTY = "Host";
public static final String PORT_PROPERTY = "Port";
/* ---------------------------------------------------------------------------------------
Keystore specific strings for the device trustStore
--------------------------------------------------------------------------------------- */
public static final String DEVICE_KEYSTORE_TYPE = "JKS";
public static final String DEVICE_KEYSTORE = "virtual_firealarm.jks";
public static final String DEVICE_KEYSTORE_PASSWORD = "wso2@virtual_firealarm";
public static final String DEVICE_PRIVATE_KEY_ALIAS = "virtual_firealarm_key";
public static final String DEVICE_CERT_ALIAS = "virtual_firealarm_cert";
public static final String SERVER_CA_CERT_ALIAS = "ca_iotServer";
}

@ -0,0 +1,341 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.http.FireAlarmHTTPCommunicator;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.mqtt.FireAlarmMQTTCommunicator;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.xmpp.FireAlarmXMPPCommunicator;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.enrollment.EnrollmentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual.VirtualHardwareManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AgentManager {
private static final Log log = LogFactory.getLog(AgentManager.class);
private static AgentManager agentManager;
private String rootPath = "";
private boolean deviceReady = false;
private boolean isAlarmOn = false;
private String deviceName, agentStatus;
private int pushInterval; // seconds
private String prevProtocol, protocol;
private String networkInterface;
private List<String> interfaceList, protocolList;
private Map<String, TransportHandler> agentCommunicator;
private AgentConfiguration agentConfigs;
private String deviceIP;
private String enrollmentEP;
private String ipRegistrationEP;
private String pushDataAPIEP;
private AgentManager() {
}
public static AgentManager getInstance() {
if (agentManager == null) {
agentManager = new AgentManager();
}
return agentManager;
}
public void init() {
agentCommunicator = new HashMap<>();
// Read IoT-Server specific configurations from the 'deviceConfig.properties' file
try {
this.agentConfigs = AgentUtilOperations.readIoTServerConfigs();
} catch (AgentCoreOperationException e) {
log.error("Reading device configuration from configuration file failed:\n");
log.error(e);
System.exit(0);
}
// Initialise IoT-Server URL endpoints from the configuration read from file
AgentUtilOperations.initializeServerEndPoints();
// Set the hostNameVerifier to the APIM-Server IPAddress to enable HTTPS handshake
AgentUtilOperations.setHTTPSConfigurations();
String analyticsPageContext = String.format(AgentConstants.DEVICE_ANALYTICS_PAGE_URL,
agentConfigs.getDeviceId(),
agentConfigs.getDeviceName());
String controlPageContext = String.format(AgentConstants.DEVICE_DETAILS_PAGE_EP,
AgentConstants.DEVICE_TYPE,
agentConfigs.getDeviceId());
this.agentStatus = AgentConstants.NOT_REGISTERED;
this.deviceName = this.agentConfigs.getDeviceName();
this.pushInterval = this.agentConfigs.getDataPushInterval();
this.networkInterface = AgentConstants.DEFAULT_NETWORK_INTERFACE;
this.protocol = AgentConstants.DEFAULT_PROTOCOL;
this.prevProtocol = protocol;
Map<String, String> xmppIPPortMap;
try {
xmppIPPortMap = TransportUtils.getHostAndPort(agentConfigs.getXmppServerEndpoint());
String xmppServer = xmppIPPortMap.get("Host");
int xmppPort = Integer.parseInt(xmppIPPortMap.get("Port"));
TransportHandler xmppCommunicator = new FireAlarmXMPPCommunicator(xmppServer, xmppPort);
agentCommunicator.put(AgentConstants.XMPP_PROTOCOL, xmppCommunicator);
} catch (TransportHandlerException e) {
log.info("XMPP Endpoint String - " + agentConfigs.getXmppServerEndpoint() +
", provided in the configuration file is invalid. XMPP is not configured.");
}
String mqttTopic = String.format(AgentConstants.MQTT_SUBSCRIBE_TOPIC, agentConfigs.getTenantDomain(),
agentConfigs.getDeviceId());
// TransportHandler httpCommunicator = new FireAlarmHTTPCommunicator();
TransportHandler mqttCommunicator = new FireAlarmMQTTCommunicator(agentConfigs.getDeviceOwner(),
agentConfigs.getDeviceId(),
agentConfigs.getMqttBrokerEndpoint(),
mqttTopic);
// agentCommunicator.put(AgentConstants.HTTP_PROTOCOL, httpCommunicator);
agentCommunicator.put(AgentConstants.MQTT_PROTOCOL, mqttCommunicator);
try {
interfaceList = new ArrayList<>(TransportUtils.getInterfaceIPMap().keySet());
protocolList = new ArrayList<>(agentCommunicator.keySet());
} catch (TransportHandlerException e) {
log.error("An error occurred whilst retrieving all NetworkInterface-IP mappings");
}
//Initializing hardware at that point
//AgentManger.setDeviceReady() method should invoked from hardware after initialization
VirtualHardwareManager.getInstance().init();
//Wait till hardware get ready
while (!deviceReady) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
log.info(AgentConstants.LOG_APPENDER + "Sleep error in 'device ready-flag' checking thread");
}
}
// try {
// if (!EnrollmentManager.getInstance().isEnrolled()) {
// EnrollmentManager.getInstance().beginEnrollmentFlow();
// }
// } catch (AgentCoreOperationException e) {
// log.error("Device Enrollment Failed:\n");
// log.error(e);
// System.exit(0);
// }
//Start agent communication
agentCommunicator.get(protocol).connect();
}
private void switchCommunicator(String stopProtocol, String startProtocol) {
agentCommunicator.get(stopProtocol).disconnect();
while (agentCommunicator.get(stopProtocol).isConnected()) {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
log.info(AgentConstants.LOG_APPENDER +
"Sleep error in 'Switch-Communicator' Thread's shutdown wait.");
}
}
agentCommunicator.get(startProtocol).connect();
}
public void setInterface(int interfaceId) {
if (interfaceId != -1) {
String newInterface = interfaceList.get(interfaceId);
if (!newInterface.equals(networkInterface)) {
networkInterface = newInterface;
if (protocol.equals(AgentConstants.HTTP_PROTOCOL) && !protocol.equals(
prevProtocol)) {
switchCommunicator(prevProtocol, protocol);
}
}
}
}
public void setProtocol(int protocolId) {
if (protocolId != -1) {
String newProtocol = protocolList.get(protocolId);
if (!protocol.equals(newProtocol)) {
prevProtocol = protocol;
protocol = newProtocol;
switchCommunicator(prevProtocol, protocol);
}
}
}
public void changeAlarmStatus(boolean isOn) {
VirtualHardwareManager.getInstance().changeAlarmStatus(isOn);
isAlarmOn = isOn;
}
public void updateAgentStatus(String status) {
this.agentStatus = status;
}
/*------------------------------------------------------------------------------------------*/
/* Getter and Setter Methods for the private variables */
/*------------------------------------------------------------------------------------------*/
public void setRootPath(String rootPath) {
this.rootPath = rootPath;
}
public String getRootPath() {
return rootPath;
}
public void setDeviceReady(boolean deviceReady) {
this.deviceReady = deviceReady;
}
public AgentConfiguration getAgentConfigs() {
return agentConfigs;
}
public String getDeviceIP() {
return deviceIP;
}
public void setDeviceIP(String deviceIP) {
this.deviceIP = deviceIP;
}
public String getEnrollmentEP() {
return enrollmentEP;
}
public void setEnrollmentEP(String enrollmentEP) {
this.enrollmentEP = enrollmentEP;
}
public String getIpRegistrationEP() {
return ipRegistrationEP;
}
public void setIpRegistrationEP(String ipRegistrationEP) {
this.ipRegistrationEP = ipRegistrationEP;
}
public String getPushDataAPIEP() {
return pushDataAPIEP;
}
public void setPushDataAPIEP(String pushDataAPIEP) {
this.pushDataAPIEP = pushDataAPIEP;
}
public String getDeviceName() {
return deviceName;
}
public String getNetworkInterface() {
return networkInterface;
}
public String getAgentStatus() {
return agentStatus;
}
public int getPushInterval() {
return pushInterval;
}
public void setPushInterval(int pushInterval) {
this.pushInterval = pushInterval;
TransportHandler transportHandler = agentCommunicator.get(protocol);
switch (protocol) {
case AgentConstants.HTTP_PROTOCOL:
((FireAlarmHTTPCommunicator) transportHandler).getDataPushServiceHandler()
.cancel(true);
break;
case AgentConstants.MQTT_PROTOCOL:
((FireAlarmMQTTCommunicator) transportHandler).getDataPushServiceHandler()
.cancel(true);
break;
case AgentConstants.XMPP_PROTOCOL:
((FireAlarmXMPPCommunicator) transportHandler).getDataPushServiceHandler()
.cancel(true);
break;
default:
log.warn("Unknown protocol " + protocol);
}
transportHandler.publishDeviceData();
if (log.isDebugEnabled()) {
log.debug("The Data Publish Interval was changed to: " + pushInterval);
}
}
public List<String> getInterfaceList() {
return interfaceList;
}
public List<String> getProtocolList() {
return protocolList;
}
/**
* Get temperature reading from device
*
* @return Temperature
*/
public int getTemperature() {
return VirtualHardwareManager.getInstance().getTemperature();
}
/**
* Get humidity reading from device
*
* @return Humidity
*/
public int getHumidity() {
return VirtualHardwareManager.getInstance().getHumidity();
}
public boolean isAlarmOn() {
return isAlarmOn;
}
}

@ -0,0 +1,439 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.http.HttpStatus;
import org.json.JSONObject;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.enrollment.EnrollmentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.CommunicationUtils;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Properties;
/**
* This class contains all the core operations of the FireAlarm agent that are common to both
* Virtual and Real Scenarios. These operations include, connecting to and subscribing to an MQTT
* queue and to a XMPP Server. Pushing temperature data to the IoT-Server at timely intervals.
* Reading device specific configuration from a configs file etc....
*/
public class AgentUtilOperations {
private static final Log log = LogFactory.getLog(AgentUtilOperations.class);
private static final String JSON_MESSAGE_KEY = "Msg";
private static final String JSON_SIGNATURE_KEY = "Sig";
private static final String JSON_SERIAL_KEY = "SerialNumber";
/**
* This method reads the agent specific configurations for the device from the
* "deviceConfigs.properties" file found at /repository/conf folder.
* If the properties file is not found in the specified path, then the configuration values
* are set to the default ones in the 'AgentConstants' class.
*
* @return an object of type 'AgentConfiguration' which contains all the necessary
* configuration attributes
*/
public static AgentConfiguration readIoTServerConfigs() throws AgentCoreOperationException {
AgentManager agentManager = AgentManager.getInstance();
AgentConfiguration iotServerConfigs = new AgentConfiguration();
Properties properties = new Properties();
InputStream propertiesInputStream = null;
String propertiesFileName = AgentConstants.AGENT_PROPERTIES_FILE_NAME;
String rootPath = "";
try {
ClassLoader loader = AgentUtilOperations.class.getClassLoader();
URL path = loader.getResource(propertiesFileName);
if (path != null) {
log.info(AgentConstants.LOG_APPENDER + path);
rootPath = path.getPath().replace("wso2-firealarm-virtual-agent.jar!/deviceConfig.properties", "")
.replace("jar:", "").replace("file:", "");
rootPath = URLDecoder.decode(rootPath, StandardCharsets.UTF_8.toString());
agentManager.setRootPath(rootPath);
String deviceConfigFilePath = rootPath + AgentConstants.AGENT_PROPERTIES_FILE_NAME;
propertiesInputStream = new FileInputStream(deviceConfigFilePath);
//load a properties file from class path, inside static method
properties.load(propertiesInputStream);
iotServerConfigs.setTenantDomain(properties.getProperty(
AgentConstants.TENANT_DOMAIN));
iotServerConfigs.setDeviceOwner(properties.getProperty(
AgentConstants.DEVICE_OWNER_PROPERTY));
iotServerConfigs.setDeviceId(properties.getProperty(
AgentConstants.DEVICE_ID_PROPERTY));
iotServerConfigs.setServerJID(properties.getProperty(
AgentConstants.SERVER_JID_PROPERTY));
iotServerConfigs.setDeviceName(properties.getProperty(
AgentConstants.DEVICE_NAME_PROPERTY));
iotServerConfigs.setHTTPS_ServerEndpoint(properties.getProperty(
AgentConstants.SERVER_HTTPS_EP_PROPERTY));
iotServerConfigs.setHTTP_ServerEndpoint(properties.getProperty(
AgentConstants.SERVER_HTTP_EP_PROPERTY));
iotServerConfigs.setApimGatewayEndpoint(properties.getProperty(
AgentConstants.APIM_GATEWAY_EP_PROPERTY));
iotServerConfigs.setMqttBrokerEndpoint(properties.getProperty(
AgentConstants.MQTT_BROKER_EP_PROPERTY));
iotServerConfigs.setXmppServerEndpoint(properties.getProperty(
AgentConstants.XMPP_SERVER_EP_PROPERTY));
iotServerConfigs.setXmppServerName(properties.getProperty(
AgentConstants.XMPP_SERVER_NAME_PROPERTY));
iotServerConfigs.setApiApplicationKey(properties.getProperty(
AgentConstants.API_APPLICATION_KEY));
iotServerConfigs.setAuthToken(properties.getProperty(
AgentConstants.AUTH_TOKEN_PROPERTY));
iotServerConfigs.setRefreshToken(properties.getProperty(
AgentConstants.REFRESH_TOKEN_PROPERTY));
iotServerConfigs.setDataPushInterval(Integer.parseInt(properties.getProperty(
AgentConstants.PUSH_INTERVAL_PROPERTY)));
log.info(AgentConstants.LOG_APPENDER + "Tenant Domain: " +
iotServerConfigs.getTenantDomain());
log.info(AgentConstants.LOG_APPENDER + "Device Owner: " +
iotServerConfigs.getDeviceOwner());
log.info(AgentConstants.LOG_APPENDER + "Device ID: " +
iotServerConfigs.getDeviceId());
log.info(AgentConstants.LOG_APPENDER + "Device Name: " +
iotServerConfigs.getDeviceName());
log.info(AgentConstants.LOG_APPENDER + "IoT Server HTTPS EndPoint: " +
iotServerConfigs.getHTTPS_ServerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "IoT Server HTTP EndPoint: " +
iotServerConfigs.getHTTP_ServerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "API-Manager Gateway EndPoint: " +
iotServerConfigs.getApimGatewayEndpoint());
log.info(AgentConstants.LOG_APPENDER + "MQTT Broker EndPoint: " +
iotServerConfigs.getMqttBrokerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "XMPP Server EndPoint: " +
iotServerConfigs.getXmppServerEndpoint());
log.info(AgentConstants.LOG_APPENDER + "Base64Encoded API Application Key: " +
iotServerConfigs.getApiApplicationKey());
log.info(AgentConstants.LOG_APPENDER + "Authentication Token: " +
iotServerConfigs.getAuthToken());
log.info(AgentConstants.LOG_APPENDER + "Refresh Token: " +
iotServerConfigs.getRefreshToken());
log.info(AgentConstants.LOG_APPENDER + "Data Push Interval: " +
iotServerConfigs.getDataPushInterval());
log.info(AgentConstants.LOG_APPENDER + "XMPP Server Name: " +
iotServerConfigs.getXmppServerName());
} else {
throw new AgentCoreOperationException(
"Failed to load path of resource [" + propertiesFileName + "] from this classpath.");
}
} catch (FileNotFoundException ex) {
String errorMsg = "[" + propertiesFileName + "] file not found at: " + rootPath;
log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg);
} catch (IOException ex) {
String errorMsg = "Error occurred whilst trying to fetch [" + propertiesFileName + "] from: " +
AgentConstants.PROPERTIES_FILE_PATH;
log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg);
} finally {
if (propertiesInputStream != null) {
try {
propertiesInputStream.close();
} catch (IOException e) {
log.error(AgentConstants.LOG_APPENDER +
"Error occurred whilst trying to close InputStream resource used to read the '" +
propertiesFileName + "' file");
}
}
}
return iotServerConfigs;
}
/**
* This method constructs the URLs for each of the API Endpoints called by the device agent
* Ex: Register API, Push-Data API
*/
public static void initializeServerEndPoints() {
AgentManager agentManager = AgentManager.getInstance();
String serverSecureEndpoint = agentManager.getAgentConfigs().getHTTPS_ServerEndpoint();
String serverUnSecureEndpoint = agentManager.getAgentConfigs().getHTTP_ServerEndpoint();
String backEndContext =AgentConstants.DEVICE_CONTROLLER_API_EP;
String scepBackEndContext = AgentConstants.DEVICE_SCEP_API_EP;
String deviceControllerAPIEndpoint = serverSecureEndpoint + backEndContext;
String deviceEnrollmentEndpoint =
serverUnSecureEndpoint + scepBackEndContext + AgentConstants.DEVICE_ENROLLMENT_API_EP;
agentManager.setEnrollmentEP(deviceEnrollmentEndpoint);
String registerEndpointURL =
deviceControllerAPIEndpoint + AgentConstants.DEVICE_REGISTER_API_EP;
agentManager.setIpRegistrationEP(registerEndpointURL);
String pushDataEndPointURL =
deviceControllerAPIEndpoint + AgentConstants.DEVICE_PUSH_TEMPERATURE_API_EP;
agentManager.setPushDataAPIEP(pushDataEndPointURL);
log.info(AgentConstants.LOG_APPENDER + "IoT Server's Device Controller API Endpoint: " +
deviceControllerAPIEndpoint);
log.info(AgentConstants.LOG_APPENDER + "Device Enrollment EndPoint: " +
registerEndpointURL);
log.info(AgentConstants.LOG_APPENDER + "DeviceIP Registration EndPoint: " +
registerEndpointURL);
log.info(AgentConstants.LOG_APPENDER + "Push-Data API EndPoint: " + pushDataEndPointURL);
}
public static void setHTTPSConfigurations() {
String apimEndpoint = AgentManager.getInstance().getAgentConfigs().getApimGatewayEndpoint();
System.setProperty("javax.net.ssl.trustStore", AgentConstants.DEVICE_KEYSTORE);
System.setProperty("javax.net.ssl.trustStorePassword", AgentConstants.DEVICE_KEYSTORE_PASSWORD);
try {
final String apimHost = TransportUtils.getHostAndPort(apimEndpoint).get(AgentConstants.HOST_PROPERTY);
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return hostname.equals(apimHost);
}
});
} catch (TransportHandlerException e) {
log.error(AgentConstants.LOG_APPENDER +
"Failed to set HTTPS HostNameVerifier to the APIMServer-Host using the APIM-Endpoint " +
"string [" + apimEndpoint + "].");
log.error(AgentConstants.LOG_APPENDER + e);
}
}
public static String prepareSecurePayLoad(String message) throws AgentCoreOperationException {
if (EnrollmentManager.getInstance().isEnrolled()) {
PrivateKey devicePrivateKey = EnrollmentManager.getInstance().getPrivateKey();
String encodedMessage = Base64.encodeBase64String(message.getBytes());
String signedPayload;
try {
signedPayload = CommunicationUtils.signMessage(encodedMessage, devicePrivateKey);
} catch (TransportHandlerException e) {
String errorMsg = "Error occurred whilst trying to sign encrypted message of: [" + message + "]";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
JSONObject jsonPayload = new JSONObject();
jsonPayload.put(JSON_MESSAGE_KEY, encodedMessage);
jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload);
//below statements are temporary fix.
jsonPayload.put(JSON_SERIAL_KEY, EnrollmentManager.getInstance().getSCEPCertificate().getSerialNumber());
return jsonPayload.toString();
} else {
return message;
}
}
public static String extractMessageFromPayload(String message) throws AgentCoreOperationException {
if (EnrollmentManager.getInstance().isEnrolled()) {
String actualMessage;
PublicKey serverPublicKey = EnrollmentManager.getInstance().getServerPublicKey();
JSONObject jsonPayload = new JSONObject(message);
Object encodedMessage = jsonPayload.get(JSON_MESSAGE_KEY);
Object signedPayload = jsonPayload.get(JSON_SIGNATURE_KEY);
boolean verification;
if (encodedMessage != null && signedPayload != null) {
try {
verification = CommunicationUtils.verifySignature(
encodedMessage.toString(), signedPayload.toString(), serverPublicKey);
} catch (TransportHandlerException e) {
String errorMsg =
"Error occurred whilst trying to verify signature on received message: [" + message + "]";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
} else {
String errorMsg = "The received message is in an INVALID format. " +
"Need to be JSON - {\"Msg\":\"<ENCRYPTED_MSG>\", \"Sig\":\"<SIGNED_MSG>\"}.";
throw new AgentCoreOperationException(errorMsg);
}
if (verification) {
actualMessage = new String(Base64.decodeBase64(encodedMessage.toString()), StandardCharsets.UTF_8);
} else {
String errorMsg = "Could not verify payload signature. The message was not signed by a valid client";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg);
}
return actualMessage;
} else {
return message;
}
}
public static String getAuthenticationMethod() {
String authMethod = "token";
switch (authMethod) {
case AgentConstants.TOKEN_AUTHENTICATION_METHOD:
return AgentConstants.TOKEN_AUTHENTICATION_METHOD;
default:
return "";
}
}
public static void refreshOAuthToken() throws AgentCoreOperationException {
AgentManager agentManager = AgentManager.getInstance();
String tokenEndpoint = agentManager.getAgentConfigs().getApimGatewayEndpoint();
tokenEndpoint = tokenEndpoint + APIManagerTokenUtils.TOKEN_ENDPOINT;
HttpURLConnection httpConnection = null;
BufferedReader connectionBuffer = null;
String requestPayload;
String dataFromBuffer;
StringBuilder responseMessage = new StringBuilder();
try {
String refreshToken = agentManager.getAgentConfigs().getRefreshToken();
String applicationScope = "device_type_" + AgentConstants.DEVICE_TYPE +
" device_" + agentManager.getAgentConfigs().getDeviceId();
requestPayload = APIManagerTokenUtils.GRANT_TYPE + "=" + APIManagerTokenUtils.REFRESH_TOKEN + "&" +
APIManagerTokenUtils.REFRESH_TOKEN + "=" + refreshToken + "&" +
APIManagerTokenUtils.SCOPE + "=" + applicationScope;
httpConnection = TransportUtils.getHttpConnection(tokenEndpoint);
httpConnection.setRequestMethod(AgentConstants.HTTP_POST);
httpConnection.setRequestProperty(AgentConstants.AUTHORIZATION_HEADER,
"Basic " + agentManager.getAgentConfigs().getApiApplicationKey());
httpConnection.setRequestProperty(AgentConstants.CONTENT_TYPE_HEADER, AgentConstants.X_WWW_FORM_URLENCODED);
httpConnection.setDoOutput(true);
DataOutputStream dataOutPutWriter = new DataOutputStream(httpConnection.getOutputStream());
dataOutPutWriter.writeBytes(requestPayload);
dataOutPutWriter.flush();
dataOutPutWriter.close();
log.info(AgentConstants.LOG_APPENDER + "Request to refresh OAuth token was sent to [" +
httpConnection.getURL() + "] with payload [" + requestPayload + "].");
log.info(AgentConstants.LOG_APPENDER + "Response [" + httpConnection.getResponseCode() + ":" +
httpConnection.getResponseMessage() + "] was received for token refresh attempt.");
if (httpConnection.getResponseCode() == HttpStatus.OK_200) {
connectionBuffer = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
while ((dataFromBuffer = connectionBuffer.readLine()) != null) {
responseMessage.append(dataFromBuffer);
}
log.info(AgentConstants.LOG_APPENDER +
"Response " + responseMessage + " was received for the token refresh call.");
updateExistingTokens(responseMessage.toString());
} else if (httpConnection.getResponseCode() == HttpStatus.BAD_REQUEST_400) {
log.error(AgentConstants.LOG_APPENDER +
"Token refresh call returned with a [400 Bad Request].\nThe refresh-token has " +
"probably expired.\nPlease contact System-Admin to get a valid refresh-token.");
} else {
log.warn(AgentConstants.LOG_APPENDER + "There was an issue with refreshing the Access Token.");
}
} catch (TransportHandlerException e) {
throw new AgentCoreOperationException(e);
} catch (ProtocolException e) {
String errorMsg = "Protocol specific error occurred when trying to set method to " +
AgentConstants.HTTP_POST + " for endpoint at: " + tokenEndpoint;
log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
} catch (IOException e) {
String errorMsg = "An IO error occurred whilst trying to get the response code from: " + tokenEndpoint +
" for a HTTP " + AgentConstants.HTTP_POST + " call.";
log.error(AgentConstants.LOG_APPENDER + errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
} finally {
if (connectionBuffer != null) {
try {
connectionBuffer.close();
} catch (IOException e) {
log.error(AgentConstants.LOG_APPENDER +
"Error encounter whilst attempting to close buffer to connection at: " +
tokenEndpoint);
}
}
if (httpConnection != null) {
httpConnection.disconnect();
}
}
}
private static void updateExistingTokens(String responseFromTokenEP) throws AgentCoreOperationException {
JSONObject jsonTokenObject = new JSONObject(responseFromTokenEP);
String newAccessToken = jsonTokenObject.get(APIManagerTokenUtils.ACCESS_TOKEN).toString();
String newRefreshToken = jsonTokenObject.get(APIManagerTokenUtils.REFRESH_TOKEN).toString();
if (newAccessToken == null || newRefreshToken == null) {
String msg =
"Neither Access-Token nor Refresh-Token was found in the response [" + responseFromTokenEP + "].";
log.error(AgentConstants.LOG_APPENDER + msg);
throw new AgentCoreOperationException(msg);
}
AgentManager.getInstance().getAgentConfigs().setAuthToken(newAccessToken);
AgentManager.getInstance().getAgentConfigs().setRefreshToken(newRefreshToken);
String deviceConfigFilePath =
AgentManager.getInstance().getRootPath() + AgentConstants.AGENT_PROPERTIES_FILE_NAME;
try {
PropertiesConfiguration propertyFileConfiguration = new PropertiesConfiguration(deviceConfigFilePath);
propertyFileConfiguration.setProperty(AgentConstants.AUTH_TOKEN_PROPERTY, newAccessToken);
propertyFileConfiguration.setProperty(AgentConstants.REFRESH_TOKEN_PROPERTY, newRefreshToken);
propertyFileConfiguration.save();
} catch (ConfigurationException e) {
String msg = "Error occurred whilst trying to update the [" + AgentConstants.AGENT_PROPERTIES_FILE_NAME +
"] at: " + deviceConfigFilePath + " will the new tokens.";
log.error(AgentConstants.LOG_APPENDER + msg);
throw new AgentCoreOperationException(msg);
}
}
private class APIManagerTokenUtils {
public static final String TOKEN_ENDPOINT = "/token";
public static final String GRANT_TYPE = "grant_type";
public static final String ACCESS_TOKEN = "access_token";
public static final String REFRESH_TOKEN = "refresh_token";
public static final String SCOPE = "scope";
}
}

@ -0,0 +1,549 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.enrollment;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
import org.jscep.client.Client;
import org.jscep.client.ClientException;
import org.jscep.client.EnrollmentResponse;
import org.jscep.client.verification.CertificateVerifier;
import org.jscep.client.verification.OptimisticCertificateVerifier;
import org.jscep.transaction.TransactionException;
import org.jscep.transport.response.Capabilities;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
import sun.security.x509.X509CertImpl;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
/**
* This class controls the entire SCEP enrolment process of the client. It is a singleton for any single client which
* has the agent code running in it. The main functionality of this class includes generating a Private-Public Key
* Pair for the enrollment flow, creating the Certificate-Sign-Request using the generated Public-Key to send to the
* SEP server, Contacting the SCEP server to receive the Signed Certificate and requesting for the server's public
* key for encrypting the payloads.
* The provider for all Cryptographic functions used in this class are "BouncyCastle" and the Asymmetric-Key pair
* algorithm used is "RSA" with a key size of 2048. The signature algorithm used is "SHA1withRSA".
* This class also holds the "SCEPUrl" (Server Url read from the configs file), the Private-Public Keys of the
* client, Signed SCEP certificate and the server's public certificate.
*/
//TODO: Need to save cert and keys to file after initial enrollment...
public class EnrollmentManager {
private static final Log log = LogFactory.getLog(EnrollmentManager.class);
private static EnrollmentManager enrollmentManager;
private static final String KEY_PAIR_ALGORITHM = "RSA";
private static final String PROVIDER = "BC";
private static final String SIGNATURE_ALG = "SHA1withRSA";
private static final String CERT_IS_CA_EXTENSION = "is_ca";
private static final int KEY_SIZE = 2048;
// Seed to our PRNG. Make sure this is initialised randomly, NOT LIKE THIS
private static final byte[] SEED = ")(*&^%$#@!".getBytes();
private static final int CERT_VALIDITY = 730;
// URL of our SCEP server
private String SCEPUrl;
private PrivateKey privateKey;
private PublicKey publicKey;
private PublicKey serverPublicKey;
private X509Certificate SCEPCertificate;
private boolean isEnrolled = false;
/**
* Constructor of the EnrollmentManager. Initializes the SCEPUrl as read from the configuration file by the
* AgentManager.
*/
private EnrollmentManager() {
this.SCEPUrl = AgentManager.getInstance().getEnrollmentEP();
//setEnrollmentStatus();
}
/**
* Method to return the current singleton instance of the EnrollmentManager.
*
* @return the current singleton instance if available and if not initializes a new instance and returns it.
*/
public static EnrollmentManager getInstance() {
if (enrollmentManager == null) {
enrollmentManager = new EnrollmentManager();
}
return enrollmentManager;
}
public void setEnrollmentStatus() {
KeyStore keyStore;
try {
keyStore = KeyStore.getInstance(AgentConstants.DEVICE_KEYSTORE_TYPE);
this.isEnrolled = (keyStore.containsAlias(AgentConstants.DEVICE_CERT_ALIAS) &&
keyStore.containsAlias(AgentConstants.DEVICE_PRIVATE_KEY_ALIAS) &&
keyStore.containsAlias(AgentConstants.SERVER_CA_CERT_ALIAS));
} catch (KeyStoreException e) {
log.error(AgentConstants.LOG_APPENDER + "An error occurred whilst accessing the device KeyStore '" +
AgentConstants.DEVICE_KEYSTORE + "' with keystore type [" +
AgentConstants.DEVICE_KEYSTORE_TYPE + "] to ensure enrollment status.");
log.error(AgentConstants.LOG_APPENDER + e);
log.warn(AgentConstants.LOG_APPENDER + "Device will be re-enrolled.");
return;
}
try {
if (this.isEnrolled) {
this.SCEPCertificate = (X509Certificate) keyStore.getCertificate(AgentConstants.DEVICE_CERT_ALIAS);
this.privateKey = (PrivateKey) keyStore.getKey(AgentConstants.DEVICE_PRIVATE_KEY_ALIAS,
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
this.publicKey = SCEPCertificate.getPublicKey();
X509Certificate serverCACert = (X509Certificate) keyStore.getCertificate(
AgentConstants.SERVER_CA_CERT_ALIAS);
this.serverPublicKey = serverCACert.getPublicKey();
log.info(AgentConstants.LOG_APPENDER +
"Device has already been enrolled. Hence, loaded certificate information from device" +
" trust-store.");
}
} catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e) {
log.error(AgentConstants.LOG_APPENDER + "An error occurred whilst accessing the device KeyStore '" +
AgentConstants.DEVICE_KEYSTORE + "' to ensure enrollment status.");
log.error(AgentConstants.LOG_APPENDER + e);
log.warn(AgentConstants.LOG_APPENDER + "Device will be re-enrolled.");
this.isEnrolled = false;
}
}
/**
* Method to control the entire enrollment flow. This method calls the method to create the Private-Public Key
* Pair, calls the specific method to generate the Certificate-Sign-Request, creates a one time self signed
* certificate to present to the SCEP server with the initial CSR, calls the specific method to connect to the
* SCEP Server and to get the SCEP Certificate and also calls the method that requests the SCEP Server for its
* PublicKey for future payload encryption.
*
* @throws AgentCoreOperationException if the private method generateCertSignRequest() fails with an error or if
* there is an error creating a self-sign certificate to present to the
* server (whilst trying to get the CSR signed)
*/
public void beginEnrollmentFlow() throws AgentCoreOperationException {
Security.addProvider(new BouncyCastleProvider());
KeyPair keyPair = generateKeyPair();
this.privateKey = keyPair.getPrivate();
this.publicKey = keyPair.getPublic();
if (log.isDebugEnabled()) {
log.info(AgentConstants.LOG_APPENDER + "DevicePrivateKey:\n[\n" + privateKey + "\n]\n");
log.info(AgentConstants.LOG_APPENDER + "DevicePublicKey:\n[\n" + publicKey + "\n]\n");
}
PKCS10CertificationRequest certSignRequest = generateCertSignRequest();
/**
* -----------------------------------------------------------------------------------------------
* Generate an ephemeral self-signed certificate. This is needed to present to the CA in the SCEP request.
* In the future, add proper EKU and attributes in the request. The CA does NOT have to honour any of this.
* -----------------------------------------------------------------------------------------------
*/
X500Name issuer = new X500Name("CN=Temporary Issuer");
BigInteger serial = new BigInteger(32, new SecureRandom());
Date fromDate = new Date();
Date toDate = new Date(System.currentTimeMillis() + (CERT_VALIDITY * 86400000L));
// Build the self-signed cert using BC, sign it with our private key (self-signed)
X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(issuer, serial, fromDate, toDate,
certSignRequest.getSubject(),
certSignRequest.getSubjectPublicKeyInfo());
ContentSigner sigGen;
X509Certificate tmpCert;
try {
sigGen = new JcaContentSignerBuilder(SIGNATURE_ALG).setProvider(PROVIDER).build(keyPair.getPrivate());
tmpCert = new JcaX509CertificateConverter().setProvider(PROVIDER).getCertificate(certBuilder.build(sigGen));
} catch (OperatorCreationException e) {
String errorMsg = "Error occurred whilst creating a ContentSigner for the Temp-Self-Signed Certificate.";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
} catch (CertificateException e) {
String errorMsg = "Error occurred whilst trying to create Temp-Self-Signed Certificate.";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
/**
* -----------------------------------------------------------------------------------------------
*/
this.SCEPCertificate = getSignedCertificateFromServer(tmpCert, certSignRequest);
this.serverPublicKey = initPublicKeyOfServer();
storeCertificateToStore(AgentConstants.DEVICE_CERT_ALIAS, SCEPCertificate);
storeKeyToKeyStore(AgentConstants.DEVICE_PRIVATE_KEY_ALIAS, this.privateKey, SCEPCertificate);
if (log.isDebugEnabled()) {
log.info(AgentConstants.LOG_APPENDER +
"SCEPCertificate, DevicePrivateKey, ServerPublicKey was saved to device keystore [" +
AgentConstants.DEVICE_KEYSTORE + "]");
log.info(AgentConstants.LOG_APPENDER + "TemporaryCertPublicKey:\n[\n" + tmpCert.getPublicKey() + "\n]\n");
log.info(AgentConstants.LOG_APPENDER + "ServerPublicKey:\n[\n" + serverPublicKey + "\n]\n");
}
}
private void storeCertificateToStore(String alias, Certificate certificate) {
KeyStore keyStore;
try {
keyStore = KeyStore.getInstance(AgentConstants.DEVICE_KEYSTORE_TYPE);
keyStore.setCertificateEntry(alias, certificate);
keyStore.store(new FileOutputStream(AgentConstants.DEVICE_KEYSTORE),
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
log.error(AgentConstants.LOG_APPENDER +
"An error occurred whilst trying to store the Certificate received from the SCEP " +
"Enrollment.");
log.error(AgentConstants.LOG_APPENDER + e);
log.warn(AgentConstants.LOG_APPENDER +
"SCEP Certificate was not stored in the keystore; " +
"Hence the device will be re-enrolled during next restart.");
}
}
private void storeKeyToKeyStore(String alias, Key cryptoKey, Certificate certInCertChain) {
KeyStore keyStore;
try {
keyStore = KeyStore.getInstance(AgentConstants.DEVICE_KEYSTORE_TYPE);
Certificate[] certChain = new Certificate[1];
certChain[0] = certInCertChain;
keyStore.setKeyEntry(alias, cryptoKey, AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray(), certChain);
keyStore.store(new FileOutputStream(AgentConstants.DEVICE_KEYSTORE),
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
log.error(AgentConstants.LOG_APPENDER +
"An error occurred whilst trying to store the key with alias " +
"[" + alias + "] in the device keystore.");
log.error(AgentConstants.LOG_APPENDER + e);
log.warn(AgentConstants.LOG_APPENDER +
"Key [" + alias + "] was not stored in the keystore; " +
"Hence the device will be re-enrolled during next restart.");
}
}
/**
* This method creates the Public-Private Key pair for the current client.
*
* @return the generated KeyPair object
* @throws AgentCoreOperationException when the given Security Provider does not exist or the Algorithmn used to
* generate the key pair is invalid.
*/
private KeyPair generateKeyPair() throws AgentCoreOperationException {
// Generate key pair
KeyPairGenerator keyPairGenerator;
try {
keyPairGenerator = KeyPairGenerator.getInstance(KEY_PAIR_ALGORITHM, PROVIDER);
keyPairGenerator.initialize(KEY_SIZE, new SecureRandom(SEED));
} catch (NoSuchAlgorithmException e) {
String errorMsg = "Algorithm [" + KEY_PAIR_ALGORITHM + "] provided for KeyPairGenerator is invalid.";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
} catch (NoSuchProviderException e) {
String errorMsg = "Provider [" + PROVIDER + "] provided for KeyPairGenerator does not exist.";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
return keyPairGenerator.genKeyPair();
}
/**
* This method creates the PKCS10 Certificate Sign Request which is to be sent to the SCEP Server using the
* generated PublicKey of the client. The certificate parameters used here are the ones from the AgentManager
* which are the values read from the configurations file.
*
* @return the PKCS10CertificationRequest object created using the client specific configs and the generated
* PublicKey
* @throws AgentCoreOperationException if an error occurs when creating a content signer to sign the CSR.
*/
private PKCS10CertificationRequest generateCertSignRequest() throws AgentCoreOperationException {
// Build the CN for the cert that's being requested.
X500NameBuilder nameBld = new X500NameBuilder(BCStyle.INSTANCE);
nameBld.addRDN(BCStyle.CN, AgentManager.getInstance().getAgentConfigs().getTenantDomain());
nameBld.addRDN(BCStyle.O, AgentManager.getInstance().getAgentConfigs().getDeviceOwner());
nameBld.addRDN(BCStyle.OU, AgentManager.getInstance().getAgentConfigs().getDeviceOwner());
nameBld.addRDN(BCStyle.UNIQUE_IDENTIFIER, AgentManager.getInstance().getAgentConfigs().getDeviceId());
nameBld.addRDN(BCStyle.SERIALNUMBER, AgentManager.getInstance().getAgentConfigs().getDeviceId());
X500Name principal = nameBld.build();
JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder(SIGNATURE_ALG).setProvider(PROVIDER);
ContentSigner contentSigner;
try {
contentSigner = contentSignerBuilder.build(this.privateKey);
} catch (OperatorCreationException e) {
String errorMsg = "Could not create content signer with private key.";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
// Generate the certificate signing request (csr = PKCS10)
PKCS10CertificationRequestBuilder reqBuilder = new JcaPKCS10CertificationRequestBuilder(principal,
this.publicKey);
return reqBuilder.build(contentSigner);
}
/**
* This method connects to the SCEP Server to fetch the signed SCEP Certificate.
*
* @param tempCert the temporary self-signed certificate of the client required for the initial CSR
* request against the SCEP Server.
* @param certSignRequest the PKCS10 Certificate-Sign-Request that is to be sent to the SCEP Server.
* @return the SCEP-Certificate for the client signed by the SCEP-Server.
* @throws AgentCoreOperationException if the SCEPUrl is invalid or if the flow of sending the CSR and getting
* the signed certificate fails or if the signed certificate cannot be
* retrieved from the reply from the server.
*/
private X509Certificate getSignedCertificateFromServer(X509Certificate tempCert,
PKCS10CertificationRequest certSignRequest)
throws AgentCoreOperationException {
X509Certificate signedSCEPCertificate = null;
URL url;
EnrollmentResponse enrolResponse;
CertStore certStore;
try {
// The URL where we are going to request our cert from
url = new URL(this.SCEPUrl);
/* // This is called when we get the certificate for our CSR signed by CA
// Implement this handler to check the CA cert in prod. We can do cert pinning here
CallbackHandler cb = new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated
methods, choose Tools | Templates.
}
};*/
// Implement verification of the CA cert. VERIFY the CA
CertificateVerifier ocv = new OptimisticCertificateVerifier();
// Instantiate our SCEP client
Client scepClient = new Client(url, ocv);
// Submit our cert for signing. SCEP server should allow the client to specify
// the SCEP CA to issue the request against, if there are multiple CAs
enrolResponse = scepClient.enrol(tempCert, this.privateKey, certSignRequest);
// Verify we got what we want, and just print out the cert.
certStore = enrolResponse.getCertStore();
for (Certificate x509Certificate : certStore.getCertificates(null)) {
if (log.isDebugEnabled()) {
log.debug(x509Certificate.toString());
}
signedSCEPCertificate = (X509Certificate) x509Certificate;
}
} catch (MalformedURLException ex) {
String errorMsg = "Could not create valid URL from given SCEP URI: " + SCEPUrl;
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, ex);
} catch (TransactionException | ClientException e) {
String errorMsg = "Enrollment process to SCEP Server at: " + SCEPUrl + " failed.";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
} catch (CertStoreException e) {
String errorMsg = "Could not retrieve [Signed-Certificate] from the response message from SCEP-Server.";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
return signedSCEPCertificate;
}
/**
* Gets the Public Key of the SCEP-Server and initializes it for later use. This method contacts the SCEP Server
* and fetches its CA Cert and extracts the Public Key of the server from the received reply.
*
* @return the public key of the SCEP Server which is to be used to encrypt pyloads.
* @throws AgentCoreOperationException if the SCEPUrl is invalid or if the flow of sending the CSR and getting
* the signed certificate fails or if the signed certificate cannot be
* retrieved from the reply from the server.
*/
private PublicKey initPublicKeyOfServer() throws AgentCoreOperationException {
URL url;
CertStore certStore;
PublicKey serverCertPublicKey = null;
try {
// The URL where we are going to request our cert from
url = new URL(this.SCEPUrl);
/* // This is called when we get the certificate for our CSR signed by CA
// Implement this handler to check the CA cert in prod. We can do cert pinning here
CallbackHandler cb = new CallbackHandler() {
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated
methods, choose Tools | Templates.
}
};*/
// Implement verification of the CA cert. VERIFY the CA
CertificateVerifier ocv = new OptimisticCertificateVerifier();
// Instantiate our SCEP client
Client scepClient = new Client(url, ocv);
// Get the CA capabilities. Should return SHA1withRSA for strongest hash and sig. Returns MD5.
if (log.isDebugEnabled()) {
Capabilities cap = scepClient.getCaCapabilities();
log.debug(String.format(
"\nStrongestCipher: %s,\nStrongestMessageDigest: %s,\nStrongestSignatureAlgorithm: %s," +
"\nIsRenewalSupported: %s,\nIsRolloverSupported: %s",
cap.getStrongestCipher(), cap.getStrongestMessageDigest(), cap.getStrongestSignatureAlgorithm(),
cap.isRenewalSupported(), cap.isRolloverSupported()));
}
certStore = scepClient.getCaCertificate();
for (Certificate cert : certStore.getCertificates(null)) {
if (cert instanceof X509Certificate) {
if (log.isDebugEnabled()) {
log.debug(((X509Certificate) cert).getIssuerDN().getName());
}
// I have chosen the CA cert based on its BasicConstraintExtension "is_ca" being set to "true"
// This is because the returned keystore may contain many certificates including RAs.
if (((Boolean) ((X509CertImpl) cert).getBasicConstraintsExtension().get(CERT_IS_CA_EXTENSION))) {
serverCertPublicKey = cert.getPublicKey();
storeCertificateToStore(AgentConstants.SERVER_CA_CERT_ALIAS, cert);
}
}
}
} catch (MalformedURLException ex) {
String errorMsg = "Could not create valid URL from given SCEP URI: " + SCEPUrl;
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, ex);
} catch (ClientException e) {
String errorMsg = "Could not retrieve [Server-Certificate] from the SCEP-Server.";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
} catch (CertStoreException e) {
String errorMsg = "Could not retrieve [Server-Certificates] from the response message from SCEP-Server.";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
} catch (IOException e) {
String errorMsg = "Error occurred whilst trying to get property ['is_ca'] from the retreived Certificates";
log.error(errorMsg);
throw new AgentCoreOperationException(errorMsg, e);
}
return serverCertPublicKey;
}
/**
* Gets the Public-Key of the client.
*
* @return the public key of the client.
*/
public PublicKey getPublicKey() {
return publicKey;
}
/**
* Gets the Private-Key of the client.
*
* @return the private key of the client.
*/
public PrivateKey getPrivateKey() {
return privateKey;
}
/**
* Gets the SCEP-Certificate of the client.
*
* @return the SCEP Certificate of the client.
*/
public X509Certificate getSCEPCertificate() {
return SCEPCertificate;
}
/**
* Gets the Public-Key of the Server.
*
* @return the pubic key of the server.
*/
public PublicKey getServerPublicKey() {
return serverPublicKey;
}
/**
* Checks whether the device has already been enrolled with the SCEP Server.
*
* @return the enrollment status; 'TRUE' if already enrolled else 'FALSE'.
*/
public boolean isEnrolled() {
return isEnrolled;
}
}

@ -0,0 +1,57 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception;
public class AgentCoreOperationException extends Exception{
private static final long serialVersionUID = 2736466230451105710L;
private String errorMessage;
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public AgentCoreOperationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public AgentCoreOperationException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public AgentCoreOperationException(String msg) {
super(msg);
setErrorMessage(msg);
}
public AgentCoreOperationException() {
super();
}
public AgentCoreOperationException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,225 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
/**
* This is a utility class which contains methods common to the communication process of a client and the server. The
* methods include encryption/decryption of payloads and signing/verification of payloads received and to be sent.
*/
public class CommunicationUtils {
private static final Log log = LogFactory.getLog(TransportUtils.class);
// The Signature Algorithm used.
private static final String SHA_512 = "SHA-512";
// The Encryption Algorithm and the Padding used.
private static final String CIPHER_PADDING = "RSA/ECB/PKCS1Padding";
/**
* Encrypts the message with the key that's passed in.
*
* @param message the message to be encrypted.
* @param encryptionKey the key to use for the encryption of the message.
* @return the encrypted message in String format.
* @throws TransportHandlerException if an error occurs with the encryption flow which can be due to Padding
* issues, encryption key being invalid or the algorithm used is unrecognizable.
*/
public static String encryptMessage(String message, Key encryptionKey) throws TransportHandlerException {
Cipher encrypter;
byte[] cipherData;
try {
encrypter = Cipher.getInstance(CIPHER_PADDING);
encrypter.init(Cipher.ENCRYPT_MODE, encryptionKey);
cipherData = encrypter.doFinal(message.getBytes(StandardCharsets.UTF_8));
} catch (NoSuchAlgorithmException e) {
String errorMsg = "Algorithm not found exception occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (NoSuchPaddingException e) {
String errorMsg = "No Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (InvalidKeyException e) {
String errorMsg = "InvalidKey exception occurred for encryptionKey \n[\n" + encryptionKey + "\n]\n";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (BadPaddingException e) {
String errorMsg = "Bad Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (IllegalBlockSizeException e) {
String errorMsg = "Illegal blockSize error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
}
return Base64.encodeBase64String(cipherData);
}
///TODO:: Exception needs to change according to the common package
/**
* Signed a given message using the PrivateKey that's passes in.
*
* @param message the message to be signed. Ideally some encrypted payload.
* @param signatureKey the PrivateKey with which the message is to be signed.
* @return the Base64Encoded String of the signed payload.
* @throws TransportHandlerException if some error occurs with the signing process which may be related to the
* signature algorithm used or the key used for signing.
*/
public static String signMessage(String message, PrivateKey signatureKey) throws TransportHandlerException {
Signature signature;
String signedEncodedString;
try {
signature = Signature.getInstance(SHA_512);
signature.initSign(signatureKey);
signature.update(Base64.decodeBase64(message));
byte[] signatureBytes = signature.sign();
signedEncodedString = Base64.encodeBase64String(signatureBytes);
} catch (NoSuchAlgorithmException e) {
String errorMsg =
"Algorithm not found exception occurred for Signature instance of [" + SHA_512 + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (SignatureException e) {
String errorMsg = "Signature exception occurred for Signature instance of [" + SHA_512 + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (InvalidKeyException e) {
String errorMsg = "InvalidKey exception occurred for signatureKey \n[\n" + signatureKey + "\n]\n";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
}
return signedEncodedString;
}
/**
* Verifies some signed-data against the a Public-Key to ensure that it was produced by the holder of the
* corresponding Private Key.
*
* @param data the actual payoad which was signed by some Private Key.
* @param signedData the signed data produced by signing the payload using a Private Key.
* @param verificationKey the corresponding Public Key which is an exact pair of the Private-Key with we expect
* the data to be signed by.
* @return true if the signed data verifies to be signed by the corresponding Private Key.
* @throws TransportHandlerException if some error occurs with the verification process which may be related to
* the signature algorithm used or the key used for signing.
*/
public static boolean verifySignature(String data, String signedData, PublicKey verificationKey)
throws TransportHandlerException {
Signature signature;
boolean verified;
try {
signature = Signature.getInstance(SHA_512);
signature.initVerify(verificationKey);
signature.update(Base64.decodeBase64(data));
verified = signature.verify(Base64.decodeBase64(signedData));
} catch (NoSuchAlgorithmException e) {
String errorMsg =
"Algorithm not found exception occurred for Signature instance of [" + SHA_512 + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (SignatureException e) {
String errorMsg = "Signature exception occurred for Signature instance of [" + SHA_512 + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (InvalidKeyException e) {
String errorMsg = "InvalidKey exception occurred for signatureKey \n[\n" + verificationKey + "\n]\n";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
}
return verified;
}
/**
* Encrypts the message with the key that's passed in.
*
* @param encryptedMessage the encrypted message that is supposed to be decrypted.
* @param decryptKey the key to use in the decryption process.
* @return the decrypted message in String format.
* @throws TransportHandlerException if an error occurs with the encryption flow which can be due to Padding
* issues, encryption key being invalid or the algorithm used is unrecognizable.
*/
public static String decryptMessage(String encryptedMessage, Key decryptKey) throws TransportHandlerException {
Cipher decrypter;
String decryptedMessage;
try {
decrypter = Cipher.getInstance(CIPHER_PADDING);
decrypter.init(Cipher.DECRYPT_MODE, decryptKey);
decryptedMessage = new String(decrypter.doFinal(Base64.decodeBase64(encryptedMessage)),
StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException e) {
String errorMsg = "Algorithm not found exception occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (NoSuchPaddingException e) {
String errorMsg = "No Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (InvalidKeyException e) {
String errorMsg = "InvalidKey exception occurred for encryptionKey \n[\n" + decryptKey + "\n]\n";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (BadPaddingException e) {
String errorMsg = "Bad Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (IllegalBlockSizeException e) {
String errorMsg = "Illegal blockSize error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
}
return decryptedMessage;
}
}

@ -0,0 +1,47 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.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();
//TODO:: Any errors needs to be thrown ahead
void processIncomingMessage(T message, String... messageParams);
void processIncomingMessage();
void publishDeviceData(String... publishData);
void publishDeviceData();
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.wso2.carbon.device.mgt.iot.virtualfirealarm.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,303 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramSocket;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.SocketException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class TransportUtils {
private static final Log log = LogFactory.getLog(TransportUtils.class);
public static final int MIN_PORT_NUMBER = 9000;
public static final int MAX_PORT_NUMBER = 11000;
/**
* Given a server endpoint as a String, this method splits it into Protocol, Host and Port
*
* @param ipString a network endpoint in the format - '<PROTOCOL>://<HOST>:<PORT>'
* @return a map with keys "Protocol", "Host" & "Port" for the related values from the ipString
* @throws TransportHandlerException
*/
public static Map<String, String> getHostAndPort(String ipString)
throws TransportHandlerException {
Map<String, String> ipPortMap = new HashMap<String, String>();
String[] ipPortArray = ipString.split(":");
if (ipPortArray.length != 3) {
String errorMsg =
"The IP String - '" + ipString +
"' is invalid. It needs to be in format '<PROTOCOL>://<HOST>:<PORT>'.";
log.info(errorMsg);
throw new TransportHandlerException(errorMsg);
}
ipPortMap.put(AgentConstants.PROTOCOL_PROPERTY, ipPortArray[0]);
ipPortMap.put(AgentConstants.HOST_PROPERTY, ipPortArray[1].replace("/", ""));
ipPortMap.put(AgentConstants.PORT_PROPERTY, ipPortArray[2]);
return ipPortMap;
}
/**
* This method validates whether a specific IP Address is of IPv4 type
*
* @param ipAddress the IP Address which needs to be validated
* @return true if it is of IPv4 type and false otherwise
*/
public static boolean validateIPv4(String ipAddress) {
try {
if (ipAddress == null || ipAddress.isEmpty()) {
return false;
}
String[] parts = ipAddress.split("\\.");
if (parts.length != 4) {
return false;
}
for (String s : parts) {
int i = Integer.parseInt(s);
if ((i < 0) || (i > 255)) {
return false;
}
}
return !ipAddress.endsWith(".");
} catch (NumberFormatException nfe) {
log.warn("The IP Address: " + ipAddress + " could not be validated against IPv4-style");
return false;
}
}
public static Map<String, String> getInterfaceIPMap() throws TransportHandlerException {
Map<String, String> interfaceToIPMap = new HashMap<String, String>();
Enumeration<NetworkInterface> networkInterfaces;
String networkInterfaceName = "";
String ipAddress;
try {
networkInterfaces = NetworkInterface.getNetworkInterfaces();
} catch (SocketException exception) {
String errorMsg =
"Error encountered whilst trying to get the list of network-interfaces";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, exception);
}
try {
for (; networkInterfaces.hasMoreElements(); ) {
networkInterfaceName = networkInterfaces.nextElement().getName();
if (log.isDebugEnabled()) {
log.debug("Network Interface: " + networkInterfaceName);
log.debug("------------------------------------------");
}
Enumeration<InetAddress> interfaceIPAddresses = NetworkInterface.getByName(
networkInterfaceName).getInetAddresses();
for (; interfaceIPAddresses.hasMoreElements(); ) {
ipAddress = interfaceIPAddresses.nextElement().getHostAddress();
if (log.isDebugEnabled()) {
log.debug("IP Address: " + ipAddress);
}
if (TransportUtils.validateIPv4(ipAddress)) {
interfaceToIPMap.put(networkInterfaceName, ipAddress);
}
}
if (log.isDebugEnabled()) {
log.debug("------------------------------------------");
}
}
} catch (SocketException exception) {
String errorMsg =
"Error encountered whilst trying to get the IP Addresses of the network " +
"interface: " + networkInterfaceName;
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, exception);
}
return interfaceToIPMap;
}
/**
* Attempts to find a free port between the MIN_PORT_NUMBER(9000) and MAX_PORT_NUMBER(11000).
* Tries 'RANDOMLY picked' port numbers between this range up-until "randomAttempts" number of
* times. If still fails, then tries each port in descending order from the MAX_PORT_NUMBER
* whilst skipping already attempted ones via random selection.
*
* @param randomAttempts no of times to TEST port numbers picked randomly over the given range
* @return an available/free port
*/
public static synchronized int getAvailablePort(int randomAttempts) {
ArrayList<Integer> failedPorts = new ArrayList<Integer>(randomAttempts);
try {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
int randomPort = MAX_PORT_NUMBER;
while (randomAttempts > 0) {
randomPort = secureRandom.nextInt(MAX_PORT_NUMBER - MIN_PORT_NUMBER) + MIN_PORT_NUMBER;
if (checkIfPortAvailable(randomPort)) {
return randomPort;
}
failedPorts.add(randomPort);
randomAttempts--;
}
randomPort = MAX_PORT_NUMBER;
while (true) {
if (!failedPorts.contains(randomPort) && checkIfPortAvailable(randomPort)) {
return randomPort;
}
randomPort--;
}
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("SHA1PRNG algorithm could not be found.");
}
}
private static boolean checkIfPortAvailable(int port) {
ServerSocket tcpSocket = null;
DatagramSocket udpSocket = null;
try {
tcpSocket = new ServerSocket(port);
tcpSocket.setReuseAddress(true);
udpSocket = new DatagramSocket(port);
udpSocket.setReuseAddress(true);
return true;
} catch (IOException ex) {
// denotes the port is in use
} finally {
if (tcpSocket != null) {
try {
tcpSocket.close();
} catch (IOException e) {
/* not to be thrown */
}
}
if (udpSocket != null) {
udpSocket.close();
}
}
return false;
}
/**
* This is a utility method that creates and returns a HTTP connection object.
*
* @param urlString the URL pattern to which the connection needs to be created
* @return an HTTPConnection object which cn be used to send HTTP requests
* @throws TransportHandlerException if errors occur when creating the HTTP connection with
* the given URL string
*/
public static HttpURLConnection getHttpConnection(String urlString) throws
TransportHandlerException {
URL connectionUrl;
HttpURLConnection httpConnection;
try {
connectionUrl = new URL(urlString);
httpConnection = (HttpURLConnection) connectionUrl.openConnection();
} catch (MalformedURLException e) {
String errorMsg = "Error occured whilst trying to form HTTP-URL from string: " + urlString;
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
} catch (IOException exception) {
String errorMsg = "Error occured whilst trying to open a connection to: " + urlString;
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, exception);
}
return httpConnection;
}
/**
* This is a utility method that reads and returns the response from a HTTP connection
*
* @param httpConnection the connection from which a response is expected
* @return the response (as a string) from the given HTTP connection
* @throws TransportHandlerException if any errors occur whilst reading the response from
* the connection stream
*/
public static String readResponseFromHttpRequest(HttpURLConnection httpConnection)
throws TransportHandlerException {
BufferedReader bufferedReader;
try {
bufferedReader = new BufferedReader(new InputStreamReader(
httpConnection.getInputStream(), StandardCharsets.UTF_8));
} catch (IOException exception) {
String errorMsg = "There is an issue with connecting the reader to the input stream at: " +
httpConnection.getURL();
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, exception);
}
String responseLine;
StringBuilder completeResponse = new StringBuilder();
try {
while ((responseLine = bufferedReader.readLine()) != null) {
completeResponse.append(responseLine);
}
} catch (IOException exception) {
String errorMsg = "Error occured whilst trying read from the connection stream at: " +
httpConnection.getURL();
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, exception);
}
try {
bufferedReader.close();
} catch (IOException exception) {
log.error("Could not succesfully close the bufferedReader to the connection at: " + httpConnection.getURL());
}
return completeResponse.toString();
}
}

@ -0,0 +1,91 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.http;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.server.Server;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
/**
* 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).
*/
public abstract class HTTPTransportHandler implements TransportHandler {
private static final Log log = LogFactory.getLog(HTTPTransportHandler.class);
protected Server server;
protected int port;
protected int timeoutInterval;
protected HTTPTransportHandler() {
this.port = TransportUtils.getAvailablePort(10);
this.server = new Server(port);
timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
}
protected HTTPTransportHandler(int port) {
this.port = port;
this.server = new Server(this.port);
timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
}
protected HTTPTransportHandler(int port, int timeoutInterval) {
this.port = port;
this.server = new Server(this.port);
this.timeoutInterval = timeoutInterval;
}
public void setTimeoutInterval(int timeoutInterval) {
this.timeoutInterval = timeoutInterval;
}
/**
* Checks whether the HTTP server is up and listening for incoming requests.
*
* @return true if the server is up & listening for requests, else false.
*/
public boolean isConnected() {
return server.isStarted();
}
protected void incrementPort() {
this.port = this.port + 1;
server = new Server(port);
}
/**
* Shuts-down the HTTP Server.
*/
public void closeConnection() throws Exception {
if (server != null && isConnected()) {
server.stop();
}
}
}

@ -0,0 +1,361 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.mqtt;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
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.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
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(false);
//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();
}
protected void connectToQueue(String username, String password) throws TransportHandlerException {
options.setUserName(username);
options.setPassword(password.toCharArray());
connectToQueue();
}
/**
* 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);
log.info("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) {
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.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.info("Got an MQTT message '" + mqttMessage.toString() + "' for topic '" + topic + "'.");
}
Thread messageProcessorThread = new Thread() {
public void run() {
processIncomingMessage(mqttMessage, topic);
}
};
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 message = "";
try {
message = iMqttDeliveryToken.getMessage().toString();
} catch (MqttException e) {
//TODO:: Throw errors
log.error(
"Error occurred whilst trying to read the message from the MQTT delivery token.");
}
String topic = iMqttDeliveryToken.getTopics()[0];
String client = iMqttDeliveryToken.getClient().getClientId();
if (log.isDebugEnabled()) {
log.debug("Message - '" + message + "' of client [" + client + "] for the topic (" +
topic + ") was delivered successfully.");
}
}
/**
* Closes the connection to the MQTT Broker.
*/
public void closeConnection() throws MqttException {
if (client != null && isConnected()) {
client.disconnect();
}
}
}

@ -0,0 +1,366 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.xmpp;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromContainsFilter;
import org.jivesoftware.smack.filter.OrFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.filter.ToContainsFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
/**
* 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 IoT-Server specific implementation for all the XMPP functionality. This includes
* connecting to a XMPP Server & Login-In using the device's/server's XMPP-Account, Setting listeners and filters on
* incoming XMPP messages and Sending XMPP replies for messages received. Makes use of the 'Smack-XMPP' library
* provided by jivesoftware/igniterealtime.
*/
public abstract class XMPPTransportHandler implements TransportHandler<Message> {
private static final Log log = LogFactory.getLog(XMPPTransportHandler.class);
protected String server;
protected int timeoutInterval; // millis
//TODO:: Shouldnt be hard-coded. Need to be read from configs
private static final int DEFAULT_XMPP_PORT = 5222;
private XMPPConnection connection;
private int port;
private ConnectionConfiguration config;
private PacketFilter filter;
private PacketListener listener;
/**
* Constructor for XMPPTransportHandler passing only the server-IP.
*
* @param server the IP of the XMPP server.
*/
protected XMPPTransportHandler(String server) {
this.server = server;
this.port = DEFAULT_XMPP_PORT;
this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
initXMPPClient();
}
/**
* Constructor for XMPPTransportHandler passing server-IP and the XMPP-port.
*
* @param server the IP of the XMPP server.
* @param port the XMPP server's port to connect to. (default - 5222)
*/
protected XMPPTransportHandler(String server, int port) {
this.server = server;
this.port = port;
this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
initXMPPClient();
}
/**
* Constructor for XMPPTransportHandler passing server-IP, the XMPP-port and the
* timeoutInterval used by listeners to the server and for reconnection schedules.
*
* @param server the IP of the XMPP server.
* @param port the XMPP server's port to connect to. (default - 5222)
* @param timeoutInterval the timeout interval to use for the connection and reconnection
*/
protected XMPPTransportHandler(String server, int port, int timeoutInterval) {
this.server = server;
this.port = port;
this.timeoutInterval = timeoutInterval;
initXMPPClient();
}
/**
* Sets the client's time-out-limit whilst waiting for XMPP-replies from server.
*
* @param millis the time in millis to be set as the time-out-limit whilst waiting for a
* XMPP-reply.
*/
public void setTimeoutInterval(int millis) {
this.timeoutInterval = millis;
}
/**
* Checks whether the connection to the XMPP-Server persists.
*
* @return true if the client is connected to the XMPP-Server, else false.
*/
@Override
public boolean isConnected() {
return connection.isConnected();
}
/**
* Initializes the XMPP Client. Sets the time-out-limit whilst waiting for XMPP-replies from
* server. Sets the XMPP configurations to connect to the server and creates the
* XMPPConnection object used for connecting and Logging-In.
*/
private void initXMPPClient() {
log.info(String.format("Initializing connection to XMPP Server at %1$s via port " +
"%2$d.", server, port));
SmackConfiguration.setPacketReplyTimeout(timeoutInterval);
config = new ConnectionConfiguration(server, port);
// TODO:: Need to enable SASL-Authentication appropriately
config.setSASLAuthenticationEnabled(false);
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
connection = new XMPPConnection(config);
}
//TODO:: Re-check all exception handling
/**
* Connects to the XMPP-Server and if attempt unsuccessful, then throws exception.
*
* @throws TransportHandlerException in the event of 'Connecting to' the XMPP server fails.
*/
protected void connectToServer() throws TransportHandlerException {
try {
connection.connect();
log.info(String.format("Connection to XMPP Server at %1$s established successfully......", server));
} catch (XMPPException xmppExcepion) {
String errorMsg = "Connection attempt to the XMPP Server at " + server + " via port " + port + " failed.";
log.info(errorMsg);
throw new TransportHandlerException(errorMsg, xmppExcepion);
}
}
/**
* If successfully established connection, then tries to Log in using the device's XMPP
* Account credentials.
*
* @param username the username of the device's XMPP-Account.
* @param password the password of the device's XMPP-Account.
* @param resource the resource the resource, specific to the XMPP-Account to which the login
* is made to
* @throws TransportHandlerException in the event of 'Logging into' the XMPP server fails.
*/
protected void loginToServer(String username, String password, String resource)
throws TransportHandlerException {
if (isConnected()) {
try {
if (resource == null) {
connection.login(username, password);
log.info(String.format("Logged into XMPP Server at %1$s as user %2$s......", server, username));
} else {
connection.login(username, password, resource);
log.info(String.format("Logged into XMPP Server at %1$s as user %2$s on resource %3$s......",
server, username, resource));
}
} catch (XMPPException xmppException) {
String errorMsg =
"Login attempt to the XMPP Server at " + server + " with username - " + username + " failed.";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, xmppException);
}
} else {
String errorMsg = "Not connected to XMPP-Server to attempt Login. Please 'connectToServer' before Login";
throw new TransportHandlerException(errorMsg);
}
}
/**
* Sets a filter for all the incoming XMPP-Messages on the Sender's JID (XMPP-Account ID).
* Also creates a listener for the incoming messages and connects the listener to the
* XMPPConnection alongside the set filter.
*
* @param senderJID the JID (XMPP-Account ID of the sender) to which the filter is to be set.
*/
protected void setFilterOnSender(String senderJID) {
filter = new AndFilter(new PacketTypeFilter(Message.class), new FromContainsFilter(
senderJID));
listener = new PacketListener() {
@Override
public void processPacket(Packet packet) {
if (packet instanceof Message) {
final Message xmppMessage = (Message) packet;
Thread msgProcessThread = new Thread() {
public void run() {
processIncomingMessage(xmppMessage);
}
};
msgProcessThread.setDaemon(true);
msgProcessThread.start();
}
}
};
connection.addPacketListener(listener, filter);
}
/**
* Sets a filter for all the incoming XMPP-Messages on the Receiver's JID (XMPP-Account ID).
* Also creates a listener for the incoming messages and connects the listener to the
* XMPPConnection alongside the set filter.
*
* @param receiverJID the JID (XMPP-Account ID of the receiver) to which the filter is to be
* set.
*/
protected void setFilterOnReceiver(String receiverJID) {
filter = new AndFilter(new PacketTypeFilter(Message.class), new ToContainsFilter(
receiverJID));
listener = new PacketListener() {
@Override
public void processPacket(Packet packet) {
if (packet instanceof Message) {
final Message xmppMessage = (Message) packet;
Thread msgProcessThread = new Thread() {
public void run() {
processIncomingMessage(xmppMessage);
}
};
msgProcessThread.setDaemon(true);
msgProcessThread.start();
}
}
};
connection.addPacketListener(listener, filter);
}
/**
* Sets a filter for all the incoming XMPP-Messages on the From-JID & To-JID (XMPP-Account IDs)
* passed in. Also creates a listener for the incoming messages and connects the listener to
* the XMPPConnection alongside the set filter.
*
* @param senderJID the From-JID (XMPP-Account ID) to which the filter is to be set.
* @param receiverJID the To-JID (XMPP-Account ID) to which the filter is to be set.
* @param andCondition if true: then filter is set with 'AND' operator (senderJID &&
* receiverJID),
* if false: then the filter is set with 'OR' operator (senderJID |
* receiverJID)
*/
protected void setMessageFilterAndListener(String senderJID, String receiverJID, boolean
andCondition) {
PacketFilter jidFilter;
if (andCondition) {
jidFilter = new AndFilter(new FromContainsFilter(senderJID), new ToContainsFilter(
receiverJID));
} else {
jidFilter = new OrFilter(new FromContainsFilter(senderJID), new ToContainsFilter(
receiverJID));
}
filter = new AndFilter(new PacketTypeFilter(Message.class), jidFilter);
listener = new PacketListener() {
@Override
public void processPacket(Packet packet) {
if (packet instanceof Message) {
final Message xmppMessage = (Message) packet;
Thread msgProcessThread = new Thread() {
public void run() {
processIncomingMessage(xmppMessage);
}
};
msgProcessThread.setDaemon(true);
msgProcessThread.start();
}
}
};
connection.addPacketListener(listener, filter);
}
/**
* Sends an XMPP message. Calls the overloaded method with Subject set to "Reply-From-Device"
*
* @param JID the JID (XMPP Account ID) to which the message is to be sent to.
* @param message the XMPP-Message that is to be sent.
*/
protected void sendXMPPMessage(String JID, String message) {
sendXMPPMessage(JID, message, "XMPP-Message");
}
/**
* Overloaded method to send an XMPP message. Includes the subject to be mentioned in the
* message that is sent.
*
* @param JID the JID (XMPP Account ID) to which the message is to be sent to.
* @param message the XMPP-Message that is to be sent.
* @param subject the subject that the XMPP-Message would carry.
*/
protected void sendXMPPMessage(String JID, String message, String subject) {
Message xmppMessage = new Message();
xmppMessage.setTo(JID);
xmppMessage.setSubject(subject);
xmppMessage.setBody(message);
xmppMessage.setType(Message.Type.chat);
sendXMPPMessage(JID, xmppMessage);
}
/**
* Sends an XMPP message.
*
* @param JID the JID (XMPP Account ID) to which the message is to be sent to.
* @param xmppMessage the XMPP-Message that is to be sent.
*/
protected void sendXMPPMessage(String JID, Message xmppMessage) {
connection.sendPacket(xmppMessage);
if (log.isDebugEnabled()) {
log.debug("Message: '" + xmppMessage.getBody() + "' sent to XMPP JID [" + JID +
"] sent successfully.");
}
}
/**
* Disables default debugger provided by the XMPPConnection.
*/
protected void disableDebugger() {
connection.DEBUG_ENABLED = false;
}
/**
* Closes the connection to the XMPP Server.
*/
public void closeConnection() {
if (connection != null && isConnected()) {
connection.disconnect();
}
}
}

@ -0,0 +1,216 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentUtilOperations;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual.ui.AgentUI;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.sampled.Clip;
import javax.swing.*;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
/**
* This class use to emulate virtual hardware functionality
*/
public class VirtualHardwareManager {
private static final Log log = LogFactory.getLog(VirtualHardwareManager.class);
private static VirtualHardwareManager virtualHardwareManager;
private AgentUI agentUI;
private Sequencer sequencer = null;
private int temperature = 30, humidity = 30;
private int temperatureMin = 20, temperatureMax = 50, humidityMin = 20, humidityMax = 50;
private int temperatureSVF = 50, humiditySVF = 50;
private boolean isTemperatureRandomized, isHumidityRandomized;
private boolean isTemperatureSmoothed, isHumiditySmoothed;
private VirtualHardwareManager(){
}
public static VirtualHardwareManager getInstance(){
if (virtualHardwareManager == null){
virtualHardwareManager = new VirtualHardwareManager();
}
return virtualHardwareManager;
}
public void init(){
try {
// Set System L&F for Device UI
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (UnsupportedLookAndFeelException e) {
log.error(
"'UnsupportedLookAndFeelException' error occurred whilst initializing the" +
" Agent UI.");
} catch (ClassNotFoundException e) {
log.error(
"'ClassNotFoundException' error occurred whilst initializing the Agent UI.");
} catch (InstantiationException e) {
log.error(
"'InstantiationException' error occurred whilst initializing the Agent UI.");
} catch (IllegalAccessException e) {
log.error(
"'IllegalAccessException' error occurred whilst initializing the Agent UI.");
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
agentUI = new AgentUI();
agentUI.setVisible(true);
}
});
setAudioSequencer();
}
/**
* Get temperature from emulated device
* @return Temperature
*/
public int getTemperature() {
if (isTemperatureRandomized) {
temperature = getRandom(temperatureMax, temperatureMin, temperature,
isTemperatureSmoothed, temperatureSVF);
agentUI.updateTemperature(temperature);
}
return temperature;
}
public void setTemperature(int temperature) {
this.temperature = temperature;
}
/**
* Get humidity from emulated device
* @return Humidity
*/
public int getHumidity() {
if (isHumidityRandomized) {
humidity = getRandom(humidityMax, humidityMin, humidity, isHumiditySmoothed,
humiditySVF);
agentUI.updateHumidity(humidity);
}
return humidity;
}
public void setHumidity(int humidity) {
this.humidity = humidity;
}
public void setTemperatureMin(int temperatureMin) {
this.temperatureMin = temperatureMin;
}
public void setTemperatureMax(int temperatureMax) {
this.temperatureMax = temperatureMax;
}
public void setHumidityMin(int humidityMin) {
this.humidityMin = humidityMin;
}
public void setHumidityMax(int humidityMax) {
this.humidityMax = humidityMax;
}
public void setIsHumidityRandomized(boolean isHumidityRandomized) {
this.isHumidityRandomized = isHumidityRandomized;
}
public void setIsTemperatureRandomized(boolean isTemperatureRandomized) {
this.isTemperatureRandomized = isTemperatureRandomized;
}
public void setTemperatureSVF(int temperatureSVF) {
this.temperatureSVF = temperatureSVF;
}
public void setHumiditySVF(int humiditySVF) {
this.humiditySVF = humiditySVF;
}
public void setIsTemperatureSmoothed(boolean isTemperatureSmoothed) {
this.isTemperatureSmoothed = isTemperatureSmoothed;
}
public void setIsHumiditySmoothed(boolean isHumiditySmoothed) {
this.isHumiditySmoothed = isHumiditySmoothed;
}
public void changeAlarmStatus(boolean isOn) {
agentUI.setAlarmStatus(isOn);
if (isOn) {
sequencer.start();
} else {
sequencer.stop();
}
}
private int getRandom(int max, int min, int current, boolean isSmoothed, int svf) {
if (isSmoothed) {
int offset = (max - min) * svf / 100;
double mx = current + offset;
max = (mx > max) ? max : (int) Math.round(mx);
double mn = current - offset;
min = (mn < min) ? min : (int) Math.round(mn);
}
try {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
return secureRandom.nextInt(max - min) + min;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("SHA1PRNG algorithm could not be found.");
}
}
private void setAudioSequencer() {
InputStream audioSrc = AgentUtilOperations.class.getResourceAsStream(
"/" + AgentConstants.AUDIO_FILE_NAME);
Sequence sequence;
try {
sequence = MidiSystem.getSequence(audioSrc);
sequencer = MidiSystem.getSequencer();
if(sequencer != null) {
sequencer.open();
sequencer.setSequence(sequence);
sequencer.setLoopCount(Clip.LOOP_CONTINUOUSLY);
}
} catch (InvalidMidiDataException e) {
log.error("AudioReader: Error whilst setting MIDI Audio reader sequence");
} catch (IOException e) {
log.error("AudioReader: Error whilst getting audio sequence from stream");
} catch (MidiUnavailableException e) {
log.error("AudioReader: Error whilst openning MIDI Audio reader sequencer");
}
}
}

@ -0,0 +1,910 @@
/*
* 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.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual.ui;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual.VirtualHardwareManager;
import java.awt.*;
import java.net.URL;
import java.util.Calendar;
import javax.swing.*;
public class AgentUI extends JFrame {
private boolean isTemperatureRandomized, isHumidityRandomized;
private boolean isTemperatureSmoothed, isHumiditySmoothed;
private volatile boolean isAlarmOn = false;
private JLabel picLabelBulbOn, picLabelBulbOff;
// Variables declaration - do not modify
private JCheckBox chkbxEmulate;
private JCheckBox chkbxHumidityRandom;
private JCheckBox chkbxHumiditySmooth;
private JCheckBox chkbxTemperatureRandom;
private JCheckBox chkbxTemperatureSmooth;
private JComboBox cmbInterface;
private JComboBox cmbPeriod;
private JComboBox cmbProtocol;
private JLabel jLabel1;
private JLabel jLabel10;
private JLabel jLabel11;
private JLabel jLabel12;
private JLabel jLabel2;
private JLabel jLabel20;
private JLabel jLabel23;
private JLabel jLabel24;
private JLabel jLabel25;
private JLabel jLabel3;
private JLabel jLabel4;
private JLabel jLabel5;
private JLabel jLabel6;
private JLabel jLabel7;
private JLabel jLabel8;
private JLabel jLabel9;
private JPanel jPanel1;
private JPanel jPanel2;
private JPanel jPanel3;
private JPanel jPanel4;
private JPanel jPanel6;
private JPanel jPanel7;
private JPanel jPanel8;
private JPanel jPanel9;
private JSeparator jSeparator1;
private JSeparator jSeparator5;
private JLabel lblAgentName;
private JLabel lblStatus;
private JPanel pnlBulbStatus;
private JSpinner spinnerHumidity;
private JSpinner spinnerInterval;
private JSpinner spinnerTemperature;
private JTextField txtHumidityMax;
private JTextField txtHumidityMin;
private JTextField txtHumiditySVF;
private JTextField txtTemperatureMax;
private JTextField txtTemperatureMin;
private JTextField txtTemperatureSVF;
// End of variables declaration
private Runnable uiUpdater = new Runnable() {
@Override
public void run() {
while (true) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
pnlBulbStatus.removeAll();
pnlBulbStatus.add(isAlarmOn ? picLabelBulbOn : picLabelBulbOff);
pnlBulbStatus.updateUI();
lblStatus.setText(AgentManager.getInstance().getAgentStatus());
if (isTemperatureRandomized) {
txtTemperatureMinActionPerformed(null);
txtTemperatureMaxActionPerformed(null);
if (isTemperatureSmoothed) {
txtTemperatureSVFActionPerformed(null);
}
}
if (isHumidityRandomized) {
txtHumidityMinActionPerformed(null);
txtHumidityMaxActionPerformed(null);
if (isHumiditySmoothed) {
txtHumiditySVFActionPerformed(null);
}
}
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
}
};
/**
* Creates new form AgentUI
*/
public AgentUI() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
private void initComponents() {
lblAgentName = new JLabel();
jLabel2 = new JLabel();
jPanel1 = new JPanel();
jLabel3 = new JLabel();
pnlBulbStatus = new JPanel();
jPanel2 = new JPanel();
jLabel4 = new JLabel();
chkbxTemperatureRandom = new JCheckBox();
jSeparator1 = new JSeparator();
jPanel7 = new JPanel();
jLabel5 = new JLabel();
txtTemperatureMin = new JTextField();
jLabel6 = new JLabel();
txtTemperatureMax = new JTextField();
jLabel10 = new JLabel();
txtTemperatureSVF = new JTextField();
spinnerTemperature = new JSpinner();
chkbxTemperatureSmooth = new JCheckBox();
jPanel6 = new JPanel();
jLabel20 = new JLabel();
lblStatus = new JLabel();
jPanel8 = new JPanel();
jLabel23 = new JLabel();
chkbxHumidityRandom = new JCheckBox();
jSeparator5 = new JSeparator();
jPanel9 = new JPanel();
jLabel24 = new JLabel();
txtHumidityMin = new JTextField();
jLabel25 = new JLabel();
txtHumidityMax = new JTextField();
txtHumiditySVF = new JTextField();
jLabel11 = new JLabel();
spinnerHumidity = new JSpinner();
chkbxHumiditySmooth = new JCheckBox();
jPanel3 = new JPanel();
jLabel7 = new JLabel();
spinnerInterval = new JSpinner();
jLabel8 = new JLabel();
jLabel9 = new JLabel();
cmbProtocol = new JComboBox();
jLabel12 = new JLabel();
cmbInterface = new JComboBox();
jPanel4 = new JPanel();
chkbxEmulate = new JCheckBox();
cmbPeriod = new JComboBox();
jLabel1 = new JLabel();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setTitle("Fire Alarm Emulator");
setResizable(false);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
setLocation(dim.width / 2 - 650 / 2, dim.height / 2 - 440 / 2);
lblAgentName.setFont(new Font("Cantarell", 1, 24)); // NOI18N
lblAgentName.setHorizontalAlignment(SwingConstants.LEFT);
lblAgentName.setText("Device Name: " + AgentManager.getInstance().getDeviceName());
Calendar now = Calendar.getInstance();
int currentYear = now.get(Calendar.YEAR);
jLabel2.setHorizontalAlignment(SwingConstants.CENTER);
jLabel2.setText("Copyright (c) " + currentYear + ", WSO2 Inc.");
jPanel1.setBackground(new Color(220, 220, 220));
jLabel3.setFont(new Font("Cantarell", 0, 18)); // NOI18N
jLabel3.setHorizontalAlignment(SwingConstants.CENTER);
jLabel3.setText("Alarm Status");
pnlBulbStatus.setBackground(new Color(220, 220, 220));
GroupLayout pnlBulbStatusLayout = new GroupLayout(pnlBulbStatus);
pnlBulbStatus.setLayout(pnlBulbStatusLayout);
pnlBulbStatusLayout.setHorizontalGroup(
pnlBulbStatusLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
pnlBulbStatusLayout.setVerticalGroup(
pnlBulbStatusLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGap(0, 167, Short.MAX_VALUE)
);
GroupLayout jPanel1Layout = new GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
.addComponent(pnlBulbStatus, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel3, GroupLayout.DEFAULT_SIZE, 190, Short.MAX_VALUE))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel3)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pnlBulbStatus, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
jPanel2.setBackground(new Color(220, 220, 220));
jLabel4.setFont(new Font("Cantarell", 0, 18)); // NOI18N
jLabel4.setHorizontalAlignment(SwingConstants.CENTER);
jLabel4.setText("Temperature");
chkbxTemperatureRandom.setText("Randomize Data");
chkbxTemperatureRandom.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chkbxTemperatureRandomActionPerformed(evt);
}
});
jSeparator1.setOrientation(SwingConstants.VERTICAL);
jPanel7.setBackground(new Color(220, 220, 220));
jLabel5.setHorizontalAlignment(SwingConstants.LEFT);
jLabel5.setText("Min");
txtTemperatureMin.setHorizontalAlignment(JTextField.CENTER);
txtTemperatureMin.setText("20");
txtTemperatureMin.setEnabled(false);
txtTemperatureMin.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtTemperatureMinActionPerformed(evt);
}
});
jLabel6.setHorizontalAlignment(SwingConstants.RIGHT);
jLabel6.setText("Max");
txtTemperatureMax.setHorizontalAlignment(JTextField.CENTER);
txtTemperatureMax.setText("50");
txtTemperatureMax.setEnabled(false);
txtTemperatureMax.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtTemperatureMaxActionPerformed(evt);
}
});
jLabel10.setHorizontalAlignment(SwingConstants.RIGHT);
jLabel10.setText("SV %");
txtTemperatureSVF.setHorizontalAlignment(JTextField.CENTER);
txtTemperatureSVF.setText("50");
txtTemperatureSVF.setEnabled(false);
txtTemperatureSVF.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtTemperatureSVFActionPerformed(evt);
}
});
GroupLayout jPanel7Layout = new GroupLayout(jPanel7);
jPanel7.setLayout(jPanel7Layout);
jPanel7Layout.setHorizontalGroup(
jPanel7Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel7Layout.createSequentialGroup()
.addComponent(jLabel5)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtTemperatureMin, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel6)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtTemperatureMax, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel10)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtTemperatureSVF, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanel7Layout.setVerticalGroup(
jPanel7Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(GroupLayout.Alignment.TRAILING, jPanel7Layout.createSequentialGroup()
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel7Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(txtTemperatureMin, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(txtTemperatureMax, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel6)
.addComponent(jLabel5)
.addComponent(jLabel10)
.addComponent(txtTemperatureSVF, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addGap(35, 35, 35))
);
spinnerTemperature.setFont(new Font("Cantarell", 1, 24)); // NOI18N
spinnerTemperature.setModel(new SpinnerNumberModel(30, 0, 100, 1));
spinnerTemperature.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
spinnerTemperatureStateChanged(evt);
}
});
chkbxTemperatureSmooth.setText("Smooth Variation");
chkbxTemperatureSmooth.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chkbxTemperatureSmoothActionPerformed(evt);
}
});
GroupLayout jPanel2Layout = new GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
.addComponent(jLabel4, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(spinnerTemperature))
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jSeparator1, GroupLayout.PREFERRED_SIZE, 6, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(jPanel7, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(chkbxTemperatureRandom)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkbxTemperatureSmooth)))
.addContainerGap())
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(jSeparator1)
.addGroup(jPanel2Layout.createSequentialGroup()
.addGroup(jPanel2Layout.createParallelGroup(
GroupLayout.Alignment.BASELINE)
.addComponent(chkbxTemperatureRandom)
.addComponent(chkbxTemperatureSmooth))
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel7, GroupLayout.PREFERRED_SIZE, 51, GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(jLabel4, GroupLayout.PREFERRED_SIZE, 23, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spinnerTemperature)))
.addContainerGap())
);
jPanel6.setBackground(new Color(253, 254, 209));
jLabel20.setText("Connection Status:");
jLabel20.setVerticalTextPosition(SwingConstants.TOP);
lblStatus.setFont(new Font("Cantarell", 1, 15)); // NOI18N
lblStatus.setText("Not Connected");
GroupLayout jPanel6Layout = new GroupLayout(jPanel6);
jPanel6.setLayout(jPanel6Layout);
jPanel6Layout.setHorizontalGroup(
jPanel6Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel6Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel20)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblStatus, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addContainerGap())
);
jPanel6Layout.setVerticalGroup(
jPanel6Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(GroupLayout.Alignment.TRAILING, jPanel6Layout.createSequentialGroup()
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel6Layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
.addComponent(jLabel20, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel6Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(lblStatus)))
.addContainerGap())
);
jPanel8.setBackground(new Color(220, 220, 220));
jLabel23.setFont(new Font("Cantarell", 0, 18)); // NOI18N
jLabel23.setHorizontalAlignment(SwingConstants.CENTER);
jLabel23.setText("Humidity");
chkbxHumidityRandom.setText("Randomize Data");
chkbxHumidityRandom.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chkbxHumidityRandomActionPerformed(evt);
}
});
jSeparator5.setOrientation(SwingConstants.VERTICAL);
jPanel9.setBackground(new Color(220, 220, 220));
jLabel24.setHorizontalAlignment(SwingConstants.LEFT);
jLabel24.setText("Min");
txtHumidityMin.setHorizontalAlignment(JTextField.CENTER);
txtHumidityMin.setText("20");
txtHumidityMin.setEnabled(false);
txtHumidityMin.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtHumidityMinActionPerformed(evt);
}
});
jLabel25.setHorizontalAlignment(SwingConstants.RIGHT);
jLabel25.setText("Max");
txtHumidityMax.setHorizontalAlignment(JTextField.CENTER);
txtHumidityMax.setText("50");
txtHumidityMax.setEnabled(false);
txtHumidityMax.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtHumidityMaxActionPerformed(evt);
}
});
txtHumiditySVF.setHorizontalAlignment(JTextField.CENTER);
txtHumiditySVF.setText("50");
txtHumiditySVF.setEnabled(false);
txtHumiditySVF.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtHumiditySVFActionPerformed(evt);
}
});
jLabel11.setHorizontalAlignment(SwingConstants.RIGHT);
jLabel11.setText("SV %");
GroupLayout jPanel9Layout = new GroupLayout(jPanel9);
jPanel9.setLayout(jPanel9Layout);
jPanel9Layout.setHorizontalGroup(
jPanel9Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel9Layout.createSequentialGroup()
.addComponent(jLabel24)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtHumidityMin, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel25)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtHumidityMax, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel11)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtHumiditySVF, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanel9Layout.setVerticalGroup(
jPanel9Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(GroupLayout.Alignment.TRAILING, jPanel9Layout.createSequentialGroup()
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel9Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel9Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(jLabel11)
.addComponent(txtHumiditySVF, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel9Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(txtHumidityMin, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(txtHumidityMax, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel25)
.addComponent(jLabel24)))
.addGap(35, 35, 35))
);
spinnerHumidity.setFont(new Font("Cantarell", 1, 24)); // NOI18N
spinnerHumidity.setModel(new SpinnerNumberModel(30, 0, 100, 1));
spinnerHumidity.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
spinnerHumidityStateChanged(evt);
}
});
chkbxHumiditySmooth.setText("Smooth Variation");
chkbxHumiditySmooth.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chkbxHumiditySmoothActionPerformed(evt);
}
});
GroupLayout jPanel8Layout = new GroupLayout(jPanel8);
jPanel8.setLayout(jPanel8Layout);
jPanel8Layout.setHorizontalGroup(
jPanel8Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel8Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel8Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(jLabel23, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE)
.addComponent(spinnerHumidity))
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jSeparator5, GroupLayout.PREFERRED_SIZE, 6, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel8Layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
.addComponent(jPanel9, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel8Layout.createSequentialGroup()
.addComponent(chkbxHumidityRandom)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkbxHumiditySmooth)))
.addContainerGap())
);
jPanel8Layout.setVerticalGroup(
jPanel8Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel8Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel8Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(jSeparator5)
.addGroup(jPanel8Layout.createSequentialGroup()
.addGroup(jPanel8Layout.createParallelGroup(
GroupLayout.Alignment.BASELINE)
.addComponent(chkbxHumidityRandom)
.addComponent(chkbxHumiditySmooth))
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel9, GroupLayout.PREFERRED_SIZE, 51, GroupLayout.PREFERRED_SIZE)
.addGap(0, 1, Short.MAX_VALUE))
.addGroup(jPanel8Layout.createSequentialGroup()
.addComponent(jLabel23, GroupLayout.PREFERRED_SIZE, 23, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spinnerHumidity)))
.addContainerGap())
);
jPanel3.setBackground(new Color(207, 233, 234));
jLabel7.setText("Data Push Interval:");
spinnerInterval.setModel(new SpinnerNumberModel(Integer.valueOf(AgentManager.getInstance().getPushInterval()), Integer.valueOf(1), null, Integer.valueOf(1)));
spinnerInterval.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
spinnerIntervalStateChanged(evt);
}
});
jLabel8.setText("Seconds");
jLabel9.setText("Protocol:");
cmbProtocol.setModel(new DefaultComboBoxModel(new String[] { "MQTT", "XMPP", "HTTP" }));
cmbProtocol.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cmbProtocolActionPerformed(evt);
}
});
jLabel12.setText("Interface:");
cmbInterface.setModel(new DefaultComboBoxModel(new String[] { "eth0" }));
cmbInterface.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cmbInterfaceActionPerformed(evt);
}
});
GroupLayout jPanel3Layout = new GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(
jPanel3Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel3Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel7)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spinnerInterval, GroupLayout.PREFERRED_SIZE, 55, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel8)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel12)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cmbInterface, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel9)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cmbProtocol, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
jPanel3Layout.setVerticalGroup(
jPanel3Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel3Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel3Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(jLabel12)
.addComponent(cmbInterface, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel3Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(jLabel7)
.addComponent(spinnerInterval, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel8)
.addComponent(jLabel9)
.addComponent(cmbProtocol, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
jPanel4.setBackground(new Color(169, 253, 173));
chkbxEmulate.setText("Emulate data");
chkbxEmulate.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chkbxEmulateActionPerformed(evt);
}
});
cmbPeriod.setModel(new DefaultComboBoxModel(new String[] { "1 hour", "1 day", "1 week", "1 month " }));
cmbPeriod.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cmbPeriodActionPerformed(evt);
}
});
jLabel1.setText("Emulation Period");
GroupLayout jPanel4Layout = new GroupLayout(jPanel4);
jPanel4.setLayout(jPanel4Layout);
jPanel4Layout.setHorizontalGroup(
jPanel4Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(jPanel4Layout.createSequentialGroup()
.addContainerGap()
.addComponent(chkbxEmulate)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel1)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cmbPeriod, GroupLayout.PREFERRED_SIZE, 162, GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
jPanel4Layout.setVerticalGroup(
jPanel4Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup()
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel4Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(chkbxEmulate)
.addComponent(cmbPeriod, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1))
.addContainerGap())
);
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(lblAgentName, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel6, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(
GroupLayout.Alignment.LEADING)
.addComponent(jPanel8, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addComponent(jLabel2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel4, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel3, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(lblAgentName, GroupLayout.PREFERRED_SIZE, 53, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel6, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel8, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addComponent(jPanel1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel3, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel4, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel2, GroupLayout.PREFERRED_SIZE, 28, GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
pack();
chkbxTemperatureSmooth.setEnabled(false);
chkbxTemperatureSmooth.setEnabled(false);
cmbInterface.removeAllItems();
for (String item : AgentManager.getInstance().getInterfaceList()){
cmbInterface.addItem(item);
}
cmbInterface.setEnabled(false);
cmbProtocol.removeAllItems();
for (String item : AgentManager.getInstance().getProtocolList()){
cmbProtocol.addItem(item);
}
cmbProtocol.setSelectedItem(AgentConstants.DEFAULT_PROTOCOL);
URL urlAlarmOn = this.getClass().getResource("/alarm-on.gif");
ImageIcon imageIconAlarmOn = new ImageIcon(urlAlarmOn);
URL urlAlarmOff = this.getClass().getResource("/alarm-off.gif");
ImageIcon imageIconAlarmOff = new ImageIcon(urlAlarmOff);
picLabelBulbOn = new JLabel(imageIconAlarmOn);
picLabelBulbOn.setSize(pnlBulbStatus.getSize());
picLabelBulbOff = new JLabel(imageIconAlarmOff);
picLabelBulbOff.setSize(pnlBulbStatus.getSize());
new Thread(uiUpdater).start();
AgentManager.getInstance().setDeviceReady(true);
}
private void chkbxTemperatureRandomActionPerformed(java.awt.event.ActionEvent evt) {
isTemperatureRandomized = chkbxTemperatureRandom.isSelected();
VirtualHardwareManager.getInstance().setIsTemperatureRandomized(isTemperatureRandomized);
spinnerTemperature.setEnabled(!isTemperatureRandomized);
txtTemperatureMax.setEnabled(isTemperatureRandomized);
txtTemperatureMin.setEnabled(isTemperatureRandomized);
chkbxTemperatureSmooth.setEnabled(isTemperatureRandomized);
txtTemperatureSVF.setEnabled(isTemperatureRandomized && isTemperatureSmoothed);
}
private void chkbxHumidityRandomActionPerformed(java.awt.event.ActionEvent evt) {
isHumidityRandomized = chkbxHumidityRandom.isSelected();
VirtualHardwareManager.getInstance().setIsHumidityRandomized(isHumidityRandomized);
spinnerHumidity.setEnabled(!isHumidityRandomized);
txtHumidityMax.setEnabled(isHumidityRandomized);
txtHumidityMin.setEnabled(isHumidityRandomized);
chkbxHumiditySmooth.setEnabled(isHumidityRandomized);
txtTemperatureSVF.setEnabled(isHumidityRandomized && isHumiditySmoothed);
}
private void spinnerTemperatureStateChanged(javax.swing.event.ChangeEvent evt) {
if (!isTemperatureRandomized) {
try {
int temperature = Integer.parseInt(spinnerTemperature.getValue().toString());
VirtualHardwareManager.getInstance().setTemperature(temperature);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Invalid temperature value", "Error", JOptionPane.ERROR_MESSAGE);
spinnerTemperature.setValue(VirtualHardwareManager.getInstance().getTemperature());
}
}
}
private void spinnerHumidityStateChanged(javax.swing.event.ChangeEvent evt) {
if (!isHumidityRandomized) {
try {
int humidity = Integer.parseInt(spinnerHumidity.getValue().toString());
VirtualHardwareManager.getInstance().setHumidity(humidity);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Invalid humidity value", "Error", JOptionPane.ERROR_MESSAGE);
spinnerHumidity.setValue(VirtualHardwareManager.getInstance().getHumidity());
}
}
}
private void txtTemperatureMinActionPerformed(java.awt.event.ActionEvent evt) {
try {
int temperature = Integer.parseInt(txtTemperatureMin.getText());
VirtualHardwareManager.getInstance().setTemperatureMin(temperature);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Invalid temperature value", "Error", JOptionPane.ERROR_MESSAGE);
txtTemperatureMin.setText("20");
}
}
private void txtTemperatureMaxActionPerformed(java.awt.event.ActionEvent evt) {
try {
int temperature = Integer.parseInt(txtTemperatureMax.getText());
VirtualHardwareManager.getInstance().setTemperatureMax(temperature);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Invalid temperature value", "Error", JOptionPane.ERROR_MESSAGE);
txtTemperatureMax.setText("50");
}
}
private void txtHumidityMinActionPerformed(java.awt.event.ActionEvent evt) {
try {
int humidity = Integer.parseInt(txtHumidityMin.getText());
VirtualHardwareManager.getInstance().setHumidityMin(humidity);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Invalid humidity value", "Error", JOptionPane.ERROR_MESSAGE);
txtHumidityMin.setText("20");
}
}
private void txtHumidityMaxActionPerformed(java.awt.event.ActionEvent evt) {
try {
int humidity = Integer.parseInt(txtHumidityMax.getText());
VirtualHardwareManager.getInstance().setHumidityMax(humidity);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Invalid humidity value", "Error", JOptionPane.ERROR_MESSAGE);
txtHumidityMax.setText("50");
}
}
private void spinnerIntervalStateChanged(javax.swing.event.ChangeEvent evt) {
try {
int interval = Integer.parseInt(spinnerInterval.getValue().toString());
AgentManager.getInstance().setPushInterval(interval);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Invalid time interval value", "Error", JOptionPane.ERROR_MESSAGE);
spinnerInterval.setValue(5);
}
}
private void cmbInterfaceActionPerformed(java.awt.event.ActionEvent evt) {
AgentManager.getInstance().setInterface(cmbInterface.getSelectedIndex());
}
private void cmbProtocolActionPerformed(java.awt.event.ActionEvent evt) {
if (cmbProtocol.getSelectedIndex() != -1 && cmbProtocol.getItemAt(
cmbProtocol.getSelectedIndex()).equals(AgentConstants.HTTP_PROTOCOL)) {
cmbInterface.setEnabled(true);
} else {
cmbInterface.setEnabled(false);
}
AgentManager.getInstance().setProtocol(cmbProtocol.getSelectedIndex());
}
private void txtTemperatureSVFActionPerformed(java.awt.event.ActionEvent evt) {
try {
int temperatureSVF = Integer.parseInt(txtTemperatureSVF.getText());
VirtualHardwareManager.getInstance().setTemperatureSVF(temperatureSVF);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Invalid value", "Error", JOptionPane.ERROR_MESSAGE);
txtTemperatureSVF.setText("50");
}
}
private void txtHumiditySVFActionPerformed(java.awt.event.ActionEvent evt) {
try {
int humiditySVF = Integer.parseInt(txtHumiditySVF.getText());
VirtualHardwareManager.getInstance().setHumiditySVF(humiditySVF);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "Invalid value", "Error", JOptionPane.ERROR_MESSAGE);
txtHumiditySVF.setText("50");
}
}
private void chkbxTemperatureSmoothActionPerformed(java.awt.event.ActionEvent evt) {
isTemperatureSmoothed = chkbxTemperatureSmooth.isSelected();
txtTemperatureSVF.setEnabled(isTemperatureSmoothed);
VirtualHardwareManager.getInstance().setIsTemperatureSmoothed(isTemperatureSmoothed);
}
private void chkbxHumiditySmoothActionPerformed(java.awt.event.ActionEvent evt) {
isHumiditySmoothed = chkbxHumiditySmooth.isSelected();
txtHumiditySVF.setEnabled(isHumiditySmoothed);
VirtualHardwareManager.getInstance().setIsHumiditySmoothed(isHumiditySmoothed);
}
private void cmbPeriodActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
}
private void chkbxEmulateActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
}
public void setAlarmStatus(boolean isAlarmOn) {
this.isAlarmOn = isAlarmOn;
}
public void updateTemperature(int temperature) {
spinnerTemperature.setValue(temperature);
spinnerTemperature.updateUI();
}
public void updateHumidity(int humidity) {
spinnerHumidity.setValue(humidity);
spinnerHumidity.updateUI();
}
}

@ -0,0 +1,35 @@
ad#
# Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
#
# Licensed 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.
#
#
#[Device-Configurations]
server-name=WSO2IoTServer
owner=shabirmean
deviceId=t4ctwq8qfl11
device-name=SMEAN_t4ctwq8qfl11
controller-context=/virtual_firealarm/device
scep-context=/virtual_firealarm_scep
https-ep=https://localhost:9443
http-ep=http://localhost:9763
apim-ep=http://192.168.67.21:8281
mqtt-ep=tcp://192.168.67.21:1883
xmpp-ep=http://204.232.188.215:5222
auth-method=token
auth-token=79d68b50ae5f5a06e812889979b3453
refresh-token=8bdda6359dddad218cff3354d5a8cb3b
network-interface=en0
push-interval=14
xmpp-server-name=localhost

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="VirtualAgentUI" default="default" basedir=".">
<description>Builds, tests, and runs the project VirtualAgentUI.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar: JAR building
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="VirtualAgentUI-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>

@ -0,0 +1,8 @@
build.xml.data.CRC32=e60df945
build.xml.script.CRC32=7c331eea
build.xml.stylesheet.CRC32=8064a381@1.75.2.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=e60df945
nbproject/build-impl.xml.script.CRC32=18800575
nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<file>file:/home/lahiru/WSO2IOT/carbon-device-mgt-plugins/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.impl/src/main/ui/src/org/wso2/carbon/device/mgt/iot/agent/virtual/VirtualAgentUI.java</file>
</group>
</open-files>
</project-private>

@ -0,0 +1,73 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processor.options=
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
build.generated.sources.dir=${build.dir}/generated-sources
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# Files in build.classes.dir which should be excluded from distribution jar
dist.archive.excludes=
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/VirtualAgentUI.jar
dist.javadoc.dir=${dist.dir}/javadoc
excludes=
includes=**
jar.compress=false
javac.classpath=
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.processorpath=\
${javac.classpath}
javac.source=1.8
javac.target=1.8
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}
javac.test.processorpath=\
${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
main.class=org.wso2.carbon.device.mgt.iot.agent.virtual.VirtualAgentUI
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project.
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
# To set system properties for unit tests define test-sys-prop.name=value:
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>VirtualAgentUI</name>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>

@ -0,0 +1,37 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.wso2.carbon.device.mgt.iot.agent.virtual;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.wso2.carbon.device.mgt.iot.agent.virtual.ui.AgentUI;
/**
*
* @author charitha
*/
public class VirtualAgentUI {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
try {
// Set System L&F
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
// handle exception
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new AgentUI().setVisible(true);
}
});
}
}

@ -0,0 +1,779 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="3"/>
<Property name="title" type="java.lang.String" value="Fire Alarm Emulator"/>
<Property name="resizable" type="boolean" value="false"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lblAgentName" alignment="0" max="32767" attributes="0"/>
<Component id="jPanel6" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel8" max="32767" attributes="0"/>
<Component id="jPanel2" max="32767" attributes="0"/>
</Group>
</Group>
<Component id="jLabel2" alignment="0" max="32767" attributes="0"/>
<Component id="jPanel4" alignment="0" max="32767" attributes="0"/>
<Component id="jPanel3" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="lblAgentName" min="-2" pref="53" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel6" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jPanel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel8" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jPanel1" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel4" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" pref="28" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="lblAgentName">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Cantarell" size="24" style="1"/>
</Property>
<Property name="horizontalAlignment" type="int" value="2"/>
<Property name="text" type="java.lang.String" value="Device Name: WSO2 IoT Virtual Agent"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="Copyright (c) 2015, WSO2 Inc."/>
</Properties>
</Component>
<Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="dc" green="dc" red="dc" type="rgb"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="pnlBulbStatus" max="32767" attributes="0"/>
<Component id="jLabel3" pref="190" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="pnlBulbStatus" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel3">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Cantarell" size="18" style="0"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="Bulb Status"/>
</Properties>
</Component>
<Container class="javax.swing.JPanel" name="pnlBulbStatus">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="dc" green="dc" red="dc" type="rgb"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="167" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel2">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="dc" green="dc" red="dc" type="rgb"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="jLabel4" max="32767" attributes="0"/>
<Component id="spinnerTemperature" max="32767" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<Component id="jSeparator1" min="-2" pref="6" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel7" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="chkbxTemperatureRandom" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="chkbxTemperatureSmooth" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jSeparator1" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="chkbxTemperatureRandom" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="chkbxTemperatureSmooth" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel7" min="-2" pref="51" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel4" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spinnerTemperature" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel4">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Cantarell" size="18" style="0"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="Temperature"/>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="chkbxTemperatureRandom">
<Properties>
<Property name="text" type="java.lang.String" value="Randomize Data"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkbxTemperatureRandomActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator1">
<Properties>
<Property name="orientation" type="int" value="1"/>
</Properties>
</Component>
<Container class="javax.swing.JPanel" name="jPanel7">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="dc" green="dc" red="dc" type="rgb"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtTemperatureMin" min="-2" pref="45" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel6" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtTemperatureMax" min="-2" pref="45" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel10" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtTemperatureSVF" min="-2" pref="45" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="txtTemperatureMin" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtTemperatureMax" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel10" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtTemperatureSVF" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="35" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel5">
<Properties>
<Property name="horizontalAlignment" type="int" value="2"/>
<Property name="text" type="java.lang.String" value="Min"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtTemperatureMin">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="20"/>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtTemperatureMinActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel6">
<Properties>
<Property name="horizontalAlignment" type="int" value="4"/>
<Property name="text" type="java.lang.String" value="Max"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtTemperatureMax">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="50"/>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtTemperatureMaxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel10">
<Properties>
<Property name="horizontalAlignment" type="int" value="4"/>
<Property name="text" type="java.lang.String" value="SV %"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtTemperatureSVF">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="50"/>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtTemperatureSVFActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JSpinner" name="spinnerTemperature">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Cantarell" size="24" style="1"/>
</Property>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="30" maximum="100" minimum="0" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
</Properties>
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spinnerTemperatureStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="chkbxTemperatureSmooth">
<Properties>
<Property name="text" type="java.lang.String" value="Smooth Variation"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkbxTemperatureSmoothActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel6">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="d1" green="fe" red="fd" type="rgb"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel20" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="lblStatus" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="273" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="jLabel20" pref="27" max="32767" attributes="0"/>
<Component id="lblStatus" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel20">
<Properties>
<Property name="text" type="java.lang.String" value="Connection Status:"/>
<Property name="verticalTextPosition" type="int" value="1"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lblStatus">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Cantarell" size="15" style="1"/>
</Property>
<Property name="text" type="java.lang.String" value="Not Connected"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel8">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="dc" green="dc" red="dc" type="rgb"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel23" min="-2" pref="100" max="-2" attributes="0"/>
<Component id="spinnerHumidity" max="32767" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<Component id="jSeparator5" min="-2" pref="6" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="jPanel9" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="chkbxHumidityRandom" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="chkbxHumiditySmooth" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jSeparator5" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="chkbxHumidityRandom" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="chkbxHumiditySmooth" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel9" min="-2" pref="51" max="-2" attributes="0"/>
<EmptySpace min="0" pref="1" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="jLabel23" min="-2" pref="23" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spinnerHumidity" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel23">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Cantarell" size="18" style="0"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="Humidity"/>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="chkbxHumidityRandom">
<Properties>
<Property name="text" type="java.lang.String" value="Randomize Data"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkbxHumidityRandomActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator5">
<Properties>
<Property name="orientation" type="int" value="1"/>
</Properties>
</Component>
<Container class="javax.swing.JPanel" name="jPanel9">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="dc" green="dc" red="dc" type="rgb"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel24" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtHumidityMin" min="-2" pref="45" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel25" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtHumidityMax" min="-2" pref="45" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel11" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="txtHumiditySVF" min="-2" pref="45" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="jLabel11" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtHumiditySVF" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="txtHumidityMin" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="txtHumidityMax" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel25" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel24" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" pref="35" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel24">
<Properties>
<Property name="horizontalAlignment" type="int" value="2"/>
<Property name="text" type="java.lang.String" value="Min"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtHumidityMin">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="20"/>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtHumidityMinActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel25">
<Properties>
<Property name="horizontalAlignment" type="int" value="4"/>
<Property name="text" type="java.lang.String" value="Max"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="txtHumidityMax">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="50"/>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtHumidityMaxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="txtHumiditySVF">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="50"/>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtHumiditySVFActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel11">
<Properties>
<Property name="horizontalAlignment" type="int" value="4"/>
<Property name="text" type="java.lang.String" value="SV %"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JSpinner" name="spinnerHumidity">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Cantarell" size="24" style="1"/>
</Property>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="30" maximum="100" minimum="0" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
</Properties>
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spinnerHumidityStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="chkbxHumiditySmooth">
<Properties>
<Property name="text" type="java.lang.String" value="Smooth Variation"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkbxHumiditySmoothActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel3">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ea" green="e9" red="cf" type="rgb"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel7" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="spinnerInterval" min="-2" pref="55" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel8" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="jLabel12" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cmbInterface" min="-2" pref="100" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel9" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cmbProtocol" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
<Component id="jLabel12" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cmbInterface" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel7" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="spinnerInterval" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel8" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel9" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cmbProtocol" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel7">
<Properties>
<Property name="text" type="java.lang.String" value="Data Push Interval:"/>
</Properties>
</Component>
<Component class="javax.swing.JSpinner" name="spinnerInterval">
<Properties>
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
<SpinnerModel initial="5" minimum="1" numberType="java.lang.Integer" stepSize="1" type="number"/>
</Property>
</Properties>
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spinnerIntervalStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel8">
<Properties>
<Property name="text" type="java.lang.String" value="Seconds"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel9">
<Properties>
<Property name="text" type="java.lang.String" value="Protocol:"/>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="cmbProtocol">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="3">
<StringItem index="0" value="MQTT"/>
<StringItem index="1" value="XMPP"/>
<StringItem index="2" value="HTTP"/>
</StringArray>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cmbProtocolActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel12">
<Properties>
<Property name="text" type="java.lang.String" value="Interface:"/>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="cmbInterface">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="1">
<StringItem index="0" value="eth0"/>
</StringArray>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cmbInterfaceActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel4">
<Properties>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ad" green="fd" red="a9" type="rgb"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="chkbxEmulate" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cmbPeriod" min="-2" pref="162" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="chkbxEmulate" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cmbPeriod" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JCheckBox" name="chkbxEmulate">
<Properties>
<Property name="text" type="java.lang.String" value="Emulate data"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkbxEmulateActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JComboBox" name="cmbPeriod">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="4">
<StringItem index="0" value="1 hour"/>
<StringItem index="1" value="1 day"/>
<StringItem index="2" value="1 week"/>
<StringItem index="3" value="1 month "/>
</StringArray>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cmbPeriodActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" value="Emulation Period"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

@ -0,0 +1,711 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.wso2.carbon.device.mgt.iot.agent.virtual.ui;
/**
*
* @author charitha
*/
public class AgentUI extends javax.swing.JFrame {
/**
* Creates new form AgentUI
*/
public AgentUI() {
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
lblAgentName = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jPanel1 = new javax.swing.JPanel();
jLabel3 = new javax.swing.JLabel();
pnlBulbStatus = new javax.swing.JPanel();
jPanel2 = new javax.swing.JPanel();
jLabel4 = new javax.swing.JLabel();
chkbxTemperatureRandom = new javax.swing.JCheckBox();
jSeparator1 = new javax.swing.JSeparator();
jPanel7 = new javax.swing.JPanel();
jLabel5 = new javax.swing.JLabel();
txtTemperatureMin = new javax.swing.JTextField();
jLabel6 = new javax.swing.JLabel();
txtTemperatureMax = new javax.swing.JTextField();
jLabel10 = new javax.swing.JLabel();
txtTemperatureSVF = new javax.swing.JTextField();
spinnerTemperature = new javax.swing.JSpinner();
chkbxTemperatureSmooth = new javax.swing.JCheckBox();
jPanel6 = new javax.swing.JPanel();
jLabel20 = new javax.swing.JLabel();
lblStatus = new javax.swing.JLabel();
jPanel8 = new javax.swing.JPanel();
jLabel23 = new javax.swing.JLabel();
chkbxHumidityRandom = new javax.swing.JCheckBox();
jSeparator5 = new javax.swing.JSeparator();
jPanel9 = new javax.swing.JPanel();
jLabel24 = new javax.swing.JLabel();
txtHumidityMin = new javax.swing.JTextField();
jLabel25 = new javax.swing.JLabel();
txtHumidityMax = new javax.swing.JTextField();
txtHumiditySVF = new javax.swing.JTextField();
jLabel11 = new javax.swing.JLabel();
spinnerHumidity = new javax.swing.JSpinner();
chkbxHumiditySmooth = new javax.swing.JCheckBox();
jPanel3 = new javax.swing.JPanel();
jLabel7 = new javax.swing.JLabel();
spinnerInterval = new javax.swing.JSpinner();
jLabel8 = new javax.swing.JLabel();
jLabel9 = new javax.swing.JLabel();
cmbProtocol = new javax.swing.JComboBox();
jLabel12 = new javax.swing.JLabel();
cmbInterface = new javax.swing.JComboBox();
jPanel4 = new javax.swing.JPanel();
chkbxEmulate = new javax.swing.JCheckBox();
cmbPeriod = new javax.swing.JComboBox();
jLabel1 = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Fire Alarm Emulator");
setResizable(false);
lblAgentName.setFont(new java.awt.Font("Cantarell", 1, 24)); // NOI18N
lblAgentName.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
lblAgentName.setText("Device Name: WSO2 IoT Virtual Agent");
jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel2.setText("Copyright (c) 2015, WSO2 Inc.");
jPanel1.setBackground(new java.awt.Color(220, 220, 220));
jLabel3.setFont(new java.awt.Font("Cantarell", 0, 18)); // NOI18N
jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel3.setText("Bulb Status");
pnlBulbStatus.setBackground(new java.awt.Color(220, 220, 220));
javax.swing.GroupLayout pnlBulbStatusLayout = new javax.swing.GroupLayout(pnlBulbStatus);
pnlBulbStatus.setLayout(pnlBulbStatusLayout);
pnlBulbStatusLayout.setHorizontalGroup(
pnlBulbStatusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE)
);
pnlBulbStatusLayout.setVerticalGroup(
pnlBulbStatusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 167, Short.MAX_VALUE)
);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(pnlBulbStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, 190, Short.MAX_VALUE))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pnlBulbStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
jPanel2.setBackground(new java.awt.Color(220, 220, 220));
jLabel4.setFont(new java.awt.Font("Cantarell", 0, 18)); // NOI18N
jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel4.setText("Temperature");
chkbxTemperatureRandom.setText("Randomize Data");
chkbxTemperatureRandom.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chkbxTemperatureRandomActionPerformed(evt);
}
});
jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
jPanel7.setBackground(new java.awt.Color(220, 220, 220));
jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
jLabel5.setText("Min");
txtTemperatureMin.setHorizontalAlignment(javax.swing.JTextField.CENTER);
txtTemperatureMin.setText("20");
txtTemperatureMin.setEnabled(false);
txtTemperatureMin.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtTemperatureMinActionPerformed(evt);
}
});
jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
jLabel6.setText("Max");
txtTemperatureMax.setHorizontalAlignment(javax.swing.JTextField.CENTER);
txtTemperatureMax.setText("50");
txtTemperatureMax.setEnabled(false);
txtTemperatureMax.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtTemperatureMaxActionPerformed(evt);
}
});
jLabel10.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
jLabel10.setText("SV %");
txtTemperatureSVF.setHorizontalAlignment(javax.swing.JTextField.CENTER);
txtTemperatureSVF.setText("50");
txtTemperatureSVF.setEnabled(false);
txtTemperatureSVF.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtTemperatureSVFActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
jPanel7.setLayout(jPanel7Layout);
jPanel7Layout.setHorizontalGroup(
jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel7Layout.createSequentialGroup()
.addComponent(jLabel5)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtTemperatureMin, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel6)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtTemperatureMax, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel10)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtTemperatureSVF, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanel7Layout.setVerticalGroup(
jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel7Layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtTemperatureMin, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(txtTemperatureMax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel6)
.addComponent(jLabel5)
.addComponent(jLabel10)
.addComponent(txtTemperatureSVF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(35, 35, 35))
);
spinnerTemperature.setFont(new java.awt.Font("Cantarell", 1, 24)); // NOI18N
spinnerTemperature.setModel(new javax.swing.SpinnerNumberModel(30, 0, 100, 1));
spinnerTemperature.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
spinnerTemperatureStateChanged(evt);
}
});
chkbxTemperatureSmooth.setText("Smooth Variation");
chkbxTemperatureSmooth.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chkbxTemperatureSmoothActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(spinnerTemperature))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 6, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(chkbxTemperatureRandom)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkbxTemperatureSmooth)))
.addContainerGap())
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSeparator1)
.addGroup(jPanel2Layout.createSequentialGroup()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(chkbxTemperatureRandom)
.addComponent(chkbxTemperatureSmooth))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spinnerTemperature)))
.addContainerGap())
);
jPanel6.setBackground(new java.awt.Color(253, 254, 209));
jLabel20.setText("Connection Status:");
jLabel20.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
lblStatus.setFont(new java.awt.Font("Cantarell", 1, 15)); // NOI18N
lblStatus.setText("Not Connected");
javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
jPanel6.setLayout(jPanel6Layout);
jPanel6Layout.setHorizontalGroup(
jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel6Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel20)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(lblStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(273, 273, 273))
);
jPanel6Layout.setVerticalGroup(
jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel6Layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jLabel20, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE)
.addComponent(lblStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
jPanel8.setBackground(new java.awt.Color(220, 220, 220));
jLabel23.setFont(new java.awt.Font("Cantarell", 0, 18)); // NOI18N
jLabel23.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel23.setText("Humidity");
chkbxHumidityRandom.setText("Randomize Data");
chkbxHumidityRandom.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chkbxHumidityRandomActionPerformed(evt);
}
});
jSeparator5.setOrientation(javax.swing.SwingConstants.VERTICAL);
jPanel9.setBackground(new java.awt.Color(220, 220, 220));
jLabel24.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
jLabel24.setText("Min");
txtHumidityMin.setHorizontalAlignment(javax.swing.JTextField.CENTER);
txtHumidityMin.setText("20");
txtHumidityMin.setEnabled(false);
txtHumidityMin.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtHumidityMinActionPerformed(evt);
}
});
jLabel25.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
jLabel25.setText("Max");
txtHumidityMax.setHorizontalAlignment(javax.swing.JTextField.CENTER);
txtHumidityMax.setText("50");
txtHumidityMax.setEnabled(false);
txtHumidityMax.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtHumidityMaxActionPerformed(evt);
}
});
txtHumiditySVF.setHorizontalAlignment(javax.swing.JTextField.CENTER);
txtHumiditySVF.setText("50");
txtHumiditySVF.setEnabled(false);
txtHumiditySVF.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtHumiditySVFActionPerformed(evt);
}
});
jLabel11.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
jLabel11.setText("SV %");
javax.swing.GroupLayout jPanel9Layout = new javax.swing.GroupLayout(jPanel9);
jPanel9.setLayout(jPanel9Layout);
jPanel9Layout.setHorizontalGroup(
jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel9Layout.createSequentialGroup()
.addComponent(jLabel24)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtHumidityMin, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel25)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtHumidityMax, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel11)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtHumiditySVF, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanel9Layout.setVerticalGroup(
jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel9Layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel11)
.addComponent(txtHumiditySVF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtHumidityMin, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(txtHumidityMax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel25)
.addComponent(jLabel24)))
.addGap(35, 35, 35))
);
spinnerHumidity.setFont(new java.awt.Font("Cantarell", 1, 24)); // NOI18N
spinnerHumidity.setModel(new javax.swing.SpinnerNumberModel(30, 0, 100, 1));
spinnerHumidity.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
spinnerHumidityStateChanged(evt);
}
});
chkbxHumiditySmooth.setText("Smooth Variation");
chkbxHumiditySmooth.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chkbxHumiditySmoothActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8);
jPanel8.setLayout(jPanel8Layout);
jPanel8Layout.setHorizontalGroup(
jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel8Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel23, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(spinnerHumidity))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jSeparator5, javax.swing.GroupLayout.PREFERRED_SIZE, 6, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jPanel9, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel8Layout.createSequentialGroup()
.addComponent(chkbxHumidityRandom)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chkbxHumiditySmooth)))
.addContainerGap())
);
jPanel8Layout.setVerticalGroup(
jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel8Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSeparator5)
.addGroup(jPanel8Layout.createSequentialGroup()
.addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(chkbxHumidityRandom)
.addComponent(chkbxHumiditySmooth))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel9, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 1, Short.MAX_VALUE))
.addGroup(jPanel8Layout.createSequentialGroup()
.addComponent(jLabel23, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spinnerHumidity)))
.addContainerGap())
);
jPanel3.setBackground(new java.awt.Color(207, 233, 234));
jLabel7.setText("Data Push Interval:");
spinnerInterval.setModel(new javax.swing.SpinnerNumberModel(5, 1, null, 1));
spinnerInterval.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
spinnerIntervalStateChanged(evt);
}
});
jLabel8.setText("Seconds");
jLabel9.setText("Protocol:");
cmbProtocol.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "MQTT", "XMPP", "HTTP" }));
cmbProtocol.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cmbProtocolActionPerformed(evt);
}
});
jLabel12.setText("Interface:");
cmbInterface.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "eth0" }));
cmbInterface.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cmbInterfaceActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel3Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel7)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(spinnerInterval, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel8)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel12)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cmbInterface, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel9)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cmbProtocol, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
jPanel3Layout.setVerticalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel12)
.addComponent(cmbInterface, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel7)
.addComponent(spinnerInterval, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel8)
.addComponent(jLabel9)
.addComponent(cmbProtocol, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
jPanel4.setBackground(new java.awt.Color(169, 253, 173));
chkbxEmulate.setText("Emulate data");
chkbxEmulate.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chkbxEmulateActionPerformed(evt);
}
});
cmbPeriod.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1 hour", "1 day", "1 week", "1 month " }));
cmbPeriod.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
cmbPeriodActionPerformed(evt);
}
});
jLabel1.setText("Emulation Period");
javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
jPanel4.setLayout(jPanel4Layout);
jPanel4Layout.setHorizontalGroup(
jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel4Layout.createSequentialGroup()
.addContainerGap()
.addComponent(chkbxEmulate)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cmbPeriod, javax.swing.GroupLayout.PREFERRED_SIZE, 162, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
jPanel4Layout.setVerticalGroup(
jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(chkbxEmulate)
.addComponent(cmbPeriod, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1))
.addContainerGap())
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lblAgentName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(lblAgentName, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void chkbxTemperatureRandomActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkbxTemperatureRandomActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_chkbxTemperatureRandomActionPerformed
private void chkbxHumidityRandomActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkbxHumidityRandomActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_chkbxHumidityRandomActionPerformed
private void spinnerTemperatureStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerTemperatureStateChanged
// TODO add your handling code here:
}//GEN-LAST:event_spinnerTemperatureStateChanged
private void spinnerHumidityStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerHumidityStateChanged
// TODO add your handling code here:
}//GEN-LAST:event_spinnerHumidityStateChanged
private void txtTemperatureMinActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtTemperatureMinActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_txtTemperatureMinActionPerformed
private void txtTemperatureMaxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtTemperatureMaxActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_txtTemperatureMaxActionPerformed
private void txtHumidityMinActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtHumidityMinActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_txtHumidityMinActionPerformed
private void txtHumidityMaxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtHumidityMaxActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_txtHumidityMaxActionPerformed
private void spinnerIntervalStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerIntervalStateChanged
// TODO add your handling code here:
}//GEN-LAST:event_spinnerIntervalStateChanged
private void cmbInterfaceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmbInterfaceActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_cmbInterfaceActionPerformed
private void cmbProtocolActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmbProtocolActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_cmbProtocolActionPerformed
private void txtTemperatureSVFActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtTemperatureSVFActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_txtTemperatureSVFActionPerformed
private void txtHumiditySVFActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtHumiditySVFActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_txtHumiditySVFActionPerformed
private void chkbxTemperatureSmoothActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkbxTemperatureSmoothActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_chkbxTemperatureSmoothActionPerformed
private void chkbxHumiditySmoothActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkbxHumiditySmoothActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_chkbxHumiditySmoothActionPerformed
private void cmbPeriodActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmbPeriodActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_cmbPeriodActionPerformed
private void chkbxEmulateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkbxEmulateActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_chkbxEmulateActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox chkbxEmulate;
private javax.swing.JCheckBox chkbxHumidityRandom;
private javax.swing.JCheckBox chkbxHumiditySmooth;
private javax.swing.JCheckBox chkbxTemperatureRandom;
private javax.swing.JCheckBox chkbxTemperatureSmooth;
private javax.swing.JComboBox cmbInterface;
private javax.swing.JComboBox cmbPeriod;
private javax.swing.JComboBox cmbProtocol;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel10;
private javax.swing.JLabel jLabel11;
private javax.swing.JLabel jLabel12;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel20;
private javax.swing.JLabel jLabel23;
private javax.swing.JLabel jLabel24;
private javax.swing.JLabel jLabel25;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JLabel jLabel8;
private javax.swing.JLabel jLabel9;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel3;
private javax.swing.JPanel jPanel4;
private javax.swing.JPanel jPanel6;
private javax.swing.JPanel jPanel7;
private javax.swing.JPanel jPanel8;
private javax.swing.JPanel jPanel9;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JSeparator jSeparator5;
private javax.swing.JLabel lblAgentName;
private javax.swing.JLabel lblStatus;
private javax.swing.JPanel pnlBulbStatus;
private javax.swing.JSpinner spinnerHumidity;
private javax.swing.JSpinner spinnerInterval;
private javax.swing.JSpinner spinnerTemperature;
private javax.swing.JTextField txtHumidityMax;
private javax.swing.JTextField txtHumidityMin;
private javax.swing.JTextField txtHumiditySVF;
private javax.swing.JTextField txtTemperatureMax;
private javax.swing.JTextField txtTemperatureMin;
private javax.swing.JTextField txtTemperatureSVF;
// End of variables declaration//GEN-END:variables
}
Loading…
Cancel
Save