Merge pull request 'virtual fire alarm sample fixing' (#15) from amalka.subasinghe/device-mgt-plugins:master into master

Reviewed-on: community/device-mgt-plugins#15
fix-test-failure
Charitha Goonetilleke 2 years ago
commit e0f95e9d4f

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2014, 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">
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>carbon-device-mgt-plugins-parent</artifactId>
<version>6.0.16-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>device-types</artifactId>
<packaging>pom</packaging>
<name>WSO2 Carbon - IoT Plugins</name>
<url>http://wso2.org</url>
<modules>
<module>virtual-fire-alarm-plugin</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.7.2</version>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

@ -0,0 +1,236 @@
<?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>6.0.16-SNAPSHOT</version>
</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,306 @@
/*
* 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 { // uudi formay 8-4-4-4-12
connectToQueue(agentManager.getAgentConfigs().getAuthToken().substring(0, 18),
agentManager.getAgentConfigs().getAuthToken().substring(19));
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;
if (message.toString().contains("BULB:ON")) {
boolean stateToSwitch = true;
agentManager.changeAlarmStatus(stateToSwitch);
log.info(AgentConstants.LOG_APPENDER + "Bulb was switched to state: 'ON'");
return;
} else if (message.toString().contains("BULB:OFF")) {
boolean stateToSwitch = false;
agentManager.changeAlarmStatus(stateToSwitch);
log.info(AgentConstants.LOG_APPENDER + "Bulb was switched to state: 'OFF'");
return;
}
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\": \"" +
System.currentTimeMillis() + "\"},\"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
}

@ -0,0 +1,350 @@
<?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">
<parent>
<artifactId>virtual-fire-alarm-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>6.0.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.api</artifactId>
<packaging>war</packaging>
<name>WSO2 Carbon - IoT Server VirtualFireAlarm API</name>
<description>WSO2 Carbon - Virtual FireAlarm Service Management API Implementation</description>
<url>http://wso2.org</url>
<properties>
<cxf-bundle-package.version>2.7.18</cxf-bundle-package.version>
</properties>
<dependencies>
<!-- CDM -->
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.certificate.mgt.core</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<scope>provided</scope>
</dependency>
<!--MQTT -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<scope>provided</scope>
</dependency>
<!--IOT -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
<version>4.1</version>
<scope>provided</scope>
</dependency>
<!--JAX-RS -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bouncycastle.wso2</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.queuing</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.base</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2</artifactId>
</exclusion>
<exclusion>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
</exclusion>
<exclusion>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
</exclusion>
<exclusion>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
</exclusion>
<exclusion>
<groupId>commons-fileupload.wso2</groupId>
<artifactId>commons-fileupload</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.ant.wso2</groupId>
<artifactId>ant</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.ant.wso2</groupId>
<artifactId>ant</artifactId>
</exclusion>
<exclusion>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.equinox</groupId>
<artifactId>javax.servlet</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.registry.api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.application.extension</artifactId>
<scope>provided</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.wso2.carbon.analytics</groupId>-->
<!-- <artifactId>org.wso2.carbon.analytics.api</artifactId>-->
<!-- <scope>provided</scope>-->
<!-- </dependency>-->
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.extensions</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-bundle</artifactId>
<version>3.0.0-milestone2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-bundle-jaxrs</artifactId>
<scope>provided</scope>
<version>${cxf-bundle-package.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-core</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.orbit.com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jaxrs</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.orbit.com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<source>${wso2.maven.compiler.source}</source>
<target>${wso2.maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warName>virtual_firealarm</warName>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>
</configuration>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>
<outputDirectory>${basedir}/target/coverage-reports/site</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,134 @@
/*
* Copyright (c) 2016, 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.service.impl;
import io.swagger.annotations.*;
import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.apimgt.annotations.api.Scopes;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* This class consists the functions/APIs specific to the "actions" of the VirtualFirealarm device-type. These APIs
* include the ones that are used by the [Device] to contact the server (i.e: Enrollment & Publishing Data) and the
* ones used by the [Server/Owner] to contact the [Device] (i.e: sending control signals). This class also initializes
* the transport 'Connectors' [XMPP & MQTT] specific to the VirtualFirealarm device-type in order to communicate with
* such devices and to receive messages form it.
*/
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "virtual_firealarm"),
@ExtensionProperty(name = "context", value = "/virtual_firealarm"),
})
}
),
tags = {
@Tag(name = "virtual_firealarm,device_management", description = "")
}
)
@Scopes(
scopes = {
@Scope(
name = "Enroll device",
description = "",
key = "perm:firealarm:enroll",
permissions = {"/device-mgt/devices/enroll/firealarm"},
roles = {"Internal/devicemgt-user"}
)
}
)
public interface VirtualFireAlarmService {
String SCOPE = "scope";
/**
* This is an API called/used from within the Server(Front-End) or by a device Owner. It sends a control command to
* the VirtualFirealarm device to switch `ON` or `OFF` its buzzer. The method also takes in the protocol to be used
* to connect-to and send the command to the device.
*
* @param deviceId the ID of the VirtualFirealarm device on which the buzzer needs to switched `ON` or `OFF`.
* @param state the state to which the buzzer on the device needs to be changed. Either "ON" or "OFF".
* (Case-Insensitive String)
*/
@POST
@Path("device/{deviceId}/buzz")
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Switch Buzzer",
notes = "",
response = Response.class,
tags = "virtual_firealarm",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:firealarm:enroll")
})
}
)
Response switchBuzzer(@PathParam("deviceId") String deviceId,
@FormParam("state") String state);
/**
* Retrieve Sensor data for the device type
*/
@Path("device/stats/{deviceId}")
@GET
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Retrieve Sensor data for the device type",
notes = "",
response = Response.class,
tags = "virtual_firealarm",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:firealarm:enroll")
})
}
)
@Consumes("application/json")
@Produces("application/json")
Response getVirtualFirealarmStats(@PathParam("deviceId") String deviceId, @QueryParam("from") long from,
@QueryParam("to") long to);
@Path("device/download")
@GET
@Produces("application/zip")
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Download agent",
notes = "",
response = Response.class,
tags = "virtual_firealarm",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = SCOPE, value = "perm:firealarm:enroll")
})
}
)
Response downloadSketch(@QueryParam("deviceName") String deviceName, @QueryParam("sketchType") String sketchType);
}

