initial import

This commit is contained in:
2026-05-28 21:17:51 +07:00
commit c347ceaf3a
97 changed files with 10497 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
build/
dist/
logs/

73
build.xml Normal file
View File

@ -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="utms-agent" default="default" basedir=".">
<description>Builds, tests, and runs the project utms-agent.</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="utms-agent-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>

View File

@ -0,0 +1,16 @@
#
# our log4j properties / configuration FILE
#
# Direct log messages to a rolling log file.
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.File=logs/utms-agent.log
log4j.appender.FILE.MaxFileSize=100MB
log4j.appender.FILE.MaxBackupIndex=10
log4j.appender.FILE.Append=true
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%d [%-5p] [%t] [%c{1}] - %m%n
# Log only to FILE.
log4j.rootLogger=WARN, FILE
log4j.logger.id.iptek.utms.agent=INFO, FILE
log4j.additivity.id.iptek.utms.agent=false

114
conf/mqtt-agents.cfg Normal file
View File

@ -0,0 +1,114 @@
## Logger
log4j.file = ${Config.Dir}/mqtt-agents-log4j.cfg
## Database
### if 'db.datasource' has been set or not empty, ignore the rest
db.driver = org.postgresql.Driver
db.url = jdbc:postgresql://localhost:5432/utms_new
db.user = utms
db.password = utms1234
# Mqtt Configuration
#mqtt.broker.url = tcp://unifiedtms.id:1883
mqtt.broker.url = tcp://192.168.4.112:1883
mqtt.clientid_prefix = SENDER_
mqtt.user = user1
mqtt.password = P@ssw0rd
mqtt.keepalive = 10
mqtt.maxinflight = 32
mqtt.cleansession = true
mqtt.autoreconnect = true
## Pending Task Configuration
pendingtask.query.limit = 100
pendingtask.periode.minutes = 30
# Minio
fileserver.endpoint = https://download.unifiedtms.id:9000
fileserver.access_key = i9ZB0sNhHaiQe7oEP0sL
fileserver.secret_key = 4bxVnKwKgkXpZJ9Dou4oprZ1E8oe3s1HuvKLRn0N
fileserver.bucket = application-bucket
fileserver.icon.path = icons
fileserver.icon.expiry = 7
fileserver.icon.timeunit = DAYS
fileserver.app.path = apps
fileserver.app.expiry = 7
fileserver.app.timeunit = DAYS
## Consumers
mqtt.consumers = heartbeat_c, diagnostic_c, device_init_c, download_ack_c
#, diagnostic_c, device_init_c, download_ack_c
### heartbeat_c
mqtt.consumer.heartbeat_c.loggingid = $queue/HEARTBEAT
#mqtt.consumer.heartbeat_c.topic = $share/def/SERVER_IN_HB_2
mqtt.consumer.heartbeat_c.topic = SERVER_IN_HB_2
mqtt.consumer.heartbeat_c.threads = 3
mqtt.consumer.heartbeat_c.clientid_prefix = SNHB_
mqtt.consumer.heartbeat_c.user = user1
mqtt.consumer.heartbeat_c.password = P@ssw0rd
mqtt.consumer.heartbeat_c.sleep = 300000
mqtt.consumer.heartbeat_c.keepalive = 10
mqtt.consumer.heartbeat_c.maxinflight = 32
mqtt.consumer.heartbeat_c.cleansession = true
mqtt.consumer.heartbeat_c.autoreconnect = true
mqtt.consumer.heartbeat_c.workerclass = id.iptek.utms.agent.worker.HeartbeatWorker
mqtt.consumer.heartbeat_c.consumermode = BATCH
mqtt.consumer.heartbeat_c.batch.capacity = 100
### diagnostic_c
mqtt.consumer.diagnostic_c.loggingid = DIAGNOSTIC
mqtt.consumer.diagnostic_c.topic = $share/def/SERVER_IN_DIAG_2
mqtt.consumer.diagnostic_c.threads = 1
mqtt.consumer.diagnostic_c.clientid_prefix = SNDIAG
mqtt.consumer.diagnostic_c.workerclass = SNDIAG_
mqtt.consumer.diagnostic_c.user = user1
mqtt.consumer.diagnostic_c.password = P@ssw0rd
mqtt.consumer.diagnostic_c.sleep = 300000
mqtt.consumer.diagnostic_c.keepalive = 10
mqtt.consumer.diagnostic_c.maxinflight = 32
mqtt.consumer.diagnostic_c.cleansession = true
mqtt.consumer.diagnostic_c.autoreconnect = true
mqtt.consumer.diagnostic_c.workerclass = id.iptek.utms.agent.worker.DiagnosticWorker
mqtt.consumer.diagnostic_c.consumermode = BATCH
mqtt.consumer.diagnostic_c.batch.capacity = 10
### device_init_c
mqtt.consumer.device_init_c.loggingid = DEVICE_INIT
mqtt.consumer.device_init_c.topic = $share/def/SERVER_IN_INIT_2
mqtt.consumer.device_init_c.threads = 10
mqtt.consumer.device_init_c.clientid_prefix = SNINIT
mqtt.consumer.device_init_c.workerclass = SNINIT_
mqtt.consumer.device_init_c.user = user1
mqtt.consumer.device_init_c.password = P@ssw0rd
mqtt.consumer.device_init_c.sleep = 300000
mqtt.consumer.device_init_c.keepalive = 10
mqtt.consumer.device_init_c.maxinflight = 32
mqtt.consumer.device_init_c.cleansession = true
mqtt.consumer.device_init_c.autoreconnect = true
mqtt.consumer.device_init_c.workerclass = id.iptek.utms.agent.worker.DeviceInitWorker
mqtt.consumer.device_init_c.consumermode = SINGLE
mqtt.consumer.device_init_c.batch.capacity = 5
### download_ack_c
mqtt.consumer.download_ack_c.loggingid = DOWNLOAD_ACK
mqtt.consumer.download_ack_c.topic = $share/def/SERVER_IN_DL_ACK
mqtt.consumer.download_ack_c.threads = 5
mqtt.consumer.download_ack_c.clientid_prefix = SNDLACK
mqtt.consumer.download_ack_c.workerclass = SNDLACK_
mqtt.consumer.download_ack_c.user = user1
mqtt.consumer.download_ack_c.password = P@ssw0rd
mqtt.consumer.download_ack_c.sleep = 60000
mqtt.consumer.download_ack_c.keepalive = 10
mqtt.consumer.download_ack_c.maxinflight = 32
mqtt.consumer.download_ack_c.cleansession = true
mqtt.consumer.download_ack_c.autoreconnect = true
mqtt.consumer.download_ack_c.workerclass = id.iptek.utms.agent.worker.DownloadTaskAckWorker
## Schedulers
#schedulers = download_task_publisher
# download_task_publisher
#scheduler.download_task_publisher.jobclass = id.iptek.utms.agent.scheduler.DownloadTaskPublisher
## CRON | SIMPLE
#scheduler.download_task_publisher.trigger.type = SIMPLE
#scheduler.download_task_publisher.trigger.interval = 10
#scheduler.download_task_publisher.trigger.repeat = 10
#scheduler.download_task_publisher.trigger.type = CRON
#scheduler.download_task_publisher.trigger.expression = 0 0/2 8-17 * * ?
scheduler.periode.minutes = 1

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/commons-codec-1.15.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/commons-id.jar Normal file

Binary file not shown.

BIN
lib/commons-io-2.13.0.jar Normal file

Binary file not shown.

BIN
lib/commons-lang-2.0.jar Normal file

Binary file not shown.

BIN
lib/commons-math3-3.6.1.jar Normal file

Binary file not shown.

BIN
lib/gson-2.8.9.jar Normal file

Binary file not shown.

BIN
lib/log4j-1.2.14.jar Normal file

Binary file not shown.

BIN
lib/log4j-api-2.20.0.jar Normal file

Binary file not shown.

BIN
lib/log4j-core-2.20.0.jar Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,14 @@
libs.CopyLibs.classpath=\
${base}/CopyLibs/org-netbeans-modules-java-j2seproject-copylibstask.jar
libs.CopyLibs.displayName=CopyLibs Task
libs.CopyLibs.prop-version=3.0
libs.Minio-Client.classpath=\
${base}/Minio-Client/minio-8.5.5-all.jar
libs.Minio-Client.displayName=Minio-Client
libs.Mqtt.classpath=\
${base}/Mqtt/org.eclipse.paho.client.mqttv3-1.2.5.jar
libs.Mqtt.displayName=Mqtt
libs.Quartz.classpath=\
${base}/Quartz/quartz-2.3.0-SNAPSHOT.jar;\
${base}/Quartz/quartz-jobs-2.3.0-SNAPSHOT.jar
libs.Quartz.displayName=Quartz

BIN
lib/postgresql-42.2.9.jar Normal file

Binary file not shown.

BIN
lib/slf4j-api-1.7.2.jar Normal file

Binary file not shown.

BIN
lib/slf4j-log4j12-1.7.2.jar Normal file

Binary file not shown.

BIN
lib/xmlbeans-5.1.1.jar Normal file

Binary file not shown.

3
manifest.mf Normal file
View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build

1796
nbproject/build-impl.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
build.xml.data.CRC32=070afaed
build.xml.script.CRC32=b80da75b
build.xml.stylesheet.CRC32=f85dc8f2@1.106.0.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=070afaed
nbproject/build-impl.xml.script.CRC32=7415c0b1
nbproject/build-impl.xml.stylesheet.CRC32=12e0a6c2@1.106.0.48

View File

View File

@ -0,0 +1,8 @@
compile.on.save=true
do.depend=false
do.jar=true
do.jlink=false
javac.debug=true
javadoc.preview=true
jlink.strip=false
user.properties.file=C:\\Users\\Ega\\AppData\\Roaming\\NetBeans\\17\\build.properties

View File

@ -0,0 +1,15 @@
<?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 name="UTMS">
<file>file:/D:/Projects/Personal/verifone/utms-agent/src/id/iptek/utms/agent/Main.java</file>
<file>file:/D:/Projects/Personal/verifone/utms-agent/conf/mqtt-agents.cfg</file>
<file>file:/D:/Projects/Personal/verifone/utms-agent/src/id/iptek/utms/agent/sample/MqttPublishSample.java</file>
</group>
<group>
<file>file:/F:/Projects/Personal/verifone/utms-agent/src/id/iptek/utms/agent/Main.java</file>
<file>file:/F:/Projects/Personal/verifone/utms-agent/src/id/iptek/utms/agent/model/ApplicationSimple.java</file>
</group>
</open-files>
</project-private>

View File

@ -0,0 +1,132 @@
annotation.processing.enabled=true
annotation.processing.enabled.in.editor=false
annotation.processing.processors.list=
annotation.processing.run.all.processors=true
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
application.title=utms-agent
application.vendor=jakar
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.modulepath=\
${run.modulepath}
debug.test.classpath=\
${run.test.classpath}
debug.test.modulepath=\
${run.test.modulepath}
# 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}/utms-agent.jar
dist.javadoc.dir=${dist.dir}/javadoc
dist.jlink.dir=${dist.dir}/jlink
dist.jlink.output=${dist.jlink.dir}/utms-agent
endorsed.classpath=
excludes=
file.reference.commons-codec-1.15.jar=lib\\commons-codec-1.15.jar
file.reference.commons-collections4-4.4.jar=lib\\commons-collections4-4.4.jar
file.reference.commons-compress-1.23.0.jar=lib\\commons-compress-1.23.0.jar
file.reference.commons-id.jar=lib\\commons-id.jar
file.reference.commons-io-2.13.0.jar=lib\\commons-io-2.13.0.jar
file.reference.commons-lang-2.0.jar=lib\\commons-lang-2.0.jar
file.reference.commons-math3-3.6.1.jar=lib\\commons-math3-3.6.1.jar
file.reference.gson-2.8.9.jar=lib\\gson-2.8.9.jar
file.reference.log4j-1.2.14.jar=lib\\log4j-1.2.14.jar
file.reference.log4j-api-2.20.0.jar=lib\\log4j-api-2.20.0.jar
file.reference.log4j-core-2.20.0.jar=lib\\log4j-core-2.20.0.jar
file.reference.log4j-rolling-appender-20120206-1607-1.2.15.jar=lib\\log4j-rolling-appender-20120206-1607-1.2.15.jar
file.reference.postgresql-42.2.9.jar=lib\\postgresql-42.2.9.jar
file.reference.slf4j-api-1.7.2.jar=lib\\slf4j-api-1.7.2.jar
file.reference.slf4j-log4j12-1.7.2.jar=lib\\slf4j-log4j12-1.7.2.jar
file.reference.xmlbeans-5.1.1.jar=lib\\xmlbeans-5.1.1.jar
includes=**
jar.compress=false
javac.classpath=\
${libs.Mqtt.classpath}:\
${file.reference.postgresql-42.2.9.jar}:\
${file.reference.log4j-1.2.14.jar}:\
${file.reference.log4j-api-2.20.0.jar}:\
${file.reference.log4j-core-2.20.0.jar}:\
${file.reference.log4j-rolling-appender-20120206-1607-1.2.15.jar}:\
${file.reference.slf4j-api-1.7.2.jar}:\
${file.reference.slf4j-log4j12-1.7.2.jar}:\
${file.reference.gson-2.8.9.jar}:\
${file.reference.commons-codec-1.15.jar}:\
${file.reference.commons-collections4-4.4.jar}:\
${file.reference.commons-compress-1.23.0.jar}:\
${file.reference.commons-io-2.13.0.jar}:\
${file.reference.commons-math3-3.6.1.jar}:\
${file.reference.xmlbeans-5.1.1.jar}:\
${file.reference.commons-id.jar}:\
${file.reference.commons-lang-2.0.jar}:\
${libs.Quartz.classpath}:\
${libs.Minio-Client.classpath}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
javac.external.vm=true
javac.modulepath=
javac.processormodulepath=
javac.processorpath=\
${javac.classpath}
javac.source=1.8
javac.target=1.8
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}
javac.test.modulepath=\
${javac.modulepath}
javac.test.processorpath=\
${javac.test.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.html5=false
javadoc.noindex=false
javadoc.nonavbar=false
javadoc.notree=false
javadoc.private=false
javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
# The jlink additional root modules to resolve
jlink.additionalmodules=
# The jlink additional command line parameters
jlink.additionalparam=
jlink.launcher=true
jlink.launcher.name=utms-agent
main.class=id.iptek.utms.agent.Main
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.modulepath=\
${javac.modulepath}
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
run.test.modulepath=\
${javac.test.modulepath}
source.encoding=UTF-8
src.dir=src
test.src.dir=test

18
nbproject/project.xml Normal file
View File

@ -0,0 +1,18 @@
<?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>utms-agent</name>
<source-roots>
<root id="src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
<libraries xmlns="http://www.netbeans.org/ns/ant-project-libraries/1">
<definitions>.\lib\nblibraries.properties</definitions>
</libraries>
</configuration>
</project>

View File

@ -0,0 +1,113 @@
package id.iptek.utms.agent;
import id.iptek.utms.agent.util.IOUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class AppConfig {
private static AppConfig self = null;
private Logger logger = LoggerFactory.getLogger(AppConfig.class);
private Properties props = new Properties();
private AppConfig() {
}
public void init(String configFile) throws Exception {
init(new File(configFile));
}
public void init(File configFile) throws Exception {
InputStream in = new FileInputStream(configFile);
try {
props.load(in);
} finally {
IOUtil.close(in);
}
}
public void set(String name, String value) {
props.setProperty(name, value);
}
public String get(String name, String defaultValue) {
String value = get(name);
if(value == null) {
value = defaultValue;
}
return value;
}
public String get(String name) {
logger.trace("#get('{}');", name);
String value = props.getProperty(name);
return value;
}
public int getAsInt(String name) {
String value = get(name);
if(value != null) {
return Integer.parseInt(value);
}
return 0;
}
public int getAsInt(String name, int defaultValue) {
String value = get(name);
if(value != null) {
return Integer.parseInt(value);
}
return defaultValue;
}
public boolean getAsBoolean(String name) {
String value = get(name);
if(value != null) {
return "true".equalsIgnoreCase(value);
}
return false;
}
public boolean getAsBoolean(String name, boolean defaultValue) {
String value = get(name);
if(value != null) {
return "true".equalsIgnoreCase(value);
}
return defaultValue;
}
public long getAsLong(String name) {
return getAsLong(name, 0L);
}
public long getAsLong(String name, long defaultValue) {
String value = get(name);
if(value != null) {
return Long.parseLong(value);
}
return defaultValue;
}
public String[] getAll(String name) {
String value = get(name);
if(value != null) {
return value.trim().split("\\s*,\\s*");
}
return new String[] {};
}
public Properties getProps() {
return props;
}
public static AppConfig getInstance() {
if (self == null) {
self = new AppConfig();
}
return self;
}
}

View File

@ -0,0 +1,117 @@
package id.iptek.utms.agent;
import id.iptek.utms.agent.model.FileReaderCacheObj;
import id.iptek.utms.agent.model.FileWriterCacheObj;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author jakar
*/
public final class DiagnosticFileCache {
protected Logger logger = LoggerFactory.getLogger(DiagnosticFileCache.class);
private static DiagnosticFileCache self = null;
private FileWriterCacheObj writerObj;
private FileReaderCacheObj readerObj;
private String fileBaseDir = null;
private int maxLinePerFile = 1000;
private DiagnosticFileChangeListener listener;
private final Object lock = new Object();
private DiagnosticFileCache() {
}
public void setListener(DiagnosticFileChangeListener listener) {
this.listener = listener;
}
public void setFileBaseDir(String fileBaseDir) {
this.fileBaseDir = fileBaseDir;
}
public File startWriter(File file) throws IOException {
synchronized (lock) {
// there is previous writer, return old file
File previousFile = null;
if (writerObj != null) {
previousFile = writerObj.getFile();
} else {
writerObj = new FileWriterCacheObj();
}
writerObj.pointToFile(file);
return previousFile;
}
}
public void setMaxLinePerFile(int maxLinePerFile) {
this.maxLinePerFile = maxLinePerFile;
}
public int getMaxLinePerFile() {
return maxLinePerFile;
}
public FileWriterCacheObj getWriter() {
return writerObj;
}
public FileWriterCacheObj writeLine(String line) throws IOException {
synchronized (lock) {
if (writerObj == null) {
logger.debug("Create new WriterObj!!");
// create new file
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
File newFile = new File(fileBaseDir, sdf.format(new Date()) + UUID.randomUUID().toString() + ".tmp");
File oldFile = startWriter(newFile);
logger.debug("Pointed to file: \"{}\"", newFile.getAbsolutePath());
if (listener != null) {
listener.fileChanged(oldFile, newFile);
}
writerObj.writeLine(line);
return writerObj;
}
if (!writerObj.writeLineWithMaxLineNo(maxLinePerFile, line)) {
// create new file
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
File newFile = new File(fileBaseDir, sdf.format(new Date()) + UUID.randomUUID().toString() + ".tmp");
File oldFile = startWriter(newFile);
logger.debug("Pointed to file: \"{}\"", newFile.getAbsolutePath());
if (listener != null) {
listener.fileChanged(oldFile, newFile);
}
// write the un-written line above
writerObj.writeLine(line);
return writerObj;
}
return writerObj;
}
}
public void setReaderObj(FileReaderCacheObj readerObj) {
this.readerObj = readerObj;
}
public FileReaderCacheObj getReaderObj() {
return readerObj;
}
public static DiagnosticFileCache getInstance() {
if(self == null) {
self = new DiagnosticFileCache();
}
return self;
}
public interface DiagnosticFileChangeListener {
void fileChanged(File oldFile, File newFile);
}
}

View File

@ -0,0 +1,41 @@
package id.iptek.utms.agent;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author jakar
*/
public final class GenericCache {
private final static Map<String, GenericCache> caches = new HashMap<>();
private final Map<String, Object> cache = new HashMap<>();
private GenericCache() {}
public void put(String name, Object value) {
cache.put(name, value);
}
public Object get(String name) {
return cache.get(name);
}
public void clear() {
cache.clear();
}
public int size() {
return cache.size();
}
public static GenericCache getCache(String name) {
GenericCache cache = caches.get(name);
if(cache == null) {
cache = new GenericCache();
caches.put(name, cache);
}
return cache;
}
}

View File

@ -0,0 +1,117 @@
package id.iptek.utms.agent;
import id.iptek.utms.agent.model.FileReaderCacheObj;
import id.iptek.utms.agent.model.FileWriterCacheObj;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author jakar
*/
public final class HeartbeatFileCache {
protected Logger logger = LoggerFactory.getLogger(HeartbeatFileCache.class);
private static HeartbeatFileCache self = null;
private FileWriterCacheObj writerObj;
private FileReaderCacheObj readerObj;
private String fileBaseDir = null;
private int maxLinePerFile = 1000;
private HeartbeatFileChangeListener listener;
private final Object lock = new Object();
private HeartbeatFileCache() {
}
public void setListener(HeartbeatFileChangeListener listener) {
this.listener = listener;
}
public void setFileBaseDir(String fileBaseDir) {
this.fileBaseDir = fileBaseDir;
}
public File startWriter(File file) throws IOException {
synchronized (lock) {
// there is previous writer, return old file
File previousFile = null;
if (writerObj != null) {
previousFile = writerObj.getFile();
} else {
writerObj = new FileWriterCacheObj();
}
writerObj.pointToFile(file);
return previousFile;
}
}
public void setMaxLinePerFile(int maxLinePerFile) {
this.maxLinePerFile = maxLinePerFile;
}
public int getMaxLinePerFile() {
return maxLinePerFile;
}
public FileWriterCacheObj getWriter() {
return writerObj;
}
public FileWriterCacheObj writeLine(String line) throws IOException {
synchronized (lock) {
if (writerObj == null) {
logger.debug("Create new WriterObj!!");
// create new file
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
File newFile = new File(fileBaseDir, sdf.format(new Date()) + UUID.randomUUID().toString() + ".tmp");
File oldFile = startWriter(newFile);
logger.debug("Pointed to file: \"{}\"", newFile.getAbsolutePath());
if (listener != null) {
listener.fileChanged(oldFile, newFile);
}
writerObj.writeLine(line);
return writerObj;
}
if (!writerObj.writeLineWithMaxLineNo(maxLinePerFile, line)) {
// create new file
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
File newFile = new File(fileBaseDir, sdf.format(new Date()) + UUID.randomUUID().toString() + ".tmp");
File oldFile = startWriter(newFile);
logger.debug("Pointed to file: \"{}\"", newFile.getAbsolutePath());
if (listener != null) {
listener.fileChanged(oldFile, newFile);
}
// write the un-written line above
writerObj.writeLine(line);
return writerObj;
}
return writerObj;
}
}
public void setReaderObj(FileReaderCacheObj readerObj) {
this.readerObj = readerObj;
}
public FileReaderCacheObj getReaderObj() {
return readerObj;
}
public static HeartbeatFileCache getInstance() {
if(self == null) {
self = new HeartbeatFileCache();
}
return self;
}
public interface HeartbeatFileChangeListener {
void fileChanged(File oldFile, File newFile);
}
}

View File

@ -0,0 +1,429 @@
package id.iptek.utms.agent;
import id.iptek.utms.agent.dao.TerminalDao;
import id.iptek.utms.agent.db.DBConn;
import id.iptek.utms.agent.model.TerminalIdObj;
import id.iptek.utms.agent.queue.ConsumerMode;
import id.iptek.utms.agent.queue.DelayMessageQueue;
import id.iptek.utms.agent.queue.DeviceInitQueueMessageHandler;
import id.iptek.utms.agent.queue.DiagnosticInfoQueueMessageHandler;
import id.iptek.utms.agent.queue.HeartBeatQueueMessageHandler;
import id.iptek.utms.agent.scheduler.job.DownloadTaskSchedulerJob;
import id.iptek.utms.agent.util.Singleton;
import id.iptek.utms.agent.worker.Worker;
import id.iptek.utms.agent.worker.WorkerFactory;
import io.minio.MinioClient;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.PropertyConfigurator;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import static org.quartz.JobBuilder.newJob;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author jakar
*/
public class Main {
private Logger logger = LoggerFactory.getLogger(Main.class);
private List<Worker> workers;
private List<DelayMessageQueue> queueHandlers;
private ExecutorService executorService = Executors.newCachedThreadPool();
private final CountDownLatch shutdownLatch = new CountDownLatch(1);
private final AtomicBoolean stopping = new AtomicBoolean(false);
private static final long QUEUE_SHUTDOWN_TIMEOUT_SECONDS = 30L;
public void start(String[] args) {
String configFile = getConfigFile(args);
File config = new File(configFile);
File configParent = config.getAbsoluteFile().getParentFile();
String baseDir = configParent != null && configParent.getParentFile() != null ? configParent.getParentFile().getAbsolutePath() : ".";
if (baseDir == null) {
baseDir = ".";
}
String configDir = (new StringBuilder()).append(baseDir).append(File.separator).append("conf").toString();
AppConfig appConfig = AppConfig.getInstance();
//init config
try {
initConfig(appConfig, baseDir, configDir, configFile);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
//init logging
try {
initLogging(appConfig);
} catch (Exception ex) {
logger.debug("Error initializing Logging: {}", ex.getMessage(), ex);
throw new RuntimeException(ex);
}
//init db
try {
initDB(appConfig);
} catch (Exception ex) {
logger.error("Error initializing DB: {}", ex.getMessage(), ex);
throw new RuntimeException(ex);
}
//init mqtt client
try {
initMqttClient(appConfig);
} catch (Exception ex) {
logger.error("Error init Mqtt Client: {}", ex.getMessage(), ex);
throw new RuntimeException(ex);
}
//init minio client
try {
initMinioClient(appConfig);
} catch (Exception ex) {
logger.error("Error init Minio Client: {}", ex.getMessage(), ex);
throw new RuntimeException(ex);
}
//load data async
try {
loadDataAsync(appConfig);
} catch (Exception ex) {
logger.error("Error load data async: {}", ex.getMessage(), ex);
throw new RuntimeException(ex);
}
//build message queue handlers
try {
buildQueueHandlers(appConfig);
} catch (Exception ex) {
logger.error("Error build & start queue handlers: {}", ex.getMessage(), ex);
throw new RuntimeException(ex);
}
//build & start workers
try {
buildAndStartWorkers(appConfig);
} catch (Exception ex) {
logger.error("Error build & start workers: {}", ex.getMessage(), ex);
throw new RuntimeException(ex);
}
//start schedulers
try {
startSchedulers(appConfig);
} catch (Exception ex) {
logger.error("Error starting schedulers: {}", ex.getMessage(), ex);
throw new RuntimeException(ex);
}
}
private String getConfigFile(String[] args) {
if (args == null || args.length == 0) {
throw new IllegalArgumentException("Usage: java -jar utms-agent.jar <config-file>");
}
if (args.length > 1 && Main.class.getName().equals(args[0])) {
return args[1];
}
return args[0];
}
private void initConfig(AppConfig appConfig, String baseDir, String configDir, String configFile) throws Exception {
File _configFile = new File(configFile);
/*if(!_configFile.isAbsolute()) {
_configFile = new File(configDir, configFile);
}*/
appConfig.init(_configFile);
appConfig.set("Config.File", _configFile.getAbsolutePath());
appConfig.set("Base.Dir", baseDir);
appConfig.set("Config.Dir", configDir);
}
private void initLogging(AppConfig appConfig) throws Exception {
String configFile = appConfig.get("log4j.file");
String configDir = appConfig.get("Config.Dir");
configFile = configFile.replace("${Config.Dir}", configDir);
BasicConfigurator.resetConfiguration();
PropertyConfigurator.configure(configFile);
logger.info("Config file: {}", appConfig.get("Config.File"));
logger.info("Base dir: {}", appConfig.get("Base.Dir"));
logger.info("Config dir: {}", configDir);
logger.info("Logging config file: {}", configFile);
logger.info("Logging initialized.");
}
private void initDB(AppConfig appConfig) throws Exception {
logger.info("Init DB ...");
String datasource = appConfig.get("db.datasource");
String driver = appConfig.get("db.driver");
String url = appConfig.get("db.url");
String user = appConfig.get("db.user");
String password = appConfig.get("db.password");
if (datasource != null && !"".equals(datasource.trim())) {
logger.debug("Using datasource.");
DBConn.getInstance().init(datasource);
} else {
logger.debug("Using traditional url, username, and password.");
DBConn.getInstance().init(driver, url, user, password);
}
logger.info("DB initialized.");
}
private void initMqttClient(AppConfig appConfig) throws Exception {
logger.info("Init Mqtt client ...");
String clientId = appConfig.get("mqtt.clientid_prefix") + RandomStringUtils.randomAlphanumeric(10);
String brokerUrl = appConfig.get("mqtt.broker.url");
String username = appConfig.get("mqtt.user");
String password = appConfig.get("mqtt.password");
int keepAlive = appConfig.getAsInt("mqtt.keepalive", 10);
int maxInFlight = appConfig.getAsInt("mqtt.maxinflight", 32);
boolean cleanSession = appConfig.getAsBoolean("mqtt.cleansession", true);
boolean autoReconnect = appConfig.getAsBoolean("mqtt.autoreconnect", true);
MemoryPersistence persistence = new MemoryPersistence();
MqttClient mqttClient = new MqttClient(brokerUrl, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(cleanSession);
connOpts.setUserName(username);
connOpts.setPassword(password.toCharArray());
connOpts.setAutomaticReconnect(autoReconnect);
connOpts.setKeepAliveInterval(keepAlive);
connOpts.setMaxInflight(maxInFlight);
logger.info("Try to connect ...");
mqttClient.connect(connOpts);
// put into Singleton
Singleton.getInstance("MQTT_CLIENT").setObject(mqttClient);
logger.info("Mqtt client initialized.");
}
private void initMinioClient(AppConfig appConfig) throws Exception {
MinioClient minioClient
= MinioClient.builder()
.endpoint(appConfig.get("fileserver.endpoint"))
.credentials(appConfig.get("fileserver.access_key"), appConfig.get("fileserver.secret_key"))
.build();
// put into Singleton
Singleton.getInstance("MINIO_CLIENT").setObject(minioClient);
}
private void buildAndStartWorkers(AppConfig appConfig) throws Exception {
logger.info("Build & Start workers ...");
workers = WorkerFactory.getInstance().buildWorkers(appConfig);
for (Worker worker : workers) {
logger.info("Start worker .. '{}'", worker.getLoggingId());
worker.setExecutorService(executorService);
worker.start();
logger.info("Worker started");
executorService.execute(worker);
}
logger.info("Workers build & started.");
}
private void buildQueueHandlers(AppConfig appConfig) throws Exception {
queueHandlers = new ArrayList<>();
logger.info("Build & Start queue handlers ...");
// heartbeat queue handler
logger.info("Start Heartbeat queue handler .. ");
DelayMessageQueue hbQueue = new DelayMessageQueue(executorService, new HeartBeatQueueMessageHandler(), 10);
hbQueue.setMode(ConsumerMode.BATCH);
hbQueue.setTotalThread(3);
hbQueue.run();
// put to singleton
Singleton.getInstance(HeartBeatQueueMessageHandler.NAME).setObject(hbQueue);
queueHandlers.add(hbQueue);
logger.info("Heartbeat queue handler started");
// diagnostic queue handler
logger.info("Start Diagnostic queue handler .. ");
DelayMessageQueue diagQueue = new DelayMessageQueue(executorService, new DiagnosticInfoQueueMessageHandler(), 3);
diagQueue.setMode(ConsumerMode.BATCH);
diagQueue.setTotalThread(2);
diagQueue.run();
// put to singleton
Singleton.getInstance(DiagnosticInfoQueueMessageHandler.NAME).setObject(diagQueue);
queueHandlers.add(diagQueue);
logger.info("Diagnostic queue handler started");
// init queue handler
logger.info("Start Init queue handler .. ");
DelayMessageQueue initQueue = new DelayMessageQueue(executorService, new DeviceInitQueueMessageHandler(), 3);
initQueue.setMode(ConsumerMode.BATCH);
initQueue.setTotalThread(2);
initQueue.run();
// put to singleton
Singleton.getInstance(DeviceInitQueueMessageHandler.NAME).setObject(initQueue);
queueHandlers.add(initQueue);
logger.info("Init queue handler started");
logger.info("Queue handlers build & started.");
}
private void loadDataAsync(AppConfig appConfig) throws Exception {
logger.info("Load data async ...");
// load terminal Id Generic Cache
loadTerminalIdCache();
logger.info("End of load data async.");
}
private void loadTerminalIdCache() throws Exception {
executorService.submit(new Runnable() {
@Override
public void run() {
try {
logger.debug("Load Terminal Id data ...");
TerminalDao terminalDao = new TerminalDao();
GenericCache cache = GenericCache.getCache("terminalId");
List<TerminalIdObj> terminalList = terminalDao.getTerminalIds();
terminalList.forEach((t) -> {
cache.put(t.getSn().toLowerCase(), t.getTerminalId());
});
logger.debug("Terminal Id data loaded: {} data.", terminalList.size());
} catch(Exception ex) {
logger.error("Error loading Terminal Id cache: {}", ex.getMessage(), ex);
}
}
});
}
private void startSchedulers(AppConfig appConfig) throws Exception {
logger.info("Start schedulers ...");
// download task scheduler
JobDetail job = newJob(DownloadTaskSchedulerJob.class)
.withIdentity("downloadTaskScheduler", "task")
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "task")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMinutes(appConfig.getAsInt("scheduler.periode.minutes", 5))
.repeatForever())
.build();
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
sched.scheduleJob(job, trigger);
sched.start();
Singleton.getInstance("SCHEDULER").setObject(sched);
logger.info("Schedulers started.");
}
private void stopQueueHandlers() throws Exception {
logger.info("Stop queue handlers ...");
if (queueHandlers == null) {
logger.info("Queue handlers have not been started.");
return;
}
long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(QUEUE_SHUTDOWN_TIMEOUT_SECONDS);
for (DelayMessageQueue queue : queueHandlers) {
try {
logger.info("Stop queue handler .. '{}'", queue.getClass());
long remainingNanos = deadline - System.nanoTime();
if (remainingNanos <= 0L) {
logger.warn("Queue graceful shutdown timeout reached, forcing queue handler '{}'", queue.getClass());
queue.stop(true);
} else {
boolean graceful = queue.stop(false, remainingNanos, TimeUnit.NANOSECONDS);
if (!graceful) {
logger.warn("Force queue handler .. '{}'", queue.getClass());
queue.stop(true);
}
}
logger.info("Queue handler stopped");
} catch (Exception ex) {
logger.error("Error stopping queue handler: {}", ex.getMessage(), ex);
}
}
logger.info("Queue handlers stopped.");
}
private void stopWorkers() throws Exception {
logger.info("Stop workers ...");
if (workers == null) {
logger.info("Workers have not been started.");
return;
}
for (Worker worker : workers) {
try {
logger.info("Stop worker .. '{}'", worker.getLoggingId());
worker.stop();
logger.info("Worker stopped");
} catch (Exception ex) {
logger.error("Error stopping worker '{}': {}", worker.getLoggingId(), ex.getMessage(), ex);
}
}
logger.info("Workers stopped.");
}
public void stop() {
if (stopping.compareAndSet(false, true)) {
try {
stopScheduler();
stopQueueHandlers();
stopWorkers();
stopMqttClient();
executorService.shutdownNow();
} catch (Exception ex) {
logger.error("Error stopping: {}", ex.getMessage(), ex);
} finally {
shutdownLatch.countDown();
}
}
}
private void stopMqttClient() throws Exception {
Object object = Singleton.getInstance("MQTT_CLIENT").getObject();
if (object instanceof MqttClient) {
MqttClient mqttClient = (MqttClient) object;
if (mqttClient.isConnected()) {
logger.info("Disconnect MQTT client ...");
mqttClient.disconnectForcibly(0L, 250L, false);
logger.info("MQTT client disconnected.");
}
mqttClient.close(true);
}
}
private void stopScheduler() throws Exception {
Object scheduler = Singleton.getInstance("SCHEDULER").getObject();
if (scheduler instanceof Scheduler) {
logger.info("Stop scheduler ...");
((Scheduler) scheduler).shutdown(false);
logger.info("Scheduler stopped.");
}
}
private void awaitShutdown() throws InterruptedException {
shutdownLatch.await();
}
public static void main(String[] args) {
final Main main = new Main();
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
main.stop();
}
}, "utms-agent-shutdown"));
try {
main.start(args);
main.awaitShutdown();
} catch (Exception ex) {
main.stop();
System.exit(1);
}
}
}

