forked from community/device-mgt-plugins
commit
83bfaded86
@ -0,0 +1,237 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
~
|
||||
~ WSO2 Inc. licenses this file to you under the Apache License,
|
||||
~ Version 2.0 (the "License"); you may not use this file except
|
||||
~ in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing,
|
||||
~ software distributed under the License is distributed on an
|
||||
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
~ KIND, either express or implied. See the License for the
|
||||
~ specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>virtual-fire-alarm-plugin</artifactId>
|
||||
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||
<version>4.1.21-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.impl</artifactId>
|
||||
<name>WSO2 Carbon - IoT Server VirtualFireAlarm Agent</name>
|
||||
<description>WSO2 Carbon - VirtualFireAlarm Device Agent Implementation</description>
|
||||
<url>http://wso2.org</url>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<source>${wso2.maven.compiler.source}</source>
|
||||
<target>${wso2.maven.compiler.target}</target>
|
||||
</configuration>
|
||||
<version>2.3.2</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>
|
||||
org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.Bootstrap
|
||||
</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<finalName>wso2-firealarm-virtual-agent</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<!-- this is used for inheritance merges -->
|
||||
<phase>package</phase>
|
||||
<!-- bind to the packaging phase -->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!--Dependency on Log4J - required by IoT Common Component-->
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--Dependency on Jetty-Server Library-->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${jetty.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--Dependency on MQTT Client Library-->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.paho</groupId>
|
||||
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||
<version>${paho.mqtt.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--Dependencies on XMPP Client Library-->
|
||||
<dependency>
|
||||
<groupId>org.igniterealtime.smack.wso2</groupId>
|
||||
<artifactId>smack</artifactId>
|
||||
<version>${smack.wso2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.igniterealtime.smack.wso2</groupId>
|
||||
<artifactId>smackx</artifactId>
|
||||
<version>${smackx.wso2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--Dependency on BouncyCastle Library for SCEP-->
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle.wso2</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>${bcprov.wso2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle.wso2</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
<version>${bcpkix.wso2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--Dependency on WSO2 JSCEP Orbit-->
|
||||
<dependency>
|
||||
<groupId>com.google.code.jscep.wso2</groupId>
|
||||
<artifactId>jscep</artifactId>
|
||||
<version>${jscep.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>${commons-lang.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<version>${common-logging.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons.io}</version>
|
||||
</dependency>
|
||||
|
||||
<!--Dependency on SLF4J - required by BouncyCastle-->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.json.wso2</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-configuration</groupId>
|
||||
<artifactId>commons-configuration</artifactId>
|
||||
<version>1.10</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>wso2-nexus</id>
|
||||
<name>WSO2 internal Repository</name>
|
||||
<url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
<updatePolicy>daily</updatePolicy>
|
||||
<checksumPolicy>ignore</checksumPolicy>
|
||||
</releases>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>wso2-maven2-repository</id>
|
||||
<url>http://dist.wso2.org/maven2</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
|
||||
<!-- Java Version Compatibility -->
|
||||
<wso2.maven.compiler.source>1.7</wso2.maven.compiler.source>
|
||||
<wso2.maven.compiler.target>1.7</wso2.maven.compiler.target>
|
||||
|
||||
<!-- Jetty Server Version -->
|
||||
<jetty.version>8.1.3.v20120416</jetty.version>
|
||||
|
||||
<!-- MQTT Paho Version -->
|
||||
<paho.mqtt.version>1.0.2</paho.mqtt.version>
|
||||
|
||||
<!-- Jivesoftware XMPP Version -->
|
||||
<smack.wso2.version>3.0.4.wso2v1</smack.wso2.version>
|
||||
<smackx.wso2.version>3.0.4.wso2v1</smackx.wso2.version>
|
||||
|
||||
<!-- BouncyCastle Version -->
|
||||
<bcprov.wso2.version>1.49.wso2v1</bcprov.wso2.version>
|
||||
<bcpkix.wso2.version>1.49.wso2v1</bcpkix.wso2.version>
|
||||
|
||||
<!-- WSO2 JSCEP Orbit Version -->
|
||||
<jscep.version>2.0.2.wso2v2</jscep.version>
|
||||
|
||||
<!-- Commons Libraries -->
|
||||
<log4j.version>1.2.17</log4j.version>
|
||||
<common-logging.version>1.2</common-logging.version>
|
||||
<commons.io>2.4</commons.io>
|
||||
<commons-codec.version>1.7</commons-codec.version>
|
||||
<commons-lang.version>2.6</commons-lang.version>
|
||||
|
||||
<!-- SLF4J Version -->
|
||||
<slf4j.version>1.7.13</slf4j.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent;
|
||||
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
|
||||
|
||||
public class Bootstrap {
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
|
||||
System.setProperty("org.apache.commons.logging.simplelog.defaultlog", "info");
|
||||
System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true");
|
||||
System.setProperty("org.apache.commons.logging.simplelog.dateTimeFormat", "HH:mm:ss");
|
||||
AgentManager.getInstance().init();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,484 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.http;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.http.HTTPTransportHandler;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class FireAlarmHTTPCommunicator extends HTTPTransportHandler {
|
||||
private static final Log log = LogFactory.getLog(FireAlarmHTTPCommunicator.class);
|
||||
|
||||
private ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
|
||||
private ScheduledFuture<?> dataPushServiceHandler;
|
||||
private ScheduledFuture<?> connectorServiceHandler;
|
||||
|
||||
public FireAlarmHTTPCommunicator() {
|
||||
super();
|
||||
}
|
||||
|
||||
public FireAlarmHTTPCommunicator(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
public FireAlarmHTTPCommunicator(int port, int reconnectionInterval) {
|
||||
super(port, reconnectionInterval);
|
||||
}
|
||||
|
||||
public ScheduledFuture<?> getDataPushServiceHandler() {
|
||||
return dataPushServiceHandler;
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
Runnable connect = new Runnable() {
|
||||
public void run() {
|
||||
if (!isConnected()) {
|
||||
try {
|
||||
processIncomingMessage();
|
||||
server.start();
|
||||
registerThisDevice();
|
||||
publishDeviceData();
|
||||
log.info("HTTP Server started at port: " + port);
|
||||
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.warn("Unable to 'START' HTTP server. Will retry after " +
|
||||
timeoutInterval / 1000 + " seconds.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
connectorServiceHandler = service.scheduleAtFixedRate(connect, 0, timeoutInterval,
|
||||
TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void processIncomingMessage() {
|
||||
server.setHandler(new AbstractHandler() {
|
||||
public void handle(String s, Request request, HttpServletRequest
|
||||
httpServletRequest,
|
||||
HttpServletResponse httpServletResponse)
|
||||
throws IOException, ServletException {
|
||||
httpServletResponse.setContentType("text/html;charset=utf-8");
|
||||
httpServletResponse.setStatus(HttpServletResponse.SC_OK);
|
||||
request.setHandled(true);
|
||||
|
||||
AgentManager agentManager = AgentManager.getInstance();
|
||||
String pathContext = request.getPathInfo();
|
||||
String separator = File.separatorChar=='\\' ? "\\\\" : File.separator ;
|
||||
|
||||
if (pathContext.toUpperCase().contains(
|
||||
separator + AgentConstants.TEMPERATURE_CONTROL)) {
|
||||
httpServletResponse.getWriter().println(
|
||||
agentManager.getTemperature());
|
||||
|
||||
} else if (pathContext.toUpperCase().contains(
|
||||
separator + AgentConstants.HUMIDITY_CONTROL)) {
|
||||
httpServletResponse.getWriter().println(
|
||||
agentManager.getHumidity());
|
||||
|
||||
} else if (pathContext.toUpperCase().contains(
|
||||
separator + AgentConstants.BULB_CONTROL)) {
|
||||
String[] pathVariables = pathContext.split(separator);
|
||||
|
||||
if (pathVariables.length != 3) {
|
||||
httpServletResponse.getWriter().println(
|
||||
"Invalid BULB-control received by the device. Need to be in " +
|
||||
"'{host}:{port}/BULB/{ON|OFF}' format.");
|
||||
return;
|
||||
}
|
||||
|
||||
String switchState = pathVariables[2];
|
||||
|
||||
if (switchState == null) {
|
||||
httpServletResponse.getWriter().println(
|
||||
"Please specify switch-status of the BULB.");
|
||||
} else {
|
||||
boolean status = switchState.toUpperCase().equals(
|
||||
AgentConstants.CONTROL_ON);
|
||||
agentManager.changeAlarmStatus(status);
|
||||
httpServletResponse.getWriter().println("Bulb is " + (status ?
|
||||
AgentConstants.CONTROL_ON : AgentConstants.CONTROL_OFF));
|
||||
}
|
||||
} else {
|
||||
httpServletResponse.getWriter().println(
|
||||
"Invalid control command received by the device.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishDeviceData() {
|
||||
final AgentManager agentManager = AgentManager.getInstance();
|
||||
int publishInterval = agentManager.getPushInterval();
|
||||
final String deviceOwner = agentManager.getAgentConfigs().getDeviceOwner();
|
||||
final String deviceID = agentManager.getAgentConfigs().getDeviceId();
|
||||
boolean simulationMode = false;
|
||||
int duration = 2 * 60;
|
||||
int frequency = 5;
|
||||
|
||||
Runnable pushDataRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
String pushDataPayload = String.format(AgentConstants.PUSH_DATA_PAYLOAD, deviceOwner,
|
||||
deviceID, (agentManager.getDeviceIP() + ":" + port),
|
||||
agentManager.getTemperature());
|
||||
executeDataPush(pushDataPayload);
|
||||
}
|
||||
};
|
||||
|
||||
if (!simulationMode) {
|
||||
dataPushServiceHandler = service.scheduleAtFixedRate(pushDataRunnable, publishInterval,
|
||||
publishInterval,
|
||||
TimeUnit.SECONDS);
|
||||
} else {
|
||||
String pushDataPayload = String.format(AgentConstants.PUSH_SIMULATION_DATA_PAYLOAD, deviceOwner,
|
||||
deviceID, (agentManager.getDeviceIP() + ":" + port),
|
||||
agentManager.getTemperature(), true, duration, frequency);
|
||||
executeDataPush(pushDataPayload);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void executeDataPush(String pushDataPayload) {
|
||||
AgentManager agentManager = AgentManager.getInstance();
|
||||
String pushDataEndPointURL = agentManager.getPushDataAPIEP();
|
||||
HttpURLConnection httpConnection;
|
||||
int responseCode = -1;
|
||||
|
||||
try {
|
||||
httpConnection = TransportUtils.getHttpConnection(agentManager.getPushDataAPIEP());
|
||||
httpConnection.setRequestMethod(AgentConstants.HTTP_POST);
|
||||
httpConnection.setRequestProperty("Authorization",
|
||||
"Bearer " + agentManager.getAgentConfigs().getAuthToken());
|
||||
httpConnection.setRequestProperty("Content-Type", AgentConstants.APPLICATION_JSON);
|
||||
|
||||
httpConnection.setDoOutput(true);
|
||||
DataOutputStream dataOutPutWriter = new DataOutputStream(httpConnection.getOutputStream());
|
||||
dataOutPutWriter.writeBytes(pushDataPayload);
|
||||
dataOutPutWriter.flush();
|
||||
dataOutPutWriter.close();
|
||||
|
||||
responseCode = httpConnection.getResponseCode();
|
||||
httpConnection.disconnect();
|
||||
|
||||
log.info(AgentConstants.LOG_APPENDER + "Message - '" + pushDataPayload +
|
||||
"' was published to server at: " + httpConnection.getURL());
|
||||
|
||||
} catch (ProtocolException exception) {
|
||||
String errorMsg =
|
||||
"Protocol specific error occurred when trying to set method to " +
|
||||
AgentConstants.HTTP_POST + " for:" + pushDataEndPointURL;
|
||||
log.error(AgentConstants.LOG_APPENDER + errorMsg);
|
||||
|
||||
} catch (IOException exception) {
|
||||
String errorMsg =
|
||||
"An IO error occurred whilst trying to get the response code from: " +
|
||||
pushDataEndPointURL + " for a " + AgentConstants.HTTP_POST + " method.";
|
||||
log.error(AgentConstants.LOG_APPENDER + errorMsg);
|
||||
|
||||
} catch (TransportHandlerException exception) {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"Error encountered whilst trying to create HTTP-Connection to IoT-Server EP at: " +
|
||||
pushDataEndPointURL);
|
||||
}
|
||||
|
||||
if (responseCode == HttpStatus.CONFLICT_409 ||
|
||||
responseCode == HttpStatus.PRECONDITION_FAILED_412) {
|
||||
log.warn(AgentConstants.LOG_APPENDER +
|
||||
"DeviceIP is being Re-Registered due to Push-Data failure with response code: " +
|
||||
responseCode);
|
||||
registerThisDevice();
|
||||
|
||||
} else if (responseCode != HttpStatus.NO_CONTENT_204) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.error(AgentConstants.LOG_APPENDER + "Status Code: " + responseCode +
|
||||
" encountered whilst trying to Push-Device-Data to IoT Server at: " +
|
||||
agentManager.getPushDataAPIEP());
|
||||
}
|
||||
agentManager.updateAgentStatus(AgentConstants.SERVER_NOT_RESPONDING);
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(AgentConstants.LOG_APPENDER + "Push-Data call with payload - " + pushDataPayload +
|
||||
", to IoT Server returned status " + responseCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
Runnable stopConnection = new Runnable() {
|
||||
public void run() {
|
||||
while (isConnected()) {
|
||||
try {
|
||||
dataPushServiceHandler.cancel(true);
|
||||
connectorServiceHandler.cancel(true);
|
||||
closeConnection();
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Unable to 'STOP' HTTP server at port: " + port);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(timeoutInterval);
|
||||
} catch (InterruptedException e1) {
|
||||
log.error(
|
||||
AgentConstants.LOG_APPENDER + "HTTP-Termination: Thread Sleep Interrupt Exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread terminatorThread = new Thread(stopConnection);
|
||||
terminatorThread.setDaemon(true);
|
||||
terminatorThread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processIncomingMessage(Object message, String... messageParams) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishDeviceData(String... publishData) {
|
||||
|
||||
}
|
||||
|
||||
public void registerThisDevice() {
|
||||
final AgentManager agentManager = AgentManager.getInstance();
|
||||
agentManager.updateAgentStatus("Registering...");
|
||||
|
||||
final Runnable ipRegistration = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (isConnected()) {
|
||||
try {
|
||||
int responseCode = registerDeviceIP(
|
||||
agentManager.getAgentConfigs().getDeviceOwner(),
|
||||
agentManager.getAgentConfigs().getDeviceId());
|
||||
|
||||
if (responseCode == HttpStatus.OK_200) {
|
||||
agentManager.updateAgentStatus(AgentConstants.REGISTERED);
|
||||
break;
|
||||
} else {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"Device Registration with IoT Server at:" + " " +
|
||||
agentManager.getIpRegistrationEP() +
|
||||
" failed with response - '" + responseCode + ":" +
|
||||
HttpStatus.getMessage(responseCode) + "'");
|
||||
agentManager.updateAgentStatus(AgentConstants.RETRYING_TO_REGISTER);
|
||||
}
|
||||
} catch (AgentCoreOperationException exception) {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"Error encountered whilst trying to register the " +
|
||||
"Device's IP at: " +
|
||||
agentManager.getIpRegistrationEP() +
|
||||
".\nCheck whether the network-interface provided is " +
|
||||
"accurate");
|
||||
agentManager.updateAgentStatus(AgentConstants.REGISTRATION_FAILED);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(timeoutInterval);
|
||||
} catch (InterruptedException e1) {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"Device Registration: Thread Sleep Interrupt Exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread ipRegisterThread = new Thread(ipRegistration);
|
||||
ipRegisterThread.setDaemon(true);
|
||||
ipRegisterThread.start();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method calls the "Register-API" of the IoT Server in order to register the device's IP
|
||||
* against its ID.
|
||||
*
|
||||
* @param deviceOwner the owner of the device by whose name the agent was downloaded.
|
||||
* (Read from configuration file)
|
||||
* @param deviceID the deviceId that is auto-generated whilst downloading the agent.
|
||||
* (Read from configuration file)
|
||||
* @return the status code of the HTTP-Post call to the Register-API of the IoT-Server
|
||||
* @throws AgentCoreOperationException if any errors occur when an HTTPConnection session is
|
||||
* created
|
||||
*/
|
||||
private int registerDeviceIP(String deviceOwner, String deviceID)
|
||||
throws AgentCoreOperationException {
|
||||
int responseCode = -1;
|
||||
final AgentManager agentManager = AgentManager.getInstance();
|
||||
|
||||
String networkInterface = agentManager.getNetworkInterface();
|
||||
String deviceIPAddress = getDeviceIP(networkInterface);
|
||||
|
||||
if (deviceIPAddress == null) {
|
||||
throw new AgentCoreOperationException(
|
||||
"An IP address could not be retrieved for the selected network interface - '" +
|
||||
networkInterface + ".");
|
||||
}
|
||||
|
||||
agentManager.setDeviceIP(deviceIPAddress);
|
||||
log.info(AgentConstants.LOG_APPENDER + "Device IP Address: " + deviceIPAddress);
|
||||
|
||||
String deviceIPRegistrationEP = agentManager.getIpRegistrationEP();
|
||||
String registerEndpointURLString =
|
||||
deviceIPRegistrationEP + File.separator + deviceOwner + File.separator + deviceID +
|
||||
File.separator + deviceIPAddress + File.separator + port;
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(AgentConstants.LOG_APPENDER + "DeviceIP Registration EndPoint: " +
|
||||
registerEndpointURLString);
|
||||
}
|
||||
|
||||
HttpURLConnection httpConnection;
|
||||
try {
|
||||
httpConnection = TransportUtils.getHttpConnection(registerEndpointURLString);
|
||||
} catch (TransportHandlerException e) {
|
||||
String errorMsg =
|
||||
"Protocol specific error occurred when trying to fetch an HTTPConnection to:" +
|
||||
" " + registerEndpointURLString;
|
||||
log.error(AgentConstants.LOG_APPENDER + errorMsg);
|
||||
throw new AgentCoreOperationException();
|
||||
}
|
||||
|
||||
try {
|
||||
httpConnection.setRequestMethod(AgentConstants.HTTP_POST);
|
||||
httpConnection.setRequestProperty("Authorization", "Bearer " +
|
||||
agentManager.getAgentConfigs().getAuthToken());
|
||||
httpConnection.setDoOutput(true);
|
||||
responseCode = httpConnection.getResponseCode();
|
||||
|
||||
} catch (ProtocolException exception) {
|
||||
String errorMsg = "Protocol specific error occurred when trying to set method to " +
|
||||
AgentConstants.HTTP_POST + " for:" + registerEndpointURLString;
|
||||
log.error(AgentConstants.LOG_APPENDER + errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, exception);
|
||||
|
||||
} catch (IOException exception) {
|
||||
String errorMsg = "An IO error occurred whilst trying to get the response code from:" +
|
||||
" " + registerEndpointURLString + " for a " + AgentConstants.HTTP_POST + " method.";
|
||||
log.error(AgentConstants.LOG_APPENDER + errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, exception);
|
||||
}
|
||||
|
||||
log.info(AgentConstants.LOG_APPENDER + "DeviceIP - " + deviceIPAddress +
|
||||
", registration with IoT Server at : " +
|
||||
agentManager.getAgentConfigs().getHTTPS_ServerEndpoint() +
|
||||
" returned status " +
|
||||
responseCode);
|
||||
|
||||
return responseCode;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------------------*/
|
||||
/* Utility methods relevant to creating and sending HTTP requests to the Iot-Server */
|
||||
/*------------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* This method is used to get the IP of the device in which the agent is run on.
|
||||
*
|
||||
* @return the IP Address of the device
|
||||
* @throws AgentCoreOperationException if any errors occur whilst trying to get the IP address
|
||||
*/
|
||||
private String getDeviceIP() throws AgentCoreOperationException {
|
||||
try {
|
||||
return Inet4Address.getLocalHost().getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
String errorMsg = "Error encountered whilst trying to get the device IP address.";
|
||||
log.error(AgentConstants.LOG_APPENDER + errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an overloaded method that fetches the public IPv4 address of the given network
|
||||
* interface
|
||||
*
|
||||
* @param networkInterfaceName the network-interface of whose IPv4 address is to be retrieved
|
||||
* @return the IP Address iof the device
|
||||
* @throws AgentCoreOperationException if any errors occur whilst trying to get details of the
|
||||
* given network interface
|
||||
*/
|
||||
private String getDeviceIP(String networkInterfaceName) throws
|
||||
AgentCoreOperationException {
|
||||
String ipAddress = null;
|
||||
try {
|
||||
Enumeration<InetAddress> interfaceIPAddresses = NetworkInterface.getByName(
|
||||
networkInterfaceName).getInetAddresses();
|
||||
for (; interfaceIPAddresses.hasMoreElements(); ) {
|
||||
InetAddress ip = interfaceIPAddresses.nextElement();
|
||||
ipAddress = ip.getHostAddress();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(AgentConstants.LOG_APPENDER + "IP Address: " + ipAddress);
|
||||
}
|
||||
|
||||
if (TransportUtils.validateIPv4(ipAddress)) {
|
||||
return ipAddress;
|
||||
}
|
||||
}
|
||||
} catch (SocketException | NullPointerException exception) {
|
||||
String errorMsg =
|
||||
"Error encountered whilst trying to get IP Addresses of the network interface: " +
|
||||
networkInterfaceName +
|
||||
".\nPlease check whether the name of the network interface used is correct";
|
||||
log.error(AgentConstants.LOG_APPENDER + errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, exception);
|
||||
}
|
||||
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.mqtt;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentUtilOperations;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.mqtt.MQTTTransportHandler;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
//TODO:: Lincence header, comments and SPECIFIC class name since its not generic
|
||||
public class FireAlarmMQTTCommunicator extends MQTTTransportHandler {
|
||||
|
||||
private static final Log log = LogFactory.getLog(FireAlarmMQTTCommunicator.class);
|
||||
|
||||
private ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
|
||||
private ScheduledFuture<?> dataPushServiceHandler;
|
||||
private static final String DEFAULT_PASSWORD = "";
|
||||
|
||||
public FireAlarmMQTTCommunicator(String deviceOwner, String deviceType,
|
||||
String mqttBrokerEndPoint, String subscribeTopic) {
|
||||
super(deviceOwner, deviceType, mqttBrokerEndPoint, subscribeTopic);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public FireAlarmMQTTCommunicator(String deviceOwner, String deviceType,
|
||||
String mqttBrokerEndPoint, String subscribeTopic,
|
||||
int intervalInMillis) {
|
||||
super(deviceOwner, deviceType, mqttBrokerEndPoint, subscribeTopic, intervalInMillis);
|
||||
}
|
||||
|
||||
public ScheduledFuture<?> getDataPushServiceHandler() {
|
||||
return dataPushServiceHandler;
|
||||
}
|
||||
|
||||
//TODO:: Terminate logs with a period
|
||||
//TODO: Need to print exceptions
|
||||
@Override
|
||||
public void connect() {
|
||||
final AgentManager agentManager = AgentManager.getInstance();
|
||||
Runnable connector = new Runnable() {
|
||||
public void run() {
|
||||
while (!isConnected()) {
|
||||
try {
|
||||
connectToQueue(agentManager.getAgentConfigs().getAuthToken(), DEFAULT_PASSWORD);
|
||||
agentManager.updateAgentStatus("Connected to MQTT Queue");
|
||||
} catch (TransportHandlerException e) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Connection to MQTT Broker at: " + mqttBrokerEndPoint +
|
||||
" failed.\n Will retry in " + timeoutInterval + " milli-seconds.");
|
||||
|
||||
if (e.getCause() != null && e.getCause() instanceof MqttSecurityException) {
|
||||
refreshOAuthToken((MqttSecurityException) e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (isConnected()) {
|
||||
subscribeToQueue();
|
||||
agentManager.updateAgentStatus("Subscribed to MQTT Queue");
|
||||
publishDeviceData();
|
||||
}
|
||||
} catch (TransportHandlerException e) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Subscription to MQTT Broker at: " +
|
||||
mqttBrokerEndPoint + " failed");
|
||||
agentManager.updateAgentStatus("Subscription to broker failed.");
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(timeoutInterval);
|
||||
} catch (InterruptedException ex) {
|
||||
log.error(AgentConstants.LOG_APPENDER + "MQTT: Connect-Thread Sleep Interrupt Exception.");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread connectorThread = new Thread(connector);
|
||||
connectorThread.setDaemon(true);
|
||||
connectorThread.start();
|
||||
}
|
||||
|
||||
private void refreshOAuthToken(final MqttSecurityException exception) {
|
||||
Runnable tokenRefresher = new Runnable() {
|
||||
public void run() {
|
||||
String authenticationMethod = AgentUtilOperations.getAuthenticationMethod();
|
||||
|
||||
try {
|
||||
if (exception.getReasonCode() == MqttSecurityException.REASON_CODE_FAILED_AUTHENTICATION &&
|
||||
authenticationMethod.equals(AgentConstants.TOKEN_AUTHENTICATION_METHOD)) {
|
||||
AgentUtilOperations.refreshOAuthToken();
|
||||
}
|
||||
} catch (AgentCoreOperationException e1) {
|
||||
log.error(AgentConstants.LOG_APPENDER + "Token Refresh Attempt Failed. " + e1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread connectorThread = new Thread(tokenRefresher);
|
||||
connectorThread.setDaemon(true);
|
||||
connectorThread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processIncomingMessage(MqttMessage message, String... messageParams) {
|
||||
final AgentManager agentManager = AgentManager.getInstance();
|
||||
String tenantDomain = agentManager.getAgentConfigs().getTenantDomain();
|
||||
String deviceOwner = agentManager.getAgentConfigs().getDeviceOwner();
|
||||
String deviceID = agentManager.getAgentConfigs().getDeviceId();
|
||||
String receivedMessage;
|
||||
String replyMessage;
|
||||
String securePayLoad;
|
||||
|
||||
try {
|
||||
receivedMessage = AgentUtilOperations.extractMessageFromPayload(message.toString());
|
||||
log.info(AgentConstants.LOG_APPENDER + "Message [" + receivedMessage + "] was received");
|
||||
} catch (AgentCoreOperationException e) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Could not extract message from payload.", e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String[] controlSignal = receivedMessage.split(":");
|
||||
// message- "<SIGNAL_TYPE>:<SIGNAL_MODE>" format.(ex: "BULB:ON", "TEMPERATURE", "HUMIDITY")
|
||||
|
||||
try {
|
||||
switch (controlSignal[0].toUpperCase()) {
|
||||
case AgentConstants.BULB_CONTROL:
|
||||
boolean stateToSwitch = controlSignal[1].equals(AgentConstants.CONTROL_ON);
|
||||
agentManager.changeAlarmStatus(stateToSwitch);
|
||||
log.info(AgentConstants.LOG_APPENDER + "Bulb was switched to state: '" + controlSignal[1] + "'");
|
||||
break;
|
||||
|
||||
case AgentConstants.TEMPERATURE_CONTROL:
|
||||
int currentTemperature = agentManager.getTemperature();
|
||||
|
||||
String replyTemperature = "Current temperature was read as: '" + currentTemperature + "C'";
|
||||
log.info(AgentConstants.LOG_APPENDER + replyTemperature);
|
||||
|
||||
String tempPublishTopic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC, tenantDomain, deviceID);
|
||||
|
||||
replyMessage = AgentConstants.TEMPERATURE_CONTROL + ":" + currentTemperature;
|
||||
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
|
||||
publishToQueue(tempPublishTopic, securePayLoad);
|
||||
break;
|
||||
|
||||
case AgentConstants.HUMIDITY_CONTROL:
|
||||
int currentHumidity = agentManager.getHumidity();
|
||||
|
||||
String replyHumidity = "Current humidity was read as: '" + currentHumidity + "%'";
|
||||
log.info(AgentConstants.LOG_APPENDER + replyHumidity);
|
||||
|
||||
String humidPublishTopic = String.format(
|
||||
AgentConstants.MQTT_PUBLISH_TOPIC, tenantDomain, deviceID);
|
||||
|
||||
replyMessage = AgentConstants.HUMIDITY_CONTROL + ":" + currentHumidity;
|
||||
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
|
||||
publishToQueue(humidPublishTopic, securePayLoad);
|
||||
break;
|
||||
|
||||
default:
|
||||
log.warn(AgentConstants.LOG_APPENDER + "'" + controlSignal[0] +
|
||||
"' is invalid and not-supported for this device-type");
|
||||
break;
|
||||
}
|
||||
} catch (AgentCoreOperationException e) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Preparing Secure payload failed", e);
|
||||
} catch (TransportHandlerException e) {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"MQTT - Publishing, reply message to the MQTT Queue at: " +
|
||||
agentManager.getAgentConfigs().getMqttBrokerEndpoint() + " failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishDeviceData() {
|
||||
final AgentManager agentManager = AgentManager.getInstance();
|
||||
int publishInterval = agentManager.getPushInterval();
|
||||
Runnable pushDataRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int currentTemperature = agentManager.getTemperature();
|
||||
String message = "{\"event\": {\"metaData\": {\"owner\": \"" + AgentManager
|
||||
.getInstance().getAgentConfigs().getDeviceOwner() + "\",\"deviceId\": \"" + AgentManager
|
||||
.getInstance().getAgentConfigs().getDeviceId() + "\",\"time\": " +
|
||||
"0},\"payloadData\": { \"temperature\": " + currentTemperature + "} }}";
|
||||
|
||||
try {
|
||||
String payLoad = AgentUtilOperations.prepareSecurePayLoad(message);
|
||||
|
||||
MqttMessage pushMessage = new MqttMessage();
|
||||
pushMessage.setPayload(payLoad.getBytes(StandardCharsets.UTF_8));
|
||||
pushMessage.setQos(DEFAULT_MQTT_QUALITY_OF_SERVICE);
|
||||
pushMessage.setRetained(false);
|
||||
|
||||
String topic = String.format(AgentConstants.MQTT_PUBLISH_TOPIC,
|
||||
agentManager.getAgentConfigs().getTenantDomain(),
|
||||
agentManager.getAgentConfigs().getDeviceId());
|
||||
|
||||
publishToQueue(topic, pushMessage);
|
||||
log.info(AgentConstants.LOG_APPENDER + "Message: '" + message + "' published to MQTT Queue at [" +
|
||||
agentManager.getAgentConfigs().getMqttBrokerEndpoint() + "] under topic [" +
|
||||
topic + "]");
|
||||
|
||||
} catch (TransportHandlerException e) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Data Publish attempt to topic - [" +
|
||||
AgentConstants.MQTT_PUBLISH_TOPIC + "] failed for payload [" + message + "]");
|
||||
} catch (AgentCoreOperationException e) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Preparing Secure payload failed", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
dataPushServiceHandler = service.scheduleAtFixedRate(pushDataRunnable, publishInterval, publishInterval,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
Runnable stopConnection = new Runnable() {
|
||||
public void run() {
|
||||
while (isConnected()) {
|
||||
|
||||
if (dataPushServiceHandler != null) {
|
||||
dataPushServiceHandler.cancel(true);
|
||||
}
|
||||
|
||||
try {
|
||||
closeConnection();
|
||||
|
||||
} catch (MqttException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.warn(AgentConstants.LOG_APPENDER +
|
||||
"Unable to 'STOP' MQTT connection at broker at: " +
|
||||
mqttBrokerEndPoint);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(timeoutInterval);
|
||||
} catch (InterruptedException e1) {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"MQTT-Terminator: Thread Sleep Interrupt Exception");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread terminatorThread = new Thread(stopConnection);
|
||||
terminatorThread.setDaemon(true);
|
||||
terminatorThread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processIncomingMessage() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishDeviceData(String... publishData) {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.xmpp;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConfiguration;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentUtilOperations;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.xmpp.XMPPTransportHandler;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class FireAlarmXMPPCommunicator extends XMPPTransportHandler {
|
||||
|
||||
private static final Log log = LogFactory.getLog(FireAlarmXMPPCommunicator.class);
|
||||
|
||||
private ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
|
||||
private ScheduledFuture<?> dataPushServiceHandler;
|
||||
private ScheduledFuture<?> connectorServiceHandler;
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
private String resource;
|
||||
private String xmppAdminJID;
|
||||
private String xmppDeviceJID;
|
||||
|
||||
public FireAlarmXMPPCommunicator(String server) {
|
||||
super(server);
|
||||
}
|
||||
|
||||
public FireAlarmXMPPCommunicator(String server, int port) {
|
||||
super(server, port);
|
||||
}
|
||||
|
||||
public FireAlarmXMPPCommunicator(String server, int port, int timeout) {
|
||||
super(server, port, timeout);
|
||||
}
|
||||
|
||||
public ScheduledFuture<?> getDataPushServiceHandler() {
|
||||
return dataPushServiceHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
final AgentManager agentManager = AgentManager.getInstance();
|
||||
username = agentManager.getAgentConfigs().getDeviceId();
|
||||
password = agentManager.getAgentConfigs().getAuthToken();
|
||||
xmppDeviceJID = username + "@" + agentManager.getAgentConfigs().getXmppServerName();
|
||||
xmppAdminJID = agentManager.getAgentConfigs().getServerJID();
|
||||
|
||||
Runnable connect = new Runnable() {
|
||||
public void run() {
|
||||
if (!isConnected()) {
|
||||
try {
|
||||
connectToServer();
|
||||
} catch (TransportHandlerException e) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Connection to XMPP server at: " + server + " failed");
|
||||
}
|
||||
|
||||
try {
|
||||
loginToServer(username, password, resource);
|
||||
agentManager.updateAgentStatus("Connected to XMPP Server");
|
||||
setMessageFilterAndListener(xmppAdminJID, xmppDeviceJID, true);
|
||||
publishDeviceData();
|
||||
} catch (TransportHandlerException e) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Login to XMPP server at: " + server + " failed");
|
||||
agentManager.updateAgentStatus("No XMPP Account for Device");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
connectorServiceHandler = service.scheduleAtFixedRate(connect, 0, timeoutInterval, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an abstract method used for post processing the received XMPP-message. This
|
||||
* method will be implemented as per requirement at the time of creating an object of this
|
||||
* class.
|
||||
*
|
||||
* @param xmppMessage the xmpp message received by the listener.
|
||||
*/
|
||||
@Override
|
||||
public void processIncomingMessage(Message xmppMessage, String... messageParams) {
|
||||
final AgentManager agentManager = AgentManager.getInstance();
|
||||
String from = xmppMessage.getFrom();
|
||||
String message = xmppMessage.getBody();
|
||||
String receivedMessage;
|
||||
String replyMessage;
|
||||
String securePayLoad;
|
||||
|
||||
try {
|
||||
receivedMessage = AgentUtilOperations.extractMessageFromPayload(message);
|
||||
log.info(AgentConstants.LOG_APPENDER + "Message [" + receivedMessage + "] was received");
|
||||
} catch (AgentCoreOperationException e) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Could not extract message from payload.", e);
|
||||
return;
|
||||
}
|
||||
|
||||
String[] controlSignal = receivedMessage.split(":");
|
||||
//message- "<SIGNAL_TYPE>:<SIGNAL_MODE>" format. (ex: "BULB:ON", "TEMPERATURE", "HUMIDITY")
|
||||
|
||||
try {
|
||||
switch (controlSignal[0].toUpperCase()) {
|
||||
case AgentConstants.BULB_CONTROL:
|
||||
if (controlSignal.length != 2) {
|
||||
replyMessage = "BULB controls need to be in the form - 'BULB:{ON|OFF}'";
|
||||
log.warn(replyMessage);
|
||||
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
|
||||
sendXMPPMessage(xmppAdminJID, securePayLoad, "CONTROL-REPLY");
|
||||
break;
|
||||
}
|
||||
|
||||
agentManager.changeAlarmStatus(controlSignal[1].equals(AgentConstants.CONTROL_ON));
|
||||
log.info(AgentConstants.LOG_APPENDER + "Bulb was switched to state: '" + controlSignal[1] + "'");
|
||||
break;
|
||||
|
||||
case AgentConstants.TEMPERATURE_CONTROL:
|
||||
int currentTemperature = agentManager.getTemperature();
|
||||
|
||||
String replyTemperature =
|
||||
"The current temperature was read to be: '" + currentTemperature +
|
||||
"C'";
|
||||
log.info(AgentConstants.LOG_APPENDER + replyTemperature);
|
||||
|
||||
replyMessage = AgentConstants.TEMPERATURE_CONTROL + ":" + currentTemperature;
|
||||
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
|
||||
sendXMPPMessage(xmppAdminJID, securePayLoad, "CONTROL-REPLY");
|
||||
break;
|
||||
|
||||
case AgentConstants.HUMIDITY_CONTROL:
|
||||
int currentHumidity = agentManager.getHumidity();
|
||||
|
||||
String replyHumidity = "The current humidity was read to be: '" + currentHumidity + "%'";
|
||||
log.info(AgentConstants.LOG_APPENDER + replyHumidity);
|
||||
|
||||
replyMessage = AgentConstants.HUMIDITY_CONTROL + ":" + currentHumidity;
|
||||
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
|
||||
sendXMPPMessage(xmppAdminJID, securePayLoad, "CONTROL-REPLY");
|
||||
break;
|
||||
|
||||
default:
|
||||
replyMessage = "'" + controlSignal[0] + "' is invalid and not-supported for this device-type";
|
||||
log.warn(replyMessage);
|
||||
securePayLoad = AgentUtilOperations.prepareSecurePayLoad(replyMessage);
|
||||
sendXMPPMessage(xmppAdminJID, securePayLoad, "CONTROL-ERROR");
|
||||
break;
|
||||
}
|
||||
} catch (AgentCoreOperationException e) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Preparing Secure payload failed", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void publishDeviceData() {
|
||||
final AgentManager agentManager = AgentManager.getInstance();
|
||||
int publishInterval = agentManager.getPushInterval();
|
||||
|
||||
Runnable pushDataRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Message xmppMessage = new Message();
|
||||
|
||||
try {
|
||||
int currentTemperature = agentManager.getTemperature();
|
||||
String message = "{\"event\": {\"metaData\": {\"owner\": \"" + AgentManager
|
||||
.getInstance().getAgentConfigs().getDeviceOwner() + "\",\"deviceId\": \"" + AgentManager
|
||||
.getInstance().getAgentConfigs().getDeviceId() + "\",\"time\": " +
|
||||
"0},\"payloadData\": { \"temperature\": " + currentTemperature + "} }}";
|
||||
String payLoad = AgentUtilOperations.prepareSecurePayLoad(message);
|
||||
|
||||
xmppMessage.setTo(xmppAdminJID);
|
||||
xmppMessage.setSubject(agentManager.getAgentConfigs().getTenantDomain());
|
||||
xmppMessage.setBody(payLoad);
|
||||
xmppMessage.setType(Message.Type.chat);
|
||||
|
||||
sendXMPPMessage(xmppAdminJID, xmppMessage);
|
||||
log.info(AgentConstants.LOG_APPENDER + "Message: '" + message + "' sent to XMPP JID - " +
|
||||
"[" + xmppAdminJID + "] under subject [" + xmppMessage.getSubject() + "].");
|
||||
} catch (AgentCoreOperationException e) {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Preparing Secure payload failed for XMPP JID - " +
|
||||
"[" + xmppAdminJID + "] with subject - [" + xmppMessage.getSubject() + "].");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
dataPushServiceHandler = service.scheduleAtFixedRate(pushDataRunnable, publishInterval,
|
||||
publishInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
Runnable stopConnection = new Runnable() {
|
||||
public void run() {
|
||||
|
||||
if (dataPushServiceHandler != null) {
|
||||
dataPushServiceHandler.cancel(true);
|
||||
}
|
||||
|
||||
if (connectorServiceHandler != null) {
|
||||
connectorServiceHandler.cancel(true);
|
||||
}
|
||||
|
||||
while (isConnected()) {
|
||||
closeConnection();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.warn(AgentConstants.LOG_APPENDER +
|
||||
"Unable to 'STOP' connection to XMPP server at: " + server);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(timeoutInterval);
|
||||
} catch (InterruptedException e1) {
|
||||
log.error(AgentConstants.LOG_APPENDER + "XMPP-Terminator: Thread Sleep Interrupt Exception");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread terminatorThread = new Thread(stopConnection);
|
||||
terminatorThread.setDaemon(true);
|
||||
terminatorThread.start();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void processIncomingMessage() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishDeviceData(String... publishData) {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
|
||||
|
||||
/**
|
||||
* A Configuration class that holds all the Agent specific details that are read from the
|
||||
* 'deviceConfig.properties' file. This file is generated by the IoT-Server at the time of
|
||||
* downloading the device agent from the IoT-Server.
|
||||
*/
|
||||
public class AgentConfiguration {
|
||||
private String tenantDomain;
|
||||
private String deviceOwner;
|
||||
private String deviceId;
|
||||
private String deviceName;
|
||||
private String HTTPS_ServerEndpoint;
|
||||
private String HTTP_ServerEndpoint;
|
||||
private String apimGatewayEndpoint;
|
||||
private String mqttBrokerEndpoint;
|
||||
private String xmppServerEndpoint;
|
||||
private String apiApplicationKey;
|
||||
private String authToken;
|
||||
private String refreshToken;
|
||||
private int dataPushInterval;
|
||||
private String xmppServerName;
|
||||
private String serverJID;
|
||||
|
||||
public String getTenantDomain() {
|
||||
return tenantDomain;
|
||||
}
|
||||
|
||||
public void setTenantDomain(String tenantDomain) {
|
||||
this.tenantDomain = tenantDomain;
|
||||
}
|
||||
|
||||
public String getDeviceOwner() {
|
||||
return deviceOwner;
|
||||
}
|
||||
|
||||
public void setDeviceOwner(String deviceOwner) {
|
||||
this.deviceOwner = deviceOwner;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public String getServerJID() {
|
||||
return serverJID;
|
||||
}
|
||||
|
||||
public void setServerJID(String serverJID) {
|
||||
this.serverJID = serverJID;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getDeviceName() {
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
public void setDeviceName(String deviceName) {
|
||||
this.deviceName = deviceName;
|
||||
}
|
||||
|
||||
public String getHTTPS_ServerEndpoint() {
|
||||
return HTTPS_ServerEndpoint;
|
||||
}
|
||||
|
||||
public void setHTTPS_ServerEndpoint(String HTTPS_ServerEndpoint) {
|
||||
this.HTTPS_ServerEndpoint = HTTPS_ServerEndpoint;
|
||||
}
|
||||
|
||||
public String getHTTP_ServerEndpoint() {
|
||||
return HTTP_ServerEndpoint;
|
||||
}
|
||||
|
||||
public void setHTTP_ServerEndpoint(String HTTP_ServerEndpoint) {
|
||||
this.HTTP_ServerEndpoint = HTTP_ServerEndpoint;
|
||||
}
|
||||
|
||||
public String getApimGatewayEndpoint() {
|
||||
return apimGatewayEndpoint;
|
||||
}
|
||||
|
||||
public void setApimGatewayEndpoint(String apimGatewayEndpoint) {
|
||||
this.apimGatewayEndpoint = apimGatewayEndpoint;
|
||||
}
|
||||
|
||||
public String getMqttBrokerEndpoint() {
|
||||
return mqttBrokerEndpoint;
|
||||
}
|
||||
|
||||
public void setMqttBrokerEndpoint(String mqttBrokerEndpoint) {
|
||||
this.mqttBrokerEndpoint = mqttBrokerEndpoint;
|
||||
}
|
||||
|
||||
public String getXmppServerEndpoint() {
|
||||
return xmppServerEndpoint;
|
||||
}
|
||||
|
||||
public void setXmppServerEndpoint(String xmppServerEndpoint) {
|
||||
this.xmppServerEndpoint = xmppServerEndpoint;
|
||||
}
|
||||
|
||||
public String getApiApplicationKey() {
|
||||
return apiApplicationKey;
|
||||
}
|
||||
|
||||
public void setApiApplicationKey(String apiApplicationKey) {
|
||||
this.apiApplicationKey = apiApplicationKey;
|
||||
}
|
||||
|
||||
public String getAuthToken() {
|
||||
return authToken;
|
||||
}
|
||||
|
||||
public void setAuthToken(String authToken) {
|
||||
this.authToken = authToken;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public int getDataPushInterval() {
|
||||
return dataPushInterval;
|
||||
}
|
||||
|
||||
public void setDataPushInterval(int dataPushInterval) {
|
||||
this.dataPushInterval = dataPushInterval;
|
||||
}
|
||||
|
||||
public String getXmppServerName() {
|
||||
return xmppServerName;
|
||||
}
|
||||
|
||||
public void setXmppServerName(String xmppServerName) {
|
||||
this.xmppServerName = xmppServerName;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
|
||||
|
||||
public class AgentConstants {
|
||||
public static final String DEVICE_TYPE = "virtual_firealarm";
|
||||
public static final String LOG_APPENDER = "AGENT_LOG:: ";
|
||||
public static final String PROPERTIES_FILE_PATH = "";
|
||||
public static final int DEFAULT_RETRY_THREAD_INTERVAL = 5000; // time in millis
|
||||
public static final String TOKEN_AUTHENTICATION_METHOD = "token";
|
||||
/* ---------------------------------------------------------------------------------------
|
||||
IoT-Server specific information
|
||||
--------------------------------------------------------------------------------------- */
|
||||
public static final String DEVICE_CONTROLLER_API_EP = "/virtual_firealarm/device";
|
||||
public static final String DEVICE_SCEP_API_EP = "/virtual_firealarm_scep";
|
||||
public static final String DEVICE_ENROLLMENT_API_EP = "/scep";
|
||||
public static final String DEVICE_REGISTER_API_EP = "/register";
|
||||
public static final String DEVICE_PUSH_TEMPERATURE_API_EP = "/temperature";
|
||||
public static final String PUSH_DATA_PAYLOAD =
|
||||
"{\"owner\":\"%s\",\"deviceId\":\"%s\",\"reply\":\"%s\",\"value\":\"%s\"}";
|
||||
|
||||
public static final String PUSH_SIMULATION_DATA_PAYLOAD =
|
||||
"{\"owner\":\"%s\",\"deviceId\":\"%s\",\"reply\":\"%s\",\"value\":\"%s\",\"isSimulated\":\"%s\"," +
|
||||
"\"duration\":\"%s\",\"frequency\":\"%s\"}";
|
||||
|
||||
public static final String DEVICE_DETAILS_PAGE_EP = "/devicemgt/device/%s?id=%s";
|
||||
public static final String DEVICE_ANALYTICS_PAGE_URL =
|
||||
"/devicemgt/device/virtual_firealarm/analytics?deviceId=%s&deviceName=%s";
|
||||
|
||||
/* ---------------------------------------------------------------------------------------
|
||||
HTTP Connection specific information for communicating with IoT-Server
|
||||
--------------------------------------------------------------------------------------- */
|
||||
public static final String HTTP_POST = "POST";
|
||||
public static final String HTTP_GET = "GET";
|
||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
public static final String CONTENT_TYPE_HEADER = "Content-Type";
|
||||
public static final String APPLICATION_JSON = "application/json";
|
||||
public static final String X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
|
||||
public static final String REGISTERED = "Registered";
|
||||
public static final String NOT_REGISTERED = "Not-Registered";
|
||||
public static final String REGISTRATION_FAILED = "Registration Failed";
|
||||
public static final String RETRYING_TO_REGISTER = "Registration Failed. Re-trying..";
|
||||
public static final String SERVER_NOT_RESPONDING = "Server not responding..";
|
||||
|
||||
/* ---------------------------------------------------------------------------------------
|
||||
MQTT Connection specific information
|
||||
--------------------------------------------------------------------------------------- */
|
||||
public static final int DEFAULT_MQTT_RECONNECTION_INTERVAL = 2; // time in seconds
|
||||
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
|
||||
public static final String MQTT_SUBSCRIBE_TOPIC = "%s/" + DEVICE_TYPE + "/%s/operation/#";
|
||||
public static final String MQTT_PUBLISH_TOPIC = "%s/" + DEVICE_TYPE + "/%s/temperature";
|
||||
|
||||
/* ---------------------------------------------------------------------------------------
|
||||
Device/Agent specific properties to be read from the 'deviceConfig.properties' file
|
||||
--------------------------------------------------------------------------------------- */
|
||||
public static final String AGENT_PROPERTIES_FILE_NAME = "deviceConfig.properties";
|
||||
public static final String TENANT_DOMAIN = "tenantDomain";
|
||||
public static final String DEVICE_OWNER_PROPERTY = "owner";
|
||||
public static final String DEVICE_ID_PROPERTY = "deviceId";
|
||||
public static final String SERVER_JID_PROPERTY = "server-jid";
|
||||
public static final String DEVICE_NAME_PROPERTY = "device-name";
|
||||
public static final String SERVER_HTTPS_EP_PROPERTY = "https-ep";
|
||||
public static final String SERVER_HTTP_EP_PROPERTY = "http-ep";
|
||||
public static final String APIM_GATEWAY_EP_PROPERTY = "apim-ep";
|
||||
public static final String MQTT_BROKER_EP_PROPERTY = "mqtt-ep";
|
||||
public static final String XMPP_SERVER_EP_PROPERTY = "xmpp-ep";
|
||||
public static final String XMPP_SERVER_NAME_PROPERTY = "xmpp-server-name";
|
||||
public static final String API_APPLICATION_KEY = "application-key";
|
||||
public static final String AUTH_TOKEN_PROPERTY = "auth-token";
|
||||
public static final String REFRESH_TOKEN_PROPERTY = "refresh-token";
|
||||
public static final String NETWORK_INTERFACE_PROPERTY = "network-interface";
|
||||
public static final String PUSH_INTERVAL_PROPERTY = "push-interval";
|
||||
/* ---------------------------------------------------------------------------------------
|
||||
Default values for the Device/Agent specific configurations listed above
|
||||
--------------------------------------------------------------------------------------- */
|
||||
public static final String DEFAULT_NETWORK_INTERFACE = "en0";
|
||||
public static final int DEFAULT_DATA_PUBLISH_INTERVAL = 15; // seconds
|
||||
public static final String DEFAULT_PROTOCOL = "MQTT";
|
||||
/* ---------------------------------------------------------------------------------------
|
||||
Control Signal specific constants to match the request context
|
||||
--------------------------------------------------------------------------------------- */
|
||||
public static final String BULB_CONTROL = "BULB";
|
||||
public static final String TEMPERATURE_CONTROL = "TEMPERATURE";
|
||||
public static final String POLICY_SIGNAL = "POLICY";
|
||||
public static final String HUMIDITY_CONTROL = "HUMIDITY";
|
||||
public static final String CONTROL_ON = "ON";
|
||||
public static final String CONTROL_OFF = "OFF";
|
||||
public static final String AUDIO_FILE_NAME = "fireAlarmSound.mid";
|
||||
/* ---------------------------------------------------------------------------------------
|
||||
Communication protocol specific Strings
|
||||
--------------------------------------------------------------------------------------- */
|
||||
public static final String TCP_PREFIX = "tcp://";
|
||||
public static final String HTTP_PREFIX = "http://";
|
||||
public static final String HTTPS_PREFIX = "https://";
|
||||
public static final String HTTP_PROTOCOL = "HTTP";
|
||||
public static final String MQTT_PROTOCOL = "MQTT";
|
||||
public static final String XMPP_PROTOCOL = "XMPP";
|
||||
public static final String PROTOCOL_PROPERTY = "Protocol";
|
||||
public static final String HOST_PROPERTY = "Host";
|
||||
public static final String PORT_PROPERTY = "Port";
|
||||
|
||||
/* ---------------------------------------------------------------------------------------
|
||||
Keystore specific strings for the device trustStore
|
||||
--------------------------------------------------------------------------------------- */
|
||||
public static final String DEVICE_KEYSTORE_TYPE = "JKS";
|
||||
public static final String DEVICE_KEYSTORE = "virtual_firealarm.jks";
|
||||
public static final String DEVICE_KEYSTORE_PASSWORD = "wso2@virtual_firealarm";
|
||||
public static final String DEVICE_PRIVATE_KEY_ALIAS = "virtual_firealarm_key";
|
||||
public static final String DEVICE_CERT_ALIAS = "virtual_firealarm_cert";
|
||||
public static final String SERVER_CA_CERT_ALIAS = "ca_iotServer";
|
||||
}
|
@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.http.FireAlarmHTTPCommunicator;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.mqtt.FireAlarmMQTTCommunicator;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.communication.xmpp.FireAlarmXMPPCommunicator;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.enrollment.EnrollmentManager;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual.VirtualHardwareManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AgentManager {
|
||||
|
||||
private static final Log log = LogFactory.getLog(AgentManager.class);
|
||||
private static AgentManager agentManager;
|
||||
private String rootPath = "";
|
||||
|
||||
private boolean deviceReady = false;
|
||||
private boolean isAlarmOn = false;
|
||||
|
||||
private String deviceName, agentStatus;
|
||||
|
||||
private int pushInterval; // seconds
|
||||
private String prevProtocol, protocol;
|
||||
|
||||
private String networkInterface;
|
||||
private List<String> interfaceList, protocolList;
|
||||
private Map<String, TransportHandler> agentCommunicator;
|
||||
|
||||
private AgentConfiguration agentConfigs;
|
||||
|
||||
private String deviceIP;
|
||||
private String enrollmentEP;
|
||||
private String ipRegistrationEP;
|
||||
private String pushDataAPIEP;
|
||||
|
||||
private AgentManager() {
|
||||
}
|
||||
|
||||
public static AgentManager getInstance() {
|
||||
if (agentManager == null) {
|
||||
agentManager = new AgentManager();
|
||||
}
|
||||
return agentManager;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
|
||||
agentCommunicator = new HashMap<>();
|
||||
// Read IoT-Server specific configurations from the 'deviceConfig.properties' file
|
||||
try {
|
||||
this.agentConfigs = AgentUtilOperations.readIoTServerConfigs();
|
||||
} catch (AgentCoreOperationException e) {
|
||||
log.error("Reading device configuration from configuration file failed:\n");
|
||||
log.error(e);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
// Initialise IoT-Server URL endpoints from the configuration read from file
|
||||
AgentUtilOperations.initializeServerEndPoints();
|
||||
// Set the hostNameVerifier to the APIM-Server IPAddress to enable HTTPS handshake
|
||||
AgentUtilOperations.setHTTPSConfigurations();
|
||||
|
||||
String analyticsPageContext = String.format(AgentConstants.DEVICE_ANALYTICS_PAGE_URL,
|
||||
agentConfigs.getDeviceId(),
|
||||
agentConfigs.getDeviceName());
|
||||
|
||||
String controlPageContext = String.format(AgentConstants.DEVICE_DETAILS_PAGE_EP,
|
||||
AgentConstants.DEVICE_TYPE,
|
||||
agentConfigs.getDeviceId());
|
||||
|
||||
this.agentStatus = AgentConstants.NOT_REGISTERED;
|
||||
this.deviceName = this.agentConfigs.getDeviceName();
|
||||
|
||||
this.pushInterval = this.agentConfigs.getDataPushInterval();
|
||||
this.networkInterface = AgentConstants.DEFAULT_NETWORK_INTERFACE;
|
||||
|
||||
this.protocol = AgentConstants.DEFAULT_PROTOCOL;
|
||||
this.prevProtocol = protocol;
|
||||
|
||||
Map<String, String> xmppIPPortMap;
|
||||
try {
|
||||
xmppIPPortMap = TransportUtils.getHostAndPort(agentConfigs.getXmppServerEndpoint());
|
||||
String xmppServer = xmppIPPortMap.get("Host");
|
||||
int xmppPort = Integer.parseInt(xmppIPPortMap.get("Port"));
|
||||
|
||||
TransportHandler xmppCommunicator = new FireAlarmXMPPCommunicator(xmppServer, xmppPort);
|
||||
agentCommunicator.put(AgentConstants.XMPP_PROTOCOL, xmppCommunicator);
|
||||
|
||||
} catch (TransportHandlerException e) {
|
||||
log.info("XMPP Endpoint String - " + agentConfigs.getXmppServerEndpoint() +
|
||||
", provided in the configuration file is invalid. XMPP is not configured.");
|
||||
}
|
||||
String mqttTopic = String.format(AgentConstants.MQTT_SUBSCRIBE_TOPIC, agentConfigs.getTenantDomain(),
|
||||
agentConfigs.getDeviceId());
|
||||
|
||||
// TransportHandler httpCommunicator = new FireAlarmHTTPCommunicator();
|
||||
TransportHandler mqttCommunicator = new FireAlarmMQTTCommunicator(agentConfigs.getDeviceOwner(),
|
||||
agentConfigs.getDeviceId(),
|
||||
agentConfigs.getMqttBrokerEndpoint(),
|
||||
mqttTopic);
|
||||
|
||||
// agentCommunicator.put(AgentConstants.HTTP_PROTOCOL, httpCommunicator);
|
||||
agentCommunicator.put(AgentConstants.MQTT_PROTOCOL, mqttCommunicator);
|
||||
|
||||
try {
|
||||
interfaceList = new ArrayList<>(TransportUtils.getInterfaceIPMap().keySet());
|
||||
protocolList = new ArrayList<>(agentCommunicator.keySet());
|
||||
} catch (TransportHandlerException e) {
|
||||
log.error("An error occurred whilst retrieving all NetworkInterface-IP mappings");
|
||||
}
|
||||
|
||||
//Initializing hardware at that point
|
||||
//AgentManger.setDeviceReady() method should invoked from hardware after initialization
|
||||
VirtualHardwareManager.getInstance().init();
|
||||
|
||||
//Wait till hardware get ready
|
||||
while (!deviceReady) {
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
log.info(AgentConstants.LOG_APPENDER + "Sleep error in 'device ready-flag' checking thread");
|
||||
}
|
||||
}
|
||||
|
||||
// try {
|
||||
// if (!EnrollmentManager.getInstance().isEnrolled()) {
|
||||
// EnrollmentManager.getInstance().beginEnrollmentFlow();
|
||||
// }
|
||||
// } catch (AgentCoreOperationException e) {
|
||||
// log.error("Device Enrollment Failed:\n");
|
||||
// log.error(e);
|
||||
// System.exit(0);
|
||||
// }
|
||||
|
||||
//Start agent communication
|
||||
agentCommunicator.get(protocol).connect();
|
||||
}
|
||||
|
||||
private void switchCommunicator(String stopProtocol, String startProtocol) {
|
||||
agentCommunicator.get(stopProtocol).disconnect();
|
||||
|
||||
while (agentCommunicator.get(stopProtocol).isConnected()) {
|
||||
try {
|
||||
Thread.sleep(250);
|
||||
} catch (InterruptedException e) {
|
||||
log.info(AgentConstants.LOG_APPENDER +
|
||||
"Sleep error in 'Switch-Communicator' Thread's shutdown wait.");
|
||||
}
|
||||
}
|
||||
|
||||
agentCommunicator.get(startProtocol).connect();
|
||||
}
|
||||
|
||||
public void setInterface(int interfaceId) {
|
||||
if (interfaceId != -1) {
|
||||
String newInterface = interfaceList.get(interfaceId);
|
||||
|
||||
if (!newInterface.equals(networkInterface)) {
|
||||
networkInterface = newInterface;
|
||||
|
||||
if (protocol.equals(AgentConstants.HTTP_PROTOCOL) && !protocol.equals(
|
||||
prevProtocol)) {
|
||||
switchCommunicator(prevProtocol, protocol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setProtocol(int protocolId) {
|
||||
if (protocolId != -1) {
|
||||
String newProtocol = protocolList.get(protocolId);
|
||||
|
||||
if (!protocol.equals(newProtocol)) {
|
||||
prevProtocol = protocol;
|
||||
protocol = newProtocol;
|
||||
switchCommunicator(prevProtocol, protocol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void changeAlarmStatus(boolean isOn) {
|
||||
VirtualHardwareManager.getInstance().changeAlarmStatus(isOn);
|
||||
isAlarmOn = isOn;
|
||||
}
|
||||
|
||||
public void updateAgentStatus(String status) {
|
||||
this.agentStatus = status;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------------------*/
|
||||
/* Getter and Setter Methods for the private variables */
|
||||
/*------------------------------------------------------------------------------------------*/
|
||||
|
||||
public void setRootPath(String rootPath) {
|
||||
this.rootPath = rootPath;
|
||||
}
|
||||
|
||||
public String getRootPath() {
|
||||
return rootPath;
|
||||
}
|
||||
|
||||
public void setDeviceReady(boolean deviceReady) {
|
||||
this.deviceReady = deviceReady;
|
||||
}
|
||||
|
||||
public AgentConfiguration getAgentConfigs() {
|
||||
return agentConfigs;
|
||||
}
|
||||
|
||||
public String getDeviceIP() {
|
||||
return deviceIP;
|
||||
}
|
||||
|
||||
public void setDeviceIP(String deviceIP) {
|
||||
this.deviceIP = deviceIP;
|
||||
}
|
||||
|
||||
public String getEnrollmentEP() {
|
||||
return enrollmentEP;
|
||||
}
|
||||
|
||||
public void setEnrollmentEP(String enrollmentEP) {
|
||||
this.enrollmentEP = enrollmentEP;
|
||||
}
|
||||
|
||||
public String getIpRegistrationEP() {
|
||||
return ipRegistrationEP;
|
||||
}
|
||||
|
||||
public void setIpRegistrationEP(String ipRegistrationEP) {
|
||||
this.ipRegistrationEP = ipRegistrationEP;
|
||||
}
|
||||
|
||||
public String getPushDataAPIEP() {
|
||||
return pushDataAPIEP;
|
||||
}
|
||||
|
||||
public void setPushDataAPIEP(String pushDataAPIEP) {
|
||||
this.pushDataAPIEP = pushDataAPIEP;
|
||||
}
|
||||
|
||||
public String getDeviceName() {
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
public String getNetworkInterface() {
|
||||
return networkInterface;
|
||||
}
|
||||
|
||||
public String getAgentStatus() {
|
||||
return agentStatus;
|
||||
}
|
||||
|
||||
public int getPushInterval() {
|
||||
return pushInterval;
|
||||
}
|
||||
|
||||
public void setPushInterval(int pushInterval) {
|
||||
this.pushInterval = pushInterval;
|
||||
TransportHandler transportHandler = agentCommunicator.get(protocol);
|
||||
|
||||
switch (protocol) {
|
||||
case AgentConstants.HTTP_PROTOCOL:
|
||||
((FireAlarmHTTPCommunicator) transportHandler).getDataPushServiceHandler()
|
||||
.cancel(true);
|
||||
break;
|
||||
case AgentConstants.MQTT_PROTOCOL:
|
||||
((FireAlarmMQTTCommunicator) transportHandler).getDataPushServiceHandler()
|
||||
.cancel(true);
|
||||
break;
|
||||
case AgentConstants.XMPP_PROTOCOL:
|
||||
((FireAlarmXMPPCommunicator) transportHandler).getDataPushServiceHandler()
|
||||
.cancel(true);
|
||||
break;
|
||||
default:
|
||||
log.warn("Unknown protocol " + protocol);
|
||||
}
|
||||
transportHandler.publishDeviceData();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("The Data Publish Interval was changed to: " + pushInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getInterfaceList() {
|
||||
return interfaceList;
|
||||
}
|
||||
|
||||
public List<String> getProtocolList() {
|
||||
return protocolList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get temperature reading from device
|
||||
*
|
||||
* @return Temperature
|
||||
*/
|
||||
public int getTemperature() {
|
||||
return VirtualHardwareManager.getInstance().getTemperature();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get humidity reading from device
|
||||
*
|
||||
* @return Humidity
|
||||
*/
|
||||
public int getHumidity() {
|
||||
return VirtualHardwareManager.getInstance().getHumidity();
|
||||
}
|
||||
|
||||
public boolean isAlarmOn() {
|
||||
return isAlarmOn;
|
||||
}
|
||||
}
|
@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.configuration.ConfigurationException;
|
||||
import org.apache.commons.configuration.PropertiesConfiguration;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.json.JSONObject;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.enrollment.EnrollmentManager;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.CommunicationUtils;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* This class contains all the core operations of the FireAlarm agent that are common to both
|
||||
* Virtual and Real Scenarios. These operations include, connecting to and subscribing to an MQTT
|
||||
* queue and to a XMPP Server. Pushing temperature data to the IoT-Server at timely intervals.
|
||||
* Reading device specific configuration from a configs file etc....
|
||||
*/
|
||||
public class AgentUtilOperations {
|
||||
|
||||
private static final Log log = LogFactory.getLog(AgentUtilOperations.class);
|
||||
private static final String JSON_MESSAGE_KEY = "Msg";
|
||||
private static final String JSON_SIGNATURE_KEY = "Sig";
|
||||
private static final String JSON_SERIAL_KEY = "SerialNumber";
|
||||
|
||||
/**
|
||||
* This method reads the agent specific configurations for the device from the
|
||||
* "deviceConfigs.properties" file found at /repository/conf folder.
|
||||
* If the properties file is not found in the specified path, then the configuration values
|
||||
* are set to the default ones in the 'AgentConstants' class.
|
||||
*
|
||||
* @return an object of type 'AgentConfiguration' which contains all the necessary
|
||||
* configuration attributes
|
||||
*/
|
||||
public static AgentConfiguration readIoTServerConfigs() throws AgentCoreOperationException {
|
||||
AgentManager agentManager = AgentManager.getInstance();
|
||||
AgentConfiguration iotServerConfigs = new AgentConfiguration();
|
||||
Properties properties = new Properties();
|
||||
InputStream propertiesInputStream = null;
|
||||
String propertiesFileName = AgentConstants.AGENT_PROPERTIES_FILE_NAME;
|
||||
String rootPath = "";
|
||||
|
||||
try {
|
||||
ClassLoader loader = AgentUtilOperations.class.getClassLoader();
|
||||
URL path = loader.getResource(propertiesFileName);
|
||||
|
||||
if (path != null) {
|
||||
log.info(AgentConstants.LOG_APPENDER + path);
|
||||
rootPath = path.getPath().replace("wso2-firealarm-virtual-agent.jar!/deviceConfig.properties", "")
|
||||
.replace("jar:", "").replace("file:", "");
|
||||
|
||||
rootPath = URLDecoder.decode(rootPath, StandardCharsets.UTF_8.toString());
|
||||
agentManager.setRootPath(rootPath);
|
||||
|
||||
String deviceConfigFilePath = rootPath + AgentConstants.AGENT_PROPERTIES_FILE_NAME;
|
||||
propertiesInputStream = new FileInputStream(deviceConfigFilePath);
|
||||
|
||||
//load a properties file from class path, inside static method
|
||||
properties.load(propertiesInputStream);
|
||||
|
||||
iotServerConfigs.setTenantDomain(properties.getProperty(
|
||||
AgentConstants.TENANT_DOMAIN));
|
||||
iotServerConfigs.setDeviceOwner(properties.getProperty(
|
||||
AgentConstants.DEVICE_OWNER_PROPERTY));
|
||||
iotServerConfigs.setDeviceId(properties.getProperty(
|
||||
AgentConstants.DEVICE_ID_PROPERTY));
|
||||
iotServerConfigs.setServerJID(properties.getProperty(
|
||||
AgentConstants.SERVER_JID_PROPERTY));
|
||||
iotServerConfigs.setDeviceName(properties.getProperty(
|
||||
AgentConstants.DEVICE_NAME_PROPERTY));
|
||||
iotServerConfigs.setHTTPS_ServerEndpoint(properties.getProperty(
|
||||
AgentConstants.SERVER_HTTPS_EP_PROPERTY));
|
||||
iotServerConfigs.setHTTP_ServerEndpoint(properties.getProperty(
|
||||
AgentConstants.SERVER_HTTP_EP_PROPERTY));
|
||||
iotServerConfigs.setApimGatewayEndpoint(properties.getProperty(
|
||||
AgentConstants.APIM_GATEWAY_EP_PROPERTY));
|
||||
iotServerConfigs.setMqttBrokerEndpoint(properties.getProperty(
|
||||
AgentConstants.MQTT_BROKER_EP_PROPERTY));
|
||||
iotServerConfigs.setXmppServerEndpoint(properties.getProperty(
|
||||
AgentConstants.XMPP_SERVER_EP_PROPERTY));
|
||||
iotServerConfigs.setXmppServerName(properties.getProperty(
|
||||
AgentConstants.XMPP_SERVER_NAME_PROPERTY));
|
||||
iotServerConfigs.setApiApplicationKey(properties.getProperty(
|
||||
AgentConstants.API_APPLICATION_KEY));
|
||||
iotServerConfigs.setAuthToken(properties.getProperty(
|
||||
AgentConstants.AUTH_TOKEN_PROPERTY));
|
||||
iotServerConfigs.setRefreshToken(properties.getProperty(
|
||||
AgentConstants.REFRESH_TOKEN_PROPERTY));
|
||||
iotServerConfigs.setDataPushInterval(Integer.parseInt(properties.getProperty(
|
||||
AgentConstants.PUSH_INTERVAL_PROPERTY)));
|
||||
|
||||
log.info(AgentConstants.LOG_APPENDER + "Tenant Domain: " +
|
||||
iotServerConfigs.getTenantDomain());
|
||||
log.info(AgentConstants.LOG_APPENDER + "Device Owner: " +
|
||||
iotServerConfigs.getDeviceOwner());
|
||||
log.info(AgentConstants.LOG_APPENDER + "Device ID: " +
|
||||
iotServerConfigs.getDeviceId());
|
||||
log.info(AgentConstants.LOG_APPENDER + "Device Name: " +
|
||||
iotServerConfigs.getDeviceName());
|
||||
log.info(AgentConstants.LOG_APPENDER + "IoT Server HTTPS EndPoint: " +
|
||||
iotServerConfigs.getHTTPS_ServerEndpoint());
|
||||
log.info(AgentConstants.LOG_APPENDER + "IoT Server HTTP EndPoint: " +
|
||||
iotServerConfigs.getHTTP_ServerEndpoint());
|
||||
log.info(AgentConstants.LOG_APPENDER + "API-Manager Gateway EndPoint: " +
|
||||
iotServerConfigs.getApimGatewayEndpoint());
|
||||
log.info(AgentConstants.LOG_APPENDER + "MQTT Broker EndPoint: " +
|
||||
iotServerConfigs.getMqttBrokerEndpoint());
|
||||
log.info(AgentConstants.LOG_APPENDER + "XMPP Server EndPoint: " +
|
||||
iotServerConfigs.getXmppServerEndpoint());
|
||||
log.info(AgentConstants.LOG_APPENDER + "Base64Encoded API Application Key: " +
|
||||
iotServerConfigs.getApiApplicationKey());
|
||||
log.info(AgentConstants.LOG_APPENDER + "Authentication Token: " +
|
||||
iotServerConfigs.getAuthToken());
|
||||
log.info(AgentConstants.LOG_APPENDER + "Refresh Token: " +
|
||||
iotServerConfigs.getRefreshToken());
|
||||
log.info(AgentConstants.LOG_APPENDER + "Data Push Interval: " +
|
||||
iotServerConfigs.getDataPushInterval());
|
||||
log.info(AgentConstants.LOG_APPENDER + "XMPP Server Name: " +
|
||||
iotServerConfigs.getXmppServerName());
|
||||
} else {
|
||||
throw new AgentCoreOperationException(
|
||||
"Failed to load path of resource [" + propertiesFileName + "] from this classpath.");
|
||||
}
|
||||
} catch (FileNotFoundException ex) {
|
||||
String errorMsg = "[" + propertiesFileName + "] file not found at: " + rootPath;
|
||||
log.error(AgentConstants.LOG_APPENDER + errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg);
|
||||
|
||||
} catch (IOException ex) {
|
||||
String errorMsg = "Error occurred whilst trying to fetch [" + propertiesFileName + "] from: " +
|
||||
AgentConstants.PROPERTIES_FILE_PATH;
|
||||
log.error(AgentConstants.LOG_APPENDER + errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg);
|
||||
} finally {
|
||||
if (propertiesInputStream != null) {
|
||||
try {
|
||||
propertiesInputStream.close();
|
||||
} catch (IOException e) {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"Error occurred whilst trying to close InputStream resource used to read the '" +
|
||||
propertiesFileName + "' file");
|
||||
}
|
||||
}
|
||||
}
|
||||
return iotServerConfigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method constructs the URLs for each of the API Endpoints called by the device agent
|
||||
* Ex: Register API, Push-Data API
|
||||
*/
|
||||
public static void initializeServerEndPoints() {
|
||||
AgentManager agentManager = AgentManager.getInstance();
|
||||
String serverSecureEndpoint = agentManager.getAgentConfigs().getHTTPS_ServerEndpoint();
|
||||
String serverUnSecureEndpoint = agentManager.getAgentConfigs().getHTTP_ServerEndpoint();
|
||||
String backEndContext =AgentConstants.DEVICE_CONTROLLER_API_EP;
|
||||
String scepBackEndContext = AgentConstants.DEVICE_SCEP_API_EP;
|
||||
|
||||
String deviceControllerAPIEndpoint = serverSecureEndpoint + backEndContext;
|
||||
|
||||
String deviceEnrollmentEndpoint =
|
||||
serverUnSecureEndpoint + scepBackEndContext + AgentConstants.DEVICE_ENROLLMENT_API_EP;
|
||||
agentManager.setEnrollmentEP(deviceEnrollmentEndpoint);
|
||||
|
||||
String registerEndpointURL =
|
||||
deviceControllerAPIEndpoint + AgentConstants.DEVICE_REGISTER_API_EP;
|
||||
agentManager.setIpRegistrationEP(registerEndpointURL);
|
||||
|
||||
String pushDataEndPointURL =
|
||||
deviceControllerAPIEndpoint + AgentConstants.DEVICE_PUSH_TEMPERATURE_API_EP;
|
||||
agentManager.setPushDataAPIEP(pushDataEndPointURL);
|
||||
|
||||
log.info(AgentConstants.LOG_APPENDER + "IoT Server's Device Controller API Endpoint: " +
|
||||
deviceControllerAPIEndpoint);
|
||||
log.info(AgentConstants.LOG_APPENDER + "Device Enrollment EndPoint: " +
|
||||
registerEndpointURL);
|
||||
log.info(AgentConstants.LOG_APPENDER + "DeviceIP Registration EndPoint: " +
|
||||
registerEndpointURL);
|
||||
log.info(AgentConstants.LOG_APPENDER + "Push-Data API EndPoint: " + pushDataEndPointURL);
|
||||
}
|
||||
|
||||
public static void setHTTPSConfigurations() {
|
||||
String apimEndpoint = AgentManager.getInstance().getAgentConfigs().getApimGatewayEndpoint();
|
||||
System.setProperty("javax.net.ssl.trustStore", AgentConstants.DEVICE_KEYSTORE);
|
||||
System.setProperty("javax.net.ssl.trustStorePassword", AgentConstants.DEVICE_KEYSTORE_PASSWORD);
|
||||
|
||||
try {
|
||||
final String apimHost = TransportUtils.getHostAndPort(apimEndpoint).get(AgentConstants.HOST_PROPERTY);
|
||||
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
|
||||
public boolean verify(String hostname, SSLSession session) {
|
||||
return hostname.equals(apimHost);
|
||||
}
|
||||
});
|
||||
} catch (TransportHandlerException e) {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"Failed to set HTTPS HostNameVerifier to the APIMServer-Host using the APIM-Endpoint " +
|
||||
"string [" + apimEndpoint + "].");
|
||||
log.error(AgentConstants.LOG_APPENDER + e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String prepareSecurePayLoad(String message) throws AgentCoreOperationException {
|
||||
if (EnrollmentManager.getInstance().isEnrolled()) {
|
||||
PrivateKey devicePrivateKey = EnrollmentManager.getInstance().getPrivateKey();
|
||||
String encodedMessage = Base64.encodeBase64String(message.getBytes());
|
||||
String signedPayload;
|
||||
try {
|
||||
signedPayload = CommunicationUtils.signMessage(encodedMessage, devicePrivateKey);
|
||||
} catch (TransportHandlerException e) {
|
||||
String errorMsg = "Error occurred whilst trying to sign encrypted message of: [" + message + "]";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
}
|
||||
|
||||
JSONObject jsonPayload = new JSONObject();
|
||||
jsonPayload.put(JSON_MESSAGE_KEY, encodedMessage);
|
||||
jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload);
|
||||
//below statements are temporary fix.
|
||||
jsonPayload.put(JSON_SERIAL_KEY, EnrollmentManager.getInstance().getSCEPCertificate().getSerialNumber());
|
||||
return jsonPayload.toString();
|
||||
} else {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
public static String extractMessageFromPayload(String message) throws AgentCoreOperationException {
|
||||
if (EnrollmentManager.getInstance().isEnrolled()) {
|
||||
String actualMessage;
|
||||
|
||||
PublicKey serverPublicKey = EnrollmentManager.getInstance().getServerPublicKey();
|
||||
JSONObject jsonPayload = new JSONObject(message);
|
||||
Object encodedMessage = jsonPayload.get(JSON_MESSAGE_KEY);
|
||||
Object signedPayload = jsonPayload.get(JSON_SIGNATURE_KEY);
|
||||
boolean verification;
|
||||
|
||||
if (encodedMessage != null && signedPayload != null) {
|
||||
try {
|
||||
verification = CommunicationUtils.verifySignature(
|
||||
encodedMessage.toString(), signedPayload.toString(), serverPublicKey);
|
||||
} catch (TransportHandlerException e) {
|
||||
String errorMsg =
|
||||
"Error occurred whilst trying to verify signature on received message: [" + message + "]";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
}
|
||||
} else {
|
||||
String errorMsg = "The received message is in an INVALID format. " +
|
||||
"Need to be JSON - {\"Msg\":\"<ENCRYPTED_MSG>\", \"Sig\":\"<SIGNED_MSG>\"}.";
|
||||
throw new AgentCoreOperationException(errorMsg);
|
||||
}
|
||||
if (verification) {
|
||||
actualMessage = new String(Base64.decodeBase64(encodedMessage.toString()), StandardCharsets.UTF_8);
|
||||
} else {
|
||||
String errorMsg = "Could not verify payload signature. The message was not signed by a valid client";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg);
|
||||
}
|
||||
return actualMessage;
|
||||
} else {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAuthenticationMethod() {
|
||||
String authMethod = "token";
|
||||
switch (authMethod) {
|
||||
case AgentConstants.TOKEN_AUTHENTICATION_METHOD:
|
||||
return AgentConstants.TOKEN_AUTHENTICATION_METHOD;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static void refreshOAuthToken() throws AgentCoreOperationException {
|
||||
|
||||
AgentManager agentManager = AgentManager.getInstance();
|
||||
String tokenEndpoint = agentManager.getAgentConfigs().getApimGatewayEndpoint();
|
||||
tokenEndpoint = tokenEndpoint + APIManagerTokenUtils.TOKEN_ENDPOINT;
|
||||
|
||||
HttpURLConnection httpConnection = null;
|
||||
BufferedReader connectionBuffer = null;
|
||||
String requestPayload;
|
||||
String dataFromBuffer;
|
||||
StringBuilder responseMessage = new StringBuilder();
|
||||
|
||||
try {
|
||||
String refreshToken = agentManager.getAgentConfigs().getRefreshToken();
|
||||
String applicationScope = "device_type_" + AgentConstants.DEVICE_TYPE +
|
||||
" device_" + agentManager.getAgentConfigs().getDeviceId();
|
||||
|
||||
requestPayload = APIManagerTokenUtils.GRANT_TYPE + "=" + APIManagerTokenUtils.REFRESH_TOKEN + "&" +
|
||||
APIManagerTokenUtils.REFRESH_TOKEN + "=" + refreshToken + "&" +
|
||||
APIManagerTokenUtils.SCOPE + "=" + applicationScope;
|
||||
|
||||
httpConnection = TransportUtils.getHttpConnection(tokenEndpoint);
|
||||
httpConnection.setRequestMethod(AgentConstants.HTTP_POST);
|
||||
httpConnection.setRequestProperty(AgentConstants.AUTHORIZATION_HEADER,
|
||||
"Basic " + agentManager.getAgentConfigs().getApiApplicationKey());
|
||||
httpConnection.setRequestProperty(AgentConstants.CONTENT_TYPE_HEADER, AgentConstants.X_WWW_FORM_URLENCODED);
|
||||
httpConnection.setDoOutput(true);
|
||||
|
||||
DataOutputStream dataOutPutWriter = new DataOutputStream(httpConnection.getOutputStream());
|
||||
dataOutPutWriter.writeBytes(requestPayload);
|
||||
dataOutPutWriter.flush();
|
||||
dataOutPutWriter.close();
|
||||
|
||||
log.info(AgentConstants.LOG_APPENDER + "Request to refresh OAuth token was sent to [" +
|
||||
httpConnection.getURL() + "] with payload [" + requestPayload + "].");
|
||||
log.info(AgentConstants.LOG_APPENDER + "Response [" + httpConnection.getResponseCode() + ":" +
|
||||
httpConnection.getResponseMessage() + "] was received for token refresh attempt.");
|
||||
|
||||
if (httpConnection.getResponseCode() == HttpStatus.OK_200) {
|
||||
connectionBuffer = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()));
|
||||
while ((dataFromBuffer = connectionBuffer.readLine()) != null) {
|
||||
responseMessage.append(dataFromBuffer);
|
||||
}
|
||||
|
||||
log.info(AgentConstants.LOG_APPENDER +
|
||||
"Response " + responseMessage + " was received for the token refresh call.");
|
||||
updateExistingTokens(responseMessage.toString());
|
||||
} else if (httpConnection.getResponseCode() == HttpStatus.BAD_REQUEST_400) {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"Token refresh call returned with a [400 Bad Request].\nThe refresh-token has " +
|
||||
"probably expired.\nPlease contact System-Admin to get a valid refresh-token.");
|
||||
} else {
|
||||
log.warn(AgentConstants.LOG_APPENDER + "There was an issue with refreshing the Access Token.");
|
||||
}
|
||||
|
||||
} catch (TransportHandlerException e) {
|
||||
throw new AgentCoreOperationException(e);
|
||||
} catch (ProtocolException e) {
|
||||
String errorMsg = "Protocol specific error occurred when trying to set method to " +
|
||||
AgentConstants.HTTP_POST + " for endpoint at: " + tokenEndpoint;
|
||||
log.error(AgentConstants.LOG_APPENDER + errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
|
||||
} catch (IOException e) {
|
||||
String errorMsg = "An IO error occurred whilst trying to get the response code from: " + tokenEndpoint +
|
||||
" for a HTTP " + AgentConstants.HTTP_POST + " call.";
|
||||
log.error(AgentConstants.LOG_APPENDER + errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
} finally {
|
||||
if (connectionBuffer != null) {
|
||||
try {
|
||||
connectionBuffer.close();
|
||||
} catch (IOException e) {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"Error encounter whilst attempting to close buffer to connection at: " +
|
||||
tokenEndpoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (httpConnection != null) {
|
||||
httpConnection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateExistingTokens(String responseFromTokenEP) throws AgentCoreOperationException {
|
||||
JSONObject jsonTokenObject = new JSONObject(responseFromTokenEP);
|
||||
String newAccessToken = jsonTokenObject.get(APIManagerTokenUtils.ACCESS_TOKEN).toString();
|
||||
String newRefreshToken = jsonTokenObject.get(APIManagerTokenUtils.REFRESH_TOKEN).toString();
|
||||
|
||||
if (newAccessToken == null || newRefreshToken == null) {
|
||||
String msg =
|
||||
"Neither Access-Token nor Refresh-Token was found in the response [" + responseFromTokenEP + "].";
|
||||
log.error(AgentConstants.LOG_APPENDER + msg);
|
||||
throw new AgentCoreOperationException(msg);
|
||||
}
|
||||
|
||||
AgentManager.getInstance().getAgentConfigs().setAuthToken(newAccessToken);
|
||||
AgentManager.getInstance().getAgentConfigs().setRefreshToken(newRefreshToken);
|
||||
String deviceConfigFilePath =
|
||||
AgentManager.getInstance().getRootPath() + AgentConstants.AGENT_PROPERTIES_FILE_NAME;
|
||||
|
||||
try {
|
||||
PropertiesConfiguration propertyFileConfiguration = new PropertiesConfiguration(deviceConfigFilePath);
|
||||
propertyFileConfiguration.setProperty(AgentConstants.AUTH_TOKEN_PROPERTY, newAccessToken);
|
||||
propertyFileConfiguration.setProperty(AgentConstants.REFRESH_TOKEN_PROPERTY, newRefreshToken);
|
||||
propertyFileConfiguration.save();
|
||||
} catch (ConfigurationException e) {
|
||||
String msg = "Error occurred whilst trying to update the [" + AgentConstants.AGENT_PROPERTIES_FILE_NAME +
|
||||
"] at: " + deviceConfigFilePath + " will the new tokens.";
|
||||
log.error(AgentConstants.LOG_APPENDER + msg);
|
||||
throw new AgentCoreOperationException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private class APIManagerTokenUtils {
|
||||
public static final String TOKEN_ENDPOINT = "/token";
|
||||
public static final String GRANT_TYPE = "grant_type";
|
||||
public static final String ACCESS_TOKEN = "access_token";
|
||||
public static final String REFRESH_TOKEN = "refresh_token";
|
||||
public static final String SCOPE = "scope";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,549 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.enrollment;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x500.X500NameBuilder;
|
||||
import org.bouncycastle.asn1.x500.style.BCStyle;
|
||||
import org.bouncycastle.cert.X509v3CertificateBuilder;
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.operator.ContentSigner;
|
||||
import org.bouncycastle.operator.OperatorCreationException;
|
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
|
||||
import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
|
||||
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
|
||||
import org.jscep.client.Client;
|
||||
import org.jscep.client.ClientException;
|
||||
import org.jscep.client.EnrollmentResponse;
|
||||
import org.jscep.client.verification.CertificateVerifier;
|
||||
import org.jscep.client.verification.OptimisticCertificateVerifier;
|
||||
import org.jscep.transaction.TransactionException;
|
||||
import org.jscep.transport.response.Capabilities;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception.AgentCoreOperationException;
|
||||
import sun.security.x509.X509CertImpl;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.Key;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Security;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertStore;
|
||||
import java.security.cert.CertStoreException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* This class controls the entire SCEP enrolment process of the client. It is a singleton for any single client which
|
||||
* has the agent code running in it. The main functionality of this class includes generating a Private-Public Key
|
||||
* Pair for the enrollment flow, creating the Certificate-Sign-Request using the generated Public-Key to send to the
|
||||
* SEP server, Contacting the SCEP server to receive the Signed Certificate and requesting for the server's public
|
||||
* key for encrypting the payloads.
|
||||
* The provider for all Cryptographic functions used in this class are "BouncyCastle" and the Asymmetric-Key pair
|
||||
* algorithm used is "RSA" with a key size of 2048. The signature algorithm used is "SHA1withRSA".
|
||||
* This class also holds the "SCEPUrl" (Server Url read from the configs file), the Private-Public Keys of the
|
||||
* client, Signed SCEP certificate and the server's public certificate.
|
||||
*/
|
||||
|
||||
//TODO: Need to save cert and keys to file after initial enrollment...
|
||||
public class EnrollmentManager {
|
||||
private static final Log log = LogFactory.getLog(EnrollmentManager.class);
|
||||
private static EnrollmentManager enrollmentManager;
|
||||
|
||||
private static final String KEY_PAIR_ALGORITHM = "RSA";
|
||||
private static final String PROVIDER = "BC";
|
||||
private static final String SIGNATURE_ALG = "SHA1withRSA";
|
||||
private static final String CERT_IS_CA_EXTENSION = "is_ca";
|
||||
private static final int KEY_SIZE = 2048;
|
||||
|
||||
// Seed to our PRNG. Make sure this is initialised randomly, NOT LIKE THIS
|
||||
private static final byte[] SEED = ")(*&^%$#@!".getBytes();
|
||||
private static final int CERT_VALIDITY = 730;
|
||||
|
||||
// URL of our SCEP server
|
||||
private String SCEPUrl;
|
||||
private PrivateKey privateKey;
|
||||
private PublicKey publicKey;
|
||||
private PublicKey serverPublicKey;
|
||||
private X509Certificate SCEPCertificate;
|
||||
private boolean isEnrolled = false;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor of the EnrollmentManager. Initializes the SCEPUrl as read from the configuration file by the
|
||||
* AgentManager.
|
||||
*/
|
||||
private EnrollmentManager() {
|
||||
this.SCEPUrl = AgentManager.getInstance().getEnrollmentEP();
|
||||
//setEnrollmentStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return the current singleton instance of the EnrollmentManager.
|
||||
*
|
||||
* @return the current singleton instance if available and if not initializes a new instance and returns it.
|
||||
*/
|
||||
public static EnrollmentManager getInstance() {
|
||||
if (enrollmentManager == null) {
|
||||
enrollmentManager = new EnrollmentManager();
|
||||
}
|
||||
return enrollmentManager;
|
||||
}
|
||||
|
||||
|
||||
public void setEnrollmentStatus() {
|
||||
KeyStore keyStore;
|
||||
try {
|
||||
keyStore = KeyStore.getInstance(AgentConstants.DEVICE_KEYSTORE_TYPE);
|
||||
|
||||
this.isEnrolled = (keyStore.containsAlias(AgentConstants.DEVICE_CERT_ALIAS) &&
|
||||
keyStore.containsAlias(AgentConstants.DEVICE_PRIVATE_KEY_ALIAS) &&
|
||||
keyStore.containsAlias(AgentConstants.SERVER_CA_CERT_ALIAS));
|
||||
|
||||
} catch (KeyStoreException e) {
|
||||
log.error(AgentConstants.LOG_APPENDER + "An error occurred whilst accessing the device KeyStore '" +
|
||||
AgentConstants.DEVICE_KEYSTORE + "' with keystore type [" +
|
||||
AgentConstants.DEVICE_KEYSTORE_TYPE + "] to ensure enrollment status.");
|
||||
log.error(AgentConstants.LOG_APPENDER + e);
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Device will be re-enrolled.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (this.isEnrolled) {
|
||||
this.SCEPCertificate = (X509Certificate) keyStore.getCertificate(AgentConstants.DEVICE_CERT_ALIAS);
|
||||
this.privateKey = (PrivateKey) keyStore.getKey(AgentConstants.DEVICE_PRIVATE_KEY_ALIAS,
|
||||
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
|
||||
this.publicKey = SCEPCertificate.getPublicKey();
|
||||
|
||||
X509Certificate serverCACert = (X509Certificate) keyStore.getCertificate(
|
||||
AgentConstants.SERVER_CA_CERT_ALIAS);
|
||||
this.serverPublicKey = serverCACert.getPublicKey();
|
||||
log.info(AgentConstants.LOG_APPENDER +
|
||||
"Device has already been enrolled. Hence, loaded certificate information from device" +
|
||||
" trust-store.");
|
||||
}
|
||||
} catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e) {
|
||||
log.error(AgentConstants.LOG_APPENDER + "An error occurred whilst accessing the device KeyStore '" +
|
||||
AgentConstants.DEVICE_KEYSTORE + "' to ensure enrollment status.");
|
||||
log.error(AgentConstants.LOG_APPENDER + e);
|
||||
log.warn(AgentConstants.LOG_APPENDER + "Device will be re-enrolled.");
|
||||
this.isEnrolled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to control the entire enrollment flow. This method calls the method to create the Private-Public Key
|
||||
* Pair, calls the specific method to generate the Certificate-Sign-Request, creates a one time self signed
|
||||
* certificate to present to the SCEP server with the initial CSR, calls the specific method to connect to the
|
||||
* SCEP Server and to get the SCEP Certificate and also calls the method that requests the SCEP Server for its
|
||||
* PublicKey for future payload encryption.
|
||||
*
|
||||
* @throws AgentCoreOperationException if the private method generateCertSignRequest() fails with an error or if
|
||||
* there is an error creating a self-sign certificate to present to the
|
||||
* server (whilst trying to get the CSR signed)
|
||||
*/
|
||||
public void beginEnrollmentFlow() throws AgentCoreOperationException {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
|
||||
KeyPair keyPair = generateKeyPair();
|
||||
this.privateKey = keyPair.getPrivate();
|
||||
this.publicKey = keyPair.getPublic();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.info(AgentConstants.LOG_APPENDER + "DevicePrivateKey:\n[\n" + privateKey + "\n]\n");
|
||||
log.info(AgentConstants.LOG_APPENDER + "DevicePublicKey:\n[\n" + publicKey + "\n]\n");
|
||||
}
|
||||
|
||||
PKCS10CertificationRequest certSignRequest = generateCertSignRequest();
|
||||
|
||||
/**
|
||||
* -----------------------------------------------------------------------------------------------
|
||||
* Generate an ephemeral self-signed certificate. This is needed to present to the CA in the SCEP request.
|
||||
* In the future, add proper EKU and attributes in the request. The CA does NOT have to honour any of this.
|
||||
* -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
X500Name issuer = new X500Name("CN=Temporary Issuer");
|
||||
BigInteger serial = new BigInteger(32, new SecureRandom());
|
||||
Date fromDate = new Date();
|
||||
Date toDate = new Date(System.currentTimeMillis() + (CERT_VALIDITY * 86400000L));
|
||||
|
||||
// Build the self-signed cert using BC, sign it with our private key (self-signed)
|
||||
X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(issuer, serial, fromDate, toDate,
|
||||
certSignRequest.getSubject(),
|
||||
certSignRequest.getSubjectPublicKeyInfo());
|
||||
ContentSigner sigGen;
|
||||
X509Certificate tmpCert;
|
||||
|
||||
try {
|
||||
sigGen = new JcaContentSignerBuilder(SIGNATURE_ALG).setProvider(PROVIDER).build(keyPair.getPrivate());
|
||||
tmpCert = new JcaX509CertificateConverter().setProvider(PROVIDER).getCertificate(certBuilder.build(sigGen));
|
||||
} catch (OperatorCreationException e) {
|
||||
String errorMsg = "Error occurred whilst creating a ContentSigner for the Temp-Self-Signed Certificate.";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
} catch (CertificateException e) {
|
||||
String errorMsg = "Error occurred whilst trying to create Temp-Self-Signed Certificate.";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
}
|
||||
/**
|
||||
* -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
this.SCEPCertificate = getSignedCertificateFromServer(tmpCert, certSignRequest);
|
||||
this.serverPublicKey = initPublicKeyOfServer();
|
||||
|
||||
storeCertificateToStore(AgentConstants.DEVICE_CERT_ALIAS, SCEPCertificate);
|
||||
storeKeyToKeyStore(AgentConstants.DEVICE_PRIVATE_KEY_ALIAS, this.privateKey, SCEPCertificate);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.info(AgentConstants.LOG_APPENDER +
|
||||
"SCEPCertificate, DevicePrivateKey, ServerPublicKey was saved to device keystore [" +
|
||||
AgentConstants.DEVICE_KEYSTORE + "]");
|
||||
log.info(AgentConstants.LOG_APPENDER + "TemporaryCertPublicKey:\n[\n" + tmpCert.getPublicKey() + "\n]\n");
|
||||
log.info(AgentConstants.LOG_APPENDER + "ServerPublicKey:\n[\n" + serverPublicKey + "\n]\n");
|
||||
}
|
||||
}
|
||||
|
||||
private void storeCertificateToStore(String alias, Certificate certificate) {
|
||||
KeyStore keyStore;
|
||||
try {
|
||||
keyStore = KeyStore.getInstance(AgentConstants.DEVICE_KEYSTORE_TYPE);
|
||||
keyStore.setCertificateEntry(alias, certificate);
|
||||
keyStore.store(new FileOutputStream(AgentConstants.DEVICE_KEYSTORE),
|
||||
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
|
||||
|
||||
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"An error occurred whilst trying to store the Certificate received from the SCEP " +
|
||||
"Enrollment.");
|
||||
log.error(AgentConstants.LOG_APPENDER + e);
|
||||
log.warn(AgentConstants.LOG_APPENDER +
|
||||
"SCEP Certificate was not stored in the keystore; " +
|
||||
"Hence the device will be re-enrolled during next restart.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void storeKeyToKeyStore(String alias, Key cryptoKey, Certificate certInCertChain) {
|
||||
KeyStore keyStore;
|
||||
try {
|
||||
keyStore = KeyStore.getInstance(AgentConstants.DEVICE_KEYSTORE_TYPE);
|
||||
Certificate[] certChain = new Certificate[1];
|
||||
certChain[0] = certInCertChain;
|
||||
|
||||
keyStore.setKeyEntry(alias, cryptoKey, AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray(), certChain);
|
||||
keyStore.store(new FileOutputStream(AgentConstants.DEVICE_KEYSTORE),
|
||||
AgentConstants.DEVICE_KEYSTORE_PASSWORD.toCharArray());
|
||||
|
||||
} catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) {
|
||||
log.error(AgentConstants.LOG_APPENDER +
|
||||
"An error occurred whilst trying to store the key with alias " +
|
||||
"[" + alias + "] in the device keystore.");
|
||||
log.error(AgentConstants.LOG_APPENDER + e);
|
||||
log.warn(AgentConstants.LOG_APPENDER +
|
||||
"Key [" + alias + "] was not stored in the keystore; " +
|
||||
"Hence the device will be re-enrolled during next restart.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates the Public-Private Key pair for the current client.
|
||||
*
|
||||
* @return the generated KeyPair object
|
||||
* @throws AgentCoreOperationException when the given Security Provider does not exist or the Algorithmn used to
|
||||
* generate the key pair is invalid.
|
||||
*/
|
||||
private KeyPair generateKeyPair() throws AgentCoreOperationException {
|
||||
|
||||
// Generate key pair
|
||||
KeyPairGenerator keyPairGenerator;
|
||||
try {
|
||||
keyPairGenerator = KeyPairGenerator.getInstance(KEY_PAIR_ALGORITHM, PROVIDER);
|
||||
keyPairGenerator.initialize(KEY_SIZE, new SecureRandom(SEED));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
String errorMsg = "Algorithm [" + KEY_PAIR_ALGORITHM + "] provided for KeyPairGenerator is invalid.";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
} catch (NoSuchProviderException e) {
|
||||
String errorMsg = "Provider [" + PROVIDER + "] provided for KeyPairGenerator does not exist.";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
}
|
||||
|
||||
return keyPairGenerator.genKeyPair();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates the PKCS10 Certificate Sign Request which is to be sent to the SCEP Server using the
|
||||
* generated PublicKey of the client. The certificate parameters used here are the ones from the AgentManager
|
||||
* which are the values read from the configurations file.
|
||||
*
|
||||
* @return the PKCS10CertificationRequest object created using the client specific configs and the generated
|
||||
* PublicKey
|
||||
* @throws AgentCoreOperationException if an error occurs when creating a content signer to sign the CSR.
|
||||
*/
|
||||
private PKCS10CertificationRequest generateCertSignRequest() throws AgentCoreOperationException {
|
||||
// Build the CN for the cert that's being requested.
|
||||
X500NameBuilder nameBld = new X500NameBuilder(BCStyle.INSTANCE);
|
||||
nameBld.addRDN(BCStyle.CN, AgentManager.getInstance().getAgentConfigs().getTenantDomain());
|
||||
nameBld.addRDN(BCStyle.O, AgentManager.getInstance().getAgentConfigs().getDeviceOwner());
|
||||
nameBld.addRDN(BCStyle.OU, AgentManager.getInstance().getAgentConfigs().getDeviceOwner());
|
||||
nameBld.addRDN(BCStyle.UNIQUE_IDENTIFIER, AgentManager.getInstance().getAgentConfigs().getDeviceId());
|
||||
nameBld.addRDN(BCStyle.SERIALNUMBER, AgentManager.getInstance().getAgentConfigs().getDeviceId());
|
||||
X500Name principal = nameBld.build();
|
||||
|
||||
JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder(SIGNATURE_ALG).setProvider(PROVIDER);
|
||||
ContentSigner contentSigner;
|
||||
|
||||
try {
|
||||
contentSigner = contentSignerBuilder.build(this.privateKey);
|
||||
} catch (OperatorCreationException e) {
|
||||
String errorMsg = "Could not create content signer with private key.";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
}
|
||||
|
||||
// Generate the certificate signing request (csr = PKCS10)
|
||||
PKCS10CertificationRequestBuilder reqBuilder = new JcaPKCS10CertificationRequestBuilder(principal,
|
||||
this.publicKey);
|
||||
return reqBuilder.build(contentSigner);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method connects to the SCEP Server to fetch the signed SCEP Certificate.
|
||||
*
|
||||
* @param tempCert the temporary self-signed certificate of the client required for the initial CSR
|
||||
* request against the SCEP Server.
|
||||
* @param certSignRequest the PKCS10 Certificate-Sign-Request that is to be sent to the SCEP Server.
|
||||
* @return the SCEP-Certificate for the client signed by the SCEP-Server.
|
||||
* @throws AgentCoreOperationException if the SCEPUrl is invalid or if the flow of sending the CSR and getting
|
||||
* the signed certificate fails or if the signed certificate cannot be
|
||||
* retrieved from the reply from the server.
|
||||
*/
|
||||
private X509Certificate getSignedCertificateFromServer(X509Certificate tempCert,
|
||||
PKCS10CertificationRequest certSignRequest)
|
||||
throws AgentCoreOperationException {
|
||||
|
||||
X509Certificate signedSCEPCertificate = null;
|
||||
URL url;
|
||||
EnrollmentResponse enrolResponse;
|
||||
CertStore certStore;
|
||||
|
||||
try {
|
||||
// The URL where we are going to request our cert from
|
||||
url = new URL(this.SCEPUrl);
|
||||
|
||||
/* // This is called when we get the certificate for our CSR signed by CA
|
||||
// Implement this handler to check the CA cert in prod. We can do cert pinning here
|
||||
CallbackHandler cb = new CallbackHandler() {
|
||||
@Override
|
||||
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
|
||||
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated
|
||||
methods, choose Tools | Templates.
|
||||
}
|
||||
};*/
|
||||
|
||||
// Implement verification of the CA cert. VERIFY the CA
|
||||
CertificateVerifier ocv = new OptimisticCertificateVerifier();
|
||||
|
||||
// Instantiate our SCEP client
|
||||
Client scepClient = new Client(url, ocv);
|
||||
|
||||
// Submit our cert for signing. SCEP server should allow the client to specify
|
||||
// the SCEP CA to issue the request against, if there are multiple CAs
|
||||
enrolResponse = scepClient.enrol(tempCert, this.privateKey, certSignRequest);
|
||||
|
||||
// Verify we got what we want, and just print out the cert.
|
||||
certStore = enrolResponse.getCertStore();
|
||||
|
||||
for (Certificate x509Certificate : certStore.getCertificates(null)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(x509Certificate.toString());
|
||||
}
|
||||
signedSCEPCertificate = (X509Certificate) x509Certificate;
|
||||
}
|
||||
|
||||
} catch (MalformedURLException ex) {
|
||||
String errorMsg = "Could not create valid URL from given SCEP URI: " + SCEPUrl;
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, ex);
|
||||
} catch (TransactionException | ClientException e) {
|
||||
String errorMsg = "Enrollment process to SCEP Server at: " + SCEPUrl + " failed.";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
} catch (CertStoreException e) {
|
||||
String errorMsg = "Could not retrieve [Signed-Certificate] from the response message from SCEP-Server.";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
}
|
||||
|
||||
return signedSCEPCertificate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the Public Key of the SCEP-Server and initializes it for later use. This method contacts the SCEP Server
|
||||
* and fetches its CA Cert and extracts the Public Key of the server from the received reply.
|
||||
*
|
||||
* @return the public key of the SCEP Server which is to be used to encrypt pyloads.
|
||||
* @throws AgentCoreOperationException if the SCEPUrl is invalid or if the flow of sending the CSR and getting
|
||||
* the signed certificate fails or if the signed certificate cannot be
|
||||
* retrieved from the reply from the server.
|
||||
*/
|
||||
private PublicKey initPublicKeyOfServer() throws AgentCoreOperationException {
|
||||
URL url;
|
||||
CertStore certStore;
|
||||
PublicKey serverCertPublicKey = null;
|
||||
|
||||
try {
|
||||
// The URL where we are going to request our cert from
|
||||
url = new URL(this.SCEPUrl);
|
||||
|
||||
/* // This is called when we get the certificate for our CSR signed by CA
|
||||
// Implement this handler to check the CA cert in prod. We can do cert pinning here
|
||||
CallbackHandler cb = new CallbackHandler() {
|
||||
@Override
|
||||
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
|
||||
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated
|
||||
methods, choose Tools | Templates.
|
||||
}
|
||||
};*/
|
||||
|
||||
// Implement verification of the CA cert. VERIFY the CA
|
||||
CertificateVerifier ocv = new OptimisticCertificateVerifier();
|
||||
|
||||
// Instantiate our SCEP client
|
||||
Client scepClient = new Client(url, ocv);
|
||||
|
||||
// Get the CA capabilities. Should return SHA1withRSA for strongest hash and sig. Returns MD5.
|
||||
if (log.isDebugEnabled()) {
|
||||
Capabilities cap = scepClient.getCaCapabilities();
|
||||
log.debug(String.format(
|
||||
"\nStrongestCipher: %s,\nStrongestMessageDigest: %s,\nStrongestSignatureAlgorithm: %s," +
|
||||
"\nIsRenewalSupported: %s,\nIsRolloverSupported: %s",
|
||||
cap.getStrongestCipher(), cap.getStrongestMessageDigest(), cap.getStrongestSignatureAlgorithm(),
|
||||
cap.isRenewalSupported(), cap.isRolloverSupported()));
|
||||
}
|
||||
|
||||
certStore = scepClient.getCaCertificate();
|
||||
|
||||
for (Certificate cert : certStore.getCertificates(null)) {
|
||||
if (cert instanceof X509Certificate) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(((X509Certificate) cert).getIssuerDN().getName());
|
||||
}
|
||||
|
||||
// I have chosen the CA cert based on its BasicConstraintExtension "is_ca" being set to "true"
|
||||
// This is because the returned keystore may contain many certificates including RAs.
|
||||
if (((Boolean) ((X509CertImpl) cert).getBasicConstraintsExtension().get(CERT_IS_CA_EXTENSION))) {
|
||||
serverCertPublicKey = cert.getPublicKey();
|
||||
storeCertificateToStore(AgentConstants.SERVER_CA_CERT_ALIAS, cert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (MalformedURLException ex) {
|
||||
String errorMsg = "Could not create valid URL from given SCEP URI: " + SCEPUrl;
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, ex);
|
||||
} catch (ClientException e) {
|
||||
String errorMsg = "Could not retrieve [Server-Certificate] from the SCEP-Server.";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
} catch (CertStoreException e) {
|
||||
String errorMsg = "Could not retrieve [Server-Certificates] from the response message from SCEP-Server.";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
} catch (IOException e) {
|
||||
String errorMsg = "Error occurred whilst trying to get property ['is_ca'] from the retreived Certificates";
|
||||
log.error(errorMsg);
|
||||
throw new AgentCoreOperationException(errorMsg, e);
|
||||
}
|
||||
|
||||
return serverCertPublicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Public-Key of the client.
|
||||
*
|
||||
* @return the public key of the client.
|
||||
*/
|
||||
public PublicKey getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Private-Key of the client.
|
||||
*
|
||||
* @return the private key of the client.
|
||||
*/
|
||||
public PrivateKey getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SCEP-Certificate of the client.
|
||||
*
|
||||
* @return the SCEP Certificate of the client.
|
||||
*/
|
||||
public X509Certificate getSCEPCertificate() {
|
||||
return SCEPCertificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Public-Key of the Server.
|
||||
*
|
||||
* @return the pubic key of the server.
|
||||
*/
|
||||
public PublicKey getServerPublicKey() {
|
||||
return serverPublicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the device has already been enrolled with the SCEP Server.
|
||||
*
|
||||
* @return the enrollment status; 'TRUE' if already enrolled else 'FALSE'.
|
||||
*/
|
||||
public boolean isEnrolled() {
|
||||
return isEnrolled;
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.exception;
|
||||
|
||||
|
||||
public class AgentCoreOperationException extends Exception{
|
||||
private static final long serialVersionUID = 2736466230451105710L;
|
||||
|
||||
private String errorMessage;
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public AgentCoreOperationException(String msg, Exception nestedEx) {
|
||||
super(msg, nestedEx);
|
||||
setErrorMessage(msg);
|
||||
}
|
||||
|
||||
public AgentCoreOperationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
|
||||
public AgentCoreOperationException(String msg) {
|
||||
super(msg);
|
||||
setErrorMessage(msg);
|
||||
}
|
||||
|
||||
public AgentCoreOperationException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public AgentCoreOperationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
|
||||
/**
|
||||
* This is a utility class which contains methods common to the communication process of a client and the server. The
|
||||
* methods include encryption/decryption of payloads and signing/verification of payloads received and to be sent.
|
||||
*/
|
||||
public class CommunicationUtils {
|
||||
private static final Log log = LogFactory.getLog(TransportUtils.class);
|
||||
|
||||
// The Signature Algorithm used.
|
||||
private static final String SHA_512 = "SHA-512";
|
||||
// The Encryption Algorithm and the Padding used.
|
||||
private static final String CIPHER_PADDING = "RSA/ECB/PKCS1Padding";
|
||||
|
||||
|
||||
/**
|
||||
* Encrypts the message with the key that's passed in.
|
||||
*
|
||||
* @param message the message to be encrypted.
|
||||
* @param encryptionKey the key to use for the encryption of the message.
|
||||
* @return the encrypted message in String format.
|
||||
* @throws TransportHandlerException if an error occurs with the encryption flow which can be due to Padding
|
||||
* issues, encryption key being invalid or the algorithm used is unrecognizable.
|
||||
*/
|
||||
public static String encryptMessage(String message, Key encryptionKey) throws TransportHandlerException {
|
||||
Cipher encrypter;
|
||||
byte[] cipherData;
|
||||
|
||||
try {
|
||||
encrypter = Cipher.getInstance(CIPHER_PADDING);
|
||||
encrypter.init(Cipher.ENCRYPT_MODE, encryptionKey);
|
||||
cipherData = encrypter.doFinal(message.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
String errorMsg = "Algorithm not found exception occurred for Cipher instance of [" + CIPHER_PADDING + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (NoSuchPaddingException e) {
|
||||
String errorMsg = "No Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (InvalidKeyException e) {
|
||||
String errorMsg = "InvalidKey exception occurred for encryptionKey \n[\n" + encryptionKey + "\n]\n";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (BadPaddingException e) {
|
||||
String errorMsg = "Bad Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
String errorMsg = "Illegal blockSize error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
}
|
||||
|
||||
return Base64.encodeBase64String(cipherData);
|
||||
}
|
||||
|
||||
///TODO:: Exception needs to change according to the common package
|
||||
/**
|
||||
* Signed a given message using the PrivateKey that's passes in.
|
||||
*
|
||||
* @param message the message to be signed. Ideally some encrypted payload.
|
||||
* @param signatureKey the PrivateKey with which the message is to be signed.
|
||||
* @return the Base64Encoded String of the signed payload.
|
||||
* @throws TransportHandlerException if some error occurs with the signing process which may be related to the
|
||||
* signature algorithm used or the key used for signing.
|
||||
*/
|
||||
public static String signMessage(String message, PrivateKey signatureKey) throws TransportHandlerException {
|
||||
|
||||
Signature signature;
|
||||
String signedEncodedString;
|
||||
|
||||
try {
|
||||
signature = Signature.getInstance(SHA_512);
|
||||
signature.initSign(signatureKey);
|
||||
signature.update(Base64.decodeBase64(message));
|
||||
|
||||
byte[] signatureBytes = signature.sign();
|
||||
signedEncodedString = Base64.encodeBase64String(signatureBytes);
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
String errorMsg =
|
||||
"Algorithm not found exception occurred for Signature instance of [" + SHA_512 + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (SignatureException e) {
|
||||
String errorMsg = "Signature exception occurred for Signature instance of [" + SHA_512 + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (InvalidKeyException e) {
|
||||
String errorMsg = "InvalidKey exception occurred for signatureKey \n[\n" + signatureKey + "\n]\n";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
}
|
||||
|
||||
return signedEncodedString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies some signed-data against the a Public-Key to ensure that it was produced by the holder of the
|
||||
* corresponding Private Key.
|
||||
*
|
||||
* @param data the actual payoad which was signed by some Private Key.
|
||||
* @param signedData the signed data produced by signing the payload using a Private Key.
|
||||
* @param verificationKey the corresponding Public Key which is an exact pair of the Private-Key with we expect
|
||||
* the data to be signed by.
|
||||
* @return true if the signed data verifies to be signed by the corresponding Private Key.
|
||||
* @throws TransportHandlerException if some error occurs with the verification process which may be related to
|
||||
* the signature algorithm used or the key used for signing.
|
||||
*/
|
||||
public static boolean verifySignature(String data, String signedData, PublicKey verificationKey)
|
||||
throws TransportHandlerException {
|
||||
|
||||
Signature signature;
|
||||
boolean verified;
|
||||
|
||||
try {
|
||||
signature = Signature.getInstance(SHA_512);
|
||||
signature.initVerify(verificationKey);
|
||||
signature.update(Base64.decodeBase64(data));
|
||||
|
||||
verified = signature.verify(Base64.decodeBase64(signedData));
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
String errorMsg =
|
||||
"Algorithm not found exception occurred for Signature instance of [" + SHA_512 + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (SignatureException e) {
|
||||
String errorMsg = "Signature exception occurred for Signature instance of [" + SHA_512 + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (InvalidKeyException e) {
|
||||
String errorMsg = "InvalidKey exception occurred for signatureKey \n[\n" + verificationKey + "\n]\n";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
}
|
||||
|
||||
return verified;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encrypts the message with the key that's passed in.
|
||||
*
|
||||
* @param encryptedMessage the encrypted message that is supposed to be decrypted.
|
||||
* @param decryptKey the key to use in the decryption process.
|
||||
* @return the decrypted message in String format.
|
||||
* @throws TransportHandlerException if an error occurs with the encryption flow which can be due to Padding
|
||||
* issues, encryption key being invalid or the algorithm used is unrecognizable.
|
||||
*/
|
||||
public static String decryptMessage(String encryptedMessage, Key decryptKey) throws TransportHandlerException {
|
||||
|
||||
Cipher decrypter;
|
||||
String decryptedMessage;
|
||||
|
||||
try {
|
||||
|
||||
decrypter = Cipher.getInstance(CIPHER_PADDING);
|
||||
decrypter.init(Cipher.DECRYPT_MODE, decryptKey);
|
||||
decryptedMessage = new String(decrypter.doFinal(Base64.decodeBase64(encryptedMessage)),
|
||||
StandardCharsets.UTF_8);
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
String errorMsg = "Algorithm not found exception occurred for Cipher instance of [" + CIPHER_PADDING + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (NoSuchPaddingException e) {
|
||||
String errorMsg = "No Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (InvalidKeyException e) {
|
||||
String errorMsg = "InvalidKey exception occurred for encryptionKey \n[\n" + decryptKey + "\n]\n";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (BadPaddingException e) {
|
||||
String errorMsg = "Bad Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
String errorMsg = "Illegal blockSize error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
}
|
||||
|
||||
return decryptedMessage;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport;
|
||||
|
||||
/**
|
||||
* This interface consists of the core functionality related to the transport between any device and the server. The
|
||||
* interface is an abstraction, regardless of the underlying protocol used for the transport. Implementation of this
|
||||
* interface by any class that caters a specific protocol (ex: HTTP, XMPP, MQTT, CoAP) would ideally have methods
|
||||
* specific to the protocol used for communication and thees methods that implement the logic related to the devices
|
||||
* using the protocol.
|
||||
*
|
||||
* @param <T> a message type specific to the protocol implemented
|
||||
*/
|
||||
public interface TransportHandler<T> {
|
||||
int DEFAULT_TIMEOUT_INTERVAL = 5000; // millis ~ 10 sec
|
||||
|
||||
void connect();
|
||||
|
||||
boolean isConnected();
|
||||
|
||||
//TODO:: Any errors needs to be thrown ahead
|
||||
void processIncomingMessage(T message, String... messageParams);
|
||||
|
||||
void processIncomingMessage();
|
||||
|
||||
void publishDeviceData(String... publishData);
|
||||
|
||||
void publishDeviceData();
|
||||
|
||||
void disconnect();
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport;
|
||||
|
||||
public class TransportHandlerException extends Exception {
|
||||
private static final long serialVersionUID = 2736466230451105440L;
|
||||
|
||||
private String errorMessage;
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public TransportHandlerException(String msg, Exception nestedEx) {
|
||||
super(msg, nestedEx);
|
||||
setErrorMessage(msg);
|
||||
}
|
||||
|
||||
public TransportHandlerException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
setErrorMessage(message);
|
||||
}
|
||||
|
||||
public TransportHandlerException(String msg) {
|
||||
super(msg);
|
||||
setErrorMessage(msg);
|
||||
}
|
||||
|
||||
public TransportHandlerException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TransportHandlerException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class TransportUtils {
|
||||
private static final Log log = LogFactory.getLog(TransportUtils.class);
|
||||
|
||||
public static final int MIN_PORT_NUMBER = 9000;
|
||||
public static final int MAX_PORT_NUMBER = 11000;
|
||||
|
||||
/**
|
||||
* Given a server endpoint as a String, this method splits it into Protocol, Host and Port
|
||||
*
|
||||
* @param ipString a network endpoint in the format - '<PROTOCOL>://<HOST>:<PORT>'
|
||||
* @return a map with keys "Protocol", "Host" & "Port" for the related values from the ipString
|
||||
* @throws TransportHandlerException
|
||||
*/
|
||||
public static Map<String, String> getHostAndPort(String ipString)
|
||||
throws TransportHandlerException {
|
||||
Map<String, String> ipPortMap = new HashMap<String, String>();
|
||||
String[] ipPortArray = ipString.split(":");
|
||||
|
||||
if (ipPortArray.length != 3) {
|
||||
String errorMsg =
|
||||
"The IP String - '" + ipString +
|
||||
"' is invalid. It needs to be in format '<PROTOCOL>://<HOST>:<PORT>'.";
|
||||
log.info(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg);
|
||||
}
|
||||
|
||||
ipPortMap.put(AgentConstants.PROTOCOL_PROPERTY, ipPortArray[0]);
|
||||
ipPortMap.put(AgentConstants.HOST_PROPERTY, ipPortArray[1].replace("/", ""));
|
||||
ipPortMap.put(AgentConstants.PORT_PROPERTY, ipPortArray[2]);
|
||||
return ipPortMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method validates whether a specific IP Address is of IPv4 type
|
||||
*
|
||||
* @param ipAddress the IP Address which needs to be validated
|
||||
* @return true if it is of IPv4 type and false otherwise
|
||||
*/
|
||||
public static boolean validateIPv4(String ipAddress) {
|
||||
try {
|
||||
if (ipAddress == null || ipAddress.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] parts = ipAddress.split("\\.");
|
||||
if (parts.length != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String s : parts) {
|
||||
int i = Integer.parseInt(s);
|
||||
if ((i < 0) || (i > 255)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !ipAddress.endsWith(".");
|
||||
|
||||
} catch (NumberFormatException nfe) {
|
||||
log.warn("The IP Address: " + ipAddress + " could not be validated against IPv4-style");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Map<String, String> getInterfaceIPMap() throws TransportHandlerException {
|
||||
|
||||
Map<String, String> interfaceToIPMap = new HashMap<String, String>();
|
||||
Enumeration<NetworkInterface> networkInterfaces;
|
||||
String networkInterfaceName = "";
|
||||
String ipAddress;
|
||||
|
||||
try {
|
||||
networkInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||
} catch (SocketException exception) {
|
||||
String errorMsg =
|
||||
"Error encountered whilst trying to get the list of network-interfaces";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, exception);
|
||||
}
|
||||
|
||||
try {
|
||||
for (; networkInterfaces.hasMoreElements(); ) {
|
||||
networkInterfaceName = networkInterfaces.nextElement().getName();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Network Interface: " + networkInterfaceName);
|
||||
log.debug("------------------------------------------");
|
||||
}
|
||||
|
||||
Enumeration<InetAddress> interfaceIPAddresses = NetworkInterface.getByName(
|
||||
networkInterfaceName).getInetAddresses();
|
||||
|
||||
for (; interfaceIPAddresses.hasMoreElements(); ) {
|
||||
ipAddress = interfaceIPAddresses.nextElement().getHostAddress();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("IP Address: " + ipAddress);
|
||||
}
|
||||
|
||||
if (TransportUtils.validateIPv4(ipAddress)) {
|
||||
interfaceToIPMap.put(networkInterfaceName, ipAddress);
|
||||
}
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("------------------------------------------");
|
||||
}
|
||||
}
|
||||
} catch (SocketException exception) {
|
||||
String errorMsg =
|
||||
"Error encountered whilst trying to get the IP Addresses of the network " +
|
||||
"interface: " + networkInterfaceName;
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, exception);
|
||||
}
|
||||
|
||||
return interfaceToIPMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to find a free port between the MIN_PORT_NUMBER(9000) and MAX_PORT_NUMBER(11000).
|
||||
* Tries 'RANDOMLY picked' port numbers between this range up-until "randomAttempts" number of
|
||||
* times. If still fails, then tries each port in descending order from the MAX_PORT_NUMBER
|
||||
* whilst skipping already attempted ones via random selection.
|
||||
*
|
||||
* @param randomAttempts no of times to TEST port numbers picked randomly over the given range
|
||||
* @return an available/free port
|
||||
*/
|
||||
public static synchronized int getAvailablePort(int randomAttempts) {
|
||||
ArrayList<Integer> failedPorts = new ArrayList<Integer>(randomAttempts);
|
||||
try {
|
||||
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
|
||||
int randomPort = MAX_PORT_NUMBER;
|
||||
while (randomAttempts > 0) {
|
||||
randomPort = secureRandom.nextInt(MAX_PORT_NUMBER - MIN_PORT_NUMBER) + MIN_PORT_NUMBER;
|
||||
if (checkIfPortAvailable(randomPort)) {
|
||||
return randomPort;
|
||||
}
|
||||
failedPorts.add(randomPort);
|
||||
randomAttempts--;
|
||||
}
|
||||
randomPort = MAX_PORT_NUMBER;
|
||||
while (true) {
|
||||
if (!failedPorts.contains(randomPort) && checkIfPortAvailable(randomPort)) {
|
||||
return randomPort;
|
||||
}
|
||||
randomPort--;
|
||||
}
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("SHA1PRNG algorithm could not be found.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean checkIfPortAvailable(int port) {
|
||||
ServerSocket tcpSocket = null;
|
||||
DatagramSocket udpSocket = null;
|
||||
|
||||
try {
|
||||
tcpSocket = new ServerSocket(port);
|
||||
tcpSocket.setReuseAddress(true);
|
||||
|
||||
udpSocket = new DatagramSocket(port);
|
||||
udpSocket.setReuseAddress(true);
|
||||
return true;
|
||||
} catch (IOException ex) {
|
||||
// denotes the port is in use
|
||||
} finally {
|
||||
if (tcpSocket != null) {
|
||||
try {
|
||||
tcpSocket.close();
|
||||
} catch (IOException e) {
|
||||
/* not to be thrown */
|
||||
}
|
||||
}
|
||||
|
||||
if (udpSocket != null) {
|
||||
udpSocket.close();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is a utility method that creates and returns a HTTP connection object.
|
||||
*
|
||||
* @param urlString the URL pattern to which the connection needs to be created
|
||||
* @return an HTTPConnection object which cn be used to send HTTP requests
|
||||
* @throws TransportHandlerException if errors occur when creating the HTTP connection with
|
||||
* the given URL string
|
||||
*/
|
||||
public static HttpURLConnection getHttpConnection(String urlString) throws
|
||||
TransportHandlerException {
|
||||
URL connectionUrl;
|
||||
HttpURLConnection httpConnection;
|
||||
|
||||
try {
|
||||
connectionUrl = new URL(urlString);
|
||||
httpConnection = (HttpURLConnection) connectionUrl.openConnection();
|
||||
} catch (MalformedURLException e) {
|
||||
String errorMsg = "Error occured whilst trying to form HTTP-URL from string: " + urlString;
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, e);
|
||||
} catch (IOException exception) {
|
||||
String errorMsg = "Error occured whilst trying to open a connection to: " + urlString;
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, exception);
|
||||
}
|
||||
return httpConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a utility method that reads and returns the response from a HTTP connection
|
||||
*
|
||||
* @param httpConnection the connection from which a response is expected
|
||||
* @return the response (as a string) from the given HTTP connection
|
||||
* @throws TransportHandlerException if any errors occur whilst reading the response from
|
||||
* the connection stream
|
||||
*/
|
||||
public static String readResponseFromHttpRequest(HttpURLConnection httpConnection)
|
||||
throws TransportHandlerException {
|
||||
BufferedReader bufferedReader;
|
||||
try {
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(
|
||||
httpConnection.getInputStream(), StandardCharsets.UTF_8));
|
||||
} catch (IOException exception) {
|
||||
String errorMsg = "There is an issue with connecting the reader to the input stream at: " +
|
||||
httpConnection.getURL();
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, exception);
|
||||
}
|
||||
|
||||
String responseLine;
|
||||
StringBuilder completeResponse = new StringBuilder();
|
||||
|
||||
try {
|
||||
while ((responseLine = bufferedReader.readLine()) != null) {
|
||||
completeResponse.append(responseLine);
|
||||
}
|
||||
} catch (IOException exception) {
|
||||
String errorMsg = "Error occured whilst trying read from the connection stream at: " +
|
||||
httpConnection.getURL();
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, exception);
|
||||
}
|
||||
try {
|
||||
bufferedReader.close();
|
||||
} catch (IOException exception) {
|
||||
log.error("Could not succesfully close the bufferedReader to the connection at: " + httpConnection.getURL());
|
||||
}
|
||||
return completeResponse.toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.http;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportUtils;
|
||||
|
||||
/**
|
||||
* This is an abstract class that implements the "TransportHandler" interface. The interface is an abstraction for
|
||||
* the core functionality with regards to device-server communication regardless of the Transport protocol. This
|
||||
* specific class contains the HTTP-Transport specific implementations. The class implements utility methods for the
|
||||
* case of a HTTP communication. However, this "abstract class", even-though it implements the "TransportHandler"
|
||||
* interface, does not contain the logic relevant to the interface methods. The specific functionality of the
|
||||
* interface methods are intended to be implemented by the concrete class that extends this abstract class and
|
||||
* utilizes the HTTP specific functionality (ideally a device API writer who would like to communicate to the device
|
||||
* via HTTP Protocol).
|
||||
*/
|
||||
public abstract class HTTPTransportHandler implements TransportHandler {
|
||||
private static final Log log = LogFactory.getLog(HTTPTransportHandler.class);
|
||||
|
||||
protected Server server;
|
||||
protected int port;
|
||||
protected int timeoutInterval;
|
||||
|
||||
protected HTTPTransportHandler() {
|
||||
this.port = TransportUtils.getAvailablePort(10);
|
||||
this.server = new Server(port);
|
||||
timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
|
||||
}
|
||||
|
||||
protected HTTPTransportHandler(int port) {
|
||||
this.port = port;
|
||||
this.server = new Server(this.port);
|
||||
timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
|
||||
}
|
||||
|
||||
protected HTTPTransportHandler(int port, int timeoutInterval) {
|
||||
this.port = port;
|
||||
this.server = new Server(this.port);
|
||||
this.timeoutInterval = timeoutInterval;
|
||||
}
|
||||
|
||||
public void setTimeoutInterval(int timeoutInterval) {
|
||||
this.timeoutInterval = timeoutInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the HTTP server is up and listening for incoming requests.
|
||||
*
|
||||
* @return true if the server is up & listening for requests, else false.
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return server.isStarted();
|
||||
}
|
||||
|
||||
|
||||
protected void incrementPort() {
|
||||
this.port = this.port + 1;
|
||||
server = new Server(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts-down the HTTP Server.
|
||||
*/
|
||||
public void closeConnection() throws Exception {
|
||||
if (server != null && isConnected()) {
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.mqtt;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
|
||||
import org.eclipse.paho.client.mqttv3.MqttCallback;
|
||||
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* This is an abstract class that implements the "TransportHandler" interface. The interface is an abstraction for
|
||||
* the core functionality with regards to device-server communication regardless of the Transport protocol. This
|
||||
* specific class contains the HTTP-Transport specific implementations. The class implements utility methods for the
|
||||
* case of a HTTP communication. However, this "abstract class", even-though it implements the "TransportHandler"
|
||||
* interface, does not contain the logic relevant to the interface methods. The specific functionality of the
|
||||
* interface methods are intended to be implemented by the concrete class that extends this abstract class and
|
||||
* utilizes the HTTP specific functionality (ideally a device API writer who would like to communicate to the device
|
||||
* via HTTP Protocol).
|
||||
* <p/>
|
||||
* This class contains the Device-Management specific implementation for all the MQTT functionality. This includes
|
||||
* connecting to a MQTT Broker & subscribing to the appropriate MQTT-topic, action plan upon losing connection or
|
||||
* successfully delivering a message to the broker and processing incoming messages. Makes use of the 'Paho-MQTT'
|
||||
* library provided by Eclipse Org.
|
||||
*/
|
||||
public abstract class MQTTTransportHandler
|
||||
implements MqttCallback, TransportHandler<MqttMessage> {
|
||||
private static final Log log = LogFactory.getLog(MQTTTransportHandler.class);
|
||||
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
|
||||
|
||||
private MqttClient client;
|
||||
private String clientId;
|
||||
private MqttConnectOptions options;
|
||||
private String clientWillTopic;
|
||||
|
||||
protected String mqttBrokerEndPoint;
|
||||
protected int timeoutInterval;
|
||||
protected String subscribeTopic;
|
||||
|
||||
/**
|
||||
* Constructor for the MQTTTransportHandler which takes in the owner, type of the device
|
||||
* and the MQTT Broker URL and the topic to subscribe.
|
||||
*
|
||||
* @param deviceOwner the owner of the device.
|
||||
* @param deviceType the CDMF Device-Type of the device.
|
||||
* @param mqttBrokerEndPoint the IP/URL of the MQTT broker endpoint.
|
||||
* @param subscribeTopic the MQTT topic to which the client is to be subscribed
|
||||
*/
|
||||
protected MQTTTransportHandler(String deviceOwner, String deviceType,
|
||||
String mqttBrokerEndPoint,
|
||||
String subscribeTopic) {
|
||||
this.clientId = deviceOwner + ":" + deviceType;
|
||||
this.subscribeTopic = subscribeTopic;
|
||||
this.clientWillTopic = deviceType + File.separator + "disconnection";
|
||||
this.mqttBrokerEndPoint = mqttBrokerEndPoint;
|
||||
this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
|
||||
this.initSubscriber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for the MQTTTransportHandler which takes in the owner, type of the device
|
||||
* and the MQTT Broker URL and the topic to subscribe. Additionally this constructor takes in
|
||||
* the reconnection-time interval between successive attempts to connect to the broker.
|
||||
*
|
||||
* @param deviceOwner the owner of the device.
|
||||
* @param deviceType the CDMF Device-Type of the device.
|
||||
* @param mqttBrokerEndPoint the IP/URL of the MQTT broker endpoint.
|
||||
* @param subscribeTopic the MQTT topic to which the client is to be subscribed
|
||||
* @param intervalInMillis the time interval in MILLI-SECONDS between successive
|
||||
* attempts to connect to the broker.
|
||||
*/
|
||||
protected MQTTTransportHandler(String deviceOwner, String deviceType,
|
||||
String mqttBrokerEndPoint, String subscribeTopic,
|
||||
int intervalInMillis) {
|
||||
this.clientId = deviceOwner + ":" + deviceType;
|
||||
this.subscribeTopic = subscribeTopic;
|
||||
//TODO:: Use constant strings
|
||||
this.clientWillTopic = deviceType + File.separator + "disconnection";
|
||||
this.mqttBrokerEndPoint = mqttBrokerEndPoint;
|
||||
this.timeoutInterval = intervalInMillis;
|
||||
this.initSubscriber();
|
||||
}
|
||||
|
||||
public void setTimeoutInterval(int timeoutInterval) {
|
||||
this.timeoutInterval = timeoutInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the MQTT-Client. Creates a client using the given MQTT-broker endpoint and the
|
||||
* clientId (which is constructed by a concatenation of [deviceOwner]:[deviceType]). Also sets
|
||||
* the client's options parameter with the clientWillTopic (in-case of connection failure) and
|
||||
* other info. Also sets the call-back this current class.
|
||||
*/
|
||||
private void initSubscriber() {
|
||||
try {
|
||||
client = new MqttClient(this.mqttBrokerEndPoint, clientId, null);
|
||||
//TODO:: Need to check for debug
|
||||
log.info("MQTT subscriber was created with ClientID : " + clientId);
|
||||
} catch (MqttException ex) {
|
||||
//TODO:: Remove unnecessary formatting and print exception
|
||||
String errorMsg = "MQTT Client Error\n" + "\tReason: " + ex.getReasonCode() +
|
||||
"\n\tMessage: " + ex.getMessage() + "\n\tLocalMsg: " +
|
||||
ex.getLocalizedMessage() + "\n\tCause: " + ex.getCause() +
|
||||
"\n\tException: " + ex;
|
||||
log.error(errorMsg);
|
||||
//TODO:: Throw the error out
|
||||
}
|
||||
|
||||
options = new MqttConnectOptions();
|
||||
options.setCleanSession(false);
|
||||
//TODO:: Use constant strings
|
||||
options.setWill(clientWillTopic, "Connection-Lost".getBytes(StandardCharsets.UTF_8), 2,
|
||||
true);
|
||||
client.setCallback(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the connection to the MQTT-Broker persists.
|
||||
*
|
||||
* @return true if the client is connected to the MQTT-Broker, else false.
|
||||
*/
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return client.isConnected();
|
||||
}
|
||||
|
||||
|
||||
protected void connectToQueue(String username, String password) throws TransportHandlerException {
|
||||
options.setUserName(username);
|
||||
options.setPassword(password.toCharArray());
|
||||
connectToQueue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the MQTT-Broker and if successfully established connection.
|
||||
*
|
||||
* @throws TransportHandlerException in the event of 'Connecting to' the MQTT broker fails.
|
||||
*/
|
||||
protected void connectToQueue() throws TransportHandlerException {
|
||||
try {
|
||||
client.connect(options);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Subscriber connected to queue at: " + this.mqttBrokerEndPoint);
|
||||
}
|
||||
} catch (MqttSecurityException ex) {
|
||||
String errorMsg = "MQTT Security Exception when connecting to queue\n" + "\tReason: " +
|
||||
" " +
|
||||
ex.getReasonCode() + "\n\tMessage: " + ex.getMessage() +
|
||||
"\n\tLocalMsg: " + ex.getLocalizedMessage() + "\n\tCause: " +
|
||||
ex.getCause() + "\n\tException: " + ex;
|
||||
//TODO:: Compulsory log of errors and remove formatted error
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(errorMsg);
|
||||
}
|
||||
throw new TransportHandlerException(errorMsg, ex);
|
||||
|
||||
} catch (MqttException ex) {
|
||||
//TODO:: Compulsory log of errors and remove formatted error
|
||||
String errorMsg = "MQTT Exception when connecting to queue\n" + "\tReason: " +
|
||||
ex.getReasonCode() + "\n\tMessage: " + ex.getMessage() +
|
||||
"\n\tLocalMsg: " + ex.getLocalizedMessage() + "\n\tCause: " +
|
||||
ex.getCause() + "\n\tException: " + ex;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(errorMsg);
|
||||
}
|
||||
throw new TransportHandlerException(errorMsg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to the MQTT-Topic specific to this MQTT Client. (The MQTT-Topic specific to the
|
||||
* device is taken in as a constructor parameter of this class) .
|
||||
*
|
||||
* @throws TransportHandlerException in the event of 'Subscribing to' the MQTT broker
|
||||
* fails.
|
||||
*/
|
||||
protected void subscribeToQueue() throws TransportHandlerException {
|
||||
try {
|
||||
//TODO:: QoS Level take it from a variable
|
||||
client.subscribe(subscribeTopic, 0);
|
||||
log.info("Subscriber '" + clientId + "' subscribed to topic: " + subscribeTopic);
|
||||
} catch (MqttException ex) {
|
||||
//TODO:: Compulsory log of errors and remove formatted error
|
||||
String errorMsg = "MQTT Exception when trying to subscribe to topic: " +
|
||||
subscribeTopic + "\n\tReason: " + ex.getReasonCode() +
|
||||
"\n\tMessage: " + ex.getMessage() + "\n\tLocalMsg: " +
|
||||
ex.getLocalizedMessage() + "\n\tCause: " + ex.getCause() +
|
||||
"\n\tException: " + ex;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(errorMsg);
|
||||
}
|
||||
|
||||
throw new TransportHandlerException(errorMsg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is used to publish reply-messages for the control signals received.
|
||||
* Invocation of this method calls its overloaded-method with a QoS equal to that of the
|
||||
* default value.
|
||||
*
|
||||
* @param topic the topic to which the reply message is to be published.
|
||||
* @param payLoad the reply-message (payload) of the MQTT publish action.
|
||||
*/
|
||||
protected void publishToQueue(String topic, String payLoad)
|
||||
throws TransportHandlerException {
|
||||
publishToQueue(topic, payLoad, DEFAULT_MQTT_QUALITY_OF_SERVICE, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an overloaded method that publishes MQTT reply-messages for control signals
|
||||
* received form the IoT-Server.
|
||||
*
|
||||
* @param topic the topic to which the reply message is to be published
|
||||
* @param payLoad the reply-message (payload) of the MQTT publish action.
|
||||
* @param qos the Quality-of-Service of the current publish action.
|
||||
* Could be 0(At-most once), 1(At-least once) or 2(Exactly once)
|
||||
*/
|
||||
protected void publishToQueue(String topic, String payLoad, int qos, boolean retained)
|
||||
throws TransportHandlerException {
|
||||
try {
|
||||
client.publish(topic, payLoad.getBytes(StandardCharsets.UTF_8), qos, retained);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Message: " + payLoad + " to MQTT topic [" + topic + "] published successfully");
|
||||
}
|
||||
} catch (MqttException ex) {
|
||||
String errorMsg =
|
||||
"MQTT Client Error" + "\n\tReason: " + ex.getReasonCode() + "\n\tMessage: " +
|
||||
ex.getMessage() + "\n\tLocalMsg: " + ex.getLocalizedMessage() +
|
||||
"\n\tCause: " + ex.getCause() + "\n\tException: " + ex;
|
||||
log.info(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void publishToQueue(String topic, MqttMessage message)
|
||||
throws TransportHandlerException {
|
||||
try {
|
||||
client.publish(topic, message);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Message: " + message.toString() + " to MQTT topic [" + topic + "] published successfully");
|
||||
}
|
||||
} catch (MqttException ex) {
|
||||
//TODO:: Compulsory log of errors and remove formatted error
|
||||
String errorMsg =
|
||||
"MQTT Client Error" + "\n\tReason: " + ex.getReasonCode() + "\n\tMessage: " +
|
||||
ex.getMessage() + "\n\tLocalMsg: " + ex.getLocalizedMessage() +
|
||||
"\n\tCause: " + ex.getCause() + "\n\tException: " + ex;
|
||||
log.info(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback method which is triggered once the MQTT client losers its connection to the broker.
|
||||
* Spawns a new thread that executes necessary actions to try and reconnect to the endpoint.
|
||||
*
|
||||
* @param throwable a Throwable Object containing the details as to why the failure occurred.
|
||||
*/
|
||||
@Override
|
||||
public void connectionLost(Throwable throwable) {
|
||||
log.warn("Lost Connection for client: " + this.clientId +
|
||||
" to " + this.mqttBrokerEndPoint + ".\nThis was due to - " + throwable.getMessage());
|
||||
|
||||
Thread reconnectThread = new Thread() {
|
||||
public void run() {
|
||||
connect();
|
||||
}
|
||||
};
|
||||
reconnectThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method which is triggered upon receiving a MQTT Message from the broker. Spawns a
|
||||
* new thread that executes any actions to be taken with the received message.
|
||||
*
|
||||
* @param topic the MQTT-Topic to which the received message was published to and the
|
||||
* client was subscribed to.
|
||||
* @param mqttMessage the actual MQTT-Message that was received from the broker.
|
||||
*/
|
||||
@Override
|
||||
public void messageArrived(final String topic, final MqttMessage mqttMessage) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.info("Got an MQTT message '" + mqttMessage.toString() + "' for topic '" + topic + "'.");
|
||||
}
|
||||
|
||||
Thread messageProcessorThread = new Thread() {
|
||||
public void run() {
|
||||
processIncomingMessage(mqttMessage, topic);
|
||||
}
|
||||
};
|
||||
messageProcessorThread.setDaemon(true);
|
||||
messageProcessorThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method which gets triggered upon successful completion of a message delivery to
|
||||
* the broker.
|
||||
*
|
||||
* @param iMqttDeliveryToken the MQTT-DeliveryToken which includes the details about the
|
||||
* specific message delivery.
|
||||
*/
|
||||
@Override
|
||||
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
|
||||
String message = "";
|
||||
try {
|
||||
message = iMqttDeliveryToken.getMessage().toString();
|
||||
} catch (MqttException e) {
|
||||
//TODO:: Throw errors
|
||||
log.error(
|
||||
"Error occurred whilst trying to read the message from the MQTT delivery token.");
|
||||
}
|
||||
String topic = iMqttDeliveryToken.getTopics()[0];
|
||||
String client = iMqttDeliveryToken.getClient().getClientId();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Message - '" + message + "' of client [" + client + "] for the topic (" +
|
||||
topic + ") was delivered successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the connection to the MQTT Broker.
|
||||
*/
|
||||
public void closeConnection() throws MqttException {
|
||||
if (client != null && isConnected()) {
|
||||
client.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.xmpp;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jivesoftware.smack.ConnectionConfiguration;
|
||||
import org.jivesoftware.smack.PacketListener;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.filter.AndFilter;
|
||||
import org.jivesoftware.smack.filter.FromContainsFilter;
|
||||
import org.jivesoftware.smack.filter.OrFilter;
|
||||
import org.jivesoftware.smack.filter.PacketFilter;
|
||||
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
||||
import org.jivesoftware.smack.filter.ToContainsFilter;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandler;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.transport.TransportHandlerException;
|
||||
|
||||
/**
|
||||
* This is an abstract class that implements the "TransportHandler" interface. The interface is an abstraction for
|
||||
* the core functionality with regards to device-server communication regardless of the Transport protocol. This
|
||||
* specific class contains the HTTP-Transport specific implementations. The class implements utility methods for the
|
||||
* case of a HTTP communication. However, this "abstract class", even-though it implements the "TransportHandler"
|
||||
* interface, does not contain the logic relevant to the interface methods. The specific functionality of the
|
||||
* interface methods are intended to be implemented by the concrete class that extends this abstract class and
|
||||
* utilizes the HTTP specific functionality (ideally a device API writer who would like to communicate to the device
|
||||
* via HTTP Protocol).
|
||||
* <p/>
|
||||
* This class contains the IoT-Server specific implementation for all the XMPP functionality. This includes
|
||||
* connecting to a XMPP Server & Login-In using the device's/server's XMPP-Account, Setting listeners and filters on
|
||||
* incoming XMPP messages and Sending XMPP replies for messages received. Makes use of the 'Smack-XMPP' library
|
||||
* provided by jivesoftware/igniterealtime.
|
||||
*/
|
||||
public abstract class XMPPTransportHandler implements TransportHandler<Message> {
|
||||
private static final Log log = LogFactory.getLog(XMPPTransportHandler.class);
|
||||
|
||||
protected String server;
|
||||
protected int timeoutInterval; // millis
|
||||
|
||||
//TODO:: Shouldnt be hard-coded. Need to be read from configs
|
||||
private static final int DEFAULT_XMPP_PORT = 5222;
|
||||
private XMPPConnection connection;
|
||||
private int port;
|
||||
private ConnectionConfiguration config;
|
||||
private PacketFilter filter;
|
||||
private PacketListener listener;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for XMPPTransportHandler passing only the server-IP.
|
||||
*
|
||||
* @param server the IP of the XMPP server.
|
||||
*/
|
||||
protected XMPPTransportHandler(String server) {
|
||||
this.server = server;
|
||||
this.port = DEFAULT_XMPP_PORT;
|
||||
this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
|
||||
initXMPPClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for XMPPTransportHandler passing server-IP and the XMPP-port.
|
||||
*
|
||||
* @param server the IP of the XMPP server.
|
||||
* @param port the XMPP server's port to connect to. (default - 5222)
|
||||
*/
|
||||
protected XMPPTransportHandler(String server, int port) {
|
||||
this.server = server;
|
||||
this.port = port;
|
||||
this.timeoutInterval = DEFAULT_TIMEOUT_INTERVAL;
|
||||
initXMPPClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for XMPPTransportHandler passing server-IP, the XMPP-port and the
|
||||
* timeoutInterval used by listeners to the server and for reconnection schedules.
|
||||
*
|
||||
* @param server the IP of the XMPP server.
|
||||
* @param port the XMPP server's port to connect to. (default - 5222)
|
||||
* @param timeoutInterval the timeout interval to use for the connection and reconnection
|
||||
*/
|
||||
protected XMPPTransportHandler(String server, int port, int timeoutInterval) {
|
||||
this.server = server;
|
||||
this.port = port;
|
||||
this.timeoutInterval = timeoutInterval;
|
||||
initXMPPClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the client's time-out-limit whilst waiting for XMPP-replies from server.
|
||||
*
|
||||
* @param millis the time in millis to be set as the time-out-limit whilst waiting for a
|
||||
* XMPP-reply.
|
||||
*/
|
||||
public void setTimeoutInterval(int millis) {
|
||||
this.timeoutInterval = millis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the connection to the XMPP-Server persists.
|
||||
*
|
||||
* @return true if the client is connected to the XMPP-Server, else false.
|
||||
*/
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return connection.isConnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the XMPP Client. Sets the time-out-limit whilst waiting for XMPP-replies from
|
||||
* server. Sets the XMPP configurations to connect to the server and creates the
|
||||
* XMPPConnection object used for connecting and Logging-In.
|
||||
*/
|
||||
private void initXMPPClient() {
|
||||
log.info(String.format("Initializing connection to XMPP Server at %1$s via port " +
|
||||
"%2$d.", server, port));
|
||||
SmackConfiguration.setPacketReplyTimeout(timeoutInterval);
|
||||
config = new ConnectionConfiguration(server, port);
|
||||
// TODO:: Need to enable SASL-Authentication appropriately
|
||||
config.setSASLAuthenticationEnabled(false);
|
||||
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
|
||||
connection = new XMPPConnection(config);
|
||||
}
|
||||
|
||||
//TODO:: Re-check all exception handling
|
||||
|
||||
/**
|
||||
* Connects to the XMPP-Server and if attempt unsuccessful, then throws exception.
|
||||
*
|
||||
* @throws TransportHandlerException in the event of 'Connecting to' the XMPP server fails.
|
||||
*/
|
||||
protected void connectToServer() throws TransportHandlerException {
|
||||
try {
|
||||
connection.connect();
|
||||
log.info(String.format("Connection to XMPP Server at %1$s established successfully......", server));
|
||||
|
||||
} catch (XMPPException xmppExcepion) {
|
||||
String errorMsg = "Connection attempt to the XMPP Server at " + server + " via port " + port + " failed.";
|
||||
log.info(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, xmppExcepion);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If successfully established connection, then tries to Log in using the device's XMPP
|
||||
* Account credentials.
|
||||
*
|
||||
* @param username the username of the device's XMPP-Account.
|
||||
* @param password the password of the device's XMPP-Account.
|
||||
* @param resource the resource the resource, specific to the XMPP-Account to which the login
|
||||
* is made to
|
||||
* @throws TransportHandlerException in the event of 'Logging into' the XMPP server fails.
|
||||
*/
|
||||
protected void loginToServer(String username, String password, String resource)
|
||||
throws TransportHandlerException {
|
||||
if (isConnected()) {
|
||||
try {
|
||||
if (resource == null) {
|
||||
connection.login(username, password);
|
||||
log.info(String.format("Logged into XMPP Server at %1$s as user %2$s......", server, username));
|
||||
} else {
|
||||
connection.login(username, password, resource);
|
||||
log.info(String.format("Logged into XMPP Server at %1$s as user %2$s on resource %3$s......",
|
||||
server, username, resource));
|
||||
}
|
||||
} catch (XMPPException xmppException) {
|
||||
String errorMsg =
|
||||
"Login attempt to the XMPP Server at " + server + " with username - " + username + " failed.";
|
||||
log.error(errorMsg);
|
||||
throw new TransportHandlerException(errorMsg, xmppException);
|
||||
}
|
||||
} else {
|
||||
String errorMsg = "Not connected to XMPP-Server to attempt Login. Please 'connectToServer' before Login";
|
||||
throw new TransportHandlerException(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets a filter for all the incoming XMPP-Messages on the Sender's JID (XMPP-Account ID).
|
||||
* Also creates a listener for the incoming messages and connects the listener to the
|
||||
* XMPPConnection alongside the set filter.
|
||||
*
|
||||
* @param senderJID the JID (XMPP-Account ID of the sender) to which the filter is to be set.
|
||||
*/
|
||||
protected void setFilterOnSender(String senderJID) {
|
||||
filter = new AndFilter(new PacketTypeFilter(Message.class), new FromContainsFilter(
|
||||
senderJID));
|
||||
listener = new PacketListener() {
|
||||
@Override
|
||||
public void processPacket(Packet packet) {
|
||||
if (packet instanceof Message) {
|
||||
final Message xmppMessage = (Message) packet;
|
||||
Thread msgProcessThread = new Thread() {
|
||||
public void run() {
|
||||
processIncomingMessage(xmppMessage);
|
||||
}
|
||||
};
|
||||
msgProcessThread.setDaemon(true);
|
||||
msgProcessThread.start();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
connection.addPacketListener(listener, filter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets a filter for all the incoming XMPP-Messages on the Receiver's JID (XMPP-Account ID).
|
||||
* Also creates a listener for the incoming messages and connects the listener to the
|
||||
* XMPPConnection alongside the set filter.
|
||||
*
|
||||
* @param receiverJID the JID (XMPP-Account ID of the receiver) to which the filter is to be
|
||||
* set.
|
||||
*/
|
||||
protected void setFilterOnReceiver(String receiverJID) {
|
||||
filter = new AndFilter(new PacketTypeFilter(Message.class), new ToContainsFilter(
|
||||
receiverJID));
|
||||
listener = new PacketListener() {
|
||||
@Override
|
||||
public void processPacket(Packet packet) {
|
||||
if (packet instanceof Message) {
|
||||
final Message xmppMessage = (Message) packet;
|
||||
Thread msgProcessThread = new Thread() {
|
||||
public void run() {
|
||||
processIncomingMessage(xmppMessage);
|
||||
}
|
||||
};
|
||||
msgProcessThread.setDaemon(true);
|
||||
msgProcessThread.start();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
connection.addPacketListener(listener, filter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets a filter for all the incoming XMPP-Messages on the From-JID & To-JID (XMPP-Account IDs)
|
||||
* passed in. Also creates a listener for the incoming messages and connects the listener to
|
||||
* the XMPPConnection alongside the set filter.
|
||||
*
|
||||
* @param senderJID the From-JID (XMPP-Account ID) to which the filter is to be set.
|
||||
* @param receiverJID the To-JID (XMPP-Account ID) to which the filter is to be set.
|
||||
* @param andCondition if true: then filter is set with 'AND' operator (senderJID &&
|
||||
* receiverJID),
|
||||
* if false: then the filter is set with 'OR' operator (senderJID |
|
||||
* receiverJID)
|
||||
*/
|
||||
protected void setMessageFilterAndListener(String senderJID, String receiverJID, boolean
|
||||
andCondition) {
|
||||
PacketFilter jidFilter;
|
||||
|
||||
if (andCondition) {
|
||||
jidFilter = new AndFilter(new FromContainsFilter(senderJID), new ToContainsFilter(
|
||||
receiverJID));
|
||||
} else {
|
||||
jidFilter = new OrFilter(new FromContainsFilter(senderJID), new ToContainsFilter(
|
||||
receiverJID));
|
||||
}
|
||||
|
||||
filter = new AndFilter(new PacketTypeFilter(Message.class), jidFilter);
|
||||
listener = new PacketListener() {
|
||||
@Override
|
||||
public void processPacket(Packet packet) {
|
||||
if (packet instanceof Message) {
|
||||
final Message xmppMessage = (Message) packet;
|
||||
Thread msgProcessThread = new Thread() {
|
||||
public void run() {
|
||||
processIncomingMessage(xmppMessage);
|
||||
}
|
||||
};
|
||||
msgProcessThread.setDaemon(true);
|
||||
msgProcessThread.start();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
connection.addPacketListener(listener, filter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends an XMPP message. Calls the overloaded method with Subject set to "Reply-From-Device"
|
||||
*
|
||||
* @param JID the JID (XMPP Account ID) to which the message is to be sent to.
|
||||
* @param message the XMPP-Message that is to be sent.
|
||||
*/
|
||||
protected void sendXMPPMessage(String JID, String message) {
|
||||
sendXMPPMessage(JID, message, "XMPP-Message");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overloaded method to send an XMPP message. Includes the subject to be mentioned in the
|
||||
* message that is sent.
|
||||
*
|
||||
* @param JID the JID (XMPP Account ID) to which the message is to be sent to.
|
||||
* @param message the XMPP-Message that is to be sent.
|
||||
* @param subject the subject that the XMPP-Message would carry.
|
||||
*/
|
||||
protected void sendXMPPMessage(String JID, String message, String subject) {
|
||||
Message xmppMessage = new Message();
|
||||
xmppMessage.setTo(JID);
|
||||
xmppMessage.setSubject(subject);
|
||||
xmppMessage.setBody(message);
|
||||
xmppMessage.setType(Message.Type.chat);
|
||||
sendXMPPMessage(JID, xmppMessage);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends an XMPP message.
|
||||
*
|
||||
* @param JID the JID (XMPP Account ID) to which the message is to be sent to.
|
||||
* @param xmppMessage the XMPP-Message that is to be sent.
|
||||
*/
|
||||
protected void sendXMPPMessage(String JID, Message xmppMessage) {
|
||||
connection.sendPacket(xmppMessage);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Message: '" + xmppMessage.getBody() + "' sent to XMPP JID [" + JID +
|
||||
"] sent successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disables default debugger provided by the XMPPConnection.
|
||||
*/
|
||||
protected void disableDebugger() {
|
||||
connection.DEBUG_ENABLED = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes the connection to the XMPP Server.
|
||||
*/
|
||||
public void closeConnection() {
|
||||
if (connection != null && isConnected()) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentUtilOperations;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual.ui.AgentUI;
|
||||
|
||||
import javax.sound.midi.InvalidMidiDataException;
|
||||
import javax.sound.midi.MidiSystem;
|
||||
import javax.sound.midi.MidiUnavailableException;
|
||||
import javax.sound.midi.Sequence;
|
||||
import javax.sound.midi.Sequencer;
|
||||
import javax.sound.sampled.Clip;
|
||||
import javax.swing.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* This class use to emulate virtual hardware functionality
|
||||
*/
|
||||
public class VirtualHardwareManager {
|
||||
|
||||
private static final Log log = LogFactory.getLog(VirtualHardwareManager.class);
|
||||
|
||||
private static VirtualHardwareManager virtualHardwareManager;
|
||||
|
||||
private AgentUI agentUI;
|
||||
private Sequencer sequencer = null;
|
||||
|
||||
private int temperature = 30, humidity = 30;
|
||||
private int temperatureMin = 20, temperatureMax = 50, humidityMin = 20, humidityMax = 50;
|
||||
private int temperatureSVF = 50, humiditySVF = 50;
|
||||
private boolean isTemperatureRandomized, isHumidityRandomized;
|
||||
private boolean isTemperatureSmoothed, isHumiditySmoothed;
|
||||
|
||||
private VirtualHardwareManager(){
|
||||
}
|
||||
|
||||
public static VirtualHardwareManager getInstance(){
|
||||
if (virtualHardwareManager == null){
|
||||
virtualHardwareManager = new VirtualHardwareManager();
|
||||
}
|
||||
return virtualHardwareManager;
|
||||
}
|
||||
|
||||
public void init(){
|
||||
try {
|
||||
// Set System L&F for Device UI
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (UnsupportedLookAndFeelException e) {
|
||||
log.error(
|
||||
"'UnsupportedLookAndFeelException' error occurred whilst initializing the" +
|
||||
" Agent UI.");
|
||||
} catch (ClassNotFoundException e) {
|
||||
log.error(
|
||||
"'ClassNotFoundException' error occurred whilst initializing the Agent UI.");
|
||||
} catch (InstantiationException e) {
|
||||
log.error(
|
||||
"'InstantiationException' error occurred whilst initializing the Agent UI.");
|
||||
} catch (IllegalAccessException e) {
|
||||
log.error(
|
||||
"'IllegalAccessException' error occurred whilst initializing the Agent UI.");
|
||||
}
|
||||
java.awt.EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
agentUI = new AgentUI();
|
||||
agentUI.setVisible(true);
|
||||
}
|
||||
});
|
||||
setAudioSequencer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get temperature from emulated device
|
||||
* @return Temperature
|
||||
*/
|
||||
public int getTemperature() {
|
||||
if (isTemperatureRandomized) {
|
||||
temperature = getRandom(temperatureMax, temperatureMin, temperature,
|
||||
isTemperatureSmoothed, temperatureSVF);
|
||||
agentUI.updateTemperature(temperature);
|
||||
}
|
||||
return temperature;
|
||||
}
|
||||
|
||||
public void setTemperature(int temperature) {
|
||||
this.temperature = temperature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get humidity from emulated device
|
||||
* @return Humidity
|
||||
*/
|
||||
public int getHumidity() {
|
||||
if (isHumidityRandomized) {
|
||||
humidity = getRandom(humidityMax, humidityMin, humidity, isHumiditySmoothed,
|
||||
humiditySVF);
|
||||
agentUI.updateHumidity(humidity);
|
||||
}
|
||||
return humidity;
|
||||
}
|
||||
|
||||
public void setHumidity(int humidity) {
|
||||
this.humidity = humidity;
|
||||
}
|
||||
|
||||
public void setTemperatureMin(int temperatureMin) {
|
||||
this.temperatureMin = temperatureMin;
|
||||
}
|
||||
|
||||
public void setTemperatureMax(int temperatureMax) {
|
||||
this.temperatureMax = temperatureMax;
|
||||
}
|
||||
|
||||
public void setHumidityMin(int humidityMin) {
|
||||
this.humidityMin = humidityMin;
|
||||
}
|
||||
|
||||
public void setHumidityMax(int humidityMax) {
|
||||
this.humidityMax = humidityMax;
|
||||
}
|
||||
|
||||
public void setIsHumidityRandomized(boolean isHumidityRandomized) {
|
||||
this.isHumidityRandomized = isHumidityRandomized;
|
||||
}
|
||||
|
||||
public void setIsTemperatureRandomized(boolean isTemperatureRandomized) {
|
||||
this.isTemperatureRandomized = isTemperatureRandomized;
|
||||
}
|
||||
|
||||
public void setTemperatureSVF(int temperatureSVF) {
|
||||
this.temperatureSVF = temperatureSVF;
|
||||
}
|
||||
|
||||
public void setHumiditySVF(int humiditySVF) {
|
||||
this.humiditySVF = humiditySVF;
|
||||
}
|
||||
|
||||
public void setIsTemperatureSmoothed(boolean isTemperatureSmoothed) {
|
||||
this.isTemperatureSmoothed = isTemperatureSmoothed;
|
||||
}
|
||||
|
||||
public void setIsHumiditySmoothed(boolean isHumiditySmoothed) {
|
||||
this.isHumiditySmoothed = isHumiditySmoothed;
|
||||
}
|
||||
|
||||
public void changeAlarmStatus(boolean isOn) {
|
||||
agentUI.setAlarmStatus(isOn);
|
||||
|
||||
if (isOn) {
|
||||
sequencer.start();
|
||||
} else {
|
||||
sequencer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private int getRandom(int max, int min, int current, boolean isSmoothed, int svf) {
|
||||
if (isSmoothed) {
|
||||
int offset = (max - min) * svf / 100;
|
||||
double mx = current + offset;
|
||||
max = (mx > max) ? max : (int) Math.round(mx);
|
||||
double mn = current - offset;
|
||||
min = (mn < min) ? min : (int) Math.round(mn);
|
||||
}
|
||||
try {
|
||||
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
|
||||
return secureRandom.nextInt(max - min) + min;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("SHA1PRNG algorithm could not be found.");
|
||||
}
|
||||
}
|
||||
|
||||
private void setAudioSequencer() {
|
||||
InputStream audioSrc = AgentUtilOperations.class.getResourceAsStream(
|
||||
"/" + AgentConstants.AUDIO_FILE_NAME);
|
||||
Sequence sequence;
|
||||
|
||||
try {
|
||||
sequence = MidiSystem.getSequence(audioSrc);
|
||||
sequencer = MidiSystem.getSequencer();
|
||||
if(sequencer != null) {
|
||||
sequencer.open();
|
||||
sequencer.setSequence(sequence);
|
||||
sequencer.setLoopCount(Clip.LOOP_CONTINUOUSLY);
|
||||
}
|
||||
} catch (InvalidMidiDataException e) {
|
||||
log.error("AudioReader: Error whilst setting MIDI Audio reader sequence");
|
||||
} catch (IOException e) {
|
||||
log.error("AudioReader: Error whilst getting audio sequence from stream");
|
||||
} catch (MidiUnavailableException e) {
|
||||
log.error("AudioReader: Error whilst openning MIDI Audio reader sequencer");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,910 @@
|
||||
/*
|
||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual.ui;
|
||||
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentConstants;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.core.AgentManager;
|
||||
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.agent.virtual.VirtualHardwareManager;
|
||||
|
||||
import java.awt.*;
|
||||
import java.net.URL;
|
||||
import java.util.Calendar;
|
||||
import javax.swing.*;
|
||||
|
||||
public class AgentUI extends JFrame {
|
||||
|
||||
private boolean isTemperatureRandomized, isHumidityRandomized;
|
||||
private boolean isTemperatureSmoothed, isHumiditySmoothed;
|
||||
|
||||
private volatile boolean isAlarmOn = false;
|
||||
|
||||
private JLabel picLabelBulbOn, picLabelBulbOff;
|
||||
|
||||
// Variables declaration - do not modify
|
||||
private JCheckBox chkbxEmulate;
|
||||
private JCheckBox chkbxHumidityRandom;
|
||||
private JCheckBox chkbxHumiditySmooth;
|
||||
private JCheckBox chkbxTemperatureRandom;
|
||||
private JCheckBox chkbxTemperatureSmooth;
|
||||
private JComboBox cmbInterface;
|
||||
private JComboBox cmbPeriod;
|
||||
private JComboBox cmbProtocol;
|
||||
private JLabel jLabel1;
|
||||
private JLabel jLabel10;
|
||||
private JLabel jLabel11;
|
||||
private JLabel jLabel12;
|
||||
private JLabel jLabel2;
|
||||
private JLabel jLabel20;
|
||||
private JLabel jLabel23;
|
||||
private JLabel jLabel24;
|
||||
private JLabel jLabel25;
|
||||
private JLabel jLabel3;
|
||||
private JLabel jLabel4;
|
||||
private JLabel jLabel5;
|
||||
private JLabel jLabel6;
|
||||
private JLabel jLabel7;
|
||||
private JLabel jLabel8;
|
||||
private JLabel jLabel9;
|
||||
private JPanel jPanel1;
|
||||
private JPanel jPanel2;
|
||||
private JPanel jPanel3;
|
||||
private JPanel jPanel4;
|
||||
private JPanel jPanel6;
|
||||
private JPanel jPanel7;
|
||||
private JPanel jPanel8;
|
||||
private JPanel jPanel9;
|
||||
private JSeparator jSeparator1;
|
||||
private JSeparator jSeparator5;
|
||||
private JLabel lblAgentName;
|
||||
private JLabel lblStatus;
|
||||
private JPanel pnlBulbStatus;
|
||||
private JSpinner spinnerHumidity;
|
||||
private JSpinner spinnerInterval;
|
||||
private JSpinner spinnerTemperature;
|
||||
private JTextField txtHumidityMax;
|
||||
private JTextField txtHumidityMin;
|
||||
private JTextField txtHumiditySVF;
|
||||
private JTextField txtTemperatureMax;
|
||||
private JTextField txtTemperatureMin;
|
||||
private JTextField txtTemperatureSVF;
|
||||
// End of variables declaration
|
||||
|
||||
private Runnable uiUpdater = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
pnlBulbStatus.removeAll();
|
||||
pnlBulbStatus.add(isAlarmOn ? picLabelBulbOn : picLabelBulbOff);
|
||||
pnlBulbStatus.updateUI();
|
||||
lblStatus.setText(AgentManager.getInstance().getAgentStatus());
|
||||
if (isTemperatureRandomized) {
|
||||
txtTemperatureMinActionPerformed(null);
|
||||
txtTemperatureMaxActionPerformed(null);
|
||||
if (isTemperatureSmoothed) {
|
||||
txtTemperatureSVFActionPerformed(null);
|
||||
}
|
||||
}
|
||||
if (isHumidityRandomized) {
|
||||
txtHumidityMinActionPerformed(null);
|
||||
txtHumidityMaxActionPerformed(null);
|
||||
if (isHumiditySmoothed) {
|
||||
txtHumiditySVFActionPerformed(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates new form AgentUI
|
||||
*/
|
||||
public AgentUI() {
|
||||
initComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void initComponents() {
|
||||
|
||||
lblAgentName = new JLabel();
|
||||
jLabel2 = new JLabel();
|
||||
jPanel1 = new JPanel();
|
||||
jLabel3 = new JLabel();
|
||||
pnlBulbStatus = new JPanel();
|
||||
jPanel2 = new JPanel();
|
||||
jLabel4 = new JLabel();
|
||||
chkbxTemperatureRandom = new JCheckBox();
|
||||
jSeparator1 = new JSeparator();
|
||||
jPanel7 = new JPanel();
|
||||
jLabel5 = new JLabel();
|
||||
txtTemperatureMin = new JTextField();
|
||||
jLabel6 = new JLabel();
|
||||
txtTemperatureMax = new JTextField();
|
||||
jLabel10 = new JLabel();
|
||||
txtTemperatureSVF = new JTextField();
|
||||
spinnerTemperature = new JSpinner();
|
||||
chkbxTemperatureSmooth = new JCheckBox();
|
||||
jPanel6 = new JPanel();
|
||||
jLabel20 = new JLabel();
|
||||
lblStatus = new JLabel();
|
||||
jPanel8 = new JPanel();
|
||||
jLabel23 = new JLabel();
|
||||
chkbxHumidityRandom = new JCheckBox();
|
||||
jSeparator5 = new JSeparator();
|
||||
jPanel9 = new JPanel();
|
||||
jLabel24 = new JLabel();
|
||||
txtHumidityMin = new JTextField();
|
||||
jLabel25 = new JLabel();
|
||||
txtHumidityMax = new JTextField();
|
||||
txtHumiditySVF = new JTextField();
|
||||
jLabel11 = new JLabel();
|
||||
spinnerHumidity = new JSpinner();
|
||||
chkbxHumiditySmooth = new JCheckBox();
|
||||
jPanel3 = new JPanel();
|
||||
jLabel7 = new JLabel();
|
||||
spinnerInterval = new JSpinner();
|
||||
jLabel8 = new JLabel();
|
||||
jLabel9 = new JLabel();
|
||||
cmbProtocol = new JComboBox();
|
||||
jLabel12 = new JLabel();
|
||||
cmbInterface = new JComboBox();
|
||||
jPanel4 = new JPanel();
|
||||
chkbxEmulate = new JCheckBox();
|
||||
cmbPeriod = new JComboBox();
|
||||
jLabel1 = new JLabel();
|
||||
|
||||
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
setTitle("Fire Alarm Emulator");
|
||||
setResizable(false);
|
||||
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
setLocation(dim.width / 2 - 650 / 2, dim.height / 2 - 440 / 2);
|
||||
|
||||
lblAgentName.setFont(new Font("Cantarell", 1, 24)); // NOI18N
|
||||
lblAgentName.setHorizontalAlignment(SwingConstants.LEFT);
|
||||
lblAgentName.setText("Device Name: " + AgentManager.getInstance().getDeviceName());
|
||||
|
||||
Calendar now = Calendar.getInstance();
|
||||
int currentYear = now.get(Calendar.YEAR);
|
||||
jLabel2.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
jLabel2.setText("Copyright (c) " + currentYear + ", WSO2 Inc.");
|
||||
|
||||
jPanel1.setBackground(new Color(220, 220, 220));
|
||||
|
||||
jLabel3.setFont(new Font("Cantarell", 0, 18)); // NOI18N
|
||||
jLabel3.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
jLabel3.setText("Alarm Status");
|
||||
|
||||
pnlBulbStatus.setBackground(new Color(220, 220, 220));
|
||||
|
||||
GroupLayout pnlBulbStatusLayout = new GroupLayout(pnlBulbStatus);
|
||||
pnlBulbStatus.setLayout(pnlBulbStatusLayout);
|
||||
pnlBulbStatusLayout.setHorizontalGroup(
|
||||
pnlBulbStatusLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
);
|
||||
pnlBulbStatusLayout.setVerticalGroup(
|
||||
pnlBulbStatusLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 167, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
GroupLayout jPanel1Layout = new GroupLayout(jPanel1);
|
||||
jPanel1.setLayout(jPanel1Layout);
|
||||
jPanel1Layout.setHorizontalGroup(
|
||||
jPanel1Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(pnlBulbStatus, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jLabel3, GroupLayout.DEFAULT_SIZE, 190, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jLabel3)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(pnlBulbStatus, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jPanel2.setBackground(new Color(220, 220, 220));
|
||||
|
||||
jLabel4.setFont(new Font("Cantarell", 0, 18)); // NOI18N
|
||||
jLabel4.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
jLabel4.setText("Temperature");
|
||||
|
||||
chkbxTemperatureRandom.setText("Randomize Data");
|
||||
chkbxTemperatureRandom.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkbxTemperatureRandomActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jSeparator1.setOrientation(SwingConstants.VERTICAL);
|
||||
|
||||
jPanel7.setBackground(new Color(220, 220, 220));
|
||||
|
||||
jLabel5.setHorizontalAlignment(SwingConstants.LEFT);
|
||||
jLabel5.setText("Min");
|
||||
|
||||
txtTemperatureMin.setHorizontalAlignment(JTextField.CENTER);
|
||||
txtTemperatureMin.setText("20");
|
||||
txtTemperatureMin.setEnabled(false);
|
||||
txtTemperatureMin.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtTemperatureMinActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel6.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
jLabel6.setText("Max");
|
||||
|
||||
txtTemperatureMax.setHorizontalAlignment(JTextField.CENTER);
|
||||
txtTemperatureMax.setText("50");
|
||||
txtTemperatureMax.setEnabled(false);
|
||||
txtTemperatureMax.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtTemperatureMaxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel10.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
jLabel10.setText("SV %");
|
||||
|
||||
txtTemperatureSVF.setHorizontalAlignment(JTextField.CENTER);
|
||||
txtTemperatureSVF.setText("50");
|
||||
txtTemperatureSVF.setEnabled(false);
|
||||
txtTemperatureSVF.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtTemperatureSVFActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
GroupLayout jPanel7Layout = new GroupLayout(jPanel7);
|
||||
jPanel7.setLayout(jPanel7Layout);
|
||||
jPanel7Layout.setHorizontalGroup(
|
||||
jPanel7Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel7Layout.createSequentialGroup()
|
||||
.addComponent(jLabel5)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtTemperatureMin, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel6)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtTemperatureMax, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel10)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtTemperatureSVF, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
jPanel7Layout.setVerticalGroup(
|
||||
jPanel7Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(GroupLayout.Alignment.TRAILING, jPanel7Layout.createSequentialGroup()
|
||||
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(jPanel7Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtTemperatureMin, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(txtTemperatureMax, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jLabel6)
|
||||
.addComponent(jLabel5)
|
||||
.addComponent(jLabel10)
|
||||
.addComponent(txtTemperatureSVF, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(35, 35, 35))
|
||||
);
|
||||
|
||||
spinnerTemperature.setFont(new Font("Cantarell", 1, 24)); // NOI18N
|
||||
spinnerTemperature.setModel(new SpinnerNumberModel(30, 0, 100, 1));
|
||||
spinnerTemperature.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
spinnerTemperatureStateChanged(evt);
|
||||
}
|
||||
});
|
||||
|
||||
chkbxTemperatureSmooth.setText("Smooth Variation");
|
||||
chkbxTemperatureSmooth.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkbxTemperatureSmoothActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
GroupLayout jPanel2Layout = new GroupLayout(jPanel2);
|
||||
jPanel2.setLayout(jPanel2Layout);
|
||||
jPanel2Layout.setHorizontalGroup(
|
||||
jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(jLabel4, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(spinnerTemperature))
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jSeparator1, GroupLayout.PREFERRED_SIZE, 6, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jPanel7, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addComponent(chkbxTemperatureRandom)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(chkbxTemperatureSmooth)))
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel2Layout.setVerticalGroup(
|
||||
jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel2Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jSeparator1)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addGroup(jPanel2Layout.createParallelGroup(
|
||||
|
||||
GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(chkbxTemperatureRandom)
|
||||
.addComponent(chkbxTemperatureSmooth))
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel7, GroupLayout.PREFERRED_SIZE, 51, GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addComponent(jLabel4, GroupLayout.PREFERRED_SIZE, 23, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spinnerTemperature)))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jPanel6.setBackground(new Color(253, 254, 209));
|
||||
|
||||
jLabel20.setText("Connection Status:");
|
||||
jLabel20.setVerticalTextPosition(SwingConstants.TOP);
|
||||
|
||||
lblStatus.setFont(new Font("Cantarell", 1, 15)); // NOI18N
|
||||
lblStatus.setText("Not Connected");
|
||||
|
||||
GroupLayout jPanel6Layout = new GroupLayout(jPanel6);
|
||||
jPanel6.setLayout(jPanel6Layout);
|
||||
jPanel6Layout.setHorizontalGroup(
|
||||
jPanel6Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel6Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jLabel20)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblStatus, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel6Layout.setVerticalGroup(
|
||||
jPanel6Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(GroupLayout.Alignment.TRAILING, jPanel6Layout.createSequentialGroup()
|
||||
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(jPanel6Layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(jLabel20, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(jPanel6Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(lblStatus)))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jPanel8.setBackground(new Color(220, 220, 220));
|
||||
|
||||
jLabel23.setFont(new Font("Cantarell", 0, 18)); // NOI18N
|
||||
jLabel23.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
jLabel23.setText("Humidity");
|
||||
|
||||
chkbxHumidityRandom.setText("Randomize Data");
|
||||
chkbxHumidityRandom.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkbxHumidityRandomActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jSeparator5.setOrientation(SwingConstants.VERTICAL);
|
||||
|
||||
jPanel9.setBackground(new Color(220, 220, 220));
|
||||
|
||||
jLabel24.setHorizontalAlignment(SwingConstants.LEFT);
|
||||
jLabel24.setText("Min");
|
||||
|
||||
txtHumidityMin.setHorizontalAlignment(JTextField.CENTER);
|
||||
txtHumidityMin.setText("20");
|
||||
txtHumidityMin.setEnabled(false);
|
||||
txtHumidityMin.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtHumidityMinActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel25.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
jLabel25.setText("Max");
|
||||
|
||||
txtHumidityMax.setHorizontalAlignment(JTextField.CENTER);
|
||||
txtHumidityMax.setText("50");
|
||||
txtHumidityMax.setEnabled(false);
|
||||
txtHumidityMax.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtHumidityMaxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
txtHumiditySVF.setHorizontalAlignment(JTextField.CENTER);
|
||||
txtHumiditySVF.setText("50");
|
||||
txtHumiditySVF.setEnabled(false);
|
||||
txtHumiditySVF.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtHumiditySVFActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel11.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
jLabel11.setText("SV %");
|
||||
|
||||
GroupLayout jPanel9Layout = new GroupLayout(jPanel9);
|
||||
jPanel9.setLayout(jPanel9Layout);
|
||||
jPanel9Layout.setHorizontalGroup(
|
||||
jPanel9Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel9Layout.createSequentialGroup()
|
||||
.addComponent(jLabel24)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtHumidityMin, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel25)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtHumidityMax, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel11)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtHumiditySVF, GroupLayout.PREFERRED_SIZE, 45, GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
jPanel9Layout.setVerticalGroup(
|
||||
jPanel9Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(GroupLayout.Alignment.TRAILING, jPanel9Layout.createSequentialGroup()
|
||||
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(jPanel9Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel9Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jLabel11)
|
||||
.addComponent(txtHumiditySVF, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(jPanel9Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtHumidityMin, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(txtHumidityMax, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jLabel25)
|
||||
.addComponent(jLabel24)))
|
||||
.addGap(35, 35, 35))
|
||||
);
|
||||
|
||||
spinnerHumidity.setFont(new Font("Cantarell", 1, 24)); // NOI18N
|
||||
spinnerHumidity.setModel(new SpinnerNumberModel(30, 0, 100, 1));
|
||||
spinnerHumidity.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
spinnerHumidityStateChanged(evt);
|
||||
}
|
||||
});
|
||||
|
||||
chkbxHumiditySmooth.setText("Smooth Variation");
|
||||
chkbxHumiditySmooth.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkbxHumiditySmoothActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
GroupLayout jPanel8Layout = new GroupLayout(jPanel8);
|
||||
jPanel8.setLayout(jPanel8Layout);
|
||||
jPanel8Layout.setHorizontalGroup(
|
||||
jPanel8Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel8Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel8Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabel23, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(spinnerHumidity))
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jSeparator5, GroupLayout.PREFERRED_SIZE, 6, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel8Layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(jPanel9, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(jPanel8Layout.createSequentialGroup()
|
||||
.addComponent(chkbxHumidityRandom)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(chkbxHumiditySmooth)))
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel8Layout.setVerticalGroup(
|
||||
jPanel8Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel8Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel8Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jSeparator5)
|
||||
.addGroup(jPanel8Layout.createSequentialGroup()
|
||||
.addGroup(jPanel8Layout.createParallelGroup(
|
||||
GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(chkbxHumidityRandom)
|
||||
.addComponent(chkbxHumiditySmooth))
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel9, GroupLayout.PREFERRED_SIZE, 51, GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 1, Short.MAX_VALUE))
|
||||
.addGroup(jPanel8Layout.createSequentialGroup()
|
||||
.addComponent(jLabel23, GroupLayout.PREFERRED_SIZE, 23, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spinnerHumidity)))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jPanel3.setBackground(new Color(207, 233, 234));
|
||||
|
||||
jLabel7.setText("Data Push Interval:");
|
||||
|
||||
spinnerInterval.setModel(new SpinnerNumberModel(Integer.valueOf(AgentManager.getInstance().getPushInterval()), Integer.valueOf(1), null, Integer.valueOf(1)));
|
||||
spinnerInterval.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
spinnerIntervalStateChanged(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel8.setText("Seconds");
|
||||
|
||||
jLabel9.setText("Protocol:");
|
||||
|
||||
cmbProtocol.setModel(new DefaultComboBoxModel(new String[] { "MQTT", "XMPP", "HTTP" }));
|
||||
cmbProtocol.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cmbProtocolActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel12.setText("Interface:");
|
||||
|
||||
cmbInterface.setModel(new DefaultComboBoxModel(new String[] { "eth0" }));
|
||||
cmbInterface.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cmbInterfaceActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
GroupLayout jPanel3Layout = new GroupLayout(jPanel3);
|
||||
jPanel3.setLayout(jPanel3Layout);
|
||||
jPanel3Layout.setHorizontalGroup(
|
||||
jPanel3Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel3Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jLabel7)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spinnerInterval, GroupLayout.PREFERRED_SIZE, 55, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel8)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jLabel12)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cmbInterface, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel9)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cmbProtocol, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel3Layout.setVerticalGroup(
|
||||
jPanel3Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
|
||||
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(jPanel3Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel3Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jLabel12)
|
||||
.addComponent(cmbInterface, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(jPanel3Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jLabel7)
|
||||
.addComponent(spinnerInterval, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jLabel8)
|
||||
.addComponent(jLabel9)
|
||||
.addComponent(cmbProtocol, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jPanel4.setBackground(new Color(169, 253, 173));
|
||||
|
||||
chkbxEmulate.setText("Emulate data");
|
||||
chkbxEmulate.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkbxEmulateActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
cmbPeriod.setModel(new DefaultComboBoxModel(new String[] { "1 hour", "1 day", "1 week", "1 month " }));
|
||||
cmbPeriod.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cmbPeriodActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel1.setText("Emulation Period");
|
||||
|
||||
GroupLayout jPanel4Layout = new GroupLayout(jPanel4);
|
||||
jPanel4.setLayout(jPanel4Layout);
|
||||
jPanel4Layout.setHorizontalGroup(
|
||||
jPanel4Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel4Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(chkbxEmulate)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jLabel1)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cmbPeriod, GroupLayout.PREFERRED_SIZE, 162, GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel4Layout.setVerticalGroup(
|
||||
jPanel4Layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup()
|
||||
.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(jPanel4Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(chkbxEmulate)
|
||||
.addComponent(cmbPeriod, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jLabel1))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
GroupLayout layout = new GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lblAgentName, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jPanel6, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(jPanel1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(
|
||||
GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jPanel8, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jPanel2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||
.addComponent(jLabel2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jPanel4, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jPanel3, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(lblAgentName, GroupLayout.PREFERRED_SIZE, 53, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel6, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(jPanel2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel8, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(jPanel1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel3, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel4, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel2, GroupLayout.PREFERRED_SIZE, 28, GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
pack();
|
||||
|
||||
chkbxTemperatureSmooth.setEnabled(false);
|
||||
chkbxTemperatureSmooth.setEnabled(false);
|
||||
|
||||
cmbInterface.removeAllItems();
|
||||
for (String item : AgentManager.getInstance().getInterfaceList()){
|
||||
cmbInterface.addItem(item);
|
||||
}
|
||||
cmbInterface.setEnabled(false);
|
||||
|
||||
cmbProtocol.removeAllItems();
|
||||
for (String item : AgentManager.getInstance().getProtocolList()){
|
||||
cmbProtocol.addItem(item);
|
||||
}
|
||||
cmbProtocol.setSelectedItem(AgentConstants.DEFAULT_PROTOCOL);
|
||||
|
||||
URL urlAlarmOn = this.getClass().getResource("/alarm-on.gif");
|
||||
ImageIcon imageIconAlarmOn = new ImageIcon(urlAlarmOn);
|
||||
|
||||
URL urlAlarmOff = this.getClass().getResource("/alarm-off.gif");
|
||||
ImageIcon imageIconAlarmOff = new ImageIcon(urlAlarmOff);
|
||||
|
||||
picLabelBulbOn = new JLabel(imageIconAlarmOn);
|
||||
picLabelBulbOn.setSize(pnlBulbStatus.getSize());
|
||||
|
||||
picLabelBulbOff = new JLabel(imageIconAlarmOff);
|
||||
picLabelBulbOff.setSize(pnlBulbStatus.getSize());
|
||||
|
||||
new Thread(uiUpdater).start();
|
||||
|
||||
AgentManager.getInstance().setDeviceReady(true);
|
||||
}
|
||||
|
||||
|
||||
private void chkbxTemperatureRandomActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
isTemperatureRandomized = chkbxTemperatureRandom.isSelected();
|
||||
VirtualHardwareManager.getInstance().setIsTemperatureRandomized(isTemperatureRandomized);
|
||||
spinnerTemperature.setEnabled(!isTemperatureRandomized);
|
||||
txtTemperatureMax.setEnabled(isTemperatureRandomized);
|
||||
txtTemperatureMin.setEnabled(isTemperatureRandomized);
|
||||
chkbxTemperatureSmooth.setEnabled(isTemperatureRandomized);
|
||||
txtTemperatureSVF.setEnabled(isTemperatureRandomized && isTemperatureSmoothed);
|
||||
}
|
||||
|
||||
private void chkbxHumidityRandomActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
isHumidityRandomized = chkbxHumidityRandom.isSelected();
|
||||
VirtualHardwareManager.getInstance().setIsHumidityRandomized(isHumidityRandomized);
|
||||
spinnerHumidity.setEnabled(!isHumidityRandomized);
|
||||
txtHumidityMax.setEnabled(isHumidityRandomized);
|
||||
txtHumidityMin.setEnabled(isHumidityRandomized);
|
||||
chkbxHumiditySmooth.setEnabled(isHumidityRandomized);
|
||||
txtTemperatureSVF.setEnabled(isHumidityRandomized && isHumiditySmoothed);
|
||||
}
|
||||
|
||||
private void spinnerTemperatureStateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
if (!isTemperatureRandomized) {
|
||||
try {
|
||||
int temperature = Integer.parseInt(spinnerTemperature.getValue().toString());
|
||||
VirtualHardwareManager.getInstance().setTemperature(temperature);
|
||||
} catch (NumberFormatException e) {
|
||||
JOptionPane.showMessageDialog(this, "Invalid temperature value", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
spinnerTemperature.setValue(VirtualHardwareManager.getInstance().getTemperature());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void spinnerHumidityStateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
if (!isHumidityRandomized) {
|
||||
try {
|
||||
int humidity = Integer.parseInt(spinnerHumidity.getValue().toString());
|
||||
VirtualHardwareManager.getInstance().setHumidity(humidity);
|
||||
} catch (NumberFormatException e) {
|
||||
JOptionPane.showMessageDialog(this, "Invalid humidity value", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
spinnerHumidity.setValue(VirtualHardwareManager.getInstance().getHumidity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void txtTemperatureMinActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
try {
|
||||
int temperature = Integer.parseInt(txtTemperatureMin.getText());
|
||||
VirtualHardwareManager.getInstance().setTemperatureMin(temperature);
|
||||
} catch (NumberFormatException e) {
|
||||
JOptionPane.showMessageDialog(this, "Invalid temperature value", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
txtTemperatureMin.setText("20");
|
||||
}
|
||||
}
|
||||
|
||||
private void txtTemperatureMaxActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
try {
|
||||
int temperature = Integer.parseInt(txtTemperatureMax.getText());
|
||||
VirtualHardwareManager.getInstance().setTemperatureMax(temperature);
|
||||
} catch (NumberFormatException e) {
|
||||
JOptionPane.showMessageDialog(this, "Invalid temperature value", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
txtTemperatureMax.setText("50");
|
||||
}
|
||||
}
|
||||
|
||||
private void txtHumidityMinActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
try {
|
||||
int humidity = Integer.parseInt(txtHumidityMin.getText());
|
||||
VirtualHardwareManager.getInstance().setHumidityMin(humidity);
|
||||
} catch (NumberFormatException e) {
|
||||
JOptionPane.showMessageDialog(this, "Invalid humidity value", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
txtHumidityMin.setText("20");
|
||||
}
|
||||
}
|
||||
|
||||
private void txtHumidityMaxActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
try {
|
||||
int humidity = Integer.parseInt(txtHumidityMax.getText());
|
||||
VirtualHardwareManager.getInstance().setHumidityMax(humidity);
|
||||
} catch (NumberFormatException e) {
|
||||
JOptionPane.showMessageDialog(this, "Invalid humidity value", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
txtHumidityMax.setText("50");
|
||||
}
|
||||
}
|
||||
|
||||
private void spinnerIntervalStateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
try {
|
||||
int interval = Integer.parseInt(spinnerInterval.getValue().toString());
|
||||
AgentManager.getInstance().setPushInterval(interval);
|
||||
} catch (NumberFormatException e) {
|
||||
JOptionPane.showMessageDialog(this, "Invalid time interval value", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
spinnerInterval.setValue(5);
|
||||
}
|
||||
}
|
||||
|
||||
private void cmbInterfaceActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
AgentManager.getInstance().setInterface(cmbInterface.getSelectedIndex());
|
||||
}
|
||||
|
||||
private void cmbProtocolActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
if (cmbProtocol.getSelectedIndex() != -1 && cmbProtocol.getItemAt(
|
||||
cmbProtocol.getSelectedIndex()).equals(AgentConstants.HTTP_PROTOCOL)) {
|
||||
cmbInterface.setEnabled(true);
|
||||
} else {
|
||||
cmbInterface.setEnabled(false);
|
||||
}
|
||||
|
||||
AgentManager.getInstance().setProtocol(cmbProtocol.getSelectedIndex());
|
||||
|
||||
}
|
||||
|
||||
private void txtTemperatureSVFActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
try {
|
||||
int temperatureSVF = Integer.parseInt(txtTemperatureSVF.getText());
|
||||
VirtualHardwareManager.getInstance().setTemperatureSVF(temperatureSVF);
|
||||
} catch (NumberFormatException e) {
|
||||
JOptionPane.showMessageDialog(this, "Invalid value", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
txtTemperatureSVF.setText("50");
|
||||
}
|
||||
}
|
||||
|
||||
private void txtHumiditySVFActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
try {
|
||||
int humiditySVF = Integer.parseInt(txtHumiditySVF.getText());
|
||||
VirtualHardwareManager.getInstance().setHumiditySVF(humiditySVF);
|
||||
} catch (NumberFormatException e) {
|
||||
JOptionPane.showMessageDialog(this, "Invalid value", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
txtHumiditySVF.setText("50");
|
||||
}
|
||||
}
|
||||
|
||||
private void chkbxTemperatureSmoothActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
isTemperatureSmoothed = chkbxTemperatureSmooth.isSelected();
|
||||
txtTemperatureSVF.setEnabled(isTemperatureSmoothed);
|
||||
VirtualHardwareManager.getInstance().setIsTemperatureSmoothed(isTemperatureSmoothed);
|
||||
}
|
||||
|
||||
private void chkbxHumiditySmoothActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
isHumiditySmoothed = chkbxHumiditySmooth.isSelected();
|
||||
txtHumiditySVF.setEnabled(isHumiditySmoothed);
|
||||
VirtualHardwareManager.getInstance().setIsHumiditySmoothed(isHumiditySmoothed);
|
||||
}
|
||||
|
||||
private void cmbPeriodActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
// TODO add your handling code here:
|
||||
}
|
||||
|
||||
private void chkbxEmulateActionPerformed(java.awt.event.ActionEvent evt) {
|
||||
// TODO add your handling code here:
|
||||
}
|
||||
|
||||
public void setAlarmStatus(boolean isAlarmOn) {
|
||||
this.isAlarmOn = isAlarmOn;
|
||||
}
|
||||
|
||||
public void updateTemperature(int temperature) {
|
||||
spinnerTemperature.setValue(temperature);
|
||||
spinnerTemperature.updateUI();
|
||||
}
|
||||
|
||||
public void updateHumidity(int humidity) {
|
||||
spinnerHumidity.setValue(humidity);
|
||||
spinnerHumidity.updateUI();
|
||||
}
|
||||
|
||||
}
|
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 12 KiB |
@ -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
|
Binary file not shown.
@ -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,3 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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,2 @@
|
||||
compile.on.save=true
|
||||
user.properties.file=/home/lahiru/.netbeans/8.2/build.properties
|
@ -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>
|
After Width: | Height: | Size: 6.8 KiB |
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.iot.agent.virtual;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import org.wso2.carbon.device.mgt.iot.agent.virtual.ui.AgentUI;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author charitha
|
||||
*/
|
||||
public class VirtualAgentUI {
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
// Set System L&F
|
||||
UIManager.setLookAndFeel(
|
||||
UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
|
||||
// handle exception
|
||||
}
|
||||
|
||||
java.awt.EventQueue.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
new AgentUI().setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,779 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="3"/>
|
||||
<Property name="title" type="java.lang.String" value="Fire Alarm Emulator"/>
|
||||
<Property name="resizable" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
|
||||
</SyntheticProperties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lblAgentName" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="jPanel6" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jPanel8" max="32767" attributes="0"/>
|
||||
<Component id="jPanel2" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Component id="jLabel2" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="jPanel4" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="jPanel3" alignment="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lblAgentName" min="-2" pref="53" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jPanel6" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jPanel2" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jPanel8" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jPanel1" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jPanel3" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jPanel4" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabel2" min="-2" pref="28" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="lblAgentName">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Cantarell" size="24" style="1"/>
|
||||
</Property>
|
||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||
<Property name="text" type="java.lang.String" value="Device Name: WSO2 IoT Virtual Agent"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel2">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="Copyright (c) 2015, WSO2 Inc."/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="jPanel1">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="dc" green="dc" red="dc" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="pnlBulbStatus" max="32767" attributes="0"/>
|
||||
<Component id="jLabel3" pref="190" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="pnlBulbStatus" max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="jLabel3">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Cantarell" size="18" style="0"/>
|
||||
</Property>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="Bulb Status"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="pnlBulbStatus">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="dc" green="dc" red="dc" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="167" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel2">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="dc" green="dc" red="dc" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="jLabel4" max="32767" attributes="0"/>
|
||||
<Component id="spinnerTemperature" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="jSeparator1" min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jPanel7" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="chkbxTemperatureRandom" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="chkbxTemperatureSmooth" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jSeparator1" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="chkbxTemperatureRandom" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="chkbxTemperatureSmooth" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jPanel7" min="-2" pref="51" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jLabel4" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="spinnerTemperature" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="jLabel4">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Cantarell" size="18" style="0"/>
|
||||
</Property>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="Temperature"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="chkbxTemperatureRandom">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Randomize Data"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkbxTemperatureRandomActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator1">
|
||||
<Properties>
|
||||
<Property name="orientation" type="int" value="1"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="jPanel7">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="dc" green="dc" red="dc" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtTemperatureMin" min="-2" pref="45" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabel6" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtTemperatureMax" min="-2" pref="45" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabel10" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtTemperatureSVF" min="-2" pref="45" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="txtTemperatureMin" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtTemperatureMax" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel10" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtTemperatureSVF" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="35" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="jLabel5">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||
<Property name="text" type="java.lang.String" value="Min"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtTemperatureMin">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="20"/>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtTemperatureMinActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel6">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="4"/>
|
||||
<Property name="text" type="java.lang.String" value="Max"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtTemperatureMax">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="50"/>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtTemperatureMaxActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel10">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="4"/>
|
||||
<Property name="text" type="java.lang.String" value="SV %"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtTemperatureSVF">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="50"/>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtTemperatureSVFActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JSpinner" name="spinnerTemperature">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Cantarell" size="24" style="1"/>
|
||||
</Property>
|
||||
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
|
||||
<SpinnerModel initial="30" maximum="100" minimum="0" numberType="java.lang.Integer" stepSize="1" type="number"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spinnerTemperatureStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="chkbxTemperatureSmooth">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Smooth Variation"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkbxTemperatureSmoothActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel6">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="d1" green="fe" red="fd" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabel20" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblStatus" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="273" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="jLabel20" pref="27" max="32767" attributes="0"/>
|
||||
<Component id="lblStatus" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="jLabel20">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Connection Status:"/>
|
||||
<Property name="verticalTextPosition" type="int" value="1"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblStatus">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Cantarell" size="15" style="1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" value="Not Connected"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel8">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="dc" green="dc" red="dc" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabel23" min="-2" pref="100" max="-2" attributes="0"/>
|
||||
<Component id="spinnerHumidity" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="jSeparator5" min="-2" pref="6" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="jPanel9" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="chkbxHumidityRandom" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="chkbxHumiditySmooth" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jSeparator5" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="chkbxHumidityRandom" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="chkbxHumiditySmooth" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jPanel9" min="-2" pref="51" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="jLabel23" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="spinnerHumidity" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="jLabel23">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Cantarell" size="18" style="0"/>
|
||||
</Property>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="Humidity"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="chkbxHumidityRandom">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Randomize Data"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkbxHumidityRandomActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator5">
|
||||
<Properties>
|
||||
<Property name="orientation" type="int" value="1"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="jPanel9">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="dc" green="dc" red="dc" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jLabel24" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtHumidityMin" min="-2" pref="45" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabel25" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtHumidityMax" min="-2" pref="45" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabel11" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="txtHumiditySVF" min="-2" pref="45" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
|
||||
<Component id="jLabel11" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtHumiditySVF" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="txtHumidityMin" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="txtHumidityMax" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel25" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel24" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="35" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="jLabel24">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="2"/>
|
||||
<Property name="text" type="java.lang.String" value="Min"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtHumidityMin">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="20"/>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtHumidityMinActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel25">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="4"/>
|
||||
<Property name="text" type="java.lang.String" value="Max"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtHumidityMax">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="50"/>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtHumidityMaxActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="txtHumiditySVF">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="0"/>
|
||||
<Property name="text" type="java.lang.String" value="50"/>
|
||||
<Property name="enabled" type="boolean" value="false"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="txtHumiditySVFActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel11">
|
||||
<Properties>
|
||||
<Property name="horizontalAlignment" type="int" value="4"/>
|
||||
<Property name="text" type="java.lang.String" value="SV %"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JSpinner" name="spinnerHumidity">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Cantarell" size="24" style="1"/>
|
||||
</Property>
|
||||
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
|
||||
<SpinnerModel initial="30" maximum="100" minimum="0" numberType="java.lang.Integer" stepSize="1" type="number"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spinnerHumidityStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="chkbxHumiditySmooth">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Smooth Variation"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkbxHumiditySmoothActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel3">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="ea" green="e9" red="cf" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabel7" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="spinnerInterval" min="-2" pref="55" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabel8" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="jLabel12" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cmbInterface" min="-2" pref="100" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabel9" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cmbProtocol" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
|
||||
<Component id="jLabel12" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cmbInterface" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="jLabel7" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="spinnerInterval" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel8" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel9" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cmbProtocol" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="jLabel7">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Data Push Interval:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSpinner" name="spinnerInterval">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor">
|
||||
<SpinnerModel initial="5" minimum="1" numberType="java.lang.Integer" stepSize="1" type="number"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spinnerIntervalStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel8">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Seconds"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel9">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Protocol:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="cmbProtocol">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="3">
|
||||
<StringItem index="0" value="MQTT"/>
|
||||
<StringItem index="1" value="XMPP"/>
|
||||
<StringItem index="2" value="HTTP"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cmbProtocolActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel12">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Interface:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="cmbInterface">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="1">
|
||||
<StringItem index="0" value="eth0"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cmbInterfaceActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="jPanel4">
|
||||
<Properties>
|
||||
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="ad" green="fd" red="a9" type="rgb"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="chkbxEmulate" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="cmbPeriod" min="-2" pref="162" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="chkbxEmulate" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cmbPeriod" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JCheckBox" name="chkbxEmulate">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Emulate data"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chkbxEmulateActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="cmbPeriod">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="4">
|
||||
<StringItem index="0" value="1 hour"/>
|
||||
<StringItem index="1" value="1 day"/>
|
||||
<StringItem index="2" value="1 week"/>
|
||||
<StringItem index="3" value="1 month "/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cmbPeriodActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabel1">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Emulation Period"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -0,0 +1,711 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.wso2.carbon.device.mgt.iot.agent.virtual.ui;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author charitha
|
||||
*/
|
||||
public class AgentUI extends javax.swing.JFrame {
|
||||
|
||||
/**
|
||||
* Creates new form AgentUI
|
||||
*/
|
||||
public AgentUI() {
|
||||
initComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
lblAgentName = new javax.swing.JLabel();
|
||||
jLabel2 = new javax.swing.JLabel();
|
||||
jPanel1 = new javax.swing.JPanel();
|
||||
jLabel3 = new javax.swing.JLabel();
|
||||
pnlBulbStatus = new javax.swing.JPanel();
|
||||
jPanel2 = new javax.swing.JPanel();
|
||||
jLabel4 = new javax.swing.JLabel();
|
||||
chkbxTemperatureRandom = new javax.swing.JCheckBox();
|
||||
jSeparator1 = new javax.swing.JSeparator();
|
||||
jPanel7 = new javax.swing.JPanel();
|
||||
jLabel5 = new javax.swing.JLabel();
|
||||
txtTemperatureMin = new javax.swing.JTextField();
|
||||
jLabel6 = new javax.swing.JLabel();
|
||||
txtTemperatureMax = new javax.swing.JTextField();
|
||||
jLabel10 = new javax.swing.JLabel();
|
||||
txtTemperatureSVF = new javax.swing.JTextField();
|
||||
spinnerTemperature = new javax.swing.JSpinner();
|
||||
chkbxTemperatureSmooth = new javax.swing.JCheckBox();
|
||||
jPanel6 = new javax.swing.JPanel();
|
||||
jLabel20 = new javax.swing.JLabel();
|
||||
lblStatus = new javax.swing.JLabel();
|
||||
jPanel8 = new javax.swing.JPanel();
|
||||
jLabel23 = new javax.swing.JLabel();
|
||||
chkbxHumidityRandom = new javax.swing.JCheckBox();
|
||||
jSeparator5 = new javax.swing.JSeparator();
|
||||
jPanel9 = new javax.swing.JPanel();
|
||||
jLabel24 = new javax.swing.JLabel();
|
||||
txtHumidityMin = new javax.swing.JTextField();
|
||||
jLabel25 = new javax.swing.JLabel();
|
||||
txtHumidityMax = new javax.swing.JTextField();
|
||||
txtHumiditySVF = new javax.swing.JTextField();
|
||||
jLabel11 = new javax.swing.JLabel();
|
||||
spinnerHumidity = new javax.swing.JSpinner();
|
||||
chkbxHumiditySmooth = new javax.swing.JCheckBox();
|
||||
jPanel3 = new javax.swing.JPanel();
|
||||
jLabel7 = new javax.swing.JLabel();
|
||||
spinnerInterval = new javax.swing.JSpinner();
|
||||
jLabel8 = new javax.swing.JLabel();
|
||||
jLabel9 = new javax.swing.JLabel();
|
||||
cmbProtocol = new javax.swing.JComboBox();
|
||||
jLabel12 = new javax.swing.JLabel();
|
||||
cmbInterface = new javax.swing.JComboBox();
|
||||
jPanel4 = new javax.swing.JPanel();
|
||||
chkbxEmulate = new javax.swing.JCheckBox();
|
||||
cmbPeriod = new javax.swing.JComboBox();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
|
||||
setTitle("Fire Alarm Emulator");
|
||||
setResizable(false);
|
||||
|
||||
lblAgentName.setFont(new java.awt.Font("Cantarell", 1, 24)); // NOI18N
|
||||
lblAgentName.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||
lblAgentName.setText("Device Name: WSO2 IoT Virtual Agent");
|
||||
|
||||
jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
|
||||
jLabel2.setText("Copyright (c) 2015, WSO2 Inc.");
|
||||
|
||||
jPanel1.setBackground(new java.awt.Color(220, 220, 220));
|
||||
|
||||
jLabel3.setFont(new java.awt.Font("Cantarell", 0, 18)); // NOI18N
|
||||
jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
|
||||
jLabel3.setText("Bulb Status");
|
||||
|
||||
pnlBulbStatus.setBackground(new java.awt.Color(220, 220, 220));
|
||||
|
||||
javax.swing.GroupLayout pnlBulbStatusLayout = new javax.swing.GroupLayout(pnlBulbStatus);
|
||||
pnlBulbStatus.setLayout(pnlBulbStatusLayout);
|
||||
pnlBulbStatusLayout.setHorizontalGroup(
|
||||
pnlBulbStatusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 0, Short.MAX_VALUE)
|
||||
);
|
||||
pnlBulbStatusLayout.setVerticalGroup(
|
||||
pnlBulbStatusLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 167, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
|
||||
jPanel1.setLayout(jPanel1Layout);
|
||||
jPanel1Layout.setHorizontalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(pnlBulbStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, 190, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel1Layout.setVerticalGroup(
|
||||
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel1Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jLabel3)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(pnlBulbStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jPanel2.setBackground(new java.awt.Color(220, 220, 220));
|
||||
|
||||
jLabel4.setFont(new java.awt.Font("Cantarell", 0, 18)); // NOI18N
|
||||
jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
|
||||
jLabel4.setText("Temperature");
|
||||
|
||||
chkbxTemperatureRandom.setText("Randomize Data");
|
||||
chkbxTemperatureRandom.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkbxTemperatureRandomActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
|
||||
|
||||
jPanel7.setBackground(new java.awt.Color(220, 220, 220));
|
||||
|
||||
jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||
jLabel5.setText("Min");
|
||||
|
||||
txtTemperatureMin.setHorizontalAlignment(javax.swing.JTextField.CENTER);
|
||||
txtTemperatureMin.setText("20");
|
||||
txtTemperatureMin.setEnabled(false);
|
||||
txtTemperatureMin.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtTemperatureMinActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
|
||||
jLabel6.setText("Max");
|
||||
|
||||
txtTemperatureMax.setHorizontalAlignment(javax.swing.JTextField.CENTER);
|
||||
txtTemperatureMax.setText("50");
|
||||
txtTemperatureMax.setEnabled(false);
|
||||
txtTemperatureMax.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtTemperatureMaxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel10.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
|
||||
jLabel10.setText("SV %");
|
||||
|
||||
txtTemperatureSVF.setHorizontalAlignment(javax.swing.JTextField.CENTER);
|
||||
txtTemperatureSVF.setText("50");
|
||||
txtTemperatureSVF.setEnabled(false);
|
||||
txtTemperatureSVF.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtTemperatureSVFActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
|
||||
jPanel7.setLayout(jPanel7Layout);
|
||||
jPanel7Layout.setHorizontalGroup(
|
||||
jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel7Layout.createSequentialGroup()
|
||||
.addComponent(jLabel5)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtTemperatureMin, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel6)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtTemperatureMax, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel10)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtTemperatureSVF, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
jPanel7Layout.setVerticalGroup(
|
||||
jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel7Layout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtTemperatureMin, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(txtTemperatureMax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jLabel6)
|
||||
.addComponent(jLabel5)
|
||||
.addComponent(jLabel10)
|
||||
.addComponent(txtTemperatureSVF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(35, 35, 35))
|
||||
);
|
||||
|
||||
spinnerTemperature.setFont(new java.awt.Font("Cantarell", 1, 24)); // NOI18N
|
||||
spinnerTemperature.setModel(new javax.swing.SpinnerNumberModel(30, 0, 100, 1));
|
||||
spinnerTemperature.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
spinnerTemperatureStateChanged(evt);
|
||||
}
|
||||
});
|
||||
|
||||
chkbxTemperatureSmooth.setText("Smooth Variation");
|
||||
chkbxTemperatureSmooth.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkbxTemperatureSmoothActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
|
||||
jPanel2.setLayout(jPanel2Layout);
|
||||
jPanel2Layout.setHorizontalGroup(
|
||||
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(spinnerTemperature))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 6, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addComponent(chkbxTemperatureRandom)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(chkbxTemperatureSmooth)))
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel2Layout.setVerticalGroup(
|
||||
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jSeparator1)
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(chkbxTemperatureRandom)
|
||||
.addComponent(chkbxTemperatureSmooth))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 0, Short.MAX_VALUE))
|
||||
.addGroup(jPanel2Layout.createSequentialGroup()
|
||||
.addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spinnerTemperature)))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jPanel6.setBackground(new java.awt.Color(253, 254, 209));
|
||||
|
||||
jLabel20.setText("Connection Status:");
|
||||
jLabel20.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
|
||||
|
||||
lblStatus.setFont(new java.awt.Font("Cantarell", 1, 15)); // NOI18N
|
||||
lblStatus.setText("Not Connected");
|
||||
|
||||
javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
|
||||
jPanel6.setLayout(jPanel6Layout);
|
||||
jPanel6Layout.setHorizontalGroup(
|
||||
jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel6Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jLabel20)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGap(273, 273, 273))
|
||||
);
|
||||
jPanel6Layout.setVerticalGroup(
|
||||
jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel6Layout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(jLabel20, javax.swing.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE)
|
||||
.addComponent(lblStatus, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jPanel8.setBackground(new java.awt.Color(220, 220, 220));
|
||||
|
||||
jLabel23.setFont(new java.awt.Font("Cantarell", 0, 18)); // NOI18N
|
||||
jLabel23.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
|
||||
jLabel23.setText("Humidity");
|
||||
|
||||
chkbxHumidityRandom.setText("Randomize Data");
|
||||
chkbxHumidityRandom.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkbxHumidityRandomActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jSeparator5.setOrientation(javax.swing.SwingConstants.VERTICAL);
|
||||
|
||||
jPanel9.setBackground(new java.awt.Color(220, 220, 220));
|
||||
|
||||
jLabel24.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
|
||||
jLabel24.setText("Min");
|
||||
|
||||
txtHumidityMin.setHorizontalAlignment(javax.swing.JTextField.CENTER);
|
||||
txtHumidityMin.setText("20");
|
||||
txtHumidityMin.setEnabled(false);
|
||||
txtHumidityMin.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtHumidityMinActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel25.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
|
||||
jLabel25.setText("Max");
|
||||
|
||||
txtHumidityMax.setHorizontalAlignment(javax.swing.JTextField.CENTER);
|
||||
txtHumidityMax.setText("50");
|
||||
txtHumidityMax.setEnabled(false);
|
||||
txtHumidityMax.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtHumidityMaxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
txtHumiditySVF.setHorizontalAlignment(javax.swing.JTextField.CENTER);
|
||||
txtHumiditySVF.setText("50");
|
||||
txtHumiditySVF.setEnabled(false);
|
||||
txtHumiditySVF.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
txtHumiditySVFActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel11.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
|
||||
jLabel11.setText("SV %");
|
||||
|
||||
javax.swing.GroupLayout jPanel9Layout = new javax.swing.GroupLayout(jPanel9);
|
||||
jPanel9.setLayout(jPanel9Layout);
|
||||
jPanel9Layout.setHorizontalGroup(
|
||||
jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel9Layout.createSequentialGroup()
|
||||
.addComponent(jLabel24)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtHumidityMin, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel25)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtHumidityMax, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel11)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(txtHumiditySVF, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
jPanel9Layout.setVerticalGroup(
|
||||
jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel9Layout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jLabel11)
|
||||
.addComponent(txtHumiditySVF, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(txtHumidityMin, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(txtHumidityMax, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jLabel25)
|
||||
.addComponent(jLabel24)))
|
||||
.addGap(35, 35, 35))
|
||||
);
|
||||
|
||||
spinnerHumidity.setFont(new java.awt.Font("Cantarell", 1, 24)); // NOI18N
|
||||
spinnerHumidity.setModel(new javax.swing.SpinnerNumberModel(30, 0, 100, 1));
|
||||
spinnerHumidity.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
spinnerHumidityStateChanged(evt);
|
||||
}
|
||||
});
|
||||
|
||||
chkbxHumiditySmooth.setText("Smooth Variation");
|
||||
chkbxHumiditySmooth.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkbxHumiditySmoothActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8);
|
||||
jPanel8.setLayout(jPanel8Layout);
|
||||
jPanel8Layout.setHorizontalGroup(
|
||||
jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel8Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabel23, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(spinnerHumidity))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jSeparator5, javax.swing.GroupLayout.PREFERRED_SIZE, 6, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(jPanel9, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(jPanel8Layout.createSequentialGroup()
|
||||
.addComponent(chkbxHumidityRandom)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(chkbxHumiditySmooth)))
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel8Layout.setVerticalGroup(
|
||||
jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel8Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jSeparator5)
|
||||
.addGroup(jPanel8Layout.createSequentialGroup()
|
||||
.addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(chkbxHumidityRandom)
|
||||
.addComponent(chkbxHumiditySmooth))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel9, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(0, 1, Short.MAX_VALUE))
|
||||
.addGroup(jPanel8Layout.createSequentialGroup()
|
||||
.addComponent(jLabel23, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spinnerHumidity)))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jPanel3.setBackground(new java.awt.Color(207, 233, 234));
|
||||
|
||||
jLabel7.setText("Data Push Interval:");
|
||||
|
||||
spinnerInterval.setModel(new javax.swing.SpinnerNumberModel(5, 1, null, 1));
|
||||
spinnerInterval.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
spinnerIntervalStateChanged(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel8.setText("Seconds");
|
||||
|
||||
jLabel9.setText("Protocol:");
|
||||
|
||||
cmbProtocol.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "MQTT", "XMPP", "HTTP" }));
|
||||
cmbProtocol.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cmbProtocolActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel12.setText("Interface:");
|
||||
|
||||
cmbInterface.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "eth0" }));
|
||||
cmbInterface.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cmbInterfaceActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
|
||||
jPanel3.setLayout(jPanel3Layout);
|
||||
jPanel3Layout.setHorizontalGroup(
|
||||
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel3Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(jLabel7)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spinnerInterval, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel8)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jLabel12)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cmbInterface, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel9)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cmbProtocol, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel3Layout.setVerticalGroup(
|
||||
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jLabel12)
|
||||
.addComponent(cmbInterface, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jLabel7)
|
||||
.addComponent(spinnerInterval, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jLabel8)
|
||||
.addComponent(jLabel9)
|
||||
.addComponent(cmbProtocol, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
jPanel4.setBackground(new java.awt.Color(169, 253, 173));
|
||||
|
||||
chkbxEmulate.setText("Emulate data");
|
||||
chkbxEmulate.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
chkbxEmulateActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
cmbPeriod.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1 hour", "1 day", "1 week", "1 month " }));
|
||||
cmbPeriod.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cmbPeriodActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel1.setText("Emulation Period");
|
||||
|
||||
javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
|
||||
jPanel4.setLayout(jPanel4Layout);
|
||||
jPanel4Layout.setHorizontalGroup(
|
||||
jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(jPanel4Layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(chkbxEmulate)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jLabel1)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(cmbPeriod, javax.swing.GroupLayout.PREFERRED_SIZE, 162, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
jPanel4Layout.setVerticalGroup(
|
||||
jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup()
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(chkbxEmulate)
|
||||
.addComponent(cmbPeriod, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jLabel1))
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lblAgentName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||
.addComponent(jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(lblAgentName, javax.swing.GroupLayout.PREFERRED_SIZE, 53, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void chkbxTemperatureRandomActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkbxTemperatureRandomActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_chkbxTemperatureRandomActionPerformed
|
||||
|
||||
private void chkbxHumidityRandomActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkbxHumidityRandomActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_chkbxHumidityRandomActionPerformed
|
||||
|
||||
private void spinnerTemperatureStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerTemperatureStateChanged
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_spinnerTemperatureStateChanged
|
||||
|
||||
private void spinnerHumidityStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerHumidityStateChanged
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_spinnerHumidityStateChanged
|
||||
|
||||
private void txtTemperatureMinActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtTemperatureMinActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtTemperatureMinActionPerformed
|
||||
|
||||
private void txtTemperatureMaxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtTemperatureMaxActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtTemperatureMaxActionPerformed
|
||||
|
||||
private void txtHumidityMinActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtHumidityMinActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtHumidityMinActionPerformed
|
||||
|
||||
private void txtHumidityMaxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtHumidityMaxActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtHumidityMaxActionPerformed
|
||||
|
||||
private void spinnerIntervalStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerIntervalStateChanged
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_spinnerIntervalStateChanged
|
||||
|
||||
private void cmbInterfaceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmbInterfaceActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cmbInterfaceActionPerformed
|
||||
|
||||
private void cmbProtocolActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmbProtocolActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cmbProtocolActionPerformed
|
||||
|
||||
private void txtTemperatureSVFActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtTemperatureSVFActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtTemperatureSVFActionPerformed
|
||||
|
||||
private void txtHumiditySVFActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtHumiditySVFActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_txtHumiditySVFActionPerformed
|
||||
|
||||
private void chkbxTemperatureSmoothActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkbxTemperatureSmoothActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_chkbxTemperatureSmoothActionPerformed
|
||||
|
||||
private void chkbxHumiditySmoothActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkbxHumiditySmoothActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_chkbxHumiditySmoothActionPerformed
|
||||
|
||||
private void cmbPeriodActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmbPeriodActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_cmbPeriodActionPerformed
|
||||
|
||||
private void chkbxEmulateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chkbxEmulateActionPerformed
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_chkbxEmulateActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JCheckBox chkbxEmulate;
|
||||
private javax.swing.JCheckBox chkbxHumidityRandom;
|
||||
private javax.swing.JCheckBox chkbxHumiditySmooth;
|
||||
private javax.swing.JCheckBox chkbxTemperatureRandom;
|
||||
private javax.swing.JCheckBox chkbxTemperatureSmooth;
|
||||
private javax.swing.JComboBox cmbInterface;
|
||||
private javax.swing.JComboBox cmbPeriod;
|
||||
private javax.swing.JComboBox cmbProtocol;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JLabel jLabel10;
|
||||
private javax.swing.JLabel jLabel11;
|
||||
private javax.swing.JLabel jLabel12;
|
||||
private javax.swing.JLabel jLabel2;
|
||||
private javax.swing.JLabel jLabel20;
|
||||
private javax.swing.JLabel jLabel23;
|
||||
private javax.swing.JLabel jLabel24;
|
||||
private javax.swing.JLabel jLabel25;
|
||||
private javax.swing.JLabel jLabel3;
|
||||
private javax.swing.JLabel jLabel4;
|
||||
private javax.swing.JLabel jLabel5;
|
||||
private javax.swing.JLabel jLabel6;
|
||||
private javax.swing.JLabel jLabel7;
|
||||
private javax.swing.JLabel jLabel8;
|
||||
private javax.swing.JLabel jLabel9;
|
||||
private javax.swing.JPanel jPanel1;
|
||||
private javax.swing.JPanel jPanel2;
|
||||
private javax.swing.JPanel jPanel3;
|
||||
private javax.swing.JPanel jPanel4;
|
||||
private javax.swing.JPanel jPanel6;
|
||||
private javax.swing.JPanel jPanel7;
|
||||
private javax.swing.JPanel jPanel8;
|
||||
private javax.swing.JPanel jPanel9;
|
||||
private javax.swing.JSeparator jSeparator1;
|
||||
private javax.swing.JSeparator jSeparator5;
|
||||
private javax.swing.JLabel lblAgentName;
|
||||
private javax.swing.JLabel lblStatus;
|
||||
private javax.swing.JPanel pnlBulbStatus;
|
||||
private javax.swing.JSpinner spinnerHumidity;
|
||||
private javax.swing.JSpinner spinnerInterval;
|
||||
private javax.swing.JSpinner spinnerTemperature;
|
||||
private javax.swing.JTextField txtHumidityMax;
|
||||
private javax.swing.JTextField txtHumidityMin;
|
||||
private javax.swing.JTextField txtHumiditySVF;
|
||||
private javax.swing.JTextField txtTemperatureMax;
|
||||
private javax.swing.JTextField txtTemperatureMin;
|
||||
private javax.swing.JTextField txtTemperatureSVF;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
Loading…
Reference in new issue