@ -0,0 +1,279 @@
/*
* Copyright (c) 2016, 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.service.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey;
import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.core.operation.mgt.ConfigOperation;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dao.DeviceEventsDAO;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dao.DeviceEventsDAOImpl;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.SensorRecord;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.ZipArchive;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.ZipUtil;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.VirtualFirealarmXMPPException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.XmppAccount;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.XmppConfig;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.XmppServerClient;
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.user.api.UserStoreException;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.*;
public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
private static final String KEY_TYPE = "PRODUCTION";
private static ApiApplicationKey apiApplicationKey;
private static Log log = LogFactory.getLog(VirtualFireAlarmServiceImpl.class);
@POST
@Path("device/{deviceId}/buzz")
public Response switchBuzzer(@PathParam("deviceId") String deviceId, @FormParam("state") String state) {
if (state == null || state.isEmpty()) {
log.error("State is not defined for the buzzer operation");
return Response.status(Response.Status.BAD_REQUEST).build();
}
String switchToState = state.toUpperCase();
if (!switchToState.equals(VirtualFireAlarmConstants.STATE_ON) && !switchToState.equals(
VirtualFireAlarmConstants.STATE_OFF)) {
log.error("The requested state change shoud be either - 'ON' or 'OFF'");
return Response.status(Response.Status.BAD_REQUEST).build();
}
try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(
new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE),
DeviceGroupConstants.Permissions.DEFAULT_OPERATOR_PERMISSIONS)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
String resource = VirtualFireAlarmConstants.BULB_CONTEXT.replace("/", "");
String actualMessage = resource + ":" + switchToState;
String publishTopic = APIUtil.getTenantDomainOftheUser() + "/"
+ VirtualFireAlarmConstants.DEVICE_TYPE + "/" + deviceId;
ConfigOperation commandOp = new ConfigOperation();
commandOp.setCode("buzz");
commandOp.setEnabled(true);
commandOp.setPayLoad(actualMessage);
Properties props = new Properties();
props.setProperty(VirtualFireAlarmConstants.CLIENT_JID_PROPERTY_KEY, deviceId + "@" + XmppConfig
.getInstance().getServerName());
props.setProperty(VirtualFireAlarmConstants.SUBJECT_PROPERTY_KEY, "CONTROL-REQUEST");
props.setProperty(VirtualFireAlarmConstants.MESSAGE_TYPE_PROPERTY_KEY,
VirtualFireAlarmConstants.CHAT_PROPERTY_KEY);
commandOp.setProperties(props);
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>();
deviceIdentifiers.add(new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE));
APIUtil.getDeviceManagementService().addOperation(VirtualFireAlarmConstants.DEVICE_TYPE, commandOp,
deviceIdentifiers);
return Response.ok().build();
} catch (InvalidDeviceException e) {
String msg = "Error occurred while executing command operation to send keywords";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (OperationManagementException e) {
String msg = "Error occurred while executing command operation upon ringing the buzzer";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
@Path("device/stats/{deviceId}")
@GET
@Consumes("application/json")
@Produces("application/json")
public Response getVirtualFirealarmStats(@PathParam("deviceId") String deviceId, @QueryParam("from") long from,
@QueryParam("to") long to) {
try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(
new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE),
DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
DeviceEventsDAO eventsDAO = new DeviceEventsDAOImpl();
SensorRecord sensorRecord = eventsDAO.getStats(deviceId, from, to);
return Response.status(Response.Status.OK.getStatusCode()).entity(sensorRecord).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
@Path("device/download")
@GET
@Produces("application/zip")
public Response downloadSketch(@QueryParam("deviceName") String deviceName,
@QueryParam("sketchType") String sketchType) {
try {
String user = APIUtil.getAuthenticatedUser() + "@" + PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getTenantDomain();
ZipArchive zipFile = createDownloadFile(user, deviceName, sketchType);
Response.ResponseBuilder response = Response.ok(zipFile.getZipFileContent());
response.status(Response.Status.OK);
response.type("application/zip");
response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\"");
Response resp = response.build();
return resp;
} catch (IllegalArgumentException ex) {
return Response.status(400).entity(ex.getMessage()).build();//bad request
} catch (DeviceManagementException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
} catch (JWTClientException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
} catch (APIManagerException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
} catch (UserStoreException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
} catch (VirtualFirealarmXMPPException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
}
}
private boolean register(String deviceId, String name) {
try {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(VirtualFireAlarmConstants.DEVICE_TYPE);
if (APIUtil.getDeviceManagementService().isEnrolled(deviceIdentifier)) {
return false;
}
Device device = new Device();
device.setDeviceIdentifier(deviceId);
EnrolmentInfo enrolmentInfo = new EnrolmentInfo();
enrolmentInfo.setDateOfEnrolment(new Date().getTime());
enrolmentInfo.setDateOfLastUpdate(new Date().getTime());
enrolmentInfo.setStatus(EnrolmentInfo.Status.ACTIVE);
enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.BYOD);
device.setName(name);
device.setType(VirtualFireAlarmConstants.DEVICE_TYPE);
enrolmentInfo.setOwner(APIUtil.getAuthenticatedUser());
device.setEnrolmentInfo(enrolmentInfo);
return APIUtil.getDeviceManagementService().enrollDevice(device);
} catch (DeviceManagementException e) {
log.error(e.getMessage(), e);
return false;
}
}
private ZipArchive createDownloadFile(String owner, String deviceName, String sketchType)
throws DeviceManagementException, APIManagerException, JWTClientException,
UserStoreException, VirtualFirealarmXMPPException {
//create new device id
String deviceId = shortUUID();
boolean status = register(deviceId, deviceName);
if (!status) {
String msg = "Error occurred while registering the device with " + "id: " + deviceId + " owner:" + owner;
throw new DeviceManagementException(msg);
}
if (apiApplicationKey == null) {
String adminUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName();
String tenantAdminDomainName = PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getTenantDomain();
String applicationUsername =
PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration()
.getAdminUserName() + "@" + PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getTenantDomain();
APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService();
String[] tags = {VirtualFireAlarmConstants.DEVICE_TYPE};
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantAdminDomainName);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(adminUsername);
PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
VirtualFireAlarmConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true,
VirtualFireAlarmConstants.APIM_APPLICATION_TOKEN_VALIDITY_PERIOD);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient();
String deviceType = sketchType.replace(" ", "");
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
StringBuilder scopes = new StringBuilder("device:" + deviceType + ":" + deviceId);
// add scopes for event publishing
scopes.append(" perm:topic:pub:" + tenantDomain + ":" + deviceType + ":" + deviceId + ":temperature");
// add scopes for retrieve operation topic /tenantDomain/deviceType/deviceId/operation/#
scopes.append(" perm:topic:sub:" + tenantDomain + ":" + deviceType + ":" + deviceId + ":operation");
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(),
apiApplicationKey.getConsumerSecret(), owner,
scopes.toString());
String accessToken = accessTokenInfo.getAccessToken();
String refreshToken = accessTokenInfo.getRefreshToken();
XmppAccount newXmppAccount = new XmppAccount();
newXmppAccount.setAccountName(deviceId);
newXmppAccount.setUsername(deviceId);
newXmppAccount.setPassword(accessToken);
newXmppAccount.setEmail(deviceId + "@" + APIUtil.getTenantDomainOftheUser());
status = XmppServerClient.createAccount(newXmppAccount);
if (!status) {
String msg = "XMPP Account was not created for device - " + deviceId + " of owner - " + owner +
".XMPP might have been disabled in org.wso2.carbon.device.mgt.iot" +
".common.config.server.configs";
throw new DeviceManagementException(msg);
}
ZipUtil ziputil = new ZipUtil();
return ziputil.createZipFile(owner, sketchType, deviceId, deviceName, apiApplicationKey.toString(),
accessToken, refreshToken);
}
private static String shortUUID() {
UUID uuid = UUID.randomUUID();
long l = ByteBuffer.wrap(uuid.toString().getBytes(StandardCharsets.UTF_8)).getLong();
return Long.toString(l, Character.MAX_RADIX);
}
}

@ -0,0 +1,89 @@
/*
* 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.service.impl.constants;
public class VirtualFireAlarmConstants {
public final static String DEVICE_TYPE = "virtual_firealarm";
public final static String DEVICE_PLUGIN_DEVICE_NAME = "DEVICE_NAME";
public final static String DEVICE_PLUGIN_DEVICE_ID = "VIRTUAL_FIREALARM_DEVICE_ID";
public final static String STATE_ON = "ON";
public final static String STATE_OFF = "OFF";
public static final String URL_PREFIX = "http://";
public static final String BULB_CONTEXT = "BULB";
public static final String POLICY_CONTEXT = "POLICY";
//sensor events sumerized table name for temperature
// public static final String TEMPERATURE_EVENT_TABLE = "IOT_PER_DEVICE_STREAM_VIRTUALFIREALARM_TEMPERATURE";
public final static String DEVICE_TYPE_PROVIDER_DOMAIN = "carbon.super";
//mqtt tranport related constants
public static final String MQTT_ADAPTER_NAME = "virtual_firealarm_mqtt";
public static final String MQTT_ADAPTER_TYPE = "oauth-mqtt";
public static final String ADAPTER_TOPIC_PROPERTY = "topic";
public static final String MQTT_PORT = "\\$\\{mqtt.broker.port\\}";
public static final String MQTT_BROKER_HOST = "\\$\\{mqtt.broker.host\\}";
public static final String CARBON_CONFIG_PORT_OFFSET = "Ports.Offset";
public static final String DEFAULT_CARBON_LOCAL_IP_PROPERTY = "carbon.local.ip";
public static final int CARBON_DEFAULT_PORT_OFFSET = 0;
public static final int DEFAULT_MQTT_PORT = 1886;
//xmpp transport related constants
public static final String XMPP_ADAPTER_NAME = "virtual_firealarm_xmpp";
public static final String XMPP_ADAPTER_TYPE = "xmpp";
public static final String PASSWORD_PROPERTY_KEY = "password";
public static final String JID_PROPERTY_KEY = "jid";
public static final String CLIENT_JID_PROPERTY_KEY = "xmpp.client.jid";
public static final String SUBJECT_PROPERTY_KEY = "xmpp.client.subject";
public static final String MESSAGE_TYPE_PROPERTY_KEY = "xmpp.client.messageType";
public static final String CHAT_PROPERTY_KEY = "chat";
public static final String USERNAME_PROPERTY_KEY = "username";
public static final String DCR_PROPERTY_KEY = "dcrUrl";
public static final String BROKER_URL_PROPERTY_KEY = "url";
public static final String SCOPES_PROPERTY_KEY = "scopes";
public static final String QOS_PROPERTY_KEY = "qos";
public static final String CLIENT_ID_PROPERTY_KEY = "qos";
public static final String CLEAR_SESSION_PROPERTY_KEY = "clearSession";
public static final String TOPIC = "topic";
public static final String SUBSCRIBED_TOPIC = "carbon.super/virtual_firealarm/+/publisher";
public static final String CONTENT_VALIDATION = "contentValidator";
public static final String CONTENT_TRANSFORMATION = "contentTransformer";
public static final String RESOURCE = "resource";
public static final String JSON_SERIAL_KEY = "SerialNumber";
public static final String TEMPERATURE_STREAM_DEFINITION = "org.wso2.iot.devices.temperature";
public static final String JSON_MESSAGE_KEY = "Msg";
public static final String JSON_SIGNATURE_KEY = "Sig";
public static final String HOST_KEY = "host";
public static final String PORT_KEY = "port";
public static final String SERVER_NAME = "serverName";
public static final String MQTT_ADAPTER_TOPIC_PROPERTY_NAME = "mqtt.adapter.topic";
public static final String APIM_APPLICATION_TOKEN_VALIDITY_PERIOD = "3600";
public static final String PERM_ENROLL_FIRE_ALARM = "/permission/admin/device-mgt/devices/enroll/firealarm";
public static final String PERM_OWNING_DEVICE_VIEW = "/permission/admin/device-mgt/devices/owning-device/view";
public static final String ROLE_NAME = "internal/devicemgt-user";
}

@ -0,0 +1,27 @@
/*
* Copyright (C) 2018 - 2023 Entgra (Pvt) Ltd, Inc - All Rights Reserved.
*
* Unauthorised copying/redistribution of this file, via any medium is strictly prohibited.
*
* Licensed under the Entgra Commercial License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://entgra.io/licenses/entgra-commercial/1.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.service.impl.dao;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.SensorRecord;
public interface DeviceEventsDAO {
SensorRecord getStats(String deviceId, long fromTime, long toTime);
}

@ -0,0 +1,120 @@
/*
* Copyright (C) 2018 - 2023 Entgra (Pvt) Ltd, Inc - All Rights Reserved.
*
* Unauthorised copying/redistribution of this file, via any medium is strictly prohibited.
*
* Licensed under the Entgra Commercial License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://entgra.io/licenses/entgra-commercial/1.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.service.impl.dao;
import org.wso2.carbon.device.mgt.common.exceptions.*;
import org.wso2.carbon.device.mgt.core.dao.util.*;
public class DeviceEventsDAOFactory {
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(DeviceEventsDAOFactory.class);
private static javax.sql.DataSource dataSource;
private static String databaseEngine;
private static final ThreadLocal<java.sql.Connection> currentConnection = new ThreadLocal<>();
public static void init(String jndiName) {
dataSource = DeviceManagementDAOUtil.lookupDataSource(jndiName, null);
try {
databaseEngine = dataSource.getConnection().getMetaData().getDatabaseProductName();
} catch (java.sql.SQLException e) {
log.error("Error occurred while retrieving config.datasource connection", e);
}
}
public static DeviceEventsDAO getDeviceEventDao() {
return new DeviceEventsDAOImpl();
}
public static void openDBConnection() throws DBConnectionException {
java.sql.Connection conn = currentConnection.get();
if (conn != null) {
throw new IllegalTransactionStateException("Database connection has already been obtained.");
}
try {
conn = dataSource.getConnection();
} catch (java.sql.SQLException e) {
throw new DBConnectionException("Failed to get a database connection.", e);
}
currentConnection.set(conn);
}
public static void beginTransaction() throws DBConnectionException {
try {
java.sql.Connection conn = dataSource.getConnection();
conn.setAutoCommit(false);
currentConnection.set(conn);
} catch (java.sql.SQLException e) {
throw new DBConnectionException("Error occurred while retrieving datasource connection", e);
}
}
public static java.sql.Connection getConnection() throws DBConnectionException {
if (currentConnection.get() == null) {
try {
currentConnection.set(dataSource.getConnection());
} catch (java.sql.SQLException e) {
throw new DBConnectionException("Error occurred while retrieving data source connection", e);
}
}
return currentConnection.get();
}
public static void commitTransaction() throws DBConnectionException {
try {
java.sql.Connection conn = currentConnection.get();
if (conn != null) {
conn.commit();
} else {
if (log.isDebugEnabled()) {
log.debug("Datasource connection associated with the current thread is null, hence commit " +
"has not been attempted");
}
}
} catch (java.sql.SQLException e) {
throw new DBConnectionException("Error occurred while committing the transaction", e);
}
}
public static void closeConnection() {
java.sql.Connection conn = currentConnection.get();
try {
if (conn != null) {
conn.close();
}
} catch (java.sql.SQLException e) {
log.error("Error occurred while close the connection");
}
currentConnection.remove();
}
public static void rollbackTransaction() {
java.sql.Connection conn = currentConnection.get();
if (conn == null) {
throw new org.wso2.carbon.device.mgt.common.exceptions.IllegalTransactionStateException("Database connection is not active. Hence, rollback is "
+ "not attempted.");
}
try {
conn.rollback();
} catch (java.sql.SQLException e) {
log.warn("Error occurred while roll-backing the transaction", e);
}
}
}

@ -0,0 +1,77 @@
/*
* Copyright (C) 2018 - 2023 Entgra (Pvt) Ltd, Inc - All Rights Reserved.
*
* Unauthorised copying/redistribution of this file, via any medium is strictly prohibited.
*
* Licensed under the Entgra Commercial License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://entgra.io/licenses/entgra-commercial/1.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.service.impl.dao;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.SensorRecord;
import org.wso2.carbon.device.mgt.common.exceptions.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Implements MobileDeviceDAO for Android Devices.
*/
public class DeviceEventsDAOImpl implements DeviceEventsDAO {
private static final Log log = LogFactory.getLog(DeviceEventsDAOImpl.class);
@Override
public SensorRecord getStats(String deviceId, long fromTime, long toTime) {
String sql = "SELECT * FROM TABLE_VIRTUALFIREALARM_CARBONSUPER_RDBMS_PUBLISHER WHERE " +
"META_DEVICEID = ? AND " +
"META_TIME >= ? AND " +
"META_TIME <= ? " +
"ORDER BY META_TIME ASC";
Map<Long, Float> stats = new LinkedHashMap<>();
try {
DeviceEventsDAOFactory.init("jdbc/EVENT_DB");
Connection conn = DeviceEventsDAOFactory.getConnection();
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, deviceId);
stmt.setLong(2, fromTime);
stmt.setLong(3, toTime);
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
stats.put(rs.getLong("META_TIME"), rs.getFloat("TEMPERATURE"));
}
}
} catch (SQLException e) {
String msg = "Error occurred while retrieving device details";
log.error(msg);
}
} catch (DBConnectionException e) {
String msg = "Error occurred while obtaining DB connection to retrieve device details";
log.error(msg);
}
// stats.entrySet()
// .stream()
// .sorted(Map.Entry.<Long, Float>comparingByKey())
// .forEach(System.out::println);
return new SensorRecord(stats);
}
}