View File

@ -0,0 +1,76 @@
package id.iptek.utms.agent.dao;
import id.iptek.utms.agent.db.DBConn;
import id.iptek.utms.agent.db.DBUtil;
import id.iptek.utms.agent.db.DatabaseException;
import id.iptek.utms.agent.model.ApplicationExt;
import id.iptek.utms.agent.model.PendingDownloadTask;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
/**
*
* @author Jaka
*/
public class ApplicationDao {
public boolean updateIconUrl(ApplicationExt app) throws DatabaseException {
boolean saved = false;
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DBConn.getInstance().getConnection();
conn.setAutoCommit(false);
pstmt = conn.prepareStatement(""
+ "update tms_application set icon_url=?,icon_url_exp=? where id=?::uuid");
int idx = 1;
pstmt.setString(idx++, app.getIconUrl());
pstmt.setTimestamp(idx++, new Timestamp(app.getIconUrlExp().getTime()));
pstmt.setString(idx++, app.getId());
saved = pstmt.executeUpdate() == 1;
conn.commit();
conn.setAutoCommit(true);
} catch (SQLException ex) {
DBUtil.rollback(conn);
throw new DatabaseException(ex);
} finally {
DBUtil.close(pstmt);
DBUtil.close(conn);
}
return saved;
}
public boolean updateAppUrl(PendingDownloadTask task, ApplicationExt app) throws DatabaseException {
boolean saved = false;
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DBConn.getInstance().getConnection();
conn.setAutoCommit(false);
pstmt = conn.prepareStatement(""
+ "update tms_download_task_application_link set download_url=?,download_url_exp=? where download_task_id=?::uuid and application_id=?::uuid");
int idx = 1;
pstmt.setString(idx++, app.getDownloadUrl());
pstmt.setTimestamp(idx++, new Timestamp(app.getDownloadUrlExp().getTime()));
pstmt.setString(idx++, task.getId());
pstmt.setString(idx++, app.getId());
saved = pstmt.executeUpdate() == 1;
conn.commit();
conn.setAutoCommit(true);
} catch (SQLException ex) {
DBUtil.rollback(conn);
throw new DatabaseException(ex);
} finally {
DBUtil.close(pstmt);
DBUtil.close(conn);
}
return saved;
}
}

View File

@ -0,0 +1,256 @@
package id.iptek.utms.agent.dao;
import id.iptek.utms.agent.db.DBConn;
import id.iptek.utms.agent.db.DBUtil;
import id.iptek.utms.agent.db.DatabaseException;
import id.iptek.utms.agent.model.ApplicationSimple;
import id.iptek.utms.agent.model.PendingDeleteTask;
import id.iptek.utms.agent.model.TaskAckReq;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Jaka
*/
public class DeleteTaskDao {
private Logger logger = LoggerFactory.getLogger(getClass());
public DeleteTaskDao() {
}
public List<PendingDeleteTask> getPendingTaskForOnlineTerminals(int minutes, int limit) throws DatabaseException {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<PendingDeleteTask> list = new ArrayList<>();
try {
conn = DBConn.getInstance().getConnection();
pstmt = conn.prepareStatement(""
+ "select "
+ " terminal.sn, "
+ " task.id,task.\"name\",task.delete_time, "
+ " app.id app_id,app.app_name,app.package_name, "
+ " log.id log_id "
+ "from public.tms_delete_task task "
+ " inner join public.tms_delete_task_log log on log.task_id=task.id "
+ " inner join public.tms_terminal terminal on log.terminal_id=terminal.id and terminal.delete_ts is null and terminal.heartbeat_status=1 "
+ " inner join public.tms_delete_task_application_simple_link link on link.delete_task_id=task.id and link.application_simple_id=log.application_simple_id "
+ " inner join public.tms_application_simple app on link.application_simple_id=app.id "
+ "where log.activity=0 and (log.last_broadcast_ts is null or (log.last_broadcast_ts < current_timestamp - interval '"+minutes+" minutes')) "
+ "order by task.create_ts desc,log.last_broadcast_ts asc "
+ "limit ? offset 0");
pstmt.setInt(1, limit);
rs = pstmt.executeQuery();
while (rs.next()) {
PendingDeleteTask task = new PendingDeleteTask();
task.setTerminalSN(rs.getString(1));
task.setId(rs.getString(2));
task.setName(rs.getString(3));
task.setDeleteTime(rs.getTimestamp(4));
ApplicationSimple app = new ApplicationSimple();
app.setId(rs.getString(5));
app.setAppName(rs.getString(6));
app.setPackageName(rs.getString(7));
task.setApp(app);
task.setLogId(rs.getString(8));
list.add(task);
}
} catch (SQLException ex) {
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn, pstmt, rs);
}
return list;
}
public List<PendingDeleteTask> getPendingTaskForTerminals(int minutes, int limit) throws DatabaseException {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<PendingDeleteTask> list = new ArrayList<>();
try {
conn = DBConn.getInstance().getConnection();
pstmt = conn.prepareStatement(""
+ "select "
+ " terminal.sn, "
+ " task.id,task.\"name\",task.delete_time, "
+ " app.id app_id,app.app_name,app.package_name, "
+ " log.id log_id "
+ "from public.tms_delete_task task "
+ " inner join public.tms_delete_task_log log on log.task_id=task.id "
+ " inner join public.tms_terminal terminal on log.terminal_id=terminal.id and terminal.delete_ts is null "
+ " inner join public.tms_delete_task_application_simple_link link on link.delete_task_id=task.id and link.application_simple_id=log.application_simple_id "
+ " inner join public.tms_application_simple app on link.application_simple_id=app.id "
+ "where log.activity=0 and (log.last_broadcast_ts is null or (log.last_broadcast_ts < current_timestamp - interval '"+minutes+" minutes')) "
+ "order by task.create_ts desc,log.last_broadcast_ts asc "
+ "limit ? offset 0");
pstmt.setInt(1, limit);
rs = pstmt.executeQuery();
while (rs.next()) {
PendingDeleteTask task = new PendingDeleteTask();
task.setTerminalSN(rs.getString(1));
task.setId(rs.getString(2));
task.setName(rs.getString(3));
task.setDeleteTime(rs.getTimestamp(4));
ApplicationSimple app = new ApplicationSimple();
app.setId(rs.getString(5));
app.setAppName(rs.getString(6));
app.setPackageName(rs.getString(7));
task.setApp(app);
task.setLogId(rs.getString(8));
list.add(task);
}
} catch (SQLException ex) {
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn, pstmt, rs);
}
return list;
}
public List<PendingDeleteTask> getPendingTaskForTerminal(String terminalSN) throws DatabaseException {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<PendingDeleteTask> list = new ArrayList<>();
try {
conn = DBConn.getInstance().getConnection();
pstmt = conn.prepareStatement(""
+ "select "
+ " terminal.sn, "
+ " task.id,task.\"name\",task.delete_time, "
+ " app.id app_id,app.app_name,app.package_name, "
+ " log.id log_id "
+ "from public.tms_delete_task task "
+ " inner join public.tms_delete_task_log log on log.task_id=task.id "
+ " inner join public.tms_terminal terminal on log.terminal_id=terminal.id and terminal.delete_ts is null "
+ " inner join public.tms_delete_task_application_simple_link link on link.delete_task_id=task.id and link.application_simple_id=log.application_simple_id "
+ " inner join public.tms_application_simple app on link.application_simple_id=app.id "
+ "where lower(terminal.sn)=? "
+ " and log.activity=0");
pstmt.setString(1, terminalSN.toLowerCase());
rs = pstmt.executeQuery();
while (rs.next()) {
PendingDeleteTask task = new PendingDeleteTask();
task.setTerminalSN(rs.getString(1));
task.setId(rs.getString(2));
task.setName(rs.getString(3));
task.setDeleteTime(rs.getTimestamp(4));
ApplicationSimple app = new ApplicationSimple();
app.setId(rs.getString(5));
app.setAppName(rs.getString(6));
app.setPackageName(rs.getString(7));
task.setApp(app);
task.setLogId(rs.getString(8));
list.add(task);
}
} catch (SQLException ex) {
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn, pstmt, rs);
}
return list;
}
public boolean saveLastBroadcastTs(PendingDeleteTask task) throws DatabaseException {
boolean saved = false;
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DBConn.getInstance().getConnection();
conn.setAutoCommit(false);
pstmt = conn.prepareStatement(""
+ "update tms_delete_task_log set last_broadcast_ts=NOW() where id=?::uuid");
pstmt.setString(1, task.getLogId());
int affectedRows = pstmt.executeUpdate();
saved = affectedRows == 1;
conn.commit();
conn.setAutoCommit(true);
} catch (SQLException ex) {
DBUtil.rollback(conn);
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn, pstmt, null);
}
return saved;
}
public boolean save(TaskAckReq ackReq) throws DatabaseException {
boolean saved = false;
Connection conn = null;
try {
conn = DBConn.getInstance().getConnection();
conn.setAutoCommit(false);
// update download task log activity
saved |= updateDeleteTaskLogActivity(conn, ackReq);
if (saved) {
int totalUnfinished = getUnfinishedTask(conn, ackReq);
if (totalUnfinished == 0) {
//logger.debug("Total unfinished is 0, set to DONE");
//boolean taskStatusUpdated = updateDownloadTaskLogStatus(conn, ackReq);
//logger.debug("Download Task status updated? {}", taskStatusUpdated);
}
}
conn.commit();
conn.setAutoCommit(true);
} catch (SQLException ex) {
DBUtil.rollback(conn);
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn);
}
return saved;
}
private boolean updateDeleteTaskLogActivity(Connection conn, TaskAckReq ackReq) throws SQLException {
boolean saved = false;
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(""
+ "update tms_delete_task_log set activity=?,message=?,update_ts=NOW(),updated_by=? where id=?::uuid");
int idx = 1;
pstmt.setInt(idx++, ackReq.getActivity());
pstmt.setString(idx++, ackReq.getMessage());
pstmt.setString(idx++, ackReq.getTerminalSN());
pstmt.setString(idx++, ackReq.getAckId());
saved = pstmt.executeUpdate() >= 1;
} finally {
DBUtil.close(pstmt);
}
return saved;
}
private int getUnfinishedTask(Connection conn, TaskAckReq ackReq) throws DatabaseException {
PreparedStatement pstmt = null;
ResultSet rs = null;
int total = 0;
try {
pstmt = conn.prepareStatement(""
+ "select count(*) from public.tms_delete_task_log "
+ "where task_id = (select id from tms_delete_task_log where id = ?::uuid) "
+ " and activity not in (3,4)");
pstmt.setString(1, ackReq.getAckId());
rs = pstmt.executeQuery();
if (rs.next()) {
total = rs.getInt(1);
}
} catch (SQLException ex) {
throw new DatabaseException(ex);
} finally {
DBUtil.close(rs);
DBUtil.close(pstmt);
}
return total;
}
}

View File

@ -0,0 +1,296 @@
package id.iptek.utms.agent.dao;
import id.iptek.utms.agent.db.DBConn;
import id.iptek.utms.agent.db.DBUtil;
import id.iptek.utms.agent.db.DatabaseException;
import id.iptek.utms.agent.model.ApplicationSimple;
import id.iptek.utms.agent.model.CellInfo;
import id.iptek.utms.agent.model.Diagnostic;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
/**
*
* @author Jaka
*/
public class DiagnosticDao {
public DiagnosticDao() {
}
public boolean save(Diagnostic diagnostic) throws DatabaseException {
boolean saved = false;
Connection conn = null;
try {
conn = DBConn.getInstance().getConnection();
conn.setAutoCommit(false);
// save heartbeat first
saved |= saveDiagnostic(conn, diagnostic);
if (saved) {
saved |= updateTerminalLastDiagnostic(conn, diagnostic);
}
conn.commit();
conn.setAutoCommit(true);
} catch (SQLException ex) {
DBUtil.rollback(conn);
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn);
}
return saved;
}
public boolean saveAll(List<Diagnostic> diagnostics) throws DatabaseException {
boolean saved = false;
Connection conn = null;
try {
conn = DBConn.getInstance().getConnection();
conn.setAutoCommit(false);
// save heartbeat first
saved |= saveDiagnostics(conn, diagnostics);
if (saved) {
saved |= updateAllTerminalLastDiagnostic(conn, diagnostics);
}
conn.commit();
conn.setAutoCommit(true);
} catch (SQLException ex) {
DBUtil.rollback(conn);
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn);
}
return saved;
}
private boolean saveDiagnostic(Connection conn, Diagnostic diagnostic) throws SQLException {
boolean saved = false;
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(""
+ "insert into tms_diagnostic_info (id,sn,battery_temp,battery_percentage,latitude,longitude,"
+ " meid,switching_times,swiping_card_times,dip_inserting_times,nfc_card_reading_times, "
+ " front_camera_open_times,rear_camera_open_times,charge_times, "
+ " total_memory,available_memory,total_flash_memory,available_flash_memory,total_mobile_data, "
+ " current_boot_time,total_boot_time,installed_apps_string,total_length_printed, "
+ " cell_name, cell_type, cell_strength, "
+ " create_ts,created_by,version) "
+ "values (?::uuid,?,?,?,?,?,"
+ " ?,?,?,?,?, "
+ " ?,?,?, "
+ " ?,?,?,?,?, "
+ " ?,?,?,?, "
+ " ?,?,?, "
+ " ?,?,1) ");
int idx = 1;
pstmt.setString(idx++, diagnostic.getId());
pstmt.setString(idx++, diagnostic.getDeviceSn());
pstmt.setDouble(idx++, diagnostic.getDiagnosticInfo().getBatteryTemp());
pstmt.setDouble(idx++, diagnostic.getDiagnosticInfo().getBatteryPercentage());
pstmt.setDouble(idx++, diagnostic.getLocationInfo().getLat());
pstmt.setDouble(idx++, diagnostic.getLocationInfo().getLng());
pstmt.setString(idx++, diagnostic.getDiagnosticInfo().getMeid());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getSwitchingTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getSwipingCardTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getDipInsertingTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getNfcCardReadingTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getFrontCameraOpenTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getRearCameraOpenTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getChargeTimes());
pstmt.setLong(idx++, getLong(diagnostic.getDiagnosticInfo().getTotalMemory()));
pstmt.setLong(idx++, getLong(diagnostic.getDiagnosticInfo().getAvailableMemory()));
pstmt.setLong(idx++, getLong(diagnostic.getDiagnosticInfo().getTotalFlashMemory()));
pstmt.setLong(idx++, getLong(diagnostic.getDiagnosticInfo().getAvailableFlashMemory()));
pstmt.setLong(idx++, getLong(diagnostic.getDiagnosticInfo().getTotalMobileData()));
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getCurrentBootTime());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getTotalBootTime());
pstmt.setString(idx++, diagnostic.getDiagnosticInfo().getInstalledAppString());
pstmt.setDouble(idx++, diagnostic.getDiagnosticInfo().getTotalLengthPrinted());
if(diagnostic.getCellInfo() != null && !diagnostic.getCellInfo().isEmpty()) {
CellInfo cellInfo = diagnostic.getCellInfo().get(0);
pstmt.setString(idx++, cellInfo.getName());
pstmt.setString(idx++, cellInfo.getType());
pstmt.setInt(idx++, cellInfo.getStrength());
} else {
pstmt.setNull(idx++, java.sql.Types.VARCHAR);
pstmt.setNull(idx++, java.sql.Types.VARCHAR);
pstmt.setNull(idx++, java.sql.Types.INTEGER);
}
pstmt.setTimestamp(idx++, new java.sql.Timestamp(diagnostic.getCreateTime().getTime()));
pstmt.setString(idx++, "system");
saved = pstmt.executeUpdate() == 1;
} finally {
DBUtil.close(pstmt);
}
return saved;
}
private boolean saveDiagnostics(Connection conn, List<Diagnostic> diagnostics) throws SQLException {
boolean saved = false;
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(""
+ "insert into tms_diagnostic_info (id,sn,battery_temp,battery_percentage,latitude,longitude,"
+ " meid,switching_times,swiping_card_times,dip_inserting_times,nfc_card_reading_times, "
+ " front_camera_open_times,rear_camera_open_times,charge_times, "
+ " total_memory,available_memory,total_flash_memory,available_flash_memory,total_mobile_data, "
+ " current_boot_time,total_boot_time,installed_apps_string,total_length_printed, "
+ " cell_name, cell_type, cell_strength, "
+ " create_ts,created_by,version) "
+ "values (?::uuid,?,?,?,?,?,"
+ " ?,?,?,?,?, "
+ " ?,?,?, "
+ " ?,?,?,?,?, "
+ " ?,?,?,?, "
+ " ?,?,?, "
+ " ?,?,1) ");
for (Diagnostic diagnostic : diagnostics) {
int idx = 1;
pstmt.setString(idx++, diagnostic.getId());
pstmt.setString(idx++, diagnostic.getDeviceSn());
pstmt.setDouble(idx++, diagnostic.getDiagnosticInfo().getBatteryTemp());
pstmt.setDouble(idx++, diagnostic.getDiagnosticInfo().getBatteryPercentage());
pstmt.setDouble(idx++, diagnostic.getLocationInfo().getLat());
pstmt.setDouble(idx++, diagnostic.getLocationInfo().getLng());
pstmt.setString(idx++, diagnostic.getDiagnosticInfo().getMeid());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getSwitchingTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getSwipingCardTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getDipInsertingTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getNfcCardReadingTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getFrontCameraOpenTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getRearCameraOpenTimes());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getChargeTimes());
pstmt.setLong(idx++, getLong(diagnostic.getDiagnosticInfo().getTotalMemory()));
pstmt.setLong(idx++, getLong(diagnostic.getDiagnosticInfo().getAvailableMemory()));
pstmt.setLong(idx++, getLong(diagnostic.getDiagnosticInfo().getTotalFlashMemory()));
pstmt.setLong(idx++, getLong(diagnostic.getDiagnosticInfo().getAvailableFlashMemory()));
pstmt.setLong(idx++, getLong(diagnostic.getDiagnosticInfo().getTotalMobileData()));
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getCurrentBootTime());
pstmt.setInt(idx++, diagnostic.getDiagnosticInfo().getTotalBootTime());
pstmt.setString(idx++, diagnostic.getDiagnosticInfo().getInstalledAppString());
pstmt.setDouble(idx++, diagnostic.getDiagnosticInfo().getTotalLengthPrinted());
if(diagnostic.getCellInfo() != null && !diagnostic.getCellInfo().isEmpty()) {
CellInfo cellInfo = diagnostic.getCellInfo().get(0);
pstmt.setString(idx++, cellInfo.getName());
pstmt.setString(idx++, cellInfo.getType());
pstmt.setInt(idx++, cellInfo.getStrength());
} else {
pstmt.setNull(idx++, java.sql.Types.VARCHAR);
pstmt.setNull(idx++, java.sql.Types.VARCHAR);
pstmt.setNull(idx++, java.sql.Types.INTEGER);
}
pstmt.setTimestamp(idx++, new java.sql.Timestamp(diagnostic.getCreateTime().getTime()));
pstmt.setString(idx++, "system");
pstmt.addBatch();
pstmt.clearParameters();
}
int[] xs = pstmt.executeBatch();
int affectedRows = 0;
for (int x : xs) {
affectedRows += x;
}
saved = affectedRows == diagnostics.size();
} finally {
DBUtil.close(pstmt);
}
return saved;
}
private boolean updateTerminalLastDiagnostic(Connection conn, Diagnostic diagnostic) throws SQLException {
boolean saved = false;
PreparedStatement pstmt = null;
try {
String appVersion = null;
String launcherVersion = null;
String vfsVersion = null;
String vfssVersion = null;
for (ApplicationSimple app : diagnostic.getInstalledApps()) {
if ("com.briit.brimobile".equals(app.getPackageName())) {
appVersion = app.getVersion();
}
if ("com.unified.launcher".equals(app.getPackageName())) {
launcherVersion = app.getVersion();
}
if ("com.vfi.smartpos.system_service".equals(app.getPackageName())) {
vfsVersion = app.getVersion();
}
if ("com.vfi.smartpos.deviceservice".equals(app.getPackageName())) {
vfssVersion = app.getVersion();
}
}
pstmt = conn.prepareStatement(""
+ "update tms_last_diagnostic_info set diagnostic_info_id=?::uuid,update_ts=now() where terminal_sn=?");
pstmt.setString(1, diagnostic.getId());
pstmt.setString(2, diagnostic.getDeviceSn());
saved = pstmt.executeUpdate() == 1;
} finally {
DBUtil.close(pstmt);
}
return saved;
}
private boolean updateAllTerminalLastDiagnostic(Connection conn, List<Diagnostic> diagnostics) throws SQLException {
boolean saved = false;
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(""
+ "update tms_last_diagnostic_info set diagnostic_info_id=?::uuid,update_ts=now() where terminal_sn=?");
for (Diagnostic diagnostic : diagnostics) {
String appVersion = null;
String launcherVersion = null;
String vfsVersion = null;
String vfssVersion = null;
for (ApplicationSimple app : diagnostic.getInstalledApps()) {
if ("com.briit.brimobile".equals(app.getPackageName())) {
appVersion = app.getVersion();
}
if ("com.unified.launcher".equals(app.getPackageName())) {
launcherVersion = app.getVersion();
}
if ("com.vfi.smartpos.system_service".equals(app.getPackageName())) {
vfsVersion = app.getVersion();
}
if ("com.vfi.smartpos.deviceservice".equals(app.getPackageName())) {
vfssVersion = app.getVersion();
}
}
pstmt.setString(1, diagnostic.getId());
pstmt.setString(2, diagnostic.getDeviceSn());
pstmt.addBatch();
pstmt.clearParameters();
}
int[] xs = pstmt.executeBatch();
int affectedRows = 0;
for (int x : xs) {
affectedRows += x;
}
saved = affectedRows > 0;
} finally {
DBUtil.close(pstmt);
}
return saved;
}
private long getLong(Object val) {
if (val instanceof String) {
String sVal = (String) val;
if (sVal.contains("B")) {
sVal = sVal.replace("B", "");
}
return Long.parseLong(sVal.trim());
} else if (val instanceof Long) {
return (Long) val;
} else if (val instanceof Double) {
return ((Double) val).longValue();
}
return 0;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,196 @@
package id.iptek.utms.agent.dao;
import id.iptek.utms.agent.db.DBConn;
import id.iptek.utms.agent.db.DBUtil;
import id.iptek.utms.agent.db.DatabaseException;
import id.iptek.utms.agent.model.CellInfo;
import id.iptek.utms.agent.model.HeartBeat;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Jaka
*/
public class HeartbeatDao {
private Logger logger = LoggerFactory.getLogger(HeartbeatDao.class);
public HeartbeatDao() {
}
public boolean save(HeartBeat hearbeat) throws DatabaseException {
boolean saved = false;
Connection conn = null;
try {
conn = DBConn.getInstance().getConnection();
conn.setAutoCommit(false);
// save heartbeat first
saved |= saveHeartBeat(conn, hearbeat);
if (saved) {
saved |= updateTerminalLastHearbeat(conn, hearbeat);
}
conn.commit();
conn.setAutoCommit(true);
} catch (SQLException ex) {
DBUtil.rollback(conn);
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn);
}
return saved;
}
public Connection getDBConnection() throws SQLException {
Connection conn = DBConn.getInstance().getConnection();
return conn;
}
public boolean saveHeartBeat(Connection conn, HeartBeat heartbeat) throws SQLException {
boolean saved = false;
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(""
+ "insert into tms_heart_beat (id,sn,battery_temp,battery_percentage,latitude,longitude,cell_name,cell_type,cell_strength,create_ts,created_by,version) "
+ "values (?::uuid,?,?,?,?,?,?,?,?,?,?,1) ");
int idx = 1;
pstmt.setString(idx++, heartbeat.getId());
pstmt.setString(idx++, heartbeat.getDeviceSn());
pstmt.setDouble(idx++, heartbeat.getDiagnosticInfo().getBatteryTemp());
pstmt.setDouble(idx++, heartbeat.getDiagnosticInfo().getBatteryPercentage());
pstmt.setDouble(idx++, heartbeat.getLocationInfo().getLat());
pstmt.setDouble(idx++, heartbeat.getLocationInfo().getLng());
if(heartbeat.getCellInfo() != null && !heartbeat.getCellInfo().isEmpty()) {
CellInfo cellInfo = heartbeat.getCellInfo().get(0);
pstmt.setString(idx++, cellInfo.getName());
pstmt.setString(idx++, cellInfo.getType());
pstmt.setInt(idx++, cellInfo.getStrength());
} else {
pstmt.setNull(idx++, java.sql.Types.VARCHAR);
pstmt.setNull(idx++, java.sql.Types.VARCHAR);
pstmt.setNull(idx++, java.sql.Types.INTEGER);
}
pstmt.setTimestamp(idx++, new java.sql.Timestamp(heartbeat.getCreateTime().getTime()));
pstmt.setString(idx++, "system");
//saved = pstmt.executeUpdate() == 1;
saved = pstmt.executeUpdate() >= 0;
} finally {
DBUtil.close(pstmt);
}
return saved;
}
public boolean saveAll(List<HeartBeat> hearbeats) throws DatabaseException {
boolean saved = false;
Connection conn = null;
try {
conn = DBConn.getInstance().getConnection();
conn.setAutoCommit(false);
// save heartbeat first
saved |= saveHeartBeats(conn, hearbeats);
if (saved) {
saved |= updateTerminalLastHearbeats(conn, hearbeats);
}
conn.commit();
conn.setAutoCommit(true);
} catch (SQLException ex) {
DBUtil.rollback(conn);
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn);
}
return saved;
}
private boolean saveHeartBeats(Connection conn, List<HeartBeat> heartbeats) throws SQLException {
boolean saved = false;
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(""
+ "insert into tms_heart_beat (id,sn,battery_temp,battery_percentage,latitude,longitude,cell_name,cell_type,cell_strength,create_ts,created_by,version) "
+ "values (?::uuid,?,?,?,?,?,?,?,?,?,?,1) ");
for(HeartBeat heartbeat : heartbeats) {
int idx = 1;
pstmt.setString(idx++, heartbeat.getId());
pstmt.setString(idx++, heartbeat.getDeviceSn());
pstmt.setDouble(idx++, heartbeat.getDiagnosticInfo().getBatteryTemp());
pstmt.setDouble(idx++, heartbeat.getDiagnosticInfo().getBatteryPercentage());
pstmt.setDouble(idx++, heartbeat.getLocationInfo().getLat());
pstmt.setDouble(idx++, heartbeat.getLocationInfo().getLng());
if(heartbeat.getCellInfo() != null && !heartbeat.getCellInfo().isEmpty()) {
CellInfo cellInfo = heartbeat.getCellInfo().get(0);
pstmt.setString(idx++, cellInfo.getName());
pstmt.setString(idx++, cellInfo.getType());
pstmt.setInt(idx++, cellInfo.getStrength());
} else {
pstmt.setNull(idx++, java.sql.Types.VARCHAR);
pstmt.setNull(idx++, java.sql.Types.VARCHAR);
pstmt.setNull(idx++, java.sql.Types.INTEGER);
}
pstmt.setTimestamp(idx++, new java.sql.Timestamp(heartbeat.getCreateTime().getTime()));
pstmt.setString(idx++, "system");
pstmt.addBatch();
pstmt.clearParameters();
}
int[] xs = pstmt.executeBatch();
int affectedRows = 0;
for(int x : xs) {
affectedRows += x;
}
//saved = affectedRows > 0;
saved = affectedRows >= 0;
} finally {
DBUtil.close(pstmt);
}
return saved;
}
private boolean updateTerminalLastHearbeat(Connection conn, HeartBeat heartbeat) throws SQLException {
boolean saved = false;
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(""
+ "update tms_last_heartbeat set heart_beat_id=?::uuid,update_ts=now() where terminal_sn=?");
pstmt.setString(1, heartbeat.getId());
pstmt.setString(2, heartbeat.getDeviceSn());
saved = pstmt.executeUpdate() == 1;
} finally {
DBUtil.close(pstmt);
}
return saved;
}
private boolean updateTerminalLastHearbeats(Connection conn, List<HeartBeat> heartbeats) throws SQLException {
boolean saved = false;
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(""
+ "update tms_last_heartbeat set heart_beat_id=?::uuid,update_ts=now() where terminal_sn=?");
for(HeartBeat heartbeat : heartbeats) {
pstmt.setString(1, heartbeat.getId());
pstmt.setString(2, heartbeat.getDeviceSn());
pstmt.addBatch();
pstmt.clearParameters();
}
int[] xs = pstmt.executeBatch();
int affectedRows = 0;
for(int x : xs) {
affectedRows += x;
}
saved = affectedRows > 0;
} finally {
DBUtil.close(pstmt);
}
return saved;
}
}

View File

@ -0,0 +1,111 @@
package id.iptek.utms.agent.dao;
import id.iptek.utms.agent.db.DBConn;
import id.iptek.utms.agent.db.DBUtil;
import id.iptek.utms.agent.db.DatabaseException;
import id.iptek.utms.agent.model.Profile;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Jaka
*/
public class ProfileDao {
public Profile getProfileForTerminal(String terminalSN) throws DatabaseException {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
Profile profile = null;
try {
conn = DBConn.getInstance().getConnection();
pstmt = conn.prepareStatement(""
+ "select "
+ " terminal.sn, "
+ " profile.id profile_id,profile.\"name\",profile.heartbeat_interval,profile.diagnostic_interval, "
+ " profile.mask_home_button,profile.mask_status_bar,profile.schedule_reboot,profile.schedule_reboot_time, "
+ " profile.is_default,profile.relocation_alert,profile.moving_threshold,profile.admin_password,profile.front_app "
+ "from public.tms_terminal terminal "
+ " inner join public.tms_device_profile profile on terminal.profile_id=profile.id "
+ "where lower(terminal.sn)=? and terminal.delete_ts is null;");
pstmt.setString(1, terminalSN.toLowerCase());
rs = pstmt.executeQuery();
if (rs.next()) {
profile = new Profile();
profile.setTerminalSN(rs.getString(1));
profile.setId(rs.getString(2));
profile.setName(rs.getString(3));
profile.setHeartbeatInterval(rs.getInt(4));
profile.setDiagnosticInterval(rs.getInt(5));
profile.setMaskHomeButton(rs.getBoolean(6));
profile.setMaskStatusButton(rs.getBoolean(7));
profile.setScheduleReboot(rs.getBoolean(8));
profile.setScheduleRebootTime(rs.getTimestamp(9));
profile.setDefault(rs.getBoolean(10));
profile.setRelocationAlert(rs.getBoolean(11));
profile.setMovingThreshold(rs.getInt(12));
profile.setAdminPassword(rs.getString(13));
profile.setFrontApp(rs.getString(14));
profile.setApps(getProfileApps(conn, profile.getId()));
profile.setGroupIds(getTerminalGroupIds(conn, terminalSN));
}
} catch (SQLException ex) {
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn, pstmt, rs);
}
return profile;
}
public List<String> getProfileApps(Connection conn, String profileId) throws SQLException {
PreparedStatement pstmt = null;
ResultSet rs = null;
List<String> apps = new ArrayList<>();
try {
pstmt = conn.prepareStatement(""
+ "select "
+ " app.package_name "
+ "from public.tms_device_profile_app app "
+ "where app.profile_id=?::uuid");
pstmt.setString(1, profileId);
rs = pstmt.executeQuery();
while (rs.next()) {
String packageName = rs.getString(1);
apps.add(packageName);
}
} finally {
DBUtil.close(null, pstmt, rs);
}
return apps;
}
public List<String> getTerminalGroupIds(Connection conn, String terminalSN) throws SQLException {
PreparedStatement pstmt = null;
ResultSet rs = null;
List<String> apps = new ArrayList<>();
try {
pstmt = conn.prepareStatement(""
+ "select ttg.id group_id "
+ "from tms_terminal_group ttg "
+ " inner join tms_terminal_group_link ttgl on ttgl.terminal_group_id = ttg.id "
+ " inner join tms_terminal tt on ttgl.terminal_id = tt.id and tt.delete_ts is null "
+ "where lower(tt.sn) = ?");
pstmt.setString(1, terminalSN.toLowerCase());
rs = pstmt.executeQuery();
while (rs.next()) {
String groupId = rs.getString(1);
apps.add(groupId);
}
} finally {
DBUtil.close(null, pstmt, rs);
}
return apps;
}
}

View File

@ -0,0 +1,74 @@
package id.iptek.utms.agent.dao;
import id.iptek.utms.agent.db.DBConn;
import id.iptek.utms.agent.db.DBUtil;
import id.iptek.utms.agent.db.DatabaseException;
import id.iptek.utms.agent.model.TerminalIdObj;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Jaka
*/
public class TerminalDao {
public TerminalDao() {
}
public List<TerminalIdObj> getTerminalIds() throws DatabaseException {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<TerminalIdObj> list = new ArrayList<>();
try {
conn = DBConn.getInstance().getConnection();
pstmt = conn.prepareStatement(""
+ "select id, sn "
+ "from tms_terminal "
+ "where delete_ts is null");
rs = pstmt.executeQuery();
while (rs.next()) {
String terminalId = rs.getString(1);
String sn = rs.getString(2);
list.add(new TerminalIdObj(sn, terminalId));
}
} catch(SQLException ex) {
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn, pstmt, rs);
}
return list;
}
public TerminalIdObj getTerminalIdBySN(String sn) throws DatabaseException {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
TerminalIdObj terminalIdObj = null;
try {
conn = DBConn.getInstance().getConnection();
pstmt = conn.prepareStatement(""
+ "select id, sn "
+ "from tms_terminal "
+ "where lower(sn)=? and delete_ts is null");
pstmt.setString(1, sn.toLowerCase());
rs = pstmt.executeQuery();
if (rs.next()) {
String terminalId = rs.getString(1);
String _sn = rs.getString(2);
terminalIdObj = new TerminalIdObj(_sn, terminalId);
}
} catch(SQLException ex) {
throw new DatabaseException(ex);
} finally {
DBUtil.close(conn, pstmt, rs);
}
return terminalIdObj;
}
}

View File

@ -0,0 +1,69 @@
package id.iptek.utms.agent.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Jaka Ramdani
*/
public class DBConn {
private static Logger logger = LoggerFactory.getLogger(DBConn.class);
private boolean isUseDatasource;
private String datasource;
private String driver;
private String url;
private String username;
private String password;
private static DBConn self;
private DBConn() {
}
public void init(String datasource) throws Exception {
this.datasource = datasource;
logger.debug("Using Data Source: {}", this.datasource);
this.isUseDatasource = true;
}
public void init(String driver, String url, String username, String password) throws Exception {
this.driver = driver;
this.url = url;
this.username = username;
this.password = password;
//load driver
logger.debug("Load JDBC driver: {}", this.driver);
Class.forName(this.driver);
}
public Connection getConnection() throws SQLException {
if(!isUseDatasource) {
return DriverManager.getConnection(url, username, password);
} else {
try {
InitialContext initialContext = new InitialContext();
DataSource dataSource = (DataSource) initialContext.lookup(this.datasource);
return dataSource.getConnection();
} catch(NamingException ex) {
throw new SQLException("Naming Exception when getting connection from datasource: {}", this.datasource, ex);
}
}
}
public static DBConn getInstance() {
if (self == null) {
self = new DBConn();
}
return self;
}
}

View File

