aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2021-09-11 22:20:12 -0700
committerAnton Tananaev <anton.tananaev@gmail.com>2021-09-11 22:20:12 -0700
commit961570af087c2b01935542f78a851a9908ccb430 (patch)
tree32e2e9e150aa8e9d419bf55159168d92ce95954d
parent55b0a40e51e0bee5d37f0f3d34b6f1dd287973f9 (diff)
downloadtrackermap-server-961570af087c2b01935542f78a851a9908ccb430.tar.gz
trackermap-server-961570af087c2b01935542f78a851a9908ccb430.tar.bz2
trackermap-server-961570af087c2b01935542f78a851a9908ccb430.zip
Add Mictrack B2316 protocol
-rw-r--r--setup/default.xml1
-rw-r--r--src/main/java/org/traccar/protocol/B2316Protocol.java37
-rw-r--r--src/main/java/org/traccar/protocol/B2316ProtocolDecoder.java162
-rw-r--r--src/test/java/org/traccar/protocol/B2316ProtocolDecoderTest.java18
4 files changed, 218 insertions, 0 deletions
diff --git a/setup/default.xml b/setup/default.xml
index b1ff04b9a..f9529d465 100644
--- a/setup/default.xml
+++ b/setup/default.xml
@@ -295,5 +295,6 @@
<entry key='flexiblereport.port'>5227</entry>
<entry key='thinkpower.port'>5228</entry>
<entry key='stb.port'>5229</entry>
+ <entry key='b2316.port'>5230</entry>
</properties>
diff --git a/src/main/java/org/traccar/protocol/B2316Protocol.java b/src/main/java/org/traccar/protocol/B2316Protocol.java
new file mode 100644
index 000000000..7f08870ce
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/B2316Protocol.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2021 Anton Tananaev (anton@traccar.org)
+ *
+ * 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.protocol;
+
+import io.netty.handler.codec.string.StringDecoder;
+import io.netty.handler.codec.string.StringEncoder;
+import org.traccar.BaseProtocol;
+import org.traccar.PipelineBuilder;
+import org.traccar.TrackerServer;
+
+public class B2316Protocol extends BaseProtocol {
+
+ public B2316Protocol() {
+ addServer(new TrackerServer(true, getName()) {
+ @Override
+ protected void addProtocolHandlers(PipelineBuilder pipeline) {
+ pipeline.addLast(new StringEncoder());
+ pipeline.addLast(new StringDecoder());
+ pipeline.addLast(new B2316ProtocolDecoder(B2316Protocol.this));
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/traccar/protocol/B2316ProtocolDecoder.java b/src/main/java/org/traccar/protocol/B2316ProtocolDecoder.java
new file mode 100644
index 000000000..854107a20
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/B2316ProtocolDecoder.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2021 Anton Tananaev (anton@traccar.org)
+ *
+ * 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.protocol;
+
+import io.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.DeviceSession;
+import org.traccar.Protocol;
+import org.traccar.model.CellTower;
+import org.traccar.model.Network;
+import org.traccar.model.Position;
+import org.traccar.model.WifiAccessPoint;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import java.io.StringReader;
+import java.net.SocketAddress;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+public class B2316ProtocolDecoder extends BaseProtocolDecoder {
+
+ public B2316ProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ private String decodeAlarm(int value) {
+ switch (value) {
+ case 1:
+ return Position.ALARM_LOW_BATTERY;
+ case 2:
+ return Position.ALARM_SOS;
+ case 3:
+ return Position.ALARM_POWER_OFF;
+ case 4:
+ return Position.ALARM_REMOVING;
+ default:
+ return null;
+ }
+ }
+
+ private Integer decodeBattery(int value) {
+ switch (value) {
+ case 0:
+ return 10;
+ case 1:
+ return 30;
+ case 2:
+ return 60;
+ case 3:
+ return 80;
+ case 4:
+ return 100;
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ JsonObject root = Json.createReader(new StringReader((String) msg)).readObject();
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, root.getString("imei"));
+ if (deviceSession == null) {
+ return null;
+ }
+
+ List<Position> positions = new LinkedList<>();
+ JsonArray data = root.getJsonArray("data");
+ for (int i = 0; i < data.size(); i++) {
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ Network network = new Network();
+
+ JsonObject item = data.getJsonObject(i);
+ Date time = new Date(item.getJsonNumber("tm").longValue() * 1000);
+
+ if (item.containsKey("gp")) {
+ String[] coordinates = item.getString("gp").split(",");
+ position.setLongitude(Double.parseDouble(coordinates[0]));
+ position.setLatitude(Double.parseDouble(coordinates[1]));
+ position.setValid(true);
+ position.setTime(time);
+ } else {
+ getLastLocation(position, time);
+ }
+
+ if (item.containsKey("ci")) {
+ String[] cell = item.getString("ci").split(",");
+ network.addCellTower(CellTower.from(
+ Integer.parseInt(cell[0]), Integer.parseInt(cell[1]),
+ Integer.parseInt(cell[2]), Integer.parseInt(cell[3]),
+ Integer.parseInt(cell[4])));
+ }
+
+ if (item.containsKey("wi")) {
+ String[] points = item.getString("wi").split(";");
+ for (String point : points) {
+ String[] values = point.split(",");
+ network.addWifiAccessPoint(WifiAccessPoint.from(
+ values[0].replaceAll("(..)", "$1:"), Integer.parseInt(values[1])));
+ }
+ }
+
+ if (item.containsKey("wn")) {
+ position.set(Position.KEY_ALARM, decodeAlarm(item.getInt("wn")));
+ }
+ if (item.containsKey("ic")) {
+ position.set(Position.KEY_ICCID, item.getString("ic"));
+ }
+ if (item.containsKey("ve")) {
+ position.set(Position.KEY_VERSION_FW, item.getString("ve"));
+ }
+ if (item.containsKey("te")) {
+ String[] temperatures = item.getString("te").split(",");
+ for (int j = 0; j < temperatures.length; j++) {
+ position.set(Position.PREFIX_TEMP + (j + 1), Integer.parseInt(temperatures[j]) * 0.1);
+ }
+ }
+ if (item.containsKey("st")) {
+ position.set(Position.KEY_STEPS, item.getInt("st"));
+ }
+ if (item.containsKey("ba")) {
+ position.set(Position.KEY_BATTERY_LEVEL, decodeBattery(item.getInt("ba")));
+ }
+ if (item.containsKey("sn")) {
+ position.set(Position.KEY_RSSI, item.getInt("sn"));
+ }
+ if (item.containsKey("hr")) {
+ position.set(Position.KEY_HEART_RATE, item.getInt("hr"));
+ }
+
+ if (network.getCellTowers() != null || network.getWifiAccessPoints() != null) {
+ position.setNetwork(network);
+ }
+
+ positions.add(position);
+ }
+
+ return positions.isEmpty() ? null : positions;
+ }
+
+}
diff --git a/src/test/java/org/traccar/protocol/B2316ProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/B2316ProtocolDecoderTest.java
new file mode 100644
index 000000000..6b9c71b0e
--- /dev/null
+++ b/src/test/java/org/traccar/protocol/B2316ProtocolDecoderTest.java
@@ -0,0 +1,18 @@
+package org.traccar.protocol;
+
+import org.junit.Test;
+import org.traccar.ProtocolTest;
+
+public class B2316ProtocolDecoderTest extends ProtocolTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ var decoder = new B2316ProtocolDecoder(null);
+
+ verifyPositions(decoder, false, text(
+ "{\"imei\":\"866349041783600\",\"data\":[{\"tm\":1631162952,\"wn\":7},{\"tm\":1631158729,\"ic\":\"89883030000059398609\",\"ve\":\"B2316.TAU.U.TH01\"},{\"tm\":1631158805,\"te\":\"312,363\",\"st\":0,\"ba\":3,\"sn\":80},{\"tm\":1631158829,\"ci\":\"505,1,8218,133179149,-108\"},{\"tm\":1631162956,\"wi\":\"101331c17f4f,-74;f46bef7953bb,-81;b09575cff1c8,-86;e2b9e5d61a7a,-88;b0ee7b4dee2f,-88;e0b9e5d61a77,-89;f66bef7953b9,-89;\",\"te\":\"335,366\",\"hr\":58,\"bp\":\"113,73\",\"st\":0,\"ba\":3,\"sn\":60},{\"tm\":1631162968,\"ci\":\"505,1,8218,133179149,-105\"}]}"));
+
+ }
+
+}