@ -0,0 +1,33 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@XmlRootElement
/**
* This stores sensor event data for virtual fire alarm sense.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class SensorRecord {
@XmlElementWrapper(required = true, name = "stats")
private Map<Long, Float> stats;
public Map<Long, Float> getStats() {
return stats;
}
public void setStats(Map<Long, Float> stats) {
this.stats = stats;
}
public SensorRecord(Map<Long, Float> stats) {
this.stats = stats;
}
}

@ -0,0 +1,35 @@
/*
* 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.service.impl.exception;
public class VirtualFireAlarmException extends Exception {
private static final long serialVersionUID = 118512086957330189L;
public VirtualFireAlarmException(String errorMessage) {
super(errorMessage);
}
public VirtualFireAlarmException(String errorMessage, Throwable throwable) {
super(errorMessage, throwable);
}
public VirtualFireAlarmException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,104 @@
/*
* Copyright (c) 2017, 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.
*/
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.listener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.user.api.AuthorizationManager;
import org.wso2.carbon.user.api.Permission;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.user.core.service.RealmService;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class VirtualFireAlarmPermissionUpdateListener implements ServletContextListener {
private static Log log = LogFactory.getLog(VirtualFireAlarmPermissionUpdateListener.class);
private static PrivilegedCarbonContext threadLocalCarbonContext;
private static RealmService realmService;
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
realmService = (RealmService) threadLocalCarbonContext.getOSGiService(RealmService.class, null);
UserStoreManager userStoreManager = getUserStoreManager();
try {
if (userStoreManager != null) {
if (!userStoreManager.isExistingRole(VirtualFireAlarmConstants.ROLE_NAME)) {
userStoreManager.addRole(VirtualFireAlarmConstants.ROLE_NAME, null, getPermissions());
} else {
getAuthorizationManager().authorizeRole(VirtualFireAlarmConstants.ROLE_NAME,
VirtualFireAlarmConstants.PERM_ENROLL_FIRE_ALARM, CarbonConstants.UI_PERMISSION_ACTION);
getAuthorizationManager().authorizeRole(VirtualFireAlarmConstants.ROLE_NAME,
VirtualFireAlarmConstants.PERM_OWNING_DEVICE_VIEW, CarbonConstants.UI_PERMISSION_ACTION);
}
}
} catch (UserStoreException e) {
log.error("Error while creating a role and adding a user for Raspberry PI.", e);
}
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
private UserStoreManager getUserStoreManager() {
UserStoreManager userStoreManager;
try {
if (realmService == null) {
String msg = "Realm service has not initialized.";
throw new IllegalStateException(msg);
}
int tenantId = threadLocalCarbonContext.getTenantId();
userStoreManager = realmService.getTenantUserRealm(tenantId).getUserStoreManager();
realmService.getTenantUserRealm(tenantId).getAuthorizationManager();
} catch (UserStoreException e) {
String msg = "Error occurred while retrieving current user store manager";
throw new IllegalStateException(msg);
}
return userStoreManager;
}
private AuthorizationManager getAuthorizationManager() {
AuthorizationManager authorizationManager;
try {
if (realmService == null) {
String msg = "Realm service has not initialized.";
throw new IllegalStateException(msg);
}
int tenantId = threadLocalCarbonContext.getTenantId();
authorizationManager = realmService.getTenantUserRealm(tenantId).getAuthorizationManager();
} catch (UserStoreException e) {
String msg = "Error occurred while retrieving current user store manager";
throw new IllegalStateException(msg);
}
return authorizationManager;
}
private Permission[] getPermissions() {
Permission androidSense = new Permission(VirtualFireAlarmConstants.PERM_ENROLL_FIRE_ALARM,
CarbonConstants.UI_PERMISSION_ACTION);
Permission view = new Permission(VirtualFireAlarmConstants.PERM_OWNING_DEVICE_VIEW,
CarbonConstants.UI_PERMISSION_ACTION);
return new Permission[]{androidSense, view};
}
}

