aboutsummaryrefslogtreecommitdiff
path: root/src/org/traccar/Server.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/traccar/Server.java')
-rw-r--r--src/org/traccar/Server.java529
1 files changed, 529 insertions, 0 deletions
diff --git a/src/org/traccar/Server.java b/src/org/traccar/Server.java
new file mode 100644
index 000000000..7dd2a5990
--- /dev/null
+++ b/src/org/traccar/Server.java
@@ -0,0 +1,529 @@
+/*
+ * Copyright 2010 Anton Tananaev (anton@tananaev.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Properties;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.sql.DriverManager;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.logging.Logger;
+import java.util.logging.FileHandler;
+import java.util.logging.Formatter;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import org.traccar.helper.NamedParameterStatement;
+import org.jboss.netty.handler.codec.string.StringDecoder;
+import org.jboss.netty.handler.codec.string.StringEncoder;
+import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.handler.logging.LoggingHandler;
+import org.traccar.protocol.xexun.XexunFrameDecoder;
+import org.traccar.protocol.xexun.XexunProtocolDecoder;
+import org.traccar.protocol.gps103.Gps103ProtocolDecoder;
+import org.traccar.protocol.tk103.Tk103ProtocolDecoder;
+import org.traccar.protocol.gl200.Gl200ProtocolDecoder;
+import org.traccar.protocol.t55.T55ProtocolDecoder;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.SimpleChannelHandler;
+
+/**
+ * Server
+ */
+public class Server implements DataManager {
+
+ /**
+ * Server list
+ */
+ private List serverList;
+
+ private boolean loggerEnable;
+
+ public Server() {
+ serverList = new LinkedList();
+ loggerEnable = false;
+ }
+
+ public boolean isLoggerEnabled() {
+ return loggerEnable;
+ }
+
+ /**
+ * Init
+ */
+ public void init(String[] arguments)
+ throws IOException, ClassNotFoundException, SQLException {
+
+ // Load properties
+ Properties properties = new Properties();
+ if (arguments.length > 0) {
+ properties.loadFromXML(new FileInputStream(arguments[0]));
+ }
+
+ initDatabase(properties);
+ initLogger(properties);
+
+ initXexunServer(properties);
+ initGps103Server(properties);
+ initTk103Server(properties);
+ initGl200Server(properties);
+ initT55Server(properties);
+ }
+
+ /**
+ * Database connection
+ */
+ private Connection connection;
+
+ private NamedParameterStatement selectDevice;
+
+ private NamedParameterStatement insertPosition;
+
+ /**
+ * Init database
+ */
+ private void initDatabase(Properties properties)
+ throws ClassNotFoundException, SQLException {
+
+ // Load driver
+ String driver = properties.getProperty("database.driver");
+ if (driver != null) {
+ Class.forName(driver);
+ }
+
+ // Connect database
+ String url = properties.getProperty("database.url");
+ String user = properties.getProperty("database.user");
+ String password = properties.getProperty("database.password");
+
+ if (user != null && password != null) {
+ connection = DriverManager.getConnection(url, user, password);
+ } else {
+ connection = DriverManager.getConnection(url);
+ }
+
+ // Init statements
+ String selectDeviceQuery = properties.getProperty("database.selectDevice");
+ if (selectDeviceQuery != null) {
+ selectDevice = new NamedParameterStatement(connection, selectDeviceQuery);
+ }
+
+ String insertPositionQuery = properties.getProperty("database.insertPosition");
+ if (insertPositionQuery != null) {
+ insertPosition = new NamedParameterStatement(connection, insertPositionQuery);
+ }
+ }
+
+ /**
+ * Devices
+ */
+ private Map devices;
+
+ public synchronized List getDevices() throws SQLException {
+
+ List deviceList = new LinkedList();
+
+ ResultSet result = selectDevice.executeQuery();
+ while (result.next()) {
+ Device device = new Device();
+ device.setId(result.getLong("id"));
+ device.setImei(result.getString("imei"));
+ deviceList.add(device);
+ }
+
+ return deviceList;
+ }
+
+ public Device getDeviceByImei(String imei) throws SQLException {
+
+ // Init device list
+ if (devices == null) {
+ devices = new HashMap();
+
+ List deviceList = getDevices();
+
+ for (Object device: deviceList) {
+ devices.put(((Device) device).getImei(), device);
+ }
+ }
+
+ return (Device) devices.get(imei);
+ }
+
+ public synchronized void setPosition(Position position) throws SQLException {
+
+ insertPosition.setLong("device_id", position.getDeviceId());
+ insertPosition.setTimestamp("time", position.getTime());
+ insertPosition.setBoolean("valid", position.getValid());
+ insertPosition.setDouble("altitude", position.getAltitude());
+ insertPosition.setDouble("latitude", position.getLatitude());
+ insertPosition.setDouble("longitude", position.getLongitude());
+ insertPosition.setDouble("speed", position.getSpeed());
+ insertPosition.setDouble("course", position.getCourse());
+
+ insertPosition.executeUpdate();
+ }
+
+ /**
+ * Init logger
+ */
+ public void initLogger(Properties properties) throws IOException {
+
+ loggerEnable = Boolean.valueOf(properties.getProperty("logger.enable"));
+
+ if (loggerEnable) {
+
+ Logger logger = Logger.getLogger("logger");
+ String fileName = properties.getProperty("logger.file");
+ if (fileName != null) {
+
+ FileHandler file = new FileHandler(fileName, true);
+
+ file.setFormatter(new Formatter() {
+ private final String LINE_SEPARATOR =
+ System.getProperty("line.separator", "\n");
+
+ private final DateFormat dateFormat =
+ new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+
+ public String format(LogRecord record) {
+ String line = dateFormat.format(new Date(record.getMillis()));
+ line += " - ";
+ line += formatMessage(record);
+ line += LINE_SEPARATOR;
+ return line;
+ }
+ });
+
+ logger.setLevel(Level.ALL);
+ logger.addHandler(file);
+ }
+ }
+ }
+
+ /**
+ * Open channel handler
+ */
+ protected class OpenChannelHandler extends SimpleChannelHandler {
+
+ private TrackerServer server;
+
+ public OpenChannelHandler(TrackerServer server) {
+ this.server = server;
+ }
+
+ @Override
+ public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) {
+ server.getChannelGroup().add(e.getChannel());
+ }
+ }
+
+ /**
+ * Xexun pipeline factory
+ */
+ protected class XexunPipelineFactory implements ChannelPipelineFactory {
+
+ private TrackerServer server;
+ private Server serverCreator;
+ private Integer resetDelay;
+
+ public XexunPipelineFactory(
+ TrackerServer server, Server serverCreator, Integer resetDelay) {
+ this.server = server;
+ this.serverCreator = serverCreator;
+ this.resetDelay = resetDelay;
+ }
+
+ public ChannelPipeline getPipeline() {
+ ChannelPipeline pipeline = Channels.pipeline();
+ pipeline.addLast("openHandler", new OpenChannelHandler(server));
+ if (serverCreator.isLoggerEnabled()) {
+ pipeline.addLast("logger", new LoggingHandler("logger"));
+ }
+ pipeline.addLast("frameDecoder", new XexunFrameDecoder());
+ pipeline.addLast("stringDecoder", new StringDecoder());
+ pipeline.addLast("objectDecoder", new XexunProtocolDecoder(serverCreator, resetDelay));
+ pipeline.addLast("handler", new TrackerEventHandler(serverCreator));
+ return pipeline;
+ }
+ }
+
+ /**
+ * Init Xexun server
+ */
+ public void initXexunServer(Properties properties) throws SQLException {
+
+ boolean enable = Boolean.valueOf(properties.getProperty("xexun.enable"));
+ if (enable) {
+
+ TrackerServer server = new TrackerServer(
+ Integer.valueOf(properties.getProperty("xexun.port")));
+
+ String resetDelay = properties.getProperty("xexun.resetDelay");
+ server.setPipelineFactory(new XexunPipelineFactory(
+ server, this, (resetDelay == null) ? 0 : Integer.valueOf(resetDelay)));
+
+ serverList.add(server);
+ }
+ }
+
+ /**
+ * Gps103 pipeline factory
+ */
+ protected class Gps103PipelineFactory implements ChannelPipelineFactory {
+
+ private TrackerServer server;
+ private Server serverCreator;
+ private Integer resetDelay;
+
+ public Gps103PipelineFactory(
+ TrackerServer server, Server serverCreator, Integer resetDelay) {
+ this.server = server;
+ this.serverCreator = serverCreator;
+ this.resetDelay = resetDelay;
+ }
+
+ public ChannelPipeline getPipeline() {
+ ChannelPipeline pipeline = Channels.pipeline();
+ pipeline.addLast("openHandler", new OpenChannelHandler(server));
+ if (serverCreator.isLoggerEnabled()) {
+ pipeline.addLast("logger", new LoggingHandler("logger"));
+ }
+ byte delimiter[] = { (byte) ';' };
+ pipeline.addLast("frameDecoder",
+ new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter)));
+ pipeline.addLast("stringDecoder", new StringDecoder());
+ pipeline.addLast("stringEncoder", new StringEncoder());
+ pipeline.addLast("objectDecoder", new Gps103ProtocolDecoder(serverCreator, resetDelay));
+ pipeline.addLast("handler", new TrackerEventHandler(serverCreator));
+ return pipeline;
+ }
+ }
+
+ /**
+ * Init Gps103 server
+ */
+ public void initGps103Server(Properties properties) throws SQLException {
+
+ boolean enable = Boolean.valueOf(properties.getProperty("gps103.enable"));
+ if (enable) {
+
+ TrackerServer server = new TrackerServer(
+ Integer.valueOf(properties.getProperty("gps103.port")));
+
+ String resetDelay = properties.getProperty("gps103.resetDelay");
+ server.setPipelineFactory(new Gps103PipelineFactory(
+ server, this, (resetDelay == null) ? 0 : Integer.valueOf(resetDelay)));
+
+ serverList.add(server);
+ }
+ }
+
+ /**
+ * Tk103 pipeline factory
+ */
+ protected class Tk103PipelineFactory implements ChannelPipelineFactory {
+
+ private TrackerServer server;
+ private Server serverCreator;
+ private Integer resetDelay;
+
+ public Tk103PipelineFactory(
+ TrackerServer server, Server serverCreator, Integer resetDelay) {
+ this.server = server;
+ this.serverCreator = serverCreator;
+ this.resetDelay = resetDelay;
+ }
+
+ public ChannelPipeline getPipeline() {
+ ChannelPipeline pipeline = Channels.pipeline();
+ pipeline.addLast("openHandler", new OpenChannelHandler(server));
+ if (serverCreator.isLoggerEnabled()) {
+ pipeline.addLast("logger", new LoggingHandler("logger"));
+ }
+ byte delimiter[] = { (byte) ')' };
+ pipeline.addLast("frameDecoder",
+ new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter)));
+ pipeline.addLast("stringDecoder", new StringDecoder());
+ pipeline.addLast("stringEncoder", new StringEncoder());
+ pipeline.addLast("objectDecoder", new Tk103ProtocolDecoder(serverCreator, resetDelay));
+ pipeline.addLast("handler", new TrackerEventHandler(serverCreator));
+ return pipeline;
+ }
+ }
+
+ /**
+ * Init Tk103 server
+ */
+ public void initTk103Server(Properties properties) throws SQLException {
+
+ boolean enable = Boolean.valueOf(properties.getProperty("tk103.enable"));
+ if (enable) {
+
+ TrackerServer server = new TrackerServer(
+ Integer.valueOf(properties.getProperty("tk103.port")));
+
+ String resetDelay = properties.getProperty("tk103.resetDelay");
+ server.setPipelineFactory(new Tk103PipelineFactory(
+ server, this, (resetDelay == null) ? 0 : Integer.valueOf(resetDelay)));
+
+ serverList.add(server);
+ }
+ }
+
+ /**
+ * Gl200 pipeline factory
+ */
+ protected class Gl200PipelineFactory implements ChannelPipelineFactory {
+
+ private TrackerServer server;
+ private Server serverCreator;
+ private Integer resetDelay;
+
+ public Gl200PipelineFactory(
+ TrackerServer server, Server serverCreator, Integer resetDelay) {
+ this.server = server;
+ this.serverCreator = serverCreator;
+ this.resetDelay = resetDelay;
+ }
+
+ public ChannelPipeline getPipeline() {
+ ChannelPipeline pipeline = Channels.pipeline();
+ pipeline.addLast("openHandler", new OpenChannelHandler(server));
+ if (serverCreator.isLoggerEnabled()) {
+ pipeline.addLast("logger", new LoggingHandler("logger"));
+ }
+ byte delimiter[] = { (byte) '$' };
+ pipeline.addLast("frameDecoder",
+ new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter)));
+ pipeline.addLast("stringDecoder", new StringDecoder());
+ pipeline.addLast("stringEncoder", new StringEncoder());
+ pipeline.addLast("objectDecoder", new Gl200ProtocolDecoder(serverCreator, resetDelay));
+ pipeline.addLast("handler", new TrackerEventHandler(serverCreator));
+ return pipeline;
+ }
+ }
+
+ /**
+ * Init Gl200 server
+ */
+ public void initGl200Server(Properties properties) throws SQLException {
+
+ boolean enable = Boolean.valueOf(properties.getProperty("gl200.enable"));
+ if (enable) {
+
+ TrackerServer server = new TrackerServer(
+ Integer.valueOf(properties.getProperty("gl200.port")));
+
+ String resetDelay = properties.getProperty("gl200.resetDelay");
+ server.setPipelineFactory(new Gl200PipelineFactory(
+ server, this, (resetDelay == null) ? 0 : Integer.valueOf(resetDelay)));
+
+ serverList.add(server);
+ }
+ }
+
+ /**
+ * T55 pipeline factory
+ */
+ protected class T55PipelineFactory implements ChannelPipelineFactory {
+
+ private TrackerServer server;
+ private Server serverCreator;
+ private Integer resetDelay;
+
+ public T55PipelineFactory(
+ TrackerServer server, Server serverCreator, Integer resetDelay) {
+ this.server = server;
+ this.serverCreator = serverCreator;
+ this.resetDelay = resetDelay;
+ }
+
+ public ChannelPipeline getPipeline() {
+ ChannelPipeline pipeline = Channels.pipeline();
+ pipeline.addLast("openHandler", new OpenChannelHandler(server));
+ if (serverCreator.isLoggerEnabled()) {
+ pipeline.addLast("logger", new LoggingHandler("logger"));
+ }
+ byte delimiter[] = { (byte) '\r', (byte) '\n' };
+ pipeline.addLast("frameDecoder",
+ new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter)));
+ pipeline.addLast("stringDecoder", new StringDecoder());
+ pipeline.addLast("stringEncoder", new StringEncoder());
+ pipeline.addLast("objectDecoder", new T55ProtocolDecoder(serverCreator, resetDelay));
+ pipeline.addLast("handler", new TrackerEventHandler(serverCreator));
+ return pipeline;
+ }
+ }
+
+ /**
+ * Init T55 server
+ */
+ public void initT55Server(Properties properties) throws SQLException {
+
+ boolean enable = Boolean.valueOf(properties.getProperty("t55.enable"));
+ if (enable) {
+
+ TrackerServer server = new TrackerServer(
+ Integer.valueOf(properties.getProperty("t55.port")));
+
+ String resetDelay = properties.getProperty("t55.resetDelay");
+ server.setPipelineFactory(new T55PipelineFactory(
+ server, this, (resetDelay == null) ? 0 : Integer.valueOf(resetDelay)));
+
+ serverList.add(server);
+ }
+ }
+
+ /**
+ * Start
+ */
+ public void start() {
+ for (Object server: serverList) {
+ ((TrackerServer) server).start();
+ }
+ }
+
+ /**
+ * Stop
+ */
+ public void stop() {
+ for (Object server: serverList) {
+ ((TrackerServer) server).stop();
+ }
+ }
+
+ /**
+ * Destroy
+ */
+ public void destroy() {
+ serverList.clear();
+ }
+
+}