@ -0,0 +1,96 @@
package id.iptek.utms.agent.db;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DBUtil {
public DBUtil() {
}
public static void rollback(Connection conn) {
if (conn != null) {
try {
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
public static void close(Connection conn, Statement st) {
close(st);
close(conn);
}
public static void close(Connection conn, PreparedStatement pstmt) {
close(pstmt);
close(conn);
}
public static void close(Connection conn, Statement st, ResultSet rs) {
close(rs);
close(st);
close(conn);
}
public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {
close(rs);
close(pstmt);
close(conn);
}
public static void close(Connection conn, CallableStatement cstmt, ResultSet rs) {
close(rs);
close(cstmt);
close(conn);
}
public static void close(Connection conn) {
try {
if (conn != null) {
conn.close();
conn = null;
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
public static void close(PreparedStatement pstmt) {
try {
if (pstmt != null) {
pstmt.close();
pstmt = null;
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
public static void close(Statement st) {
try {
if (st != null) {
st.close();
st = null;
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
public static void close(ResultSet rs) {
try {
if (rs != null) {
rs.close();
rs = null;
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}

View File

@ -0,0 +1,16 @@
package id.iptek.utms.agent.db;
public class DatabaseException extends RuntimeException {
public DatabaseException(String message) {
super(message);
}
public DatabaseException(Throwable th) {
super(th);
}
public DatabaseException(String message, Throwable th) {
super(message, th);
}
}

View File

@ -0,0 +1,210 @@
package id.iptek.utms.agent.model;
import java.util.Date;
public class Application {
protected String id;
protected String appName;
protected String packageName;
protected String version;
protected String companyName;
protected boolean uninstallable;
protected String description;
protected String apkId;
protected String fileId;
protected String fileExt;
protected Date fileCreateDate;
protected String checksum;
public Application() {
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the appName
*/
public String getAppName() {
return appName;
}
/**
* @param appName the appName to set
*/
public void setAppName(String appName) {
this.appName = appName;
}
/**
* @return the packageName
*/
public String getPackageName() {
return packageName;
}
/**
* @param packageName the packageName to set
*/
public void setPackageName(String packageName) {
this.packageName = packageName;
}
/**
* @return the version
*/
public String getVersion() {
return version;
}
/**
* @param version the version to set
*/
public void setVersion(String version) {
this.version = version;
}
/**
* @return the companyName
*/
public String getCompanyName() {
return companyName;
}
/**
* @param companyName the companyName to set
*/
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
/**
* @return the uninstallable
*/
public boolean isUninstallable() {
return uninstallable;
}
/**
* @param uninstallable the uninstallable to set
*/
public void setUninstallable(boolean uninstallable) {
this.uninstallable = uninstallable;
}
/**
* @return the description
*/
public String getDescription() {
return description;
}
/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @return the apkId
*/
public String getApkId() {
return apkId;
}
/**
* @param apkId the apkId to set
*/
public void setApkId(String apkId) {
this.apkId = apkId;
}
/**
* @return the fileId
*/
public String getFileId() {
return fileId;
}
/**
* @param fileId the fileId to set
*/
public void setFileId(String fileId) {
this.fileId = fileId;
}
/**
* @return the fileExt
*/
public String getFileExt() {
return fileExt;
}
/**
* @param fileExt the fileExt to set
*/
public void setFileExt(String fileExt) {
this.fileExt = fileExt;
}
/**
* @return the fileCreateDate
*/
public Date getFileCreateDate() {
return fileCreateDate;
}
/**
* @param fileCreateDate the fileCreateDate to set
*/
public void setFileCreateDate(Date fileCreateDate) {
this.fileCreateDate = fileCreateDate;
}
/**
* @return the checksum
*/
public String getChecksum() {
return checksum;
}
/**
* @param checksum the checksum to set
*/
public void setChecksum(String checksum) {
this.checksum = checksum;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Application{");
sb.append("id=").append(id);
sb.append(", appName=").append(appName);
sb.append(", packageName=").append(packageName);
sb.append(", version=").append(version);
sb.append(", companyName=").append(companyName);
sb.append(", uninstallable=").append(uninstallable);
sb.append(", description=").append(description);
sb.append(", apkId=").append(apkId);
sb.append(", fileId=").append(fileId);
sb.append(", fileExt=").append(fileExt);
sb.append(", fileCreateDate=").append(fileCreateDate);
sb.append(", checksum=").append(checksum);
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,146 @@
package id.iptek.utms.agent.model;
import java.util.Date;
/**
*
* @author jakar
*/
public class ApplicationExt extends Application {
private String uniqueName;
private String downloadUrl;
private Date downloadUrlExp;
private long fileSize;
private String uniqueIconName;
private String iconUrl;
private Date iconUrlExp;
/**
* @return the uniqueName
*/
public String getUniqueName() {
return uniqueName;
}
/**
* @param uniqueName the uniqueName to set
*/
public void setUniqueName(String uniqueName) {
this.uniqueName = uniqueName;
}
/**
* @return the downloadUrl
*/
public String getDownloadUrl() {
return downloadUrl;
}
/**
* @param downloadUrl the downloadUrl to set
*/
public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
/**
* @return the downloadUrlExp
*/
public Date getDownloadUrlExp() {
return downloadUrlExp;
}
/**
* @param downloadUrlExp the downloadUrlExp to set
*/
public void setDownloadUrlExp(Date downloadUrlExp) {
this.downloadUrlExp = downloadUrlExp;
}
/**
* @return the fileSize
*/
public long getFileSize() {
return fileSize;
}
/**
* @param fileSize the fileSize to set
*/
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
/**
* @return the uniqueIconName
*/
public String getUniqueIconName() {
return uniqueIconName;
}
/**
* @param uniqueIconName the uniqueIconName to set
*/
public void setUniqueIconName(String uniqueIconName) {
this.uniqueIconName = uniqueIconName;
}
/**
* @return the iconUrl
*/
public String getIconUrl() {
return iconUrl;
}
/**
* @param iconUrl the iconUrl to set
*/
public void setIconUrl(String iconUrl) {
this.iconUrl = iconUrl;
}
/**
* @return the iconUrlExp
*/
public Date getIconUrlExp() {
return iconUrlExp;
}
/**
* @param iconUrlExp the iconUrlExp to set
*/
public void setIconUrlExp(Date iconUrlExp) {
this.iconUrlExp = iconUrlExp;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ApplicationExt{");
sb.append("id=").append(id);
sb.append(", appName=").append(appName);
sb.append(", packageName=").append(packageName);
sb.append(", version=").append(version);
sb.append(", companyName=").append(companyName);
sb.append(", uninstallable=").append(uninstallable);
sb.append(", description=").append(description);
sb.append(", apkId=").append(apkId);
sb.append(", fileId=").append(fileId);
sb.append(", fileExt=").append(fileExt);
sb.append(", fileCreateDate=").append(fileCreateDate);
sb.append(", checksum=").append(checksum);
sb.append(", uniqueName=").append(uniqueName);
sb.append(", downloadUrl=").append(downloadUrl);
sb.append(", downloadUrlExp=").append(downloadUrlExp);
sb.append(", fileSize=").append(fileSize);
sb.append(", uniqueIconName=").append(uniqueIconName);
sb.append(", iconUrl=").append(iconUrl);
sb.append(", iconUrlExp=").append(iconUrlExp);
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,53 @@
package id.iptek.utms.agent.model;
import javax.annotation.Generated;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
@Generated("jsonschema2pojo")
public class ApplicationSimple {
private String id;
@SerializedName("app_name")
@Expose
private String appName;
@SerializedName("package_name")
@Expose
private String packageName;
@SerializedName("version")
@Expose
private String version;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}

View File

@ -0,0 +1,55 @@
package id.iptek.utms.agent.model;
import javax.annotation.Generated;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
@Generated("jsonschema2pojo")
public class CellInfo {
@SerializedName("name")
@Expose
private String name;
@SerializedName("cid")
@Expose
private String cid;
@SerializedName("type")
@Expose
private String type;
@SerializedName("strength")
@Expose
private Integer strength;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Integer getStrength() {
return strength;
}
public void setStrength(Integer strength) {
this.strength = strength;
}
}

View File

@ -0,0 +1,140 @@
package id.iptek.utms.agent.model;
import java.util.List;
import javax.annotation.Generated;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.Date;
@Generated("jsonschema2pojo")
public class Diagnostic {
private String id;
@SerializedName("req_id")
@Expose
private String reqId;
@SerializedName("req_type")
@Expose
private String reqType;
@SerializedName("req_time")
@Expose
private String reqTime;
@SerializedName("device_sn")
@Expose
private String deviceSn;
@SerializedName("diagnostic_info")
@Expose
private DiagnosticInfo diagnosticInfo;
@SerializedName("location_info")
@Expose
private LocationInfo locationInfo;
@SerializedName("cell_info")
@Expose
private List<CellInfo> cellInfo;
@SerializedName("installed_apps")
@Expose
private List<ApplicationSimple> installedApps = null;
private Date createTime;
private String terminalId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getReqId() {
return reqId;
}
public void setReqId(String reqId) {
this.reqId = reqId;
}
public String getReqType() {
return reqType;
}
public void setReqType(String reqType) {
this.reqType = reqType;
}
public String getReqTime() {
return reqTime;
}
public void setReqTime(String reqTime) {
this.reqTime = reqTime;
}
public String getDeviceSn() {
return deviceSn;
}
public void setDeviceSn(String deviceSn) {
this.deviceSn = deviceSn;
}
public DiagnosticInfo getDiagnosticInfo() {
return diagnosticInfo;
}
public void setDiagnosticInfo(DiagnosticInfo diagnosticInfo) {
this.diagnosticInfo = diagnosticInfo;
}
public LocationInfo getLocationInfo() {
return locationInfo;
}
public void setLocationInfo(LocationInfo locationInfo) {
this.locationInfo = locationInfo;
}
public List<CellInfo> getCellInfo() {
return cellInfo;
}
public void setCellInfo(List<CellInfo> cellInfo) {
this.cellInfo = cellInfo;
}
public List<ApplicationSimple> getInstalledApps() {
return installedApps;
}
public void setInstalledApps(List<ApplicationSimple> installedApps) {
this.installedApps = installedApps;
}
/**
* @return the createTime
*/
public Date getCreateTime() {
return createTime;
}
/**
* @param createTime the createTime to set
*/
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* @return the terminalId
*/
public String getTerminalId() {
return terminalId;
}
/**
* @param terminalId the terminalId to set
*/
public void setTerminalId(String terminalId) {
this.terminalId = terminalId;
}
}

View File

@ -0,0 +1,246 @@
package id.iptek.utms.agent.model;
import javax.annotation.Generated;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
@Generated("jsonschema2pojo")
public class DiagnosticInfo {
@SerializedName("imei")
@Expose
private String imei;
@SerializedName("meid")
@Expose
private String meid;
@SerializedName("battery_temp")
@Expose
private double batteryTemp;
@SerializedName("battery_percentage")
@Expose
private double batteryPercentage;
@SerializedName("total_memory")
@Expose
private String totalMemory;
@SerializedName("available_memory")
@Expose
private String availableMemory;
@SerializedName("total_flash_memory")
@Expose
private String totalFlashMemory;
@SerializedName("available_flash_memory")
@Expose
private String availableFlashMemory;
@SerializedName("total_mobile_data")
@Expose
private String totalMobileData;
@SerializedName("switching_times")
@Expose
private int switchingTimes;
@SerializedName("current_boot_time")
@Expose
private int currentBootTime;
@SerializedName("total_boot_time")
@Expose
private int totalBootTime;
@SerializedName("total_length_printed")
@Expose
private double totalLengthPrinted;
@SerializedName("swiping_card_times")
@Expose
private int swipingCardTimes;
@SerializedName("dip_inserting_times")
@Expose
private int dipInsertingTimes;
@SerializedName("nfc_card_reading_times")
@Expose
private int nfcCardReadingTimes;
@SerializedName("front_camera_open_times")
@Expose
private int frontCameraOpenTimes;
@SerializedName("rear_camera_open_times")
@Expose
private int rearCameraOpenTimes;
@SerializedName("charge_times")
@Expose
private int chargeTimes;
@SerializedName("new_diagnostic")
@Expose
private Boolean newDiagnostic;
private String installedAppString;
public String getImei() {
return imei;
}
public void setImei(String imei) {
this.imei = imei;
}
public String getMeid() {
return meid;
}
public void setMeid(String meid) {
this.meid = meid;
}
public double getBatteryTemp() {
return batteryTemp;
}
public void setBatteryTemp(double batteryTemp) {
this.batteryTemp = batteryTemp;
}
public double getBatteryPercentage() {
return batteryPercentage;
}
public void setBatteryPercentage(double batteryPercentage) {
this.batteryPercentage = batteryPercentage;
}
public String getTotalMemory() {
return totalMemory;
}
public void setTotalMemory(String totalMemory) {
this.totalMemory = totalMemory;
}
public String getAvailableMemory() {
return availableMemory;
}
public void setAvailableMemory(String availableMemory) {
this.availableMemory = availableMemory;
}
public String getTotalFlashMemory() {
return totalFlashMemory;
}
public void setTotalFlashMemory(String totalFlashMemory) {
this.totalFlashMemory = totalFlashMemory;
}
public String getAvailableFlashMemory() {
return availableFlashMemory;
}
public void setAvailableFlashMemory(String availableFlashMemory) {
this.availableFlashMemory = availableFlashMemory;
}
public String getTotalMobileData() {
return totalMobileData;
}
public void setTotalMobileData(String totalMobileData) {
this.totalMobileData = totalMobileData;
}
public int getSwitchingTimes() {
return switchingTimes;
}
public void setSwitchingTimes(int switchingTimes) {
this.switchingTimes = switchingTimes;
}
public int getCurrentBootTime() {
return currentBootTime;
}
public void setCurrentBootTime(int currentBootTime) {
this.currentBootTime = currentBootTime;
}
public int getTotalBootTime() {
return totalBootTime;
}
public void setTotalBootTime(int totalBootTime) {
this.totalBootTime = totalBootTime;
}
public double getTotalLengthPrinted() {
return totalLengthPrinted;
}
public void setTotalLengthPrinted(double totalLengthPrinted) {
this.totalLengthPrinted = totalLengthPrinted;
}
public int getSwipingCardTimes() {
return swipingCardTimes;
}
public void setSwipingCardTimes(int swipingCardTimes) {
this.swipingCardTimes = swipingCardTimes;
}
public int getDipInsertingTimes() {
return dipInsertingTimes;
}
public void setDipInsertingTimes(int dipInsertingTimes) {
this.dipInsertingTimes = dipInsertingTimes;
}
public int getNfcCardReadingTimes() {
return nfcCardReadingTimes;
}
public void setNfcCardReadingTimes(int nfcCardReadingTimes) {
this.nfcCardReadingTimes = nfcCardReadingTimes;
}
public int getFrontCameraOpenTimes() {
return frontCameraOpenTimes;
}
public void setFrontCameraOpenTimes(int frontCameraOpenTimes) {
this.frontCameraOpenTimes = frontCameraOpenTimes;
}
public int getRearCameraOpenTimes() {
return rearCameraOpenTimes;
}
public void setRearCameraOpenTimes(int rearCameraOpenTimes) {
this.rearCameraOpenTimes = rearCameraOpenTimes;
}
public int getChargeTimes() {
return chargeTimes;
}
public void setChargeTimes(int chargeTimes) {
this.chargeTimes = chargeTimes;
}
public Boolean getNewDiagnostic() {
return newDiagnostic;
}
public void setNewDiagnostic(Boolean newDiagnostic) {
this.newDiagnostic = newDiagnostic;
}
/**
* @return the installedAppString
*/
public String getInstalledAppString() {
return installedAppString;
}
/**
* @param installedAppString the installedAppString to set
*/
public void setInstalledAppString(String installedAppString) {
this.installedAppString = installedAppString;
}
}

View File

@ -0,0 +1,176 @@
package id.iptek.utms.agent.model;
import id.iptek.utms.agent.model.enumeration.DownloadTimeType;
import id.iptek.utms.agent.model.enumeration.InstallationNotificationType;
import id.iptek.utms.agent.model.enumeration.InstallationTimeType;
import id.iptek.utms.agent.model.enumeration.PublishTimeType;
import id.iptek.utms.agent.model.enumeration.TaskStatus;
import java.io.Serializable;
import java.util.Date;
/**
*
* @author Jaka
*/
public class DownloadTask implements Serializable {
private String id;
private String name;
private PublishTimeType publishTimeType;
private Date publishTime;
private DownloadTimeType downloadTimeType;
private Date downloadTime;
private InstallationTimeType installationTimeType;
private Date installationTime;
private InstallationNotificationType installationNotification;
private TaskStatus status;
public DownloadTask() {
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the publishTimeType
*/
public PublishTimeType getPublishTimeType() {
return publishTimeType;
}
/**
* @param publishTimeType the publishTimeType to set
*/
public void setPublishTimeType(int publishTimeType) {
this.publishTimeType = PublishTimeType.fromValue(publishTimeType);
}
/**
* @return the publishTime
*/
public Date getPublishTime() {
return publishTime;
}
/**
* @param publishTime the publishTime to set
*/
public void setPublishTime(Date publishTime) {
this.publishTime = publishTime;
}
/**
* @return the downloadTimeType
*/
public DownloadTimeType getDownloadTimeType() {
return downloadTimeType;
}
/**
* @param downloadTimeType the downloadTimeType to set
*/
public void setDownloadTimeType(int downloadTimeType) {
this.downloadTimeType = DownloadTimeType.fromValue(downloadTimeType);
}
/**
* @return the downloadTime
*/
public Date getDownloadTime() {
return downloadTime;
}
/**
* @param downloadTime the downloadTime to set
*/
public void setDownloadTime(Date downloadTime) {
this.downloadTime = downloadTime;
}
/**
* @return the installationTimeType
*/
public InstallationTimeType getInstallationTimeType() {
return installationTimeType;
}
/**
* @param installationTimeType the installationTimeType to set
*/
public void setInstallationTimeType(int installationTimeType) {
this.installationTimeType = InstallationTimeType.fromValue(installationTimeType);
}
/**
* @return the installationTime
*/
public Date getInstallationTime() {
return installationTime;
}
/**
* @param installationTime the installationTime to set
*/
public void setInstallationTime(Date installationTime) {
this.installationTime = installationTime;
}
/**
* @return the installationNotification
*/
public InstallationNotificationType getInstallationNotification() {
return installationNotification;
}
/**
* @param installationNotification the installationNotification to set
*/
public void setInstallationNotification(int installationNotification) {
this.installationNotification = InstallationNotificationType.fromValue(installationNotification);
}
/**
* @return the status
*/
public TaskStatus getStatus() {
return status;
}
/**
* @param status the status to set
*/
public void setStatus(int status) {
this.status = TaskStatus.fromValue(status);
}
@Override
public String toString() {
return "DownloadTask{" + "id=" + id + ", name=" + name + ", publishTimeType=" + publishTimeType + ", publishTime=" + publishTime + ", downloadTimeType=" + downloadTimeType + ", downloadTime=" + downloadTime + ", installationTimeType=" + installationTimeType + ", installationTime=" + installationTime + ", installationNotification=" + installationNotification + ", status=" + status + '}';
}
}

View File

@ -0,0 +1,75 @@
package id.iptek.utms.agent.model;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* @author jakar
*/
public class FileReaderCacheObj implements Serializable {
private File file;
private BufferedReader reader;
private final AtomicInteger currentReadRowNum = new AtomicInteger(0);
public FileReaderCacheObj() {
}
/**
* @return the file
*/
public File getFile() {
return file;
}
/**
* @param file the file to set
*/
public void setFile(File file) {
this.file = file;
}
/**
* @return the reader
*/
public BufferedReader getReader() {
return reader;
}
/**
* @return the currentReadRowNum
*/
public AtomicInteger getCurrentReadRowNum() {
return currentReadRowNum;
}
public void pointToFile(File file) throws IOException {
if(file == null) {
throw new IllegalArgumentException("File cannot be null!");
}
if(!file.exists()) {
throw new IOException("File not exists!");
}
if(!file.canRead()) {
throw new IOException("File not readable!");
}
this.file = file;
this.reader = new BufferedReader(new FileReader(this.file));
this.currentReadRowNum.set(0);
}
public void closeReader() throws IOException {
if(this.reader != null) {
this.reader.close();
this.file = null;
this.currentReadRowNum.set(0);
} else {
// ignore null reader
}
}
}

View File

@ -0,0 +1,118 @@
package id.iptek.utms.agent.model;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* @author jakar
*/
public class FileWriterCacheObj implements Serializable {
private File file;
private BufferedWriter writer;
private final AtomicInteger currentWriteRowNum = new AtomicInteger(0);
private final Object lock = new Object();
public FileWriterCacheObj() {
}
/**
* @return the file
*/
public File getFile() {
return file;
}
/**
* @param file the file to set
*/
public void setFile(File file) {
this.file = file;
}
/**
* @return the reader
*/
public BufferedWriter getWriter() {
return writer;
}
/**
* @return the currentReadRowNum
*/
public AtomicInteger getCurrentWriteRowNum() {
return currentWriteRowNum;
}
public void pointToFile(File file) throws IOException {
if(file == null) {
throw new IllegalArgumentException("File cannot be null!");
}
/*
if(file.exists()) {
throw new IOException("File exists!");
}
if(!file.canWrite()) {
throw new IOException("File not writable!");
}*/
// close old writer
synchronized (lock) {
if(this.writer != null) {
this.writer.flush();
try {
this.writer.close();
} catch(IOException ignore) {}
this.writer = null;
}
this.file = file;
this.writer = new BufferedWriter(new FileWriter(this.file));
this.currentWriteRowNum.set(0);
}
}
public void closeWriter() throws IOException {
if(this.writer != null) {
synchronized (lock) {
this.writer.close();
this.file = null;
this.currentWriteRowNum.set(0);
}
} else {
// ignore null reader
}
}
public BufferedWriter writeLine(String line) throws IOException {
if(this.writer == null) {
throw new IOException("Writer cannot be null!");
}
synchronized (lock) {
this.writer.write(line);
this.writer.newLine();
this.writer.flush();
}
this.currentWriteRowNum.incrementAndGet();
return this.writer;
}
public boolean writeLineWithMaxLineNo(int maxLineNo, String line) throws IOException {
if(this.writer == null) {
throw new IOException("Writer cannot be null!");
}
if(this.currentWriteRowNum.get() < maxLineNo) {
synchronized (lock) {
this.writer.write(line);
this.writer.newLine();
this.writer.flush();
}
this.currentWriteRowNum.incrementAndGet();
return true;
}
return false;
}
}

View File

@ -0,0 +1,200 @@
package id.iptek.utms.agent.model;
import javax.annotation.Generated;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.io.File;
import java.util.Date;
import java.util.List;
@Generated("jsonschema2pojo")
public class HeartBeat {
private String id;
@SerializedName("req_id")
@Expose
private String reqId;
@SerializedName("req_type")
@Expose
private String reqType;
@SerializedName("req_time")
@Expose
private String reqTime;
@SerializedName("device_sn")
@Expose
private String deviceSn;
@SerializedName("diagnostic_info")
@Expose
private DiagnosticInfo diagnosticInfo;
@SerializedName("location_info")
@Expose
private LocationInfo locationInfo;
@SerializedName("cell_info")
@Expose
private List<CellInfo> cellInfo;
private File fileLocation;
private Date createTime;
private String terminalId;
private String cellInfoString;
@Expose
@SerializedName("cell_type")
private String cellType;
@Expose
@SerializedName("cell_name")
private String cellName;
@Expose
@SerializedName("cell_strength")
private Integer cellStrength;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getReqId() {
return reqId;
}
public void setReqId(String reqId) {
this.reqId = reqId;
}
public String getReqType() {
return reqType;
}
public void setReqType(String reqType) {
this.reqType = reqType;
}
public String getReqTime() {
return reqTime;
}
public void setReqTime(String reqTime) {
this.reqTime = reqTime;
}
public String getDeviceSn() {
return deviceSn;
}
public void setDeviceSn(String deviceSn) {
this.deviceSn = deviceSn;
}
public DiagnosticInfo getDiagnosticInfo() {
return diagnosticInfo;
}
public void setDiagnosticInfo(DiagnosticInfo diagnosticInfo) {
this.diagnosticInfo = diagnosticInfo;
}
public LocationInfo getLocationInfo() {
return locationInfo;
}
public void setLocationInfo(LocationInfo locationInfo) {
this.locationInfo = locationInfo;
}
public List<CellInfo> getCellInfo() {
return cellInfo;
}
public void setCellInfo(List<CellInfo> cellInfo) {
this.cellInfo = cellInfo;
}
public File getFileLocation() {
return fileLocation;
}
public void setFileLocation(File fileLocation) {
this.fileLocation = fileLocation;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
* @return the terminalId
*/
public String getTerminalId() {
return terminalId;
}
/**
* @param terminalId the terminalId to set
*/
public void setTerminalId(String terminalId) {
this.terminalId = terminalId;
}
/**
* @return the cellInfoString
*/
public String getCellInfoString() {
return cellInfoString;
}
/**
* @param cellInfoString the cellInfoString to set
*/
public void setCellInfoString(String cellInfoString) {
this.cellInfoString = cellInfoString;
}
/**
* @return the cellType
*/
public String getCellType() {
return cellType;
}
/**
* @param cellType the cellType to set
*/
public void setCellType(String cellType) {
this.cellType = cellType;
}
/**
* @return the cellName
*/
public String getCellName() {
return cellName;
}
/**
* @param cellName the cellName to set
*/
public void setCellName(String cellName) {
this.cellName = cellName;
}
/**
* @return the cellStrength
*/
public Integer getCellStrength() {
return cellStrength;
}
/**
* @param cellStrength the cellStrength to set
*/
public void setCellStrength(Integer cellStrength) {
this.cellStrength = cellStrength;
}
}

View File

@ -0,0 +1,34 @@
package id.iptek.utms.agent.model;
import javax.annotation.Generated;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
@Generated("jsonschema2pojo")
public class LocationInfo {
@SerializedName("lat")
@Expose
private Double lat;
@SerializedName("lng")
@Expose
private Double lng;
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
public Double getLng() {
return lng;
}
public void setLng(Double lng) {
this.lng = lng;
}
}

View File

@ -0,0 +1,130 @@
package id.iptek.utms.agent.model;
import java.io.Serializable;
import java.util.Date;
/**
*
* @author Jaka
*/
public class PendingDeleteTask implements Serializable {
private String terminalSN;
private String id;
private String name;
private Date deleteTime;
private Date lastBroadcastTs;
private ApplicationSimple app;
private int activity;
private String logId;
public PendingDeleteTask() {
}
/**
* @return the terminalSN
*/
public String getTerminalSN() {
return terminalSN;
}
/**
* @param terminalSN the terminalSN to set
*/
public void setTerminalSN(String terminalSN) {
this.terminalSN = terminalSN;
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the deleteTime
*/
public Date getDeleteTime() {
return deleteTime;
}
/**
* @param deleteTime the deleteTime to set
*/
public void setDeleteTime(Date deleteTime) {
this.deleteTime = deleteTime;
}
/**
* @return the lastBroadcastTs
*/
public Date getLastBroadcastTs() {
return lastBroadcastTs;
}
/**
* @param lastBroadcastTs the lastBroadcastTs to set
*/
public void setLastBroadcastTs(Date lastBroadcastTs) {
this.lastBroadcastTs = lastBroadcastTs;
}
/**
* @return the app
*/
public ApplicationSimple getApp() {
return app;
}
/**
* @param app the app to set
*/
public void setApp(ApplicationSimple app) {
this.app = app;
}
/**
* @return the activity
*/
public int getActivity() {
return activity;
}
/**
* @param activity the activity to set
*/
public void setActivity(int activity) {
this.activity = activity;
}
public String getLogId() {
return logId;
}
public void setLogId(String logId) {
this.logId = logId;
}
}

View File

@ -0,0 +1,234 @@
package id.iptek.utms.agent.model;
import java.io.Serializable;
import java.util.Date;
/**
*
* @author Jaka
*/
public class PendingDownloadTask implements Serializable {
private String terminalSN;
private String terminalGroupId;
private String id;
private String name;
private int downloadTimeType;
private Date downloadTime;
private int installationTimeType;
private Date installationTime;
private int installationNotification;
private Date lastBroadcastTs;
private int activity;
private String logId;
private Application app;
public PendingDownloadTask() {
}
/**
* @return the terminalSN
*/
public String getTerminalSN() {
return terminalSN;
}
/**
* @param terminalSN the terminalSN to set
*/
public void setTerminalSN(String terminalSN) {
this.terminalSN = terminalSN;
}
/**
* @return the terminalGroupId
*/
public String getTerminalGroupId() {
return terminalGroupId;
}
/**
* @param terminalGroupId the terminalGroupId to set
*/
public void setTerminalGroupId(String terminalGroupId) {
this.terminalGroupId = terminalGroupId;
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the downloadTimeType
*/
public int getDownloadTimeType() {
return downloadTimeType;
}
/**
* @param downloadTimeType the downloadTimeType to set
*/
public void setDownloadTimeType(int downloadTimeType) {
this.downloadTimeType = downloadTimeType;
}
/**
* @return the downloadTime
*/
public Date getDownloadTime() {
return downloadTime;
}
/**
* @param downloadTime the downloadTime to set
*/
public void setDownloadTime(Date downloadTime) {
this.downloadTime = downloadTime;
}
/**
* @return the installationTimeType
*/
public int getInstallationTimeType() {
return installationTimeType;
}
/**
* @param installationTimeType the installationTimeType to set
*/
public void setInstallationTimeType(int installationTimeType) {
this.installationTimeType = installationTimeType;
}
/**
* @return the installationTime
*/
public Date getInstallationTime() {
return installationTime;
}
/**
* @param installationTime the installationTime to set
*/
public void setInstallationTime(Date installationTime) {
this.installationTime = installationTime;
}
/**
* @return the installationNotification
*/
public int getInstallationNotification() {
return installationNotification;
}
/**
* @param installationNotification the installationNotification to set
*/
public void setInstallationNotification(int installationNotification) {
this.installationNotification = installationNotification;
}
/**
* @return the lastBroadcastTs
*/
public Date getLastBroadcastTs() {
return lastBroadcastTs;
}
/**
* @param lastBroadcastTs the lastBroadcastTs to set
*/
public void setLastBroadcastTs(Date lastBroadcastTs) {
this.lastBroadcastTs = lastBroadcastTs;
}
/**
* @return the activity
*/
public int getActivity() {
return activity;
}
/**
* @param activity the activity to set
*/
public void setActivity(int activity) {
this.activity = activity;
}
/**
* @return the logId
*/
public String getLogId() {
return logId;
}
/**
* @param logId the logId to set
*/
public void setLogId(String logId) {
this.logId = logId;
}
/**
* @return the app
*/
public Application getApp() {
return app;
}
/**
* @param app the app to set
*/
public void setApp(Application app) {
this.app = app;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("PendingDownloadTask{");
sb.append("terminalSN=").append(terminalSN);
sb.append(", terminalGroupId=").append(terminalGroupId);
sb.append(", id=").append(id);
sb.append(", name=").append(name);
sb.append(", downloadTimeType=").append(downloadTimeType);
sb.append(", downloadTime=").append(downloadTime);
sb.append(", installationTimeType=").append(installationTimeType);
sb.append(", installationTime=").append(installationTime);
sb.append(", installationNotification=").append(installationNotification);
sb.append(", lastBroadcastTs=").append(lastBroadcastTs);
sb.append(", activity=").append(activity);
sb.append(", logId=").append(logId);
sb.append(", app=").append(app);
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,257 @@
package id.iptek.utms.agent.model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
*
* @author Jaka
*/
public class Profile implements Serializable {
private String terminalSN;
private String id;
private String name;
private int heartbeatInterval;
private int diagnosticInterval;
private boolean maskHomeButton;
private boolean maskStatusButton;
private boolean scheduleReboot;
private Date scheduleRebootTime;
private boolean isDefault;
private boolean relocationAlert;
private int movingThreshold;
private String adminPassword;
private String frontApp;
private List<String> groupIds;
private List<String> apps;
/**
* @return the terminalSN
*/
public String getTerminalSN() {
return terminalSN;
}
/**
* @param terminalSN the terminalSN to set
*/
public void setTerminalSN(String terminalSN) {
this.terminalSN = terminalSN;
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the heartbeatInterval
*/
public int getHeartbeatInterval() {
return heartbeatInterval;
}
/**
* @param heartbeatInterval the heartbeatInterval to set
*/
public void setHeartbeatInterval(int heartbeatInterval) {
this.heartbeatInterval = heartbeatInterval;
}
/**
* @return the diagnosticInterval
*/
public int getDiagnosticInterval() {
return diagnosticInterval;
}
/**
* @param diagnosticInterval the diagnosticInterval to set
*/
public void setDiagnosticInterval(int diagnosticInterval) {
this.diagnosticInterval = diagnosticInterval;
}
/**
* @return the maskHomeButton
*/
public boolean isMaskHomeButton() {
return maskHomeButton;
}
/**
* @param maskHomeButton the maskHomeButton to set
*/
public void setMaskHomeButton(boolean maskHomeButton) {
this.maskHomeButton = maskHomeButton;
}
/**
* @return the maskStatusButton
*/
public boolean isMaskStatusButton() {
return maskStatusButton;
}
/**
* @param maskStatusButton the maskStatusButton to set
*/
public void setMaskStatusButton(boolean maskStatusButton) {
this.maskStatusButton = maskStatusButton;
}
/**
* @return the scheduleReboot
*/
public boolean isScheduleReboot() {
return scheduleReboot;
}
/**
* @param scheduleReboot the scheduleReboot to set
*/
public void setScheduleReboot(boolean scheduleReboot) {
this.scheduleReboot = scheduleReboot;
}
/**
* @return the scheduleRebootTime
*/
public Date getScheduleRebootTime() {
return scheduleRebootTime;
}
/**
* @param scheduleRebootTime the scheduleRebootTime to set
*/
public void setScheduleRebootTime(Date scheduleRebootTime) {
this.scheduleRebootTime = scheduleRebootTime;
}
/**
* @return the isDefault
*/
public boolean isDefault() {
return isDefault;
}
/**
* @param isDefault the isDefault to set
*/
public void setDefault(boolean isDefault) {
this.isDefault = isDefault;
}
/**
* @return the relocationAlert
*/
public boolean isRelocationAlert() {
return relocationAlert;
}
/**
* @param relocationAlert the relocationAlert to set
*/
public void setRelocationAlert(boolean relocationAlert) {
this.relocationAlert = relocationAlert;
}
/**
* @return the movingThreshold
*/
public int getMovingThreshold() {
return movingThreshold;
}
/**
* @param movingThreshold the movingThreshold to set
*/
public void setMovingThreshold(int movingThreshold) {
this.movingThreshold = movingThreshold;
}
/**
* @return the adminPassword
*/
public String getAdminPassword() {
return adminPassword;
}
/**
* @param adminPassword the adminPassword to set
*/
public void setAdminPassword(String adminPassword) {
this.adminPassword = adminPassword;
}
/**
* @return the frontApp
*/
public String getFrontApp() {
return frontApp;
}
/**
* @param frontApp the frontApp to set
*/
public void setFrontApp(String frontApp) {
this.frontApp = frontApp;
}
/**
* @return the apps
*/
public List<String> getApps() {
if(apps == null) {
apps = new ArrayList<>();
}
return apps;
}
/**
* @param apps the apps to set
*/
public void setApps(List<String> apps) {
this.apps = apps;
}
/**
* @return the groupIds
*/
public List<String> getGroupIds() {
return groupIds;
}
/**
* @param groupIds the groupIds to set
*/
public void setGroupIds(List<String> groupIds) {
this.groupIds = groupIds;
}
}

View File

@ -0,0 +1,61 @@
package id.iptek.utms.agent.model;
import java.io.Serializable;
import java.util.List;
/**
*
* @author Jaka
*/
public class SimplePendingDownloadTask implements Serializable {
private String id;
private String name;
private List<String> groupIds;
public SimplePendingDownloadTask() {
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the groupIds
*/
public List<String> getGroupIds() {
return groupIds;
}
/**
* @param groupIds the groupIds to set
*/
public void setGroupIds(List<String> groupIds) {
this.groupIds = groupIds;
}
}

View File

@ -0,0 +1,120 @@
package id.iptek.utms.agent.model;
import java.io.Serializable;
/**
*
* @author Jaka
*/
public class TaskAckReq implements Serializable {
private String reqId;
private String terminalSN;
private String ackId;
private String terminalId;
private int activity;
private String message;
private String taskId;
private String terminalGroupId;
private boolean broadcasted;
public TaskAckReq() {
}
/**
* @return the reqId
*/
public String getReqId() {
return reqId;
}
/**
* @param reqId the reqId to set
*/
public void setReqId(String reqId) {
this.reqId = reqId;
}
/**
* @return the terminalSN
*/
public String getTerminalSN() {
return terminalSN;
}
/**
* @param terminalSN the terminalSN to set
*/
public void setTerminalSN(String terminalSN) {
this.terminalSN = terminalSN;
}
/**
* @return the ackId
*/
public String getAckId() {
return ackId;
}
/**
* @param ackId the ackId to set
*/
public void setAckId(String ackId) {
this.ackId = ackId;
}
public String getTerminalId() {
return terminalId;
}
public void setTerminalId(String terminalId) {
this.terminalId = terminalId;
}
public String getTerminalGroupId() {
return terminalGroupId;
}
public void setTerminalGroupId(String terminalGroupId) {
this.terminalGroupId = terminalGroupId;
}
public int getActivity() {
return activity;
}
public void setActivity(int activity) {
this.activity = activity;
}
/**
* @return the message
*/
public String getMessage() {
return message;
}
/**
* @param message the message to set
*/
public void setMessage(String message) {
this.message = message;
}
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public boolean isBroadcasted() {
return broadcasted;
}
public void setBroadcasted(boolean broadcasted) {
this.broadcasted = broadcasted;
}
}

View File

@ -0,0 +1,80 @@
package id.iptek.utms.agent.model;
import java.io.Serializable;
import java.util.Objects;
/**
*
* @author jakar
*/
public class TerminalIdObj implements Serializable {
private String sn;
private String terminalId;
public TerminalIdObj() {
}
public TerminalIdObj(String sn, String terminalId) {
this.sn = sn;
this.terminalId = terminalId;
}
/**
* @return the sn
*/
public String getSn() {
return sn;
}
/**
* @param sn the sn to set
*/
public void setSn(String sn) {
this.sn = sn;
}
/**
* @return the terminalId
*/
public String getTerminalId() {
return terminalId;
}
/**
* @param terminalId the terminalId to set
*/
public void setTerminalId(String terminalId) {
this.terminalId = terminalId;
}
@Override
public int hashCode() {
int hash = 3;
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TerminalIdObj other = (TerminalIdObj) obj;
if (!Objects.equals(this.sn, other.sn)) {
return false;
}
return Objects.equals(this.terminalId, other.terminalId);
}
@Override
public String toString() {
return "TerminalIdObj{" + "sn=" + sn + ", terminalId=" + terminalId + '}';
}
}

View File

@ -0,0 +1,32 @@
package id.iptek.utms.agent.model.enumeration;
/**
*
* @author jakar
*/
public enum DownloadTimeType {
NEXT_CONTACT(1),
DATE_TIME(2);
private final int value;
private DownloadTimeType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static DownloadTimeType fromValue(int value) {
DownloadTimeType val = null;
for(DownloadTimeType _val : DownloadTimeType.values()) {
if(_val.getValue() == value) {
val = _val;
break;
}
}
return val;
}
}

View File

@ -0,0 +1,32 @@
package id.iptek.utms.agent.model.enumeration;
/**
*
* @author jakar
*/
public enum InstallationNotificationType {
SILENT(1),
NEED_CONFIRMATION(2);
private final int value;
private InstallationNotificationType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static InstallationNotificationType fromValue(int value) {
InstallationNotificationType val = null;
for(InstallationNotificationType _val : InstallationNotificationType.values()) {
if(_val.getValue() == value) {
val = _val;
break;
}
}
return val;
}
}

View File

@ -0,0 +1,32 @@
package id.iptek.utms.agent.model.enumeration;
/**
*
* @author jakar
*/
public enum InstallationTimeType {
IMMEDIATE_AFTER_DOWNLOAD(1),
DATE_TIME(2);
private final int value;
private InstallationTimeType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static InstallationTimeType fromValue(int value) {
InstallationTimeType val = null;
for(InstallationTimeType _val : InstallationTimeType.values()) {
if(_val.getValue() == value) {
val = _val;
break;
}
}
return val;
}
}

View File

@ -0,0 +1,32 @@
package id.iptek.utms.agent.model.enumeration;
/**
*
* @author jakar
*/
public enum PublishTimeType {
IMMEDIATE(1),
DATE_TIME(2);
private final int value;
private PublishTimeType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static PublishTimeType fromValue(int value) {
PublishTimeType val = null;
for(PublishTimeType _val : PublishTimeType.values()) {
if(_val.getValue() == value) {
val = _val;
break;
}
}
return val;
}
}

View File

@ -0,0 +1,40 @@
package id.iptek.utms.agent.model.enumeration;
/**
*
* @author jakar
*/
public enum TaskActivity {
INITIAL(0),
PUBLISHED(1),
ACCEPTED(2),
DOWNLOAD_STARTED(3),
DOWNLOAD_SUCCESS(4),
DOWNLOAD_FAIL(5),
INSTALL_STARTED(6),
INSTALL_SUCCESS(7),
INSTALL_FAIL(8),
EXPIRED(99);
private final int value;
private TaskActivity(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static TaskActivity fromValue(int value) {
TaskActivity val = null;
for(TaskActivity _val : TaskActivity.values()) {
if(_val.getValue() == value) {
val = _val;
break;
}
}
return val;
}
}

View File

@ -0,0 +1,36 @@
package id.iptek.utms.agent.model.enumeration;
/**
*
* @author jakar
*/
public enum TaskStatus {
INITIAL(0),
NOT_STARTED(1),
IN_PROGRESS(2),
CANCELLED(3),
DONE(4),
EXPIRED(99);
private final int value;
private TaskStatus(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static TaskStatus fromValue(int value) {
TaskStatus val = null;
for(TaskStatus _val : TaskStatus.values()) {
if(_val.getValue() == value) {
val = _val;
break;
}
}
return val;
}
}

View File

@ -0,0 +1,11 @@
package id.iptek.utms.agent.queue;
/**
*
* @author jakar
*/
public enum ConsumerMode {
SINGLE, BATCH;
}

View File

@ -0,0 +1,212 @@
package id.iptek.utms.agent.queue;
import id.iptek.utms.agent.db.DatabaseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author jakar
* @param <T>
*/
public class DelayMessageQueue<T> {
private final Logger logger = LoggerFactory.getLogger(getClass());
private ExecutorService executorservice;
private int capacity = 10;
private ConsumerMode mode = ConsumerMode.SINGLE;
private QueueMessageHandler<T> handler;
private final ConcurrentLinkedQueue<T> queue = new ConcurrentLinkedQueue<>();
private boolean running = false;
private int totalThread = 1;
private ExecutorService internalExec = null;
private Future internalWorker = null;
private long batchFlushIntervalMillis = 1000L;
public DelayMessageQueue() {
}
public DelayMessageQueue(ExecutorService executorservice, QueueMessageHandler<T> handler) {
this(executorservice, handler, 10);
}
public DelayMessageQueue(ExecutorService executorservice, QueueMessageHandler<T> handler, int capacity) {
this.executorservice = executorservice;
this.handler = handler;
this.capacity = capacity;
}
public void setExecutorservice(ExecutorService executorservice) {
this.executorservice = executorservice;
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
public int getCapacity() {
return capacity;
}
public void setMode(ConsumerMode mode) {
this.mode = mode;
}
public void setHandler(QueueMessageHandler<T> handler) {
this.handler = handler;
}
public void setTotalThread(int totalThread) {
this.totalThread = totalThread;
}
public void setBatchFlushIntervalMillis(long batchFlushIntervalMillis) {
this.batchFlushIntervalMillis = batchFlushIntervalMillis;
}
public void run() {
logger.info("Run queue worker ...");
this.running = true;
internalExec = Executors.newFixedThreadPool(totalThread);
internalWorker = this.executorservice.submit(new QueueRunnable());
}
public void stop(boolean interrupt) {
logger.info("Stopping queue worker ...");
stop(interrupt, 0L, TimeUnit.MILLISECONDS);
}
public boolean stop(boolean interrupt, long timeout, TimeUnit unit) {
logger.info("Stopping queue worker ...");
this.running = false;
if(internalWorker == null) {
logger.warn("Queue worker has not been run!");
return true;
}
try {
if(interrupt) {
internalWorker.cancel(true);
} else if(!internalWorker.isDone()) {
if(timeout > 0L) {
internalWorker.get(timeout, unit);
} else {
internalWorker.get();
}
}
} catch(Exception ex) {
logger.warn("Queue worker did not stop gracefully: {}", ex.getMessage());
}
internalExec.shutdown();
try {
boolean terminated = timeout > 0L ? internalExec.awaitTermination(timeout, unit) : internalExec.awaitTermination(0L, TimeUnit.MILLISECONDS);
if(!terminated) {
logger.warn("Queue handler tasks did not finish within {} {}", timeout, unit);
internalExec.shutdownNow();
return false;
}
} catch(InterruptedException ex) {
logger.warn("Interrupted while waiting queue handler tasks: {}", ex.getMessage());
internalExec.shutdownNow();
Thread.currentThread().interrupt();
return false;
}
return true;
}
public boolean add(T message) {
return queue.add(message);
}
class QueueRunnable implements Runnable {
private final List<T> internalList = new ArrayList<>();
private long lastFlushTime = System.currentTimeMillis();
@Override
public void run() {
while(running || !queue.isEmpty()) {
try {
T message = queue.poll();
if(message != null) {
if(mode == ConsumerMode.BATCH) {
// handled batches
internalList.add(message);
// check capacity
if(internalList.size() >= capacity) {
flushBatch();
}
} else if(mode == ConsumerMode.SINGLE) {
// run job using separate runnable
Runnable run = new Runnable() {
@Override
public void run() {
try {
// handle single
boolean handled = handler.handleMessage(message);
logger.debug("Message handled? {}", handled);
} catch(DatabaseException ex) {
logger.error("Error saving heartbeats: {}", ex.getMessage(), ex);
}
}
};
internalExec.execute(run);
}
} else {
if(mode == ConsumerMode.BATCH && !internalList.isEmpty()
&& System.currentTimeMillis() - lastFlushTime >= batchFlushIntervalMillis) {
flushBatch();
}
TimeUnit.MILLISECONDS.sleep(100L);
}
if(mode == ConsumerMode.BATCH && !internalList.isEmpty()
&& System.currentTimeMillis() - lastFlushTime >= batchFlushIntervalMillis) {
flushBatch();
}
} catch(InterruptedException ex) {
logger.debug("Queue worker interrupted: {}", ex.getMessage());
Thread.currentThread().interrupt();
break;
} catch(Exception ex) {
logger.error("Error consuming queue : {}", ex.getMessage(), ex);
}
}
if(mode == ConsumerMode.BATCH && !internalList.isEmpty()) {
flushBatch();
}
}
private void flushBatch() {
List<T> workingList = new ArrayList<>();
workingList.addAll(internalList);
internalList.clear();
lastFlushTime = System.currentTimeMillis();
// run job using separate runnable
Runnable run = new Runnable() {
@Override
public void run() {
try {
boolean handled = handler.handleMessages(workingList);
logger.debug("Batch messages handled? {}", handled);
} catch(DatabaseException ex) {
logger.error("Error saving heartbeats: {}", ex.getMessage(), ex);
}
}
};
internalExec.execute(run);
}
}
}

View File

@ -0,0 +1,134 @@
package id.iptek.utms.agent.queue;
import com.google.gson.Gson;
import id.iptek.utms.agent.dao.ProfileDao;
import id.iptek.utms.agent.model.Profile;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author jakar
*/
public class DeviceInitQueueMessageHandler implements QueueMessageHandler<Map> {
public final static String NAME = "DEV_INIT_QUEUE_HANDLER";
private Logger logger = LoggerFactory.getLogger(getClass());
private ProfileDao profileDao = new ProfileDao();
private SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
public DeviceInitQueueMessageHandler() {
}
@Override
public boolean handleMessage(Map message) {
boolean processed = false;
try {
logger.debug("Handling init request: {}", message);
long start = System.currentTimeMillis();
MqttClient mqttClient = (MqttClient) message.get("MQTT");
String terminalSN = (String) message.get("device_sn");
Profile profile = profileDao.getProfileForTerminal(terminalSN);
if (profile != null) {
broadcastProfile(mqttClient, profile);
} else {
logger.warn("No profile for SN: {}", terminalSN);
}
processed = true;
long end = System.currentTimeMillis();
logger.debug("Saved in {}ms", (end-start));
return processed;
} catch(Exception ex) {
logger.error("Error handling init: {}", ex.getMessage(), ex);
return false;
}
}
@Override
public boolean handleMessages(List<Map> messages) {
try {
logger.debug("Handling list of init requests: {}", messages.size());
long start = System.currentTimeMillis();
boolean processed = false;
for(Map message : messages) {
MqttClient mqttClient = (MqttClient) message.get("MQTT");
String terminalSN = (String) message.get("device_sn");
Profile profile = profileDao.getProfileForTerminal(terminalSN);
if (profile != null) {
broadcastProfile(mqttClient, profile);
} else {
logger.warn("No profile for SN: {}", terminalSN);
}
processed |= true;
}
long end = System.currentTimeMillis();
logger.debug("Saved in {}ms", (end-start));
return processed;
} catch(Exception ex) {
logger.error("Error handling list of init requests: {}", ex.getMessage(), ex);
return false;
}
}
// send profile to device topic via mqtt
public void broadcastProfile(MqttClient mqttClient,
Profile profile) throws Exception {
logger.debug("Publish profile ...");
try {
try {
Gson gson = new Gson();
int qos = 2;
String topicName = profile.getTerminalSN().toUpperCase() + "_IN";
// generate json
Map messageMap = new HashMap<>();
messageMap.put("req_id", UUID.randomUUID().toString());
messageMap.put("req_time", dateTimeFormat.format(new Date()));
messageMap.put("req_type", "UPDATE_PARAM");
// profile map
Map profileMap = new HashMap<>();
profileMap.put("id", profile.getId());
profileMap.put("name", profile.getName());
profileMap.put("hearbeat_interval", profile.getHeartbeatInterval());
profileMap.put("diagnostic_interval", profile.getDiagnosticInterval());
profileMap.put("mask_home_button", profile.isMaskHomeButton());
profileMap.put("mask_status_button", profile.isMaskStatusButton());
profileMap.put("schedule_reboot", profile.isScheduleReboot());
if (profile.isScheduleReboot()) {
profileMap.put("schedule_reboot_time", timeFormat.format(profile.getScheduleRebootTime()));
}
profileMap.put("relocation_alert", profile.isRelocationAlert());
profileMap.put("moving_threshold", profile.getMovingThreshold());
profileMap.put("admin_password", profile.getAdminPassword());
// additional
profileMap.put("front_app", profile.getFrontApp());
profileMap.put("apps_home_list", profile.getApps());
profileMap.put("group_list", profile.getGroupIds());
messageMap.put("profile", profileMap);
String messageData = gson.toJson(messageMap);
logger.debug("Try publish message to: {}", topicName);
mqttClient.publish(topicName, messageData.getBytes(), qos, false);
logger.debug("Message published!");
} catch (Exception ex) {
logger.error("Error publish to device: {}", ex.getMessage(), ex);
} finally {
}
} finally {
logger.debug("Publish profile DONE");
}
}
}

View File

@ -0,0 +1,52 @@
package id.iptek.utms.agent.queue;
import id.iptek.utms.agent.dao.DiagnosticDao;
import id.iptek.utms.agent.model.Diagnostic;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author jakar
*/
public class DiagnosticInfoQueueMessageHandler implements QueueMessageHandler<Diagnostic> {
public final static String NAME = "DIAGNOSTIC_QUEUE_HANDLER";
private Logger logger = LoggerFactory.getLogger(getClass());
private DiagnosticDao dao = new DiagnosticDao();
public DiagnosticInfoQueueMessageHandler() {
}
@Override
public boolean handleMessage(Diagnostic message) {
try {
logger.debug("Saving diagnostic: {}", message);
long start = System.currentTimeMillis();
boolean saved = dao.save(message);
long end = System.currentTimeMillis();
logger.debug("Saved in {}ms", (end-start));
return saved;
} catch(Exception ex) {
logger.error("Error handling diagnostic: {}", ex.getMessage(), ex);
return false;
}
}
@Override
public boolean handleMessages(List<Diagnostic> messages) {
try {
logger.debug("Saving list of diagnostics: {}", messages.size());
long start = System.currentTimeMillis();
boolean saved = dao.saveAll(messages);
long end = System.currentTimeMillis();
logger.debug("Saved in {}ms", (end-start));
return saved;
} catch(Exception ex) {
logger.error("Error handling list of diagnostics: {}", ex.getMessage(), ex);
return false;
}
}
}

View File

@ -0,0 +1,52 @@
package id.iptek.utms.agent.queue;
import id.iptek.utms.agent.dao.HeartbeatDao;
import id.iptek.utms.agent.model.HeartBeat;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author jakar
*/
public class HeartBeatQueueMessageHandler implements QueueMessageHandler<HeartBeat> {
public final static String NAME = "HEARTBEAT_QUEUE_HANDLER";
private Logger logger = LoggerFactory.getLogger(getClass());
private HeartbeatDao dao = new HeartbeatDao();
public HeartBeatQueueMessageHandler() {
}
@Override
public boolean handleMessage(HeartBeat message) {
try {
logger.debug("Saving heartbeat: {}", message);
long start = System.currentTimeMillis();
boolean saved = dao.save(message);
long end = System.currentTimeMillis();
logger.debug("Saved in {}ms", (end-start));
return saved;
} catch(Exception ex) {
logger.error("Error handling heartbeat: {}", ex.getMessage(), ex);
return false;
}
}
@Override
public boolean handleMessages(List<HeartBeat> messages) {
try {
logger.debug("Saving list of heartbeats: {}", messages.size());
long start = System.currentTimeMillis();
boolean saved = dao.saveAll(messages);
long end = System.currentTimeMillis();
logger.debug("Saved in {}ms", (end-start));
return saved;
} catch(Exception ex) {
logger.error("Error handling list of heartbeats: {}", ex.getMessage(), ex);
return false;
}
}
}

View File

@ -0,0 +1,25 @@
package id.iptek.utms.agent.queue;
import java.util.List;
/**
*
* @author jakar
*/
public interface QueueMessageHandler<T> {
/**
* Handle message
* @param message
* @return
*/
public boolean handleMessage(T message);
/**
* Handle batch of messages at same time
* @param messages
* @return
*/
public boolean handleMessages(List<T> messages);
}

View File

@ -0,0 +1,52 @@
package id.iptek.utms.agent.sample;
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.persist.MemoryPersistence;
public class MqttPublishSample {
public static void main(String[] args) {
String topic = "SERVER_IN_DIAG";
String content = "{\"req_id\":\"a971d68e-1fcc-4eeb-ba96-6c4e6e867a06\",\"req_type\":\"DIAGNOSTIC\",\"req_time\":\"20250827140806\",\"device_sn\":\"V9E0191945\",\"diagnostic_info\":{\"imei\":\"863188045199949\",\"meid\":\"\",\"battery_temp\":\" 250\",\"battery_percentage\":\"100\",\"total_memory\":\"1997537280\",\"available_memory\":\"1308291072\",\"total_flash_memory\":\"16000000000B\",\"available_flash_memory\":\"11429019648\",\"total_mobile_data\":\"1248910\",\"switching_times\":\"0\",\"current_boot_time\":\"0\",\"total_boot_time\":\"104\",\"total_length_printed\":\"13097.0\",\"swiping_card_times\":\"297\",\"dip_inserting_times\":\"273\",\"nfc_card_reading_times\":\"124\",\"front_camera_open_times\":\"0\",\"rear_camera_open_times\":\"0\",\"new_diagnostic\":true,\"sam_available\":true},\"location_info\":{\"lat\":-6.357999801635742,\"lng\":106.81169891357422},\"installed_apps\":[{\"app_name\":\"CPU Info\",\"package_name\":\"com.kgurgul.cpuinfo\",\"version\":\"6.0.0\"},{\"app_name\":\"NSICCSDemo\",\"package_name\":\"com.unified.nsiccsdemo\",\"version\":\"1.0\"},{\"app_name\":\"VFSystemService\",\"package_name\":\"com.vfi.smartpos.system_service\",\"version\":\"1.14.0.1\"},{\"app_name\":\"Telnet\",\"package_name\":\"koushikdutta.telnet\",\"version\":\"1.0.1\"},{\"app_name\":\"Athena\",\"package_name\":\"dev.sebaubuntu.athena.dev\",\"version\":\"1.1.0\"},{\"app_name\":\"UTMS\",\"package_name\":\"com.unified.launcher\",\"version\":\"1.4.3.BIT\"},{\"app_name\":\"Bank Index\",\"package_name\":\"com.iptek.index\",\"version\":\"1.1.4.DEV\"},{\"app_name\":\"VFService\",\"package_name\":\"com.vfi.smartpos.deviceservice\",\"version\":\"3.11.7.1\"}],\"device_info_ex\":{\"SN\":\"V9E0191945\",\"PN\":\"M550-104-22-EUA-6\",\"IMSI\":\"510019134244830\",\"IMEI\":\"863188045199949\",\"MEID\":\"\",\"manufacture\":\"Verifone\",\"deviceModel\":\"X990\",\"androidOsVer\":\"10\",\"androidKernalVer\":\"Linux version 4.14.133 (linbx@v-dev) (gcc version 4.9.x 20150123 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Aug 4 11:30:37 CST 2022\",\"romVer\":\"3A.1.385(202208041133 INTL)\",\"firmwareVer\":\"V3.1.0.20220804\",\"hardwareVer\":\"M550-10X-XX-XXX-6 Rev.C\",\"SPVer\":\"X990-V1.0.26(202209080934)\",\"VFSerivceVer\":\"3.11.7.1\",\"VRKSn\":\"\",\"SponsorID\":\"\",\"SponsorName\":\"\",\"bootVer\":\"X990-1.0.0.A10(20220707)\"}}";
//String content = "{\"req_id\":\"7484442f-1d5c-4d51-96bc-ed7cb0ec8b95\",\"req_time\":\"2023-07-30 18:39:00\",\"req_type\":\"RESET_CONNECTION\"}";
int qos = 2;
String broker = "tcp://192.168.4.112:1883";
String clientId = "JavaSample";
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
connOpts.setUserName("user1");
connOpts.setPassword("P@ssw0rd".toCharArray());
//connOpts.setUserName("wira");
//connOpts.setPassword("wira1234".toCharArray());
System.out.println("Connecting to broker: "+broker);
sampleClient.connect(connOpts);
System.out.println("Connected");
System.out.println("Publishing message: "+content);
MqttMessage message = new MqttMessage(content.getBytes());
message.setQos(qos);
//message.setRetained(true);
sampleClient.publish(topic, message);
System.out.println("Message published");
sampleClient.disconnect();
System.out.println("Disconnected");
System.exit(0);
} catch(MqttException me) {
System.out.println("reason "+me.getReasonCode());
System.out.println("msg "+me.getMessage());
System.out.println("loc "+me.getLocalizedMessage());
System.out.println("cause "+me.getCause());
System.out.println("excep "+me);
me.printStackTrace();
}
}
}

View File

@ -0,0 +1,87 @@
package id.iptek.utms.agent.sample;
import java.util.concurrent.TimeUnit;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
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.persist.MemoryPersistence;
public class MqttSubscribeSample {
public static void main(String[] args) {
final String topic = "5354b64f-c52c-45e0-8b26-49b5d5352e44";
final String topic2 = "V1E0352316_IN";
//V1E0352316_IN
int qos = 2;
//String broker = "tcp://verifone.id:1883";
String broker = "tcp://bit.unifiedtms.id:1883";
String clientId = "SN02";
MemoryPersistence persistence = new MemoryPersistence();
try {
final MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
//connOpts.setUserName("wira");
//connOpts.setPassword("wira1234".toCharArray());
connOpts.setUserName("user1");
connOpts.setPassword("P@ssw0rd".toCharArray());
connOpts.setAutomaticReconnect(true);
connOpts.setKeepAliveInterval(10000);
System.out.println("Connecting to broker: " + broker);
sampleClient.setCallback(new MqttCallbackExtended() {
@Override
public void connectComplete(boolean bln, String string) {
System.out.println("Connect complete? " + bln + " : " + string);
try {
sampleClient.subscribe(topic);
sampleClient.subscribe(topic2);
} catch(MqttException ex) {
System.err.println("Error subscribe topic: " + topic);
}
}
@Override
public void connectionLost(Throwable thrwbl) {
System.err.println("Connection Lost: " + thrwbl);
}
@Override
public void messageArrived(String topic, MqttMessage mm) throws Exception {
System.out.println("<< [" + topic + "] " + new String(mm.getPayload()) + " (" + mm.getId() + " - " + mm.getQos() + ")");
}
@Override
public void deliveryComplete(IMqttDeliveryToken imdt) {
System.err.println("Delivery Complete: " + imdt.getMessageId());
}
});
sampleClient.connect(connOpts);
System.out.println("Connected");
//sampleClient.subscribe(topic);
try {
TimeUnit.SECONDS.sleep(100);
} catch(InterruptedException ex) {
ex.printStackTrace();
}
sampleClient.disconnect();
System.out.println("Disconnected");
System.exit(0);
} catch (MqttException me) {
System.out.println("reason " + me.getReasonCode());
System.out.println("msg " + me.getMessage());
System.out.println("loc " + me.getLocalizedMessage());
System.out.println("cause " + me.getCause());
System.out.println("excep " + me);
me.printStackTrace();
}
}
}

View File

@ -0,0 +1,299 @@
package id.iptek.utms.agent.scheduler.job;
import com.google.gson.Gson;
import id.iptek.utms.agent.AppConfig;
import id.iptek.utms.agent.dao.ApplicationDao;
import id.iptek.utms.agent.dao.DownloadTaskDao;
import id.iptek.utms.agent.model.ApplicationExt;
import id.iptek.utms.agent.model.DownloadTask;
import id.iptek.utms.agent.model.PendingDownloadTask;
import id.iptek.utms.agent.model.enumeration.TaskStatus;
import id.iptek.utms.agent.util.Singleton;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.http.Method;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import org.apache.commons.codec.digest.DigestUtils;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author jakar
*/
public class DownloadTaskPublisherJob implements Job {
private final Logger logger = LoggerFactory.getLogger(getClass());
private ApplicationDao appDao = new ApplicationDao();
private DownloadTaskDao dao = new DownloadTaskDao();
private static final SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat sdfYEAR = new SimpleDateFormat("yyyy");
private static final SimpleDateFormat sdfMONTH = new SimpleDateFormat("MM");
private static final SimpleDateFormat sdfDATE = new SimpleDateFormat("dd");
public DownloadTaskPublisherJob() {
}
@Override
public void execute(JobExecutionContext jec) throws JobExecutionException {
try {
logger.info("Execute publish task job ..");
JobDataMap dataMap = jec.getMergedJobDataMap();
// get task
DownloadTask task = (DownloadTask) dataMap.get("task");
logger.info(">> {}", task);
if(task.getStatus() == TaskStatus.INITIAL) {
boolean populated = dao.populateAndBuildDownloadTaskLogs(task);
logger.info("Populated? {}", populated);
}
List<PendingDownloadTask> groupPendingDownloadTasks = dao.getUnpublishedPendingTaskByTerminalGroup(task);
List<PendingDownloadTask> pendingDownloadTasks = dao.getUnpublishedPendingTaskByTerminal(task);
MqttClient mqttClient = (MqttClient) Singleton.getInstance("MQTT_CLIENT").getObject();
logger.info("Total Group Pending Download Tasks: {}", groupPendingDownloadTasks.size());
for(PendingDownloadTask downloadTask : groupPendingDownloadTasks) {
logger.info(">> [1] task={}, group={}, app={}", downloadTask.getId(), downloadTask.getTerminalGroupId(), downloadTask.getApp().getId());
broadcastDownloadTasksToDevice(mqttClient, downloadTask);
}
logger.info("Total Pending Download Tasks: {}", pendingDownloadTasks.size());
for(PendingDownloadTask downloadTask : pendingDownloadTasks) {
logger.info(">> [2] task={}, terminal={}, app={}", downloadTask.getId(), downloadTask.getTerminalSN(), downloadTask.getApp().getId());
broadcastDownloadTasksToDevice(mqttClient, downloadTask);
}
} catch(Exception ex) {
logger.error("Error publish task: {}", ex.getMessage(), ex);
} finally {}
}
// send download task to device topic via mqtt
protected void broadcastDownloadTasksToDevice(MqttClient mqttClient,
PendingDownloadTask task) throws Exception {
logger.debug("Broadcast tasks ...");
try {
int qos = 2;
String topicName;
// broadcast to group or specific SN
boolean broadcastToGroup = false;
if(task.getTerminalGroupId() != null) {
topicName = task.getTerminalGroupId();
broadcastToGroup = true;
} else {
topicName = task.getTerminalSN().toUpperCase() + "_IN";
}
AppConfig appConfig = AppConfig.getInstance();
Date now = Calendar.getInstance().getTime();
ApplicationExt app = (ApplicationExt) task.getApp();
String bucketName = appConfig.get("fileserver.bucket");
// check icon url expiry
Date iconUrlExp = app.getIconUrlExp();
if(iconUrlExp == null || now.after(iconUrlExp)) {
logger.debug("Icon url expired: {}", iconUrlExp);
String iconUniqueName = app.getUniqueIconName();
String path = appConfig.get("fileserver.icon.path");
int expiry = appConfig.getAsInt("fileserver.icon.expiry", 7);
TimeUnit timeUnit = getTimeUnit(appConfig, "fileserver.icon.timeunit", "server.icon.timeunit", "DAYS");
Date iconExpiryDate = getExpiryDate(now, expiry, timeUnit);
logger.info("Generate icon url for app '{}', old expiry: {}", app.getId(), iconUrlExp);
String iconDownloadUrl = generateDownloadUrl(bucketName, path, iconUniqueName,
expiry, timeUnit);
app.setIconUrl(iconDownloadUrl);
app.setIconUrlExp(iconExpiryDate);
logger.info("Icon url generated for app '{}', new expiry: {}", app.getId(), iconExpiryDate);
boolean iconUrlUpdated = appDao.updateIconUrl(app);
logger.info("Icon url updated? {}", iconUrlUpdated);
}
// check download url expiry
Date downloadUrlExp = app.getDownloadUrlExp();
if(downloadUrlExp == null || now.after(downloadUrlExp)) {
logger.info("Download app url expired for task '{}', app '{}', old expiry: {}", task.getId(), app.getId(), downloadUrlExp);
String uniqueName = app.getUniqueName();
String path = appConfig.get("fileserver.app.path");
int expiry = appConfig.getAsInt("fileserver.app.expiry", 7);
TimeUnit timeUnit = getTimeUnit(appConfig, "fileserver.app.timeunit", "server.app.timeunit", "DAYS");
Date appExpiryDate = getExpiryDate(now, expiry, timeUnit);
logger.info("Generate app url for task '{}', app '{}'", task.getId(), app.getId());
String appDownloadUrl = generateDownloadUrl(bucketName, path, uniqueName,
expiry, timeUnit);
app.setDownloadUrl(appDownloadUrl);
app.setDownloadUrlExp(appExpiryDate);
logger.info("App url generated for task '{}', app '{}', new expiry: {}", task.getId(), app.getId(), appExpiryDate);
boolean appUrlUpdated = appDao.updateAppUrl(task, app);
logger.info("App url updated? {}", appUrlUpdated);
}
// generate json
Gson gson = new Gson();
Map messageMap = new HashMap<>();
messageMap.put("req_id", UUID.randomUUID().toString());
messageMap.put("req_time", dateTimeFormat.format(new Date()));
// we'll use log's id as ack_id
if(broadcastToGroup) {
String ackId = "BROADCAST_" + task.getId();
messageMap.put("ack_id", ackId);
} else {
messageMap.put("ack_id", task.getLogId());
}
messageMap.put("req_type", "DOWNLOAD_APP_TASK");
// task map
Map taskMap = new HashMap<>();
taskMap.put("id", task.getId());
taskMap.put("name", task.getName());
taskMap.put("download_time_type", getDownloadTimeTypeName(task.getDownloadTimeType()));
if (task.getDownloadTimeType() == 2) {
taskMap.put("download_time", dateTimeFormat.format(task.getDownloadTime()));
}
taskMap.put("installation_time_type", getInstallationTimeTypeName(task.getInstallationTimeType()));
if (task.getInstallationTimeType() == 2) {
taskMap.put("installation_time", dateTimeFormat.format(task.getInstallationTime()));
}
taskMap.put("installation_notification", getInstallationNotificationName(task.getInstallationNotification()));
messageMap.put("task", taskMap);
// app map
Map appMap = new HashMap<>();
appMap.put("id", app.getId());
appMap.put("name", app.getAppName());
appMap.put("package_name", app.getPackageName());
appMap.put("version", app.getVersion());
appMap.put("company", app.getCompanyName());
appMap.put("uninstallable", app.isUninstallable());
appMap.put("description", app.getDescription());
appMap.put("download_url", app.getDownloadUrl());
appMap.put("md5_checksum", app.getChecksum());
messageMap.put("app", appMap);
String messageData = gson.toJson(messageMap);
logger.debug("Try publish message to: {}", topicName);
logger.debug(">> {}", messageData);
mqttClient.publish(topicName, messageData.getBytes(), qos, false);
logger.debug("Message published!");
// change log's last broadcast time
if(broadcastToGroup) {
boolean updated = dao.updateGroupLastBroadcastTs(task);
logger.debug("Download task group last broadcast time updated? {}", updated);
} else {
boolean updated = dao.updateTerminalLastBroadcastTs(task);
logger.debug("Download task terminal last broadcast time updated? {}", updated);
}
} finally {
logger.debug("Start broadcast download tasks DONE");
}
}
private String getDownloadTimeTypeName(int type) {
switch (type) {
case 1:
return "NEXT_CONTACT";
case 2:
return "DATETIME";
}
return null;
}
private String getInstallationTimeTypeName(int type) {
switch (type) {
case 1:
return "IMMEDIATE_AFTER_DOWNLOAD";
case 2:
return "DATETIME";
}
return null;
}
private String getInstallationNotificationName(int type) {
switch (type) {
case 1:
return "SILENT";
case 2:
return "NEED_CONFIRMATION";
}
return null;
}
private String getFilePath(String fileId, String fileExt, Date fileCreateDate) {
String filePath = AppConfig.getInstance().get("file.dir") + File.separator
+ sdfYEAR.format(fileCreateDate) + File.separator
+ sdfMONTH.format(fileCreateDate) + File.separator
+ sdfDATE.format(fileCreateDate) + File.separator
+ fileId + "." + fileExt;
return filePath;
}
private String md5Checksum(byte[] bytes) throws Exception {
try {
String checksum = DigestUtils.md5Hex(bytes);
return checksum;
} finally {
}
}
private String generateDownloadUrl(String bucketName, String path, String uniqueName, int expiry, TimeUnit expiryTimeUnit) throws Exception {
MinioClient minioClient = (MinioClient) Singleton.getInstance("MINIO_CLIENT").getObject();
String url
= minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(path + "/" + uniqueName)
.expiry(expiry, expiryTimeUnit)
.build());
return url;
}
private Date getExpiryDate(Date now, int expiry, TimeUnit timeUnit) {
Calendar cal = Calendar.getInstance();
cal.setTime(now);
switch (timeUnit) {
case MILLISECONDS:
cal.add(Calendar.MILLISECOND, expiry);
break;
case SECONDS:
cal.add(Calendar.SECOND, expiry);
break;
case MINUTES:
cal.add(Calendar.MINUTE, expiry);
break;
case HOURS:
cal.add(Calendar.HOUR_OF_DAY, expiry);
break;
case DAYS:
cal.add(Calendar.DAY_OF_MONTH, expiry);
break;
}
return cal.getTime();
}
private TimeUnit getTimeUnit(AppConfig appConfig, String name, String legacyName, String defaultValue) {
String value = appConfig.get(name);
if(value == null) {
value = appConfig.get(legacyName, defaultValue);
}
return TimeUnit.valueOf(value.trim().toUpperCase());
}
}

View File

@ -0,0 +1,120 @@
package id.iptek.utms.agent.scheduler.job;
import id.iptek.utms.agent.dao.DownloadTaskDao;
import id.iptek.utms.agent.model.DownloadTask;
import id.iptek.utms.agent.model.enumeration.PublishTimeType;
import id.iptek.utms.agent.util.Singleton;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.quartz.Job;
import static org.quartz.JobBuilder.newJob;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author jakar
*/
public class DownloadTaskSchedulerJob implements Job {
private final Logger logger = LoggerFactory.getLogger(getClass());
private DownloadTaskDao dao = new DownloadTaskDao();
public DownloadTaskSchedulerJob() {
}
@Override
public void execute(JobExecutionContext jec) throws JobExecutionException {
try {
logger.info("Execute job ..");
List<DownloadTask> tasks = dao.getUnscheduledTasks();
logger.info("Done query");
logger.info("Got {} tasks", tasks.size());
/*List<String> scheduledJobIds = (List<String>) Singleton.getInstance("SCHEDULER_JOBS").getObject();
if(scheduledJobIds == null) {
scheduledJobIds = new ArrayList<>();
Singleton.getInstance("SCHEDULER_JOBS").setObject(scheduledJobIds);
}*/
for(DownloadTask task : tasks) {
/*if(scheduledJobIds.contains(task.getId())) {
logger.info("Download Task with id '{}' is already scheduled.", task.getId());
} else {
logger.info("Will schedule download task with id: {}", task.getId());
scheduleTask(task);
scheduledJobIds.add(task.getId());
}*/
logger.info("Will schedule download task with id: {}", task.getId());
scheduleTask(task);
}
} catch(Exception ex) {
logger.error("Error get tasks: {}", ex.getMessage(), ex);
} finally {}
}
private void scheduleTask(DownloadTask task) throws SchedulerException {
// get quartz scheduler
Scheduler sched = (Scheduler) Singleton.getInstance("SCHEDULER").getObject();
JobKey jobkey = new JobKey("download-task-" + task.getId(), "publish-task");
if(sched.checkExists(jobkey)) return;
if(task.getPublishTimeType() == PublishTimeType.IMMEDIATE) {
// publish job in next 1 minutes
JobDataMap map = new JobDataMap();
map.put("task", task);
JobDetail job = newJob(DownloadTaskPublisherJob.class)
.withIdentity(jobkey)
.usingJobData(map)
.build();
Calendar time = Calendar.getInstance();
time.add(Calendar.MINUTE, 1);
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("download-task-trigger-" + task.getId(), "publish-task")
.startAt(time.getTime())
.build();
sched.scheduleJob(job, trigger);
logger.info("Task id-{} scheduled @{}", task.getId(), trigger.getFinalFireTime());
} else if(task.getPublishTimeType() == PublishTimeType.DATE_TIME) {
Calendar time = Calendar.getInstance();
// compare publish time with current time
Date publishTime = task.getPublishTime();
JobDataMap map = new JobDataMap();
map.put("task", task);
JobDetail job = newJob(DownloadTaskPublisherJob.class)
.withIdentity(jobkey)
.usingJobData(map)
.build();
if(time.getTime().equals(publishTime) || time.getTime().after(publishTime)) {
// publish it next 5 minutes
time.add(Calendar.MINUTE, 1);
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("download-task-trigger-" + task.getId(), "publish-task")
.startAt(time.getTime())
.build();
sched.scheduleJob(job, trigger);
logger.info("Task id-{} scheduled @{}", task.getId(), trigger.getFinalFireTime());
} else {
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("download-task-trigger-" + task.getId(), "publish-task")
.startAt(publishTime)
.build();
sched.scheduleJob(job, trigger);
logger.info("Task id-{} scheduled @{}", task.getId(), trigger.getFinalFireTime());
}
}
}
}

View File

@ -0,0 +1,51 @@
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package id.iptek.utms.agent.test;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.http.Method;
import java.util.concurrent.TimeUnit;
/**
*
* @author jakar
*/
public class TestMinio {
public static void main(String[] args) throws Exception {
MinioClient minioClient
= MinioClient.builder()
.endpoint("https://download.unifiedtms.id:9000")
.credentials("i9ZB0sNhHaiQe7oEP0sL", "4bxVnKwKgkXpZJ9Dou4oprZ1E8oe3s1HuvKLRn0N")
.build();
String uniqueName = "1693968324774app_ico.png";
String uniqueApkName = "1693223977836Facebook Lite_368.0.0.5.95_Apkpure.apk";
String url
= minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket("application-bucket")
.object("icons/" + uniqueName)
.expiry(1, TimeUnit.MINUTES)
.build());
System.out.println("URL: " + url);
String apkUrl
= minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket("application-bucket")
.object("apps/" + uniqueApkName)
.expiry(1, TimeUnit.MINUTES)
.build());
System.out.println("APK URL: " + apkUrl);
System.exit(0);
}
}

View File

@ -0,0 +1,18 @@
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package id.iptek.utms.agent.test;
/**
*
* @author jakar
*/
public class TestSubstring {
public static void main(String[] args) {
String ackId = "BROADCAST-1234";
System.out.println(">> " + ackId.substring(10));
}
}

View File

@ -0,0 +1,135 @@
package id.iptek.utms.agent.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Jaka Ramdani
*/
public class FileUtil {
private static Logger log = LoggerFactory.getLogger(FileUtil.class);
private FileUtil() {
}
public static void copy(String srcPath, String dstPath) throws IOException, Exception {
copy(srcPath, dstPath, false);
}
public static void copy(String srcPath, String dstPath, boolean overwrite) throws IOException, Exception {
log.debug("\"{}\" -> \"{}\"", srcPath, dstPath);
File srcFile = new File(srcPath);
File dstFile = new File(dstPath);
if (srcFile.exists() && !srcFile.isDirectory()) {
if (dstFile.exists() && dstFile.isDirectory()) {
String[] _filenames = srcPath.split("[\\/\\\\]");
dstFile = new File(dstFile, _filenames[_filenames.length - 1]);
} else if (dstFile.exists() && !overwrite) {
throw new IOException("Destination file \"" + dstPath + "\" is exists, not overwriting file.");
} else if (dstFile.exists()) {
//remove existing file
if (!dstFile.delete()) {
throw new IOException("Can not remove old destination file \"" + dstPath + "\".");
}
}
//create new file
byte[] srcBytes = StreamUtil.read(new FileInputStream(srcFile));
StreamUtil.write(new FileOutputStream(dstFile), srcBytes, true);
} else {
throw new IOException("Source file \"" + srcFile + "\" is not exists or is a directory.");
}
}
public static void move(String srcPath, String dstPath) throws IOException, Exception {
move(srcPath, dstPath, false);
}
public static void move(String srcPath, String dstPath, boolean overwrite) throws IOException, Exception {
copy(srcPath, dstPath, overwrite);
delete(srcPath);
}
public static boolean delete(String path) throws IOException, Exception {
File srcFile = new File(path);
if (srcFile.exists() && !srcFile.isDirectory()) {
boolean deleted = new File(path).delete();
if (deleted) {
log.debug("\"{}\" removed", path);
} else {
log.debug("\"{}\" NOT removed", path);
}
return deleted;
} else {
throw new IOException("Source file \"" + srcFile + "\" is not exists or is a directory.");
}
}
public static String[] list(String path) throws IOException, Exception {
log.debug("list: \"{}\"", path);
return new File(path).list();
}
public static String[] list(String path, FilenameFilter fileNameFilter) throws IOException, Exception {
log.debug("list: \"{}\"", path);
return new File(path).list(fileNameFilter);
}
public static File[] listFiles(File parent, FilenameFilter fileNameFilter) throws IOException, Exception {
return listFiles(parent, fileNameFilter, false);
}
public static File[] listFiles(File parent, FilenameFilter fileNameFilter, boolean nameOrdered) throws IOException, Exception {
return listFiles(parent.getAbsolutePath(), fileNameFilter, nameOrdered);
}
public static File[] listFiles(String path, FilenameFilter fileNameFilter) throws IOException, Exception {
return listFiles(path, fileNameFilter, false);
}
public static File[] listFiles(String path, FilenameFilter fileNameFilter, boolean nameOrdered) throws IOException, Exception {
log.debug("list: \"{}\"", path);
File[] files = new File(path).listFiles(fileNameFilter);
if (nameOrdered) {
Arrays.sort(files, new Comparator<File>() {
@Override
public int compare(File f1, File f2) {
return f2.getName().compareTo(f1.getName());
}
});
}
return files;
}
public static boolean mkdirs(String path) throws IOException, Exception {
return mkdirs(path, false);
}
public static boolean mkdirs(String path, boolean silentOnExists) throws IOException, Exception {
File file = new File(path);
if (file.exists()) {
if (silentOnExists) {
log.debug("\"{}\" is already exists. keep silence ..", path);
return true;
}
throw new IOException("\"" + path + "\" is already exists.");
}
boolean created = file.mkdirs();
if (created) {
log.debug("\"{}\" created", path);
} else {
log.debug("\"{}\" NOT created", path);
}
return created;
}
}

View File

@ -0,0 +1,71 @@
package id.iptek.utms.agent.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
/**
*
* @author Jaka Ramdani
*/
public final class IOUtil {
private IOUtil() {
}
public static byte[] read(InputStream in) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
int i = -1;
byte[] buffer = new byte[1024*4];
while( (i = in.read(buffer)) != -1 ) {
baos.write(buffer, 0, i);
}
baos.flush();
} finally {
close(in);
}
return baos.toByteArray();
}
public static void close(InputStream in) {
if(in != null) {
try {
in.close();
} catch(IOException ignore) {}
in = null;
}
}
public static void close(OutputStream out) {
if(out != null) {
try {
out.close();
} catch(IOException ignore) {}
out = null;
}
}
public static void close(Reader reader) {
if(reader != null) {
try {
reader.close();
} catch(IOException ignore) {}
reader = null;
}
}
public static void write(byte[] bytes, OutputStream out) throws IOException {
out.write(bytes);
out.flush();
out.close();
}
public static void write(String text, OutputStream out) throws IOException {
out.write(text.getBytes());
}
}

View File

@ -0,0 +1,29 @@
package id.iptek.utms.agent.util;
import java.util.HashMap;
import java.util.Map;
public final class Singleton {
private final static Map<String, Singleton> INSTANCES = new HashMap<>();
private Object object;
private Singleton() {}
public void setObject(Object object) {
this.object = object;
}
public Object getObject() {
return object;
}
public static Singleton getInstance(String name) {
Singleton instance = INSTANCES.get(name);
if(instance == null) {
instance = new Singleton();
INSTANCES.put(name, instance);
}
return instance;
}
}

View File

@ -0,0 +1,96 @@
package id.iptek.utms.agent.util;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.codec.binary.Base64;
/**
*
* @author Jaka Ramdani
*/
public final class StreamUtil {
private StreamUtil() {
}
public static String readAsBase64(InputStream is) throws IOException {
byte[] bytes = read(is);
return Base64.encodeBase64String(bytes);
}
public static byte[] read(InputStream is) throws IOException {
return read(is, true);
}
public static byte[] read(InputStream is, boolean close) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
byte[] buffer = new byte[10*1024];
int i = -1;
while( (i = is.read(buffer)) > 0 ) {
baos.write(buffer, 0, i);
}
baos.flush();
} finally {
if(is != null && close) {
try {
is.close();
} catch(IOException ignore) {}
is = null;
}
}
return baos.toByteArray();
}
public static void write(OutputStream os, byte[] bytes, boolean close) throws IOException {
try {
int maxPerWrite = 10*1024;
int len = bytes.length;
int written = 0;
while(written < len) {
int write = (len - written) >= maxPerWrite ? maxPerWrite : (len - written);
os.write(bytes, written, write);
written += write;
}
os.flush();
} finally {
if(os != null && close) {
try {
os.close();
} catch(IOException ignore) {}
os = null;
}
}
}
public static void close(InputStream in) {
if(in != null) {
try {
in.close();
} catch(IOException ignore) {}
in = null;
}
}
public static void close(OutputStream out) {
if(out != null) {
try {
out.close();
} catch(IOException ignore) {}
out = null;
}
}
public static void main(String[] args) {
try {
String file = "G:\\Pictures\\Avatar-Me.jpg";
String imageBase64 = readAsBase64(new FileInputStream(file));
System.out.println("ImageBase64:\n" + imageBase64);
} catch(Exception ex) {
ex.printStackTrace();
}
}
}

View File

@ -0,0 +1,134 @@
package id.iptek.utms.agent.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.id.random.SessionIdGenerator;
/**
*
* @author Jaka Ramdani
*/
public final class StringUtil {
private StringUtil() {
}
public static String decodeHtml(String strValue) {
String strResult = "";
if (strValue != null) {
String strInfo = strValue;
StringBuffer sbResult = null;
try {
sbResult = new StringBuffer(strInfo);
int intStart = 0;
int intEnd = 0;
while (true) {
if (strInfo.indexOf("&lt;") != -1) {
intStart = strInfo.indexOf("&lt;");
intEnd = intStart + "&lt;".length();
sbResult.replace(intStart, intEnd, "<");
strInfo = sbResult.toString();
continue;
}
if (strInfo.indexOf("&gt;") != -1) {
intStart = strInfo.indexOf("&gt;");
intEnd = intStart + "&gt;".length();
sbResult.replace(intStart, intEnd, ">");
strInfo = sbResult.toString();
continue;
}
if (strInfo.indexOf("&amp;") != -1) {
intStart = strInfo.indexOf("&amp;");
intEnd = intStart + "&amp;".length();
sbResult.replace(intStart, intEnd, "&");
strInfo = sbResult.toString();
continue;
}
if (strInfo.indexOf("&quot;") != -1) {
intStart = strInfo.indexOf("&quot;");
intEnd = intStart + "&quot;".length();
sbResult.replace(intStart, intEnd, "\"");
strInfo = sbResult.toString();
continue;
}
if (strInfo.indexOf("&nbsp;") == -1) {
break;
}
intStart = strInfo.indexOf("&nbsp;");
intEnd = intStart + "&nbsp;".length();
sbResult.replace(intStart, intEnd, " ");
strInfo = sbResult.toString();
}
strResult = sbResult.toString();
} catch (Exception e) {
strResult = "";
} finally {
sbResult = null;
}
}
return strResult;
}
public StringBuilder collect(String msg) {
StringBuilder sb = new StringBuilder();
sb.append("<HTML>\n");
sb.append("<HEAD>\n");
sb.append("<TITLE>\n");
sb.append("</TITLE>\n");
sb.append("</HEAD>\n");
sb.append("<BODY background=#ffffff>\n");
for (int i = 0; i < msg.length(); i++) {
char currentChar = msg.charAt(i);
if ((currentChar == '\n') || (currentChar == '\n')) {
sb.append("<BR>");
} else if (currentChar == ' ') {
sb.append("&nbsp;");
} else {
sb.append(currentChar);
}
}
sb.append("</BODY>\n");
sb.append("</HTML>\n");
return sb;
}
public static String getMD5Hash(String string) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(string.getBytes());
byte[] digest = md5.digest();
string = Base64.encodeBase64String(digest);
} catch (NoSuchAlgorithmException e1) {
e1.printStackTrace();
}
return string;
}
private static String byteArrToHexString(byte[] bArr) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bArr.length; i++) {
int unsigned = bArr[i] & 0xff;
if (unsigned < 0x10) {
sb.append("0");
}
sb.append(Integer.toHexString((unsigned)));
}
return sb.toString();
}
public static void main(String[] args) {
SessionIdGenerator gidGenerator = new SessionIdGenerator();
String gid = DigestUtils.md5Hex(gidGenerator.nextStringIdentifier());
System.err.println(">> gid: " + gid);
}
}

View File

@ -0,0 +1,58 @@
package id.iptek.utms.agent.worker;
import com.google.gson.Gson;
import id.iptek.utms.agent.AppConfig;
import id.iptek.utms.agent.queue.ConsumerMode;
import id.iptek.utms.agent.queue.DelayMessageQueue;
import id.iptek.utms.agent.queue.DeviceInitQueueMessageHandler;
import id.iptek.utms.agent.util.Singleton;
import java.util.Map;
import org.eclipse.paho.client.mqttv3.MqttMessage;
/**
*
* @author Jaka
*/
public class DeviceInitWorker extends Worker {
public DeviceInitWorker() {
}
@Override
void init(String consumerName, AppConfig appConfig) throws Exception {
super.init(consumerName, appConfig);
DelayMessageQueue<Map> queue = (DelayMessageQueue<Map>) Singleton.getInstance(DeviceInitQueueMessageHandler.NAME).getObject();
ConsumerMode mode = ConsumerMode.valueOf(appConfig.get("mqtt.consumer."+consumerName+".consumermode", "SINGLE"));
int batchCapacity = appConfig.getAsInt("mqtt.consumer."+consumerName+".batch.capacity", 10);
queue.setCapacity(batchCapacity);
queue.setMode(mode);
}
@Override
public void messageArrived(String string, MqttMessage mm) throws Exception {
try {
String json = new String(mm.getPayload());
logger.debug("<< " + json + " (" + mm.getId() + " - " + mm.getQos() + ")");
Gson gson = new Gson();
Map map = gson.fromJson(json, Map.class);
String terminalSN = (String) map.get("device_sn");
if(terminalSN == null) {
logger.debug("SN Information null!");
return;
}
// put mqttclient to the map
map.put("MQTT", mqttClient);
DelayMessageQueue<Map> queue = (DelayMessageQueue<Map>) Singleton.getInstance(DeviceInitQueueMessageHandler.NAME).getObject();
boolean queued = queue.add(map);
if(!queued) {
logger.error("Init request NOT queued: {}", queued);
}
} catch (Exception ex) {
logger.error("Init: {}", ex.getMessage(), ex);
}
}
}

View File

@ -0,0 +1,184 @@
package id.iptek.utms.agent.worker;
import com.google.gson.Gson;
import id.iptek.utms.agent.AppConfig;
import id.iptek.utms.agent.model.ApplicationSimple;
import id.iptek.utms.agent.model.Diagnostic;
import id.iptek.utms.agent.model.DiagnosticInfo;
import id.iptek.utms.agent.model.LocationInfo;
import id.iptek.utms.agent.queue.ConsumerMode;
import id.iptek.utms.agent.queue.DelayMessageQueue;
import id.iptek.utms.agent.queue.DiagnosticInfoQueueMessageHandler;
import id.iptek.utms.agent.util.Singleton;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.eclipse.paho.client.mqttv3.MqttMessage;
public class DiagnosticWorker extends Worker {
@Override
void init(String consumerName, AppConfig appConfig) throws Exception {
super.init(consumerName, appConfig);
DelayMessageQueue<Diagnostic> queue = (DelayMessageQueue<Diagnostic>) Singleton.getInstance(DiagnosticInfoQueueMessageHandler.NAME).getObject();
ConsumerMode mode = ConsumerMode.valueOf(appConfig.get("mqtt.consumer."+consumerName+".consumermode", "SINGLE"));
int batchCapacity = appConfig.getAsInt("mqtt.consumer."+consumerName+".batch.capacity", 10);
queue.setCapacity(batchCapacity);
queue.setMode(mode);
}
@Override
public void messageArrived(String string, MqttMessage mm) throws Exception {
try {
String json = new String(mm.getPayload());
this.logger.debug("<< " + json + " (" + mm.getId() + " - " + mm.getQos() + ")");
Gson gson = new Gson();
Map diagnosticReqMap = (Map) gson.fromJson(json, Map.class);
if(!"DIAGNOSTIC".equals((String) diagnosticReqMap.get("req_type"))) {
// skip message
return;
}
Diagnostic diagnosticReq = mapDiagnosticData(diagnosticReqMap);
// set id
diagnosticReq.setId(UUID.randomUUID().toString());
diagnosticReq.setCreateTime(new Date());
DelayMessageQueue<Diagnostic> queue = (DelayMessageQueue<Diagnostic>) Singleton.getInstance(DiagnosticInfoQueueMessageHandler.NAME).getObject();
boolean queued = queue.add(diagnosticReq);
if(!queued) {
logger.error("Diagnostic NOT queued: {}", queued);
}
} catch (Exception ex) {
this.logger.error("Error saving diagnostic: {}", ex.getMessage(), ex);
}
}
private Diagnostic mapDiagnosticData(Map map) {
String reqId = (String) map.get("req_id");
String terminalSN = (String) map.get("device_sn");
Diagnostic diagnostic = new Diagnostic();
diagnostic.setId(UUID.randomUUID().toString());
diagnostic.setReqId(reqId);
diagnostic.setDeviceSn(terminalSN);
Map diagnosticInfoMap = (Map) map.get("diagnostic_info");
boolean isNewDiagnostic = getBoolean(diagnosticInfoMap, "new_diagnostic");
DiagnosticInfo diagnosticInfo = new DiagnosticInfo();
diagnostic.setDiagnosticInfo(diagnosticInfo);
diagnosticInfo.setBatteryPercentage(getInt(diagnosticInfoMap, "battery_percentage"));
double temp = getDouble(diagnosticInfoMap, "battery_temp");
if (isNewDiagnostic) {
temp /= 10.0D;
}
diagnosticInfo.setBatteryTemp(temp);
diagnosticInfo.setMeid((String) diagnosticInfoMap.get("meid"));
diagnosticInfo.setTotalMemory((String) diagnosticInfoMap.get("total_memory"));
diagnosticInfo.setAvailableMemory((String) diagnosticInfoMap.get("available_memory"));
diagnosticInfo.setTotalFlashMemory((String) diagnosticInfoMap.get("total_flash_memory"));
diagnosticInfo.setAvailableFlashMemory((String) diagnosticInfoMap.get("available_flash_memory"));
diagnosticInfo.setTotalMobileData((String) diagnosticInfoMap.get("total_mobile_data"));
diagnosticInfo.setCurrentBootTime(getInt(diagnosticInfoMap, "current_boot_time"));
diagnosticInfo.setTotalBootTime(getInt(diagnosticInfoMap, "total_boot_time"));
diagnosticInfo.setTotalLengthPrinted(getDouble(diagnosticInfoMap, "total_length_printed"));
diagnosticInfo.setSwitchingTimes(getInt(diagnosticInfoMap, "switching_times"));
diagnosticInfo.setSwipingCardTimes(getInt(diagnosticInfoMap, "swiping_card_times"));
diagnosticInfo.setDipInsertingTimes(getInt(diagnosticInfoMap, "dip_inserting_times"));
diagnosticInfo.setNfcCardReadingTimes(getInt(diagnosticInfoMap, "nfc_card_reading_times"));
diagnosticInfo.setFrontCameraOpenTimes(getInt(diagnosticInfoMap, "front_camera_open_times"));
diagnosticInfo.setRearCameraOpenTimes(getInt(diagnosticInfoMap, "rear_camera_open_times"));
diagnosticInfo.setChargeTimes(getInt(diagnosticInfoMap, "charge_times"));
List<Map<String, Object>> installedApps = (List<Map<String, Object>>) map.get("installed_apps");
if (installedApps != null) {
List<ApplicationSimple> applications = new ArrayList<>();
installedApps.forEach(appMap -> {
String appName = getString(appMap, "app_name");
String packageName = getString(appMap, "package_name");
String version = getString(appMap, "version");
ApplicationSimple appSimple = new ApplicationSimple();
appSimple.setId(UUID.randomUUID().toString());
appSimple.setAppName(appName);
appSimple.setPackageName(packageName);
appSimple.setVersion(version);
applications.add(appSimple);
});
diagnostic.setInstalledApps(applications);
Gson gson = new Gson();
String installedAppString = gson.toJson(applications);
diagnosticInfo.setInstalledAppString(installedAppString);
}
Map locationInfoMap = (Map) map.get("location_info");
LocationInfo locationInfo = new LocationInfo();
diagnostic.setLocationInfo(locationInfo);
locationInfo.setLat((Double) locationInfoMap.get("lat"));
locationInfo.setLng((Double) locationInfoMap.get("lng"));
return diagnostic;
}
private boolean getBoolean(Map map, String key) {
Object val = map.get(key);
if (val instanceof String) {
String sVal = (String) val;
return Boolean.parseBoolean(sVal.trim());
}
if (val instanceof Boolean) {
return ((Boolean) val).booleanValue();
}
return false;
}
private double getDouble(Map map, String key) {
Object val = map.get(key);
if (val instanceof String) {
String sVal = (String) val;
return Double.parseDouble(sVal.trim());
}
if (val instanceof Double) {
return ((Double) val).doubleValue();
}
if (val instanceof Integer) {
return ((Double) val).doubleValue();
}
return 0.0D;
}
private int getInt(Map map, String key) {
Object val = map.get(key);
if (val instanceof String) {
String sVal = (String) val;
return Integer.parseInt(sVal.trim());
}
if (val instanceof Integer) {
return ((Integer) val).intValue();
}
if (val instanceof Double) {
return ((Double) val).intValue();
}
return 0;
}
private long getLong(Map map, String key) {
Object val = map.get(key);
if (val instanceof String) {
String sVal = (String) val;
if (sVal.contains("B")) {
sVal = sVal.replace("B", "");
}
return Long.parseLong(sVal.trim());
}
if (val instanceof Long) {
return ((Long) val).longValue();
}
if (val instanceof Double) {
return ((Double) val).longValue();
}
return 0L;
}
private String getString(Map map, String key) {
return (String) map.get(key);
}
}

View File

@ -0,0 +1,165 @@
package id.iptek.utms.agent.worker;
import com.google.gson.Gson;
import id.iptek.utms.agent.GenericCache;
import id.iptek.utms.agent.dao.DownloadTaskDao;
import id.iptek.utms.agent.dao.TerminalDao;
import id.iptek.utms.agent.model.TaskAckReq;
import id.iptek.utms.agent.model.TerminalIdObj;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
/**
*
* @author Jaka
*/
public class DownloadTaskAckWorker extends Worker {
private DownloadTaskDao dao = new DownloadTaskDao();
private SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private TerminalDao terminalDao = new TerminalDao();
public DownloadTaskAckWorker() {
}
@Override
public void messageArrived(String string, MqttMessage mm) throws Exception {
try {
String json = new String(mm.getPayload());
logger.debug("<< " + json + " (" + mm.getId() + " - " + mm.getQos() + ")");
Gson gson = new Gson();
Map map = gson.fromJson(json, Map.class);
String reqId = UUID.randomUUID().toString();
String requestType = (String) map.get("req_type");
if(!"DOWNLOAD_ACK".equals(requestType)) {
return;
}
String terminalSN = (String) map.get("device_sn");
String ackId = (String) map.get("ack_id");
String status = (String) map.get("status");
if("ACCEPTED".equals(status)) {
status = "NOT_STARTED";
}
int activity = translateActivityFromStatus(status);
TaskAckReq req = new TaskAckReq();
req.setReqId(reqId);
req.setAckId(ackId);
req.setTerminalSN(terminalSN);
req.setActivity(activity);
if(ackId.startsWith("BROADCAST_")) {
String taskId = ackId.substring(10);
req.setBroadcasted(true);
req.setTaskId(taskId);
}
// get terminal id from cache
String terminalId = getTerminalIdBySN(terminalSN);
if(terminalId != null) {
req.setTerminalId(terminalId);
boolean saved = dao.save(req);
logger.debug("Download task ACK request saved? {}", saved);
if(saved) {
if("INSTALL_SUCCESS".equals(status) ||
"INSTALL_FAIL".equals(status)) {
// send ack DOWNLOAD_TASK_CONFIRM_ACK
broadcastDownloadTasksConfirmACK(mqttClient, terminalSN, ackId);
}
}
} else {
logger.warn("Invalid SN: {}", terminalSN);
}
} catch(Exception ex) {
logger.error("Download task ACK: {}", ex.getMessage(), ex);
}
}
private int translateActivityFromStatus(String status) {
int activity = 0; // initial
switch(status) {
case "INITIAL":
activity = 0;
break;
case "NOT_STARTED":
activity = 1;
break;
case "DOWNLOAD_STARTED":
activity = 2;
break;
case "DOWNLOAD_SUCCESS":
activity = 3;
break;
case "DOWNLOAD_FAIL":
activity = 4;
break;
case "INSTALL_STARTED":
activity = 5;
break;
case "INSTALL_SUCCESS":
activity = 6;
break;
case "INSTALL_FAIL":
activity = 7;
break;
case "ACCEPTED":
activity = 8;
break;
}
return activity;
}
// send download task to device topic via mqtt
public void broadcastDownloadTasksConfirmACK(MqttClient mqttClient,
String terminalSN,
String ackId) throws Exception {
logger.debug("Broadcast tasks ...");
try {
try {
int qos = 2;
String topicName = terminalSN.toUpperCase() + "_IN";
// generate json
Gson gson = new Gson();
Map messageMap = new HashMap<>();
messageMap.put("req_id", UUID.randomUUID().toString());
messageMap.put("req_time", dateTimeFormat.format(new Date()));
// we'll use log's id as ack_id
messageMap.put("ack_id", ackId);
messageMap.put("req_type", "DOWNLOAD_TASK_CONFIRM_ACK");
String messageData = gson.toJson(messageMap);
logger.debug("Try publish message to: {}", topicName);
mqttClient.publish(topicName, messageData.getBytes(), qos, false);
logger.debug("Message published!");
} catch(Exception ex) {
logger.error("Error publish to device: {}", ex.getMessage(), ex);
} finally {
}
} finally {
logger.debug("Start broadcast download tasks DONE");
}
}
private String getTerminalIdBySN(String sn) throws Exception {
try {
GenericCache cache = GenericCache.getCache("terminalId");
String terminalId = (String) cache.get(sn.toLowerCase());
if(terminalId == null) {
// load from db first
TerminalIdObj terminalObj = terminalDao.getTerminalIdBySN(sn);
if(terminalObj != null) {
terminalId = terminalObj.getTerminalId();
cache.put(sn.toLowerCase(), terminalId);
}
}
return terminalId;
} finally {}
}
}

View File

@ -0,0 +1,64 @@
package id.iptek.utms.agent.worker;
import com.google.gson.Gson;
import id.iptek.utms.agent.AppConfig;
import id.iptek.utms.agent.model.HeartBeat;
import id.iptek.utms.agent.queue.ConsumerMode;
import id.iptek.utms.agent.queue.DelayMessageQueue;
import id.iptek.utms.agent.queue.HeartBeatQueueMessageHandler;
import id.iptek.utms.agent.util.Singleton;
import java.util.Date;
import java.util.UUID;
import org.eclipse.paho.client.mqttv3.MqttMessage;
/**
*
* @author Jaka
*/
public class HeartbeatWorker extends Worker {
public HeartbeatWorker() {
}
@Override
void init(String consumerName, AppConfig appConfig) throws Exception {
super.init(consumerName, appConfig);
DelayMessageQueue<HeartBeat> queue = (DelayMessageQueue<HeartBeat>) Singleton.getInstance(HeartBeatQueueMessageHandler.NAME).getObject();
ConsumerMode mode = ConsumerMode.valueOf(appConfig.get("mqtt.consumer."+consumerName+".consumermode", "SINGLE"));
int batchCapacity = appConfig.getAsInt("mqtt.consumer."+consumerName+".batch.capacity", 10);
queue.setCapacity(batchCapacity);
queue.setMode(mode);
}
@Override
protected void doSomething() throws Exception {
// do something
}
@Override
public void messageArrived(String string, MqttMessage mm) throws Exception {
try {
String json = new String(mm.getPayload());
logger.debug("<< " + json + " (" + mm.getId() + " - " + mm.getQos() + ")");
Gson gson = new Gson();
HeartBeat heartbeatReq = gson.fromJson(json, HeartBeat.class);
if(!"HEARTBEAT".equals(heartbeatReq.getReqType())) {
// skip message
return;
}
// set id
heartbeatReq.setId(UUID.randomUUID().toString());
heartbeatReq.setCreateTime(new Date());
DelayMessageQueue<HeartBeat> queue = (DelayMessageQueue<HeartBeat>) Singleton.getInstance(HeartBeatQueueMessageHandler.NAME).getObject();
boolean queued = queue.add(heartbeatReq);
if(!queued) {
logger.error("Heartbeat NOT queued: {}", queued);
}
} catch (Exception ex) {
logger.error("Error processing heartbeat: {}", ex.getMessage(), ex);
}
}
}

View File

@ -0,0 +1,623 @@
package id.iptek.utms.agent.worker;
import com.google.gson.Gson;
import id.iptek.utms.agent.AppConfig;
import id.iptek.utms.agent.GenericCache;
import id.iptek.utms.agent.dao.DeleteTaskDao;
import id.iptek.utms.agent.dao.DownloadTaskDao;
import id.iptek.utms.agent.model.Application;
import id.iptek.utms.agent.model.ApplicationSimple;
import id.iptek.utms.agent.model.PendingDeleteTask;
import id.iptek.utms.agent.model.PendingDownloadTask;
import id.iptek.utms.agent.model.SimplePendingDownloadTask;
import id.iptek.utms.agent.util.IOUtil;
import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Jaka
*/
public abstract class Worker implements MqttCallbackExtended, Runnable {
protected Logger logger;
private String brokerUrl;
private String loggingId;
private String topic;
private String clientIdPrefix;
private String user;
private String password;
private long sleep;
private long keepAlive;
private boolean cleanSession;
private int maxInflight;
private boolean autoReconnect;
private long reconnectDelayMillis;
/**
* mqtt *
*/
private MemoryPersistence persistence = new MemoryPersistence();
protected MqttClient mqttClient;
private volatile boolean running = false;
private DeleteTaskDao deleteTaskDao = new DeleteTaskDao();
private DownloadTaskDao downloadTaskDao = new DownloadTaskDao();
private static final SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat sdfYEAR = new SimpleDateFormat("yyyy");
private static final SimpleDateFormat sdfMONTH = new SimpleDateFormat("MM");
private static final SimpleDateFormat sdfDATE = new SimpleDateFormat("dd");
protected ExecutorService executorService = null;
public Worker() {
}
public void setExecutorService(ExecutorService executorService) {
this.executorService = executorService;
}
/**
* @return the brokerUrl
*/
public String getBrokerUrl() {
return brokerUrl;
}
/**
* @return the loggingId
*/
public String getLoggingId() {
return loggingId;
}
/**
* @return the topic
*/
public String getTopic() {
return topic;
}
/**
* @return the clientIdPrefix
*/
public String getClientIdPrefix() {
return clientIdPrefix;
}
/**
* @return the user
*/
public String getUser() {
return user;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @return the sleep
*/
public long getSleep() {
return sleep;
}
/**
* @return the keepAlive
*/
public long getKeepAlive() {
return keepAlive;
}
/**
* @return the cleanSession
*/
public boolean isCleanSession() {
return cleanSession;
}
/**
* @return the maxInflight
*/
public int getMaxInflight() {
return maxInflight;
}
/**
* @return the autoReconnect
*/
public boolean isAutoReconnect() {
return autoReconnect;
}
void init(String consumerName, AppConfig appConfig) throws Exception {
String _brokerUrl = appConfig.get("mqtt.broker.url");
String _loggingId = appConfig.get("mqtt.consumer." + consumerName + ".loggingid");
String _topic = appConfig.get("mqtt.consumer." + consumerName + ".topic");
String _clientIdPrefix = appConfig.get("mqtt.consumer." + consumerName + ".clientid_prefix");
String _user = appConfig.get("mqtt.consumer." + consumerName + ".user");
String _password = appConfig.get("mqtt.consumer." + consumerName + ".password");
long _sleep = appConfig.getAsLong("mqtt.consumer." + consumerName + ".sleep");
long _keepAlive = appConfig.getAsLong("mqtt.consumer." + consumerName + ".keepalive", 10L);
int _maxInflight = appConfig.getAsInt("mqtt.consumer." + consumerName + ".maxinflight", 32);
boolean _cleanSession = appConfig.getAsBoolean("mqtt.consumer." + consumerName + ".cleansession", true);
boolean _autoReconnect = appConfig.getAsBoolean("mqtt.consumer." + consumerName + ".autoreconnect", true);
long _reconnectDelayMillis = appConfig.getAsLong("mqtt.consumer." + consumerName + ".reconnect.delay.millis", 5000L);
this.brokerUrl = _brokerUrl;
this.loggingId = _loggingId;
this.topic = _topic;
this.clientIdPrefix = _clientIdPrefix;
this.user = _user;
this.password = _password;
this.sleep = _sleep;
this.keepAlive = _keepAlive;
this.maxInflight = _maxInflight;
this.cleanSession = _cleanSession;
this.autoReconnect = _autoReconnect;
this.reconnectDelayMillis = _reconnectDelayMillis;
// init logger
//logger = LoggerFactory.getLogger(getClass() + "." + _loggingId);
logger = LoggerFactory.getLogger(getClass());
}
public void start() throws Exception {
try {
this.running = true;
logger.info("Starting ...");
String clientId = getClientIdPrefix() + RandomStringUtils.randomAlphanumeric(10);
mqttClient = new MqttClient(brokerUrl, clientId, persistence);
} finally {
}
}
public void stop() throws Exception {
try {
this.running = false;
if (mqttClient != null) {
mqttClient.disconnectForcibly(0L, 250L, false);
mqttClient.close(true);
}
} finally {
// no-op
}
}
@Override
public void connectionLost(Throwable thrwbl) {
logger.warn("Connection Lost: " + thrwbl);
}
@Override
public void deliveryComplete(IMqttDeliveryToken imdt) {
// no-op
}
@Override
public void connectComplete(boolean bln, String string) {
if (getTopic() != null) {
try {
logger.info("Connected, subscribe to '{}'", getTopic());
mqttClient.subscribe(getTopic());
} catch (Exception ex) {
logger.error("Error subscribe topic: " + topic);
}
} else {
logger.debug("No topic subscribed!");
}
}
@Override
public void run() {
do {
try {
if (mqttClient != null && !mqttClient.isConnected()) {
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(isCleanSession());
connOpts.setUserName(getUser());
if (getPassword() != null) {
connOpts.setPassword(getPassword().toCharArray());
}
connOpts.setAutomaticReconnect(isAutoReconnect());
connOpts.setKeepAliveInterval((int) getKeepAlive());
connOpts.setMaxInflight(getMaxInflight());
mqttClient.setCallback(this);
logger.info("Started ...");
logger.info("Try to connect ...");
try {
mqttClient.connect(connOpts);
} catch (Exception ex) {
logger.error("Error connect MQTT broker: {}", ex.getMessage(), ex);
sleepBeforeReconnect();
continue;
}
}
// do something
try {
doSomething();
} catch (Exception ex) {
logger.error("Error doing something: {}", ex.getMessage(), ex);
}
if (getSleep() != 0L) {
try {
logger.info("Sleep for {} ms", getSleep());
TimeUnit.MILLISECONDS.sleep(getSleep());
} catch (InterruptedException ex) {
logger.error("Sleep got interrupted: {}", ex.getMessage(), ex);
Thread.currentThread().interrupt();
break;
}
}
} catch (Exception ex) {
logger.error("Error run: {}", ex.getMessage(), ex);
}
} while (running);
}
private void sleepBeforeReconnect() {
try {
logger.info("Wait {} ms before reconnecting MQTT broker", reconnectDelayMillis);
TimeUnit.MILLISECONDS.sleep(reconnectDelayMillis);
} catch (InterruptedException ex) {
logger.error("Reconnect wait interrupted: {}", ex.getMessage(), ex);
Thread.currentThread().interrupt();
running = false;
}
}
protected void doSomething() throws Exception {
}
/*
protected void publishPendingTasks(String terminalSN) {
boolean dummy = true;
if (dummy) {
return;
}
// pending delete task
List<PendingDeleteTask> pendingDeleteTaskList = deleteTaskDao.getPendingTaskForTerminal(terminalSN);
pendingDeleteTaskList.forEach((t) -> {
try {
broadcastDeleteTasksToDevice(mqttClient, t);
} catch (Exception ex) {
logger.error("Error push delete task: [{}, {}, {}]", t.getTerminalSN(), t.getId(), t.getLogId());
}
});
// pending download task
List<PendingDownloadTask> pendingDownloadTaskList = downloadTaskDao.getPendingTaskForTerminal(terminalSN);
pendingDownloadTaskList.forEach((t) -> {
try {
broadcastDownloadTasksToDevice(mqttClient, t);
} catch (Exception ex) {
logger.error("Error push download task: [{}, {}, {}]", t.getTerminalSN(), t.getId(), t.getLogId());
}
});
}
protected void publishPendingTasksForAll(int limit, int periodeMinutes, boolean checkOnline) {
// pending delete task
Date currentTime = downloadTaskDao.getCurrentTime();
logger.debug("Current server time: {}", currentTime);
logger.debug("Get all pending delete tasks ..");
List<PendingDeleteTask> pendingDeleteTaskList = null;
if(checkOnline) {
pendingDeleteTaskList = deleteTaskDao.getPendingTaskForOnlineTerminals(periodeMinutes, limit);
} else {
pendingDeleteTaskList = deleteTaskDao.getPendingTaskForTerminals(periodeMinutes, limit);
}
logger.debug("... got {} task item.", pendingDeleteTaskList.size());
pendingDeleteTaskList.forEach((t) -> {
try {
broadcastDeleteTasksToDevice(mqttClient, t);
} catch (Exception ex) {
logger.error("Error push delete task: [{}, {}, {}]", t.getTerminalSN(), t.getId(), t.getLogId(), ex);
}
});
logger.debug("Get all pending download tasks ..");
List<PendingDownloadTask> pendingDownloadTaskList = null;
if(checkOnline) {
pendingDownloadTaskList = downloadTaskDao.getPendingTaskForOnlineTerminals(periodeMinutes, limit);
} else {
pendingDownloadTaskList = downloadTaskDao.getPendingTaskForTerminals(periodeMinutes, limit);
}
logger.debug("... got {} task item.", pendingDownloadTaskList.size());
pendingDownloadTaskList.forEach((t) -> {
try {
broadcastDownloadTasksToDevice(mqttClient, t);
} catch (Exception ex) {
logger.error("Error push download task: [{}, {}, {}]", t.getTerminalSN(), t.getId(), t.getLogId(), ex);
}
});
}
protected void publishBroadcastPendingTasksForAll() {
// pending delete task
Date currentTime = downloadTaskDao.getCurrentTime();
logger.debug("Current server time: {}", currentTime);
logger.debug("Get all pending download tasks ..");
// pending download task
logger.debug("Get next BROADCAST pending download tasks ..");
PendingDownloadTask nextBroadcastDownloadTask = downloadTaskDao.getNextPendingTaskForBroadcast();
if(nextBroadcastDownloadTask != null) {
logger.debug("Pending BROADCAST download task: \"{}\"", nextBroadcastDownloadTask.getName());
try {
// cache last broadcasted task
GenericCache taskCache = GenericCache.getCache("LAST_BROADCAST_DOWNLOAD_TASK");
taskCache.put("task_id", nextBroadcastDownloadTask.getId());
broadcastDownloadTasksToDevice(mqttClient, nextBroadcastDownloadTask);
} catch(Exception ex) {
logger.error("Error BROADCAST download task: [{}]", nextBroadcastDownloadTask.getId());
}
}
}
// send delete task to device topic via mqtt
private void broadcastDeleteTasksToDevice(MqttClient mqttClient,
PendingDeleteTask task) throws Exception {
logger.debug("Broadcast tasks ...");
try {
int qos = 2;
String topicName = task.getTerminalSN().toUpperCase() + "_IN";
// generate json
Gson gson = new Gson();
Map messageMap = new HashMap<>();
messageMap.put("req_id", UUID.randomUUID().toString());
messageMap.put("req_time", dateTimeFormat.format(new Date()));
// we'll use log's id as ack_id
messageMap.put("ack_id", task.getLogId());
messageMap.put("req_type", "DELETE_APP_TASK");
// task map
Map taskMap = new HashMap<>();
taskMap.put("id", task.getId());
taskMap.put("name", task.getName());
taskMap.put("delete_time", task.getDeleteTime() != null ? dateTimeFormat.format(task.getDeleteTime()) : null);
messageMap.put("task", taskMap);
// app map
ApplicationSimple app = task.getApp();
Map appMap = new HashMap<>();
appMap.put("id", app.getId());
appMap.put("name", app.getAppName());
appMap.put("package_name", app.getPackageName());
messageMap.put("app", appMap);
String messageData = gson.toJson(messageMap);
logger.debug("Try publish message to: {}", topicName);
mqttClient.publish(topicName, messageData.getBytes(), qos, false);
logger.debug("Message published!");
// change log's last broadcast time
boolean updated = deleteTaskDao.saveLastBroadcastTs(task);
logger.debug("Delete task log last broadcast time updated? {}", updated);
} finally {
logger.debug("Start broadcast delete tasks DONE");
}
}
// send download task to device topic via mqtt
protected void broadcastDownloadTasksToDevice(MqttClient mqttClient,
PendingDownloadTask task) throws Exception {
logger.debug("Broadcast tasks ...");
try {
int qos = 2;
String topicName;
if(!"SN".equals(task.getTerminalSN().toUpperCase())) {
topicName = task.getTerminalSN().toUpperCase() + "_IN";
} else {
topicName = "SERVER_OUT";
}
// generate json
Gson gson = new Gson();
Map messageMap = new HashMap<>();
messageMap.put("req_id", UUID.randomUUID().toString());
messageMap.put("req_time", dateTimeFormat.format(new Date()));
// we'll use log's id as ack_id
messageMap.put("ack_id", task.getLogId());
messageMap.put("req_type", "DOWNLOAD_APP_TASK");
// task map
Map taskMap = new HashMap<>();
taskMap.put("id", task.getId());
taskMap.put("name", task.getName());
taskMap.put("download_time_type", getDownloadTimeTypeName(task.getDownloadTimeType()));
if (task.getDownloadTimeType() == 2) {
taskMap.put("download_time", dateTimeFormat.format(task.getDownloadTime()));
}
taskMap.put("installation_time_type", getInstallationTimeTypeName(task.getInstallationTimeType()));
if (task.getInstallationTimeType() == 2) {
taskMap.put("installation_time", dateTimeFormat.format(task.getInstallationTime()));
}
taskMap.put("installation_notification", getInstallationNotificationName(task.getInstallationNotification()));
messageMap.put("task", taskMap);
// app map
Application app = task.getApp();
Map appMap = new HashMap<>();
appMap.put("id", app.getId());
appMap.put("name", app.getAppName());
appMap.put("package_name", app.getPackageName());
appMap.put("version", app.getVersion());
appMap.put("company", app.getCompanyName());
appMap.put("uninstallable", app.isUninstallable());
appMap.put("description", app.getDescription());
if (app.getDownloadUrl() != null) {
appMap.put("download_url", app.getDownloadUrl());
appMap.put("md5_checksum", app.getChecksum());
} else {
String downloadURL = AppConfig.getInstance().get("file.download.url");
if (downloadURL != null) {
downloadURL = downloadURL.replace("{$id}", app.getApkId());
}
appMap.put("download_url", downloadURL);
String filePath = getFilePath(app.getFileId(), app.getFileExt(), app.getFileCreateDate());
appMap.put("md5_checksum", md5Checksum(IOUtil.read(new FileInputStream(filePath))));
}
messageMap.put("app", appMap);
String messageData = gson.toJson(messageMap);
logger.debug("Try publish message to: {}", topicName);
mqttClient.publish(topicName, messageData.getBytes(), qos, false);
logger.debug("Message published!");
// change log's last broadcast time
if(!"BROADCAST".equals(task.getLogId())) {
boolean updated = downloadTaskDao.saveLastBroadcastTs(task);
logger.debug("Download task log last broadcast time updated? {}", updated);
} else {
logger.debug("Do not update last broadcast time because this is broadcasted task!");
}
} finally {
logger.debug("Start broadcast download tasks DONE");
}
}
// send NONE ack for invalid download task-SN to device topic via mqtt
protected void broadcastNoneDownloadTasksToDevice(MqttClient mqttClient,
String sn, String taskId) throws Exception {
logger.debug("Broadcast NONE tasks ...");
try {
int qos = 2;
String topicName = sn.toUpperCase() + "_IN";
// generate json
Gson gson = new Gson();
Map messageMap = new HashMap<>();
messageMap.put("req_id", UUID.randomUUID().toString());
messageMap.put("req_type", "NONE");
messageMap.put("req_time", dateTimeFormat.format(new Date()));
messageMap.put("task_id", taskId);
String messageData = gson.toJson(messageMap);
logger.debug("Try publish message to: {}", topicName);
mqttClient.publish(topicName, messageData.getBytes(), qos, false);
logger.debug("Message published!");
} finally {
logger.debug("Start broadcast NONE download tasks DONE");
}
}
protected void publishBroadcastCheckPendingTasksForAll() {
// pending check task
Date currentTime = downloadTaskDao.getCurrentTime();
logger.debug("Current server time: {}", currentTime);
logger.debug("Get all pending check tasks ..");
List<SimplePendingDownloadTask> tasks = downloadTaskDao.getPendingTasksForBroadcast();
if(!tasks.isEmpty()) {
tasks.forEach((task) -> {
try {
logger.debug("Pending BROADCAST check task: \"{} - {}\"", task.getId(), task.getName());
broadcastCheckTaskToDevice(mqttClient, task);
} catch(Exception ex) {
logger.error("Error BROADCAST check task: [{} - {}]", task.getId(), task.getName());
}
});
}
}
// broadcast check task to all device topic via mqtt
private void broadcastCheckTaskToDevice(MqttClient mqttClient,
SimplePendingDownloadTask task) throws Exception {
logger.debug("Broadcast tasks ...");
try {
int qos = 2;
String topicName = "SERVER_OUT";
// generate json
Gson gson = new Gson();
Map messageMap = new HashMap<>();
messageMap.put("req_id", UUID.randomUUID().toString());
messageMap.put("req_time", dateTimeFormat.format(new Date()));
// we'll put task id here as key so same task will be ignored by device if received
// more than 1 time
messageMap.put("task_id", task.getId());
messageMap.put("req_type", "CHECK_TASK");
messageMap.put("group_list", task.getGroupIds());
String messageData = gson.toJson(messageMap);
logger.debug("Try publish message to: {}", topicName);
mqttClient.publish(topicName, messageData.getBytes(), qos, false);
logger.debug("Message published!");
} finally {
logger.debug("Start broadcast check tasks DONE");
}
}
private String getDownloadTimeTypeName(int type) {
switch (type) {
case 1:
return "NEXT_CONTACT";
case 2:
return "DATETIME";
}
return null;
}
private String getInstallationTimeTypeName(int type) {
switch (type) {
case 1:
return "IMMEDIATE_AFTER_DOWNLOAD";
case 2:
return "DATETIME";
}
return null;
}
private String getInstallationNotificationName(int type) {
switch (type) {
case 1:
return "SILENT";
case 2:
return "NEED_CONFIRMATION";
}
return null;
}
private String getFilePath(String fileId, String fileExt, Date fileCreateDate) {
String filePath = AppConfig.getInstance().get("file.dir") + File.separator
+ sdfYEAR.format(fileCreateDate) + File.separator
+ sdfMONTH.format(fileCreateDate) + File.separator
+ sdfDATE.format(fileCreateDate) + File.separator
+ fileId + "." + fileExt;
return filePath;
}
private String md5Checksum(byte[] bytes) throws Exception {
try {
String checksum = DigestUtils.md5Hex(bytes);
return checksum;
} finally {
}
}*/
}

View File

@ -0,0 +1,51 @@
package id.iptek.utms.agent.worker;
import id.iptek.utms.agent.AppConfig;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Jaka
*/
public final class WorkerFactory {
private static WorkerFactory self;
private static final Logger logger = LoggerFactory.getLogger(WorkerFactory.class);
private WorkerFactory() {
}
public List<Worker> buildWorkers(AppConfig config) throws Exception {
List<Worker> workers = new ArrayList<>();
try {
String[] consumerNames = config.getAll("mqtt.consumers");
logger.info("Build workers ...");
for(String consumerName : consumerNames) {
logger.debug("Build worker: '{}'", consumerName);
String workerClass = config.get("mqtt.consumer." + consumerName + ".workerclass");
Class clazz = Class.forName(workerClass);
int _threads = config.getAsInt("mqtt.consumer." + consumerName + ".threads", 1);
for(int a = 0; a < _threads; a++) {
Worker worker = (Worker) clazz.newInstance();
worker.init(consumerName, config);
workers.add(worker);
}
}
logger.info("... done build workers.");
} finally {
}
return workers;
}
public static WorkerFactory getInstance() {
if(self == null) {
self = new WorkerFactory();
}
return self;
}
}

15
utms-agent.service Normal file
View File

@ -0,0 +1,15 @@
[Unit]
Description=UTMS Agent
After=network.target
[Service]
Type=simple
User=tomcat
Group=tomcat
WorkingDirectory=/opt/utms-agent
ExecStart=/usr/bin/java -jar /opt/utms-agent/utms-agent.jar /opt/utms-agent/conf/mqtt-agents.cfg
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target