@ -0,0 +1,94 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
/**
* This class provides utility functions used by REST-API.
*/
public class APIUtil {
private static Log log = LogFactory.getLog(APIUtil.class);
public static String getAuthenticatedUser() {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
String username = threadLocalCarbonContext.getUsername();
String tenantDomain = threadLocalCarbonContext.getTenantDomain();
if (username.endsWith(tenantDomain)) {
return username.substring(0, username.lastIndexOf("@"));
}
return username;
}
public static DeviceManagementProviderService getDeviceManagementService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceManagementProviderService deviceManagementProviderService =
(DeviceManagementProviderService) ctx.getOSGiService(DeviceManagementProviderService.class, null);
if (deviceManagementProviderService == null) {
String msg = "Device Management service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return deviceManagementProviderService;
}
public static APIManagementProviderService getAPIManagementProviderService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
APIManagementProviderService apiManagementProviderService =
(APIManagementProviderService) ctx.getOSGiService(APIManagementProviderService.class, null);
if (apiManagementProviderService == null) {
String msg = "API management provider service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return apiManagementProviderService;
}
public static JWTClientManagerService getJWTClientManagerService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
JWTClientManagerService jwtClientManagerService =
(JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
if (jwtClientManagerService == null) {
String msg = "JWT Client manager service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return jwtClientManagerService;
}
public static String getTenantDomainOftheUser() {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
return threadLocalCarbonContext.getTenantDomain();
}
public static DeviceAccessAuthorizationService getDeviceAccessAuthorizationService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceAccessAuthorizationService deviceAccessAuthorizationService =
(DeviceAccessAuthorizationService) ctx.getOSGiService(DeviceAccessAuthorizationService.class, null);
if (deviceAccessAuthorizationService == null) {
String msg = "Device Authorization service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return deviceAccessAuthorizationService;
}
public static PlatformConfigurationManagementService getTenantConfigurationManagementService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
PlatformConfigurationManagementService tenantConfigurationManagementService =
(PlatformConfigurationManagementService) ctx.getOSGiService(PlatformConfigurationManagementService.class, null);
if (tenantConfigurationManagementService == null) {
String msg = "Tenant configuration Management service not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return tenantConfigurationManagementService;
}
}

@ -0,0 +1,25 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
public class VirtualFireAlarmUtilConstants {
public static final String TENANT_DOMAIN = "TENANT_DOMAIN";
public static final String DEVICE_OWNER = "DEVICE_OWNER";
public static final String DEVICE_ID = "DEVICE_ID";
public static final String DEVICE_NAME = "DEVICE_NAME";
public static final String HTTPS_EP = "HTTPS_EP";
public static final String HTTP_EP = "HTTP_EP";
public static final String APIM_EP = "APIM_EP";
public static final String MQTT_EP = "MQTT_EP";
public static final String XMPP_EP = "XMPP_EP";
public static final String VIRTUAL_FIREALARM_HTTPS_EP = "VIRTUAL_FIREALARM_HTTPS_EP";
public static final String VIRTUAL_FIREALARM_HTTP_EP = "VIRTUAL_FIREALARM_HTTP_EP";
public static final String VIRTUAL_FIREALARM_APIM_EP = "VIRTUAL_FIREALARM_APIM_EP";
public static final String VIRTUAL_FIREALARM_MQTT_EP = "VIRTUAL_FIREALARM_MQTT_EP";
public static final String VIRTUAL_FIREALARM_XMPP_EP = "VIRTUAL_FIREALARM_XMPP_EP";
public static final String API_APPLICATION_KEY = "API_APPLICATION_KEY";
public static final String DEVICE_TOKEN = "DEVICE_TOKEN";
public static final String DEVICE_REFRESH_TOKEN = "DEVICE_REFRESH_TOKEN";
public static final String SERVER_NAME = "SERVER_NAME";
public static final String SERVER_JID = "SERVER_JID";
}

@ -0,0 +1,43 @@
/*
* 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.service.impl.util;
import java.util.zip.ZipOutputStream;
/**
* This is an utility class to hold zip files.
*/
public class ZipArchive {
private byte[] zipFileContent = null;
private String fileName = null;
public ZipArchive(String fileName, byte[] zipFile) {
this.fileName = fileName;
this.zipFileContent = zipFile;
}
public byte[] getZipFileContent() {
return zipFileContent;
}
public String getFileName() {
return fileName;
}
}

@ -0,0 +1,341 @@
/*
* Copyright (c) 2016, 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.service.impl.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.application.extension.constants.ApiApplicationConstants;
import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.XmppConfig;
import org.wso2.carbon.utils.CarbonUtils;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* This is used to create a zip file that includes the necessary configuration required for the agent.
*/
public class ZipUtil {
private static final Log log = LogFactory.getLog(ZipUtil.class);
private static final String LOCALHOST = "localhost";
private static final String HTTPS_PROTOCOL_URL = "https://${iot.gateway.host}:${iot.gateway.https.port}";
private static final String HTTP_PROTOCOL_URL = "http://${iot.gateway.host}:${iot.gateway.http.port}";
private static final String CONFIG_TYPE = "general";
private static final String DEFAULT_MQTT_ENDPOINT = "tcp://${mqtt.broker.host}:${mqtt.broker.port}";
public ZipArchive createZipFile(String owner, String deviceType, String deviceId, String deviceName,
String apiApplicationKey, String token, String refreshToken)
throws DeviceManagementException {
String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches";
String templateSketchPath = sketchFolder + File.separator + deviceType;
String iotServerIP;
try {
iotServerIP = "127.0.0.1"; //getServerUrl();
String httpsServerEP = Utils.replaceSystemProperty(HTTPS_PROTOCOL_URL);
String httpServerEP = Utils.replaceSystemProperty(HTTP_PROTOCOL_URL);
String mqttEndpoint = Utils.replaceSystemProperty(DEFAULT_MQTT_ENDPOINT);
if (mqttEndpoint.contains(LOCALHOST)) {
mqttEndpoint = mqttEndpoint.replace(LOCALHOST, iotServerIP);
httpsServerEP = httpsServerEP.replace(LOCALHOST, iotServerIP);
httpServerEP = httpServerEP.replace(LOCALHOST, iotServerIP);
}
String xmppEndpoint = "";
if (XmppConfig.getInstance().isEnabled()) {
xmppEndpoint = XmppConfig.getInstance().getHost() + ":" + XmppConfig.getInstance().getPort();
if (xmppEndpoint.contains(LOCALHOST)) {
xmppEndpoint = xmppEndpoint.replace(LOCALHOST, iotServerIP);
}
}
PlatformConfiguration configuration = APIUtil.getTenantConfigurationManagementService().getConfiguration(
CONFIG_TYPE);
if (configuration != null && configuration.getConfiguration() != null && configuration
.getConfiguration().size() > 0) {
List<ConfigurationEntry> configurations = configuration.getConfiguration();
for (ConfigurationEntry configurationEntry : configurations) {
switch (configurationEntry.getName()) {
case VirtualFireAlarmUtilConstants.VIRTUAL_FIREALARM_HTTPS_EP:
httpsServerEP = (String)configurationEntry.getValue();
break;
case VirtualFireAlarmUtilConstants.VIRTUAL_FIREALARM_HTTP_EP:
httpServerEP = (String)configurationEntry.getValue();
break;
case VirtualFireAlarmUtilConstants.VIRTUAL_FIREALARM_MQTT_EP:
mqttEndpoint = (String)configurationEntry.getValue();
break;
case VirtualFireAlarmUtilConstants.VIRTUAL_FIREALARM_XMPP_EP:
xmppEndpoint = (String)configurationEntry.getValue();
break;
}
}
}
String base64EncodedApplicationKey = getBase64EncodedAPIAppKey(apiApplicationKey).trim();
Map<String, String> contextParams = new HashMap<>();
contextParams.put(VirtualFireAlarmUtilConstants.TENANT_DOMAIN, APIUtil.getTenantDomainOftheUser());
contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_OWNER, owner);
contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_ID, deviceId);
contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_NAME, deviceName);
contextParams.put(VirtualFireAlarmUtilConstants.HTTPS_EP, httpsServerEP);
contextParams.put(VirtualFireAlarmUtilConstants.HTTP_EP, httpServerEP);
contextParams.put(VirtualFireAlarmUtilConstants.APIM_EP, httpServerEP);
contextParams.put(VirtualFireAlarmUtilConstants.MQTT_EP, mqttEndpoint);
contextParams.put(VirtualFireAlarmUtilConstants.XMPP_EP, "XMPP:" + xmppEndpoint);
contextParams.put(VirtualFireAlarmUtilConstants.API_APPLICATION_KEY, base64EncodedApplicationKey);
contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_TOKEN, token);
contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_REFRESH_TOKEN, refreshToken);
contextParams.put(VirtualFireAlarmUtilConstants.SERVER_NAME, XmppConfig.getInstance().getServerName() == null
? "" : XmppConfig.getInstance().getServerName());
contextParams.put(VirtualFireAlarmUtilConstants.SERVER_JID, XmppConfig.getInstance().getJid() == null
? "" : XmppConfig.getInstance().getJid());
ZipArchive zipFile;
zipFile = getSketchArchive(templateSketchPath, contextParams, deviceName);
return zipFile;
} catch (IOException e) {
throw new DeviceManagementException("Zip File Creation Failed", e);
} catch (ConfigurationManagementException e) {
throw new DeviceManagementException("Failed to retrieve configuration", e);
}
}
private String getBase64EncodedAPIAppKey(String apiAppCredentialsAsJSONString) {
JSONObject jsonObject = new JSONObject(apiAppCredentialsAsJSONString);
String consumerKey = jsonObject.get(ApiApplicationConstants.OAUTH_CLIENT_ID).toString();
String consumerSecret = jsonObject.get(ApiApplicationConstants.OAUTH_CLIENT_SECRET).toString();
String stringToEncode = consumerKey + ":" + consumerSecret;
return Base64.encodeBase64String(stringToEncode.getBytes());
}
private static String getServerUrl() {
try {
return org.apache.axis2.util.Utils.getIpAddress();
} catch (SocketException e) {
log.warn("Failed retrieving the hostname, therefore set to localhost", e);
return "localhost";
}
}
private ZipArchive getSketchArchive(String templateSketchPath, Map contextParams
, String zipFileName)
throws DeviceManagementException, IOException {
String sketchPath = CarbonUtils.getCarbonHome() + File.separator + templateSketchPath;
zipFileName = zipFileName + ".zip";
try {
Map<String, List<String>> properties = getProperties(sketchPath + File.separator + "sketch" + ".properties");
List<String> templateFiles = properties.get("templates");
List<TemplateFile> processTemplateFiles = new ArrayList<>();
for (String templateFile : templateFiles) {
TemplateFile tFile = new TemplateFile();
tFile.setContent(parseTemplate(templateSketchPath + File.separator + templateFile, contextParams));
tFile.setFileName(templateFile);
processTemplateFiles.add(tFile);
}
templateFiles.add("sketch.properties"); // ommit copying the props file
byte[] zip = createZipArchive(templateSketchPath, processTemplateFiles);
return new ZipArchive(zipFileName, zip);
} catch (IOException ex) {
throw new DeviceManagementException(
"Error occurred when trying to read property " + "file sketch.properties", ex);
}
}
private static Map<String, List<String>> getProperties(String propertyFilePath) throws IOException {
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream(propertyFilePath);
// load a properties file
prop.load(input);
Map<String, List<String>> properties = new HashMap<String, List<String>>();
String templates = prop.getProperty("templates");
List<String> list = new ArrayList<String>(Arrays.asList(templates.split(",")));
properties.put("templates", list);
final String filename = prop.getProperty("zipfilename");
list = new ArrayList<String>() {{
add(filename);
}};
properties.put("zipfilename", list);
return properties;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
log.error("Failed closing connection", e);
}
}
}
}
private static String parseTemplate(String srcFile, Map contextParams) throws IOException {
//read from file
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(srcFile);
String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8.toString());
Iterator iterator = contextParams.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry mapEntry = (Map.Entry) iterator.next();
content = content.replaceAll("\\$\\{" + mapEntry.getKey() + "\\}", mapEntry.getValue().toString());
}
return content;
} finally {
if (inputStream != null) {
inputStream.close();
}
}
}
private static byte[] createZipArchive(String srcFolder, List<TemplateFile> processTemplateFiles) throws IOException {
ZipOutputStream out = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
out = new ZipOutputStream(new BufferedOutputStream(baos));
File subDir = new File(srcFolder);
String subdirList[] = subDir.list();
if (subdirList == null) {
log.warn("The sub directory " + subDir.getAbsolutePath() + " is empty");
return null;
}
for (String sd : subdirList) {
// get a list of files from current directory
File f = new File(srcFolder + File.separator + sd);
if (f.isDirectory()) {
String files[] = f.list();
if (files == null) {
log.warn("The current directory " + f.getAbsolutePath() + " is empty. Has no files");
return null;
}
for (int i = 0; i < files.length; i++) {
boolean fileAdded = false;
for (TemplateFile templateFile : processTemplateFiles) {
if (files[i].equals(templateFile.getFileName())) {
ZipEntry entry = new ZipEntry(templateFile.getFileName());
out.putNextEntry(entry);
out.write(templateFile.getContent().getBytes());
out.closeEntry();
fileAdded = true;
break;
} else if (f.getName().equals("sketch.properties")) {
fileAdded = true;
break;
}
}
if (fileAdded) {
continue;
}
ZipEntry entry = new ZipEntry(sd + File.separator + files[i]);
out.putNextEntry(entry);
out.write(IOUtils.toByteArray(new FileInputStream(srcFolder + File.separator + sd
+ File.separator + files[i])));
out.closeEntry();
}
} else //it is just a file
{
boolean fileAdded = false;
for (TemplateFile templateFile : processTemplateFiles) {
if (f.getName().equals(templateFile.getFileName())) {
ZipEntry entry = new ZipEntry(templateFile.getFileName());
out.putNextEntry(entry);
out.write(templateFile.getContent().getBytes());
out.closeEntry();
fileAdded = true;
break;
} else if (f.getName().equals("sketch.properties")) {
fileAdded = true;
break;
}
}
if (fileAdded) {
continue;
}
ZipEntry entry = new ZipEntry(sd);
out.putNextEntry(entry);
out.write(IOUtils.toByteArray(new FileInputStream(f)));
out.closeEntry();
}
}
out.finish();
} finally {
if (out != null) {
out.close();
}
}
return baos.toByteArray();
}
public class TemplateFile {
private String content;
private String fileName;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}
}

@ -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.service.impl.xmpp;
public class VirtualFirealarmXMPPException extends Exception{
private String errorMessage;
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public VirtualFirealarmXMPPException(String msg, Exception nestedEx) {
super(msg, nestedEx);
setErrorMessage(msg);
}
public VirtualFirealarmXMPPException(String message, Throwable cause) {
super(message, cause);
setErrorMessage(message);
}
public VirtualFirealarmXMPPException(String msg) {
super(msg);
setErrorMessage(msg);
}
public VirtualFirealarmXMPPException() {
super();
}
public VirtualFirealarmXMPPException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,63 @@
/*
* 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.service.impl.xmpp;
/**
* holds the information related to account that needs to be created on xmpp server.
*/
public class XmppAccount {
private String username;
private String password;
private String accountName;
private String email;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

@ -0,0 +1,124 @@
/*
* 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.service.impl.xmpp;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class XmppConfig {
private String host;
private int port;
private String username;
private String password;
private String serverName;
private boolean enabled;
private String jid;
private static XmppConfig xmppConfig = new XmppConfig();
private static final Log log = LogFactory.getLog(XmppConfig.class);
private static final String ENABLED = "enabled";
private static final String USERNAME = "username";
private static final String PASSWORD = "password";
private static final String HOST = "host";
private static final String PORT = "port";
private static final String SERVERNAME = "serverName";
private static final String JID = "jid";
private XmppConfig() {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("../xmpp.properties");
Properties properties = new Properties();
try {
properties.load(input);
enabled = Boolean.parseBoolean(properties.getProperty(ENABLED, "false"));
host = properties.getProperty(HOST);
port = Integer.parseInt(properties.getProperty(PORT));
username = properties.getProperty(USERNAME);
password = properties.getProperty(PASSWORD);
serverName = properties.getProperty(SERVERNAME);
jid = properties.getProperty(JID);
} catch (IOException e) {
log.error("Failed to load xmpp config properties.");
}
}
public static XmppConfig getInstance() {
return xmppConfig;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getServerName() {
return serverName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getJid() {
return jid;
}
public void setJid(String jid) {
this.jid = jid;
}
}

@ -0,0 +1,66 @@
/*
* 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.service.impl.xmpp;
import org.jivesoftware.smack.AccountManager;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import java.util.HashMap;
import java.util.Map;
public class XmppServerClient {
public static boolean createAccount(XmppAccount xmppAccount) throws VirtualFirealarmXMPPException {
if (XmppConfig.getInstance().isEnabled()) {
if (xmppAccount != null) {
try {
ConnectionConfiguration config = new ConnectionConfiguration(XmppConfig.getInstance().getHost(),
XmppConfig.getInstance().getPort(),
"Accounts");
XMPPConnection xmppConnection = new XMPPConnection(config);
xmppConnection.connect();
xmppConnection.login(XmppConfig.getInstance().getUsername(), XmppConfig.getInstance().getPassword());
AccountManager accountManager = xmppConnection.getAccountManager();
Map<String, String> attributes = new HashMap<>();
attributes.put("username", xmppAccount.getUsername());
attributes.put("password", xmppAccount.getPassword());
attributes.put("email", xmppAccount.getEmail());
attributes.put("name", xmppAccount.getAccountName());
accountManager.createAccount(xmppAccount.getUsername(), xmppAccount.getPassword(), attributes);
xmppConnection.disconnect();
return true;
} catch (XMPPException e) {
if (e.getXMPPError().getCode() == 409) {
//AccountAlreadyExist
return true;
} else {
throw new VirtualFirealarmXMPPException(
"XMPP account creation failed. Error: " + e.getLocalizedMessage(), e);
}
}
} else {
throw new VirtualFirealarmXMPPException("Invalid XMPP attributes");
}
} else {
return true;
}
}
}

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016, 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.
-->
<!-- This file contains the list of permissions that are associated with URL end points
of the web app. Each permission should contain the name, permission path ,API path
(URL) , HTTP method and OAUTH2 authorization scope (not-required).
When defining dynamic paths for APIs, path variables are denoted by '*' notation.
NOTE: All the endpoints of the web app should be available in this file. Otherwise
it will result 403 error at the runtime.
-->
<PermissionConfiguration>
<APIVersion></APIVersion>
<!-- Device related APIs -->
<Permission>
<name>Download device</name>
<path>/device-mgt/user/devices</path>
<url>/device/download</url>
<method>GET</method>
<scope>virtual_firealarm_user</scope>
</Permission>
<Permission>
<name>Control Buzz</name>
<path>/device-mgt/user/operation</path>
<url>/device/*/buzz</url>
<method>POST</method>
<scope>virtual_firealarm_user</scope>
</Permission>
<Permission>
<name>Get Stats</name>
<path>/device-mgt/user/stats</path>
<url>/device/stats/*</url>
<method>GET</method>
<scope>virtual_firealarm_user</scope>
</Permission>
</PermissionConfiguration>

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ Copyright 2005-2013 WSO2, Inc. (http://wso2.com)
~
~ 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.
-->
<!--
This file defines class loading policy of the whole container. But this behaviour can be overridden by individual webapps by putting this file into the META-INF/ directory.
-->
<Classloading xmlns="http://wso2.org/projects/as/classloading">
<!-- Parent-first or child-first. Default behaviour is child-first.-->
<ParentFirst>false</ParentFirst>
<!--
Default environments that contains provides to all the webapps. This can be overridden by individual webapps by specifing required environments
Tomcat environment is the default and every webapps gets it even if they didn't specify it.
e.g. If a webapps requires CXF, they will get both Tomcat and CXF.
-->
<Environments>CXF3,Carbon</Environments>
</Classloading>

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2016, 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.
-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<jaxrs:server id="VirtualFireAlarm" address="/">
<jaxrs:serviceBeans>
<bean id="VirtualFireAlarmService"
class="org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.VirtualFireAlarmServiceImpl">
</bean>
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
</beans>

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
metadata-complete="true">
<display-name>WSO2 IoT Server</display-name>
<description>WSO2 IoT Server</description>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>isSharedWithAllTenants</param-name>
<param-value>true</param-value>
</context-param>
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<listener-class>org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.listener.VirtualFireAlarmPermissionUpdateListener</listener-class>
</listener>
</web-app>

@ -0,0 +1,25 @@
#
# Copyright (c) 2016, 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.
#
#
#[XMPP-Configurations]
enabled=false
username=admin
password=admin
host=localhost
port=5222
serverName=localhost
jid=admin@localhost

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2014, 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">
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>device-types</artifactId>
<version>6.0.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>virtual-fire-alarm-plugin</artifactId>
<packaging>pom</packaging>
<name>WSO2 Carbon - Virtual Fire Alarm Plugin</name>
<url>http://wso2.org</url>
<modules>
<module>org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.impl</module>
<module>org.wso2.carbon.device.mgt.iot.virtualfirealarm.api</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.7.2</version>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

@ -199,7 +199,7 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
try {
String mqttMsgString = mqttMessage.toString();
String msgText = mqttMsgString.substring(mqttMsgString.indexOf("{"), mqttMsgString.indexOf("}") +1);
String msgText = mqttMsgString.substring(mqttMsgString.indexOf("{"), mqttMsgString.lastIndexOf("}") + 1);
if (log.isDebugEnabled()) {
log.debug(msgText);
}

@ -467,8 +467,8 @@ public class ExServer {
String deviceType = null;
String deviceId = null;
for (String scope : scopeArray) {
if (scope.startsWith("device_")) {
String[] scopeParts = scope.split("_");
if (scope.startsWith("device:")) {
String[] scopeParts = scope.split(":");
deviceType = scopeParts[1];
deviceId = scopeParts[2];
break;

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016, 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">
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>carbon-device-mgt-plugins-parent</artifactId>
<version>6.0.16-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>device-types-feature</artifactId>
<packaging>pom</packaging>
<name>WSO2 Carbon - Device Management IoT Plugins Feature</name>
<url>http://wso2.org</url>
<modules>
<module>virtual-fire-alarm-plugin-feature</module>
</modules>
</project>

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2016, 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/maven-v4_0_0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>virtual-fire-alarm-plugin-feature</artifactId>
<version>6.0.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.backend.feature</artifactId>
<packaging>pom</packaging>
<name>WSO2 Carbon - IoT Server VirtualFireAlarm Backend Feature</name>
<url>http://wso2.org</url>
<description>This feature contains the VirtualFireAlarm Device type specific backend implementations for the IoT Server
</description>
<!-- <properties>-->
<!-- <orbit.h2.version>1.4.199.wso2v1</orbit.h2.version>-->
<!-- </properties>-->
<dependencies>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.api</artifactId>
<version>${carbon.devicemgt.plugins.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.wso2.orbit.com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${orbit.h2.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>src/main/resources</outputDirectory>
<resources>
<resource>
<directory>resources</directory>
<includes>
<include>build.properties</include>
<include>p2.inf</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-jaxrs-war</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.api
</artifactId>
<type>war</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/maven-shared-archive-resources/webapps/</outputDirectory>
<destFileName>virtual_firealarm.war</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<execution>
<id>copy-agent-jar</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.impl
</artifactId>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/maven-shared-archive-resources/agent/</outputDirectory>
<destFileName>wso2-firealarm-virtual-agent.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.wso2.maven</groupId>
<artifactId>carbon-p2-plugin</artifactId>
<version>${carbon.p2.plugin.version}</version>
<executions>
<execution>
<id>p2-feature-generation</id>
<phase>package</phase>
<goals>
<goal>p2-feature-gen</goal>
</goals>
<configuration>
<id>org.wso2.carbon.device.mgt.iot.virtualfirealarm.backend</id>
<propertiesFile>../../../features/etc/feature.properties</propertiesFile>
<adviceFile>
<properties>
<propertyDef>org.wso2.carbon.p2.category.type:server</propertyDef>
<propertyDef>org.eclipse.equinox.p2.type.group:true</propertyDef>
</properties>
</adviceFile>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,34 @@
#
# 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]
tenantDomain=${TENANT_DOMAIN}
owner=${DEVICE_OWNER}
deviceId=${DEVICE_ID}
device-name=${DEVICE_NAME}
https-ep=${HTTPS_EP}
http-ep=${HTTP_EP}
apim-ep=${APIM_EP}
mqtt-ep=${MQTT_EP}
xmpp-ep=${XMPP_EP}
application-key=${API_APPLICATION_KEY}
auth-token=${DEVICE_TOKEN}
refresh-token=${DEVICE_REFRESH_TOKEN}
push-interval=15
xmpp-server-name=${SERVER_NAME}
server-jid=${SERVER_JID}

@ -0,0 +1,7 @@
@echo off
echo.
echo.WSO2 IOT Sample
echo.Virtual Fire Alarm
echo.initializing agent
echo.
java -jar wso2-firealarm-virtual-agent.jar

@ -0,0 +1,190 @@
#!/bin/bash
echo "----------------------------------------------------------------"
echo "| WSO2 IOT Sample "
echo "| Virtual RaspiAlarm "
echo "| ---------------- "
echo "| ....initializing startup-script "
echo "----------------------------------------------------------------"
#while true; do
# read -p "What is the network-interface of your device that the Agent should use (find from ifconfig. ex: wlan0,en0,eth0..) > " interface
#
# echo "Setting the network-interface to " $interface
# sed s/^network-interface=.*/network-interface=$interface/ deviceConfig.properties > myTmp
# mv -f myTmp deviceConfig.properties
# break;
#done
#
#while true; do
# read -p "Whats the time-interval (in seconds) between successive Data-Pushes to the WSO2-IoT-Server (ex: '60' indicates 1 minute) > " interval
#
# if [ $interval -eq $interval 2>/dev/null ]
# then
# echo "Setting data-push interval to " $interval " seconds."
# sed s/^push-interval=.*/push-interval=$interval/ deviceConfig.properties > myTmp
# mv -f myTmp deviceConfig.properties
# break;
# else
# echo "Input needs to be an integer indicating the number seconds between successive data-pushes."
# fi
#done
java -jar wso2-firealarm-virtual-agent.jar
#while true; do
# read -p "Do you wish to run 'apt-get update' and continue? [Yes/No] " yn
# case $yn in
# [Yy]* ) sudo apt-get update;
# break;;
# [Nn]* ) echo "Continuing without apt-get update...";
# break;;
# * ) echo "Please answer yes or no.";
# esac
#done
#
#if [ $? -ne 0 ]; then
# echo "apt-get update failed.... Some dependencies may not get installed"
# echo "If an already installed version of the package exists, try running:"
# echo "----------------------------------------------------------------"
# echo "sudo -i"
# echo "cd /var/lib/dpkg/info"
# echo "rm -rf wso2-raspi-alarm*"
# echo "dpkg --remove --force-remove-reinstreq wso2-raspi-alarm"
# echo "exit"
# echo "----------------------------------------------------------------"
# echo "Retry Installation...."
# break;
#fi
#
#echo "Installing 'gdebi' package..."
#sudo apt-get install gdebi # installation of gdebi
#
#
#if [ $? -ne 0 ]; then
# echo "gdebi installation failed.... dependencies will not be installed without gdebi"
# read -p "Do you wish to continue without gdebi? [Yes/No] " yn
# case $yn in
# [Yy]* ) echo "Continueing without gdebi.....";;
# [Nn]* ) echo "Try to resolve errors and re-run the script.";
# exit;;
# * ) exit;;
# esac
#fi
#
#
#for f in ./wso2-raspi-alarm_1.0_armhf.deb; do
# ## Check if the glob gets expanded to existing files.
# ## If not, f here will be exactly the pattern above
# ## and the exists test will evaluate to false.
# # [ -e "$f" ] && echo "'wso2-raspi-alarm_1.0_armhf.deb' file found and installing" || echo "'wso2-raspi-alarm_1.0_armhf.deb' file does not exist in current path"; exit;
# if [ -e "$f" ]; then
# echo "'wso2-raspi-alarm_1.0_armhf.deb' file found and installing now...."
# else
# echo "'wso2-raspi-alarm_1.0_armhf.deb' file does not exist in current path. \nExiting installation...";
# exit;
# fi
# ## This is all we needed to know, so we can break after the first iteration
# break
#done
#
#echo "Installing the 'wso2-raspi-alarm deb package'"
#sudo gdebi wso2-raspi-alarm_1.0_armhf.deb
#
#if [ $? -ne 0 ]; then
# echo "Installation Failed...."
# exit;
#fi
#sudo killall -9 python
#
#for f in ./RaspberryAgent.zip; do
# ## Check if the glob gets expanded to existing files.
# ## If not, f here will be exactly the pattern above
# ## and the exists test will evaluate to false.
# # [ -e "$f" ] && echo "'wso2-raspi-alarm_1.0_armhf.deb' file found and installing" || echo "'wso2-raspi-alarm_1.0_armhf.deb' file does not exist in current path"; exit;
# if [ -e "$f" ]; then
# echo "Agent files found......"
# sudo rm -rf /usr/local/src/RaspberryAgent
# sudo unzip RaspberryAgent.zip -d /usr/local/src/
# else
# echo "'RaspberryAgent.zip' file does not exist in current path. \nInstalling without upgrading agent...";
# fi
# ## This is all we needed to know, so we can break after the first iteration
# break
#done
#
#for f in /usr/local/src/RaspberryAgent/rc.local; do
# ## Check if the glob gets expanded to existing files.
# ## If not, f here will be exactly the pattern above
# ## and the exists test will evaluate to false.
# if [ -e "$f" ]; then
# echo "Copying boot script"
# sudo mv /usr/local/src/RaspberryAgent/rc.local /etc/rc.local
# sudo chmod +x /etc/rc.local
# else
# echo "Unable to set agent statup on boot";
# fi
# ## This is all we needed to know, so we can break after the first iteration
# break
#done
#
#for f in ./deviceConfigs.cfg; do
# ## Check if the glob gets expanded to existing files.
# ## If not, f here will be exactly the pattern above
# ## and the exists test will evaluate to false.
# if [ -e "$f" ]; then
# echo "Configuration file found......"
# else
# echo "'deviceConfigs.cfg' file does not exist in current path. \nExiting installation...";
# exit;
# fi
# ## This is all we needed to know, so we can break after the first iteration
# break
#done
#
#echo "Altering Configuration file"
#sed -i 's|[/,]||g' deviceConfigs.cfg
#
#echo "Copying configurations file to /usr/local/src/RaspberryAgent"
#sudo cp ./deviceConfigs.cfg /usr/local/src/RaspberryAgent/
#
#if [ $? -ne 0 ]; then
# echo "Copying configuration file failed...."
# exit;
#fi
#
#while true; do
# read -p "Whats the time-interval (in seconds) between successive Data-Pushes to the WSO2-DC (ex: '60' indicates 1 minute) > " input
#
# if [ $input -eq $input 2>/dev/null ]
# then
# echo "Setting data-push interval to $input seconds."
# echo $input > /usr/local/src/RaspberryAgent/time-interval
# break;
# else
# echo "Input needs to be an integer indicating the number seconds between successive data-pushes."
# fi
#done
#
#cd /usr/local/src/RaspberryAgent/
#sudo chmod +x RaspberryStats.py
#sudo nohup ./RaspberryStats.py -i $input </dev/null &
#
#if [ $? -ne 0 ]; then
# echo "Could not start the service..."
# exit;
#else
# echo "Running the RaspberryAgent service...."
#fi
#
#echo "--------------------------------------------------------------------------"
#echo "| Successfully Started "
#echo "| -------------------------- "
#echo "| cd to /usr/local/src/RaspberryAgent"
#echo "| run 'sudo nohup ./RaspberryStats.py -i time </dev/null &'to start service manually."
#echo "| Relapce time with the time-interval (in seconds) between successive Data-Pushes to the WSO2-DC (ex: '60' indicates 1 minute)"
#echo "| Find logs at: /usr/local/src/RaspberryAgent/logs/RaspberryStats.log"
#echo "---------------------------------------------------------------------------"

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2016, 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.
-->
<DeviceTypeConfiguration name="virtual_firealarm">
<Features>
<Feature code="buzz">
<Name>Control buzzer</Name>
<Description>Control buzzer on Virtual Firealarm</Description>
<Operation context="/virtual_firealarm/device/{deviceId}/buzz" method="POST">
</Operation>
</Feature>
</Features>
<ProvisioningConfig>
<SharedWithAllTenants>true</SharedWithAllTenants>
</ProvisioningConfig>
<PushNotificationProviderConfig type="MQTT">
<FileBasedProperties>true</FileBasedProperties>
</PushNotificationProviderConfig>
<!--<PushNotificationProviderConfig type="XMPP">-->
<!--<FileBasedProperties>true</FileBasedProperties>-->
<!--&lt;!&ndash;if file based properties is set to false then the configuration will be picked from platform configuration&ndash;&gt;-->
<!--<ConfigProperties>-->
<!--<Property Name="xmpp.adapter.name">virtualfirealarm.xmpp.adapter</Property>-->
<!--<Property Name="host">localhost</Property>-->
<!--<Property Name="port">5222</Property>-->
<!--<Property Name="username">admin</Property>-->
<!--<Property Name="password">admin</Property>-->
<!--<Property Name="jid">admin@localhost</Property>-->
<!--<Property Name="server.name">localhost</Property>-->
<!--</ConfigProperties>-->
<!--</PushNotificationProviderConfig>-->
<License>
<Language>en_US</Language>
<Version>1.0.0</Version>
<Text>This is license text</Text>
</License>
</DeviceTypeConfiguration>

@ -0,0 +1,16 @@
instructions.configure = \
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../../repository/deployment/server/webapps/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.virtualfirealarm.backend_${feature.version}/webapps/,target:${installFolder}/../../../repository/deployment/server/webapps/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../../repository/deployment/server/devicetypes/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.virtualfirealarm.backend_${feature.version}/devicetypes/,target:${installFolder}/../../../repository/deployment/server/devicetypes/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.virtualfirealarm.backend_${feature.version}/receiver/,target:${installFolder}/../../../repository/deployment/server/eventreceivers/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.virtualfirealarm.backend_${feature.version}/streams/,target:${installFolder}/../../../repository/deployment/server/eventstreams/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.virtualfirealarm.backend_${feature.version}/publisher/,target:${installFolder}/../../../repository/deployment/server/eventpublishers/,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../../repository/resources/sketches/);\
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../../repository/resources/sketches/virtual_firealarm/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.virtualfirealarm.backend_${feature.version}/agent/,target:${installFolder}/../../../repository/resources/sketches/virtual_firealarm/,overwrite:true);\
instructions.unconfigure = \
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../../repository/deployment/server/webapps/virtual_firealarm.war);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../../repository/deployment/server/webapps/virtual_firealarm);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../../repository/deployment/server/devicetypes/virtual_firealarm.xml);\

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<eventPublisher name="virtual_firealarm_rdbms_publisher-carbon.super" processing="enable"
statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventpublisher">
<from streamName="iot.per.device.stream.virtualfirealarm" version="1.0.0"/>
<mapping customMapping="disable" type="map"/>
<to eventAdapterType="rdbms">
<property name="datasource.name">EVENT_DB</property>
<property name="table.name">table_virtualfirealarm_carbonsuper_rdbms_publisher</property>
<property name="execution.mode">insert</property>
</to>
</eventPublisher>

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016, 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.
-->
<eventReceiver name="virtualfirealarm_receiver-carbon.super" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-mqtt">
<property name="contentTransformer"/>
<property name="topic">carbon.super/virtual_firealarm/+/temperature</property>
<property name="contentValidator">default</property>
<property name="cleanSession">true</property>
</from>
<mapping customMapping="disable" type="json"/>
<to streamName="iot.per.device.stream.virtualfirealarm" version="1.0.0"/>
</eventReceiver>

@ -0,0 +1,16 @@
{
"name": "iot.per.device.stream.virtualfirealarm",
"version": "1.0.0",
"nickName": "virtual_firealarm",
"description": "Temperature data received from the virtual_firealarm",
"metaData": [
{"name":"owner","type":"STRING"},
{"name":"deviceId","type":"STRING"},
{"name":"time","type":"TIMESTAMP"}
],
"payloadData": [
{
"name": "temperature","type": "FLOAT"
}
]
}

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016, 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">
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>device-types-feature</artifactId>
<version>6.0.16-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>virtual-fire-alarm-plugin-feature</artifactId>
<packaging>pom</packaging>
<name>WSO2 Carbon - IoT Server VirtualFireAlarm Device Feature</name>
<url>http://wso2.org</url>
<modules>
<module>org.wso2.carbon.device.mgt.iot.virtualfirealarm.backend.feature</module>
</modules>
</project>

@ -37,10 +37,12 @@
<modules>
<module>components/extensions</module>
<module>components/mobile-plugins</module>
<module>components/device-types</module>
<!--<module>components/test-coverage</module>-->
<module>features/analytics-feature</module>
<module>features/mobile-plugins-feature</module>
<module>features/extensions-feature</module>
<module>features/device-types-feature</module>
</modules>
<dependencyManagement>
@ -491,6 +493,16 @@
<artifactId>org.wso2.carbon.device.mgt.mobile.android.api</artifactId>
<version>${carbon.devicemgt.plugins.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.api</artifactId>
<version>${carbon.devicemgt.plugins.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.impl</artifactId>
<version>${carbon.devicemgt.plugins.version}</version>
</dependency>
<!-- AppM dependencies -->
<dependency>

Loading…
Cancel
Save