aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/traccar/model/Position.java1
-rw-r--r--src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java290
2 files changed, 285 insertions, 6 deletions
diff --git a/src/main/java/org/traccar/model/Position.java b/src/main/java/org/traccar/model/Position.java
index 6032dc588..92271854d 100644
--- a/src/main/java/org/traccar/model/Position.java
+++ b/src/main/java/org/traccar/model/Position.java
@@ -90,6 +90,7 @@ public class Position extends Message {
public static final String KEY_RESULT = "result";
public static final String KEY_DRIVER_UNIQUE_ID = "driverUniqueId";
+ public static final String KEY_BMS_INFO = "bms";
// Start with 1 not 0
public static final String PREFIX_TEMP = "temp";
diff --git a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
index 1f8fb66dd..cdc7ef45e 100644
--- a/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/Gt06ProtocolDecoder.java
@@ -15,6 +15,7 @@
*/
package org.traccar.protocol;
+import com.fasterxml.jackson.databind.ObjectMapper;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
@@ -39,14 +40,191 @@ import org.traccar.model.WifiAccessPoint;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
-import java.util.Calendar;
-import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.TimeZone;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.HashMap;
import java.util.regex.Pattern;
public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
+ static class ComplexBMS {
+ private Long time;
+ private Short relativeSoc;
+ private Integer remainingCap;
+ private Short absoluteSoc;
+ private Integer fullCap;
+ private Short soh;
+ private Integer innerTemp;
+ private Integer realCurrent;
+ private Integer voltage;
+ private Integer cycleIndex;
+ private List<Integer> batterysVol;
+ private Integer currChargingInterval;
+ private Integer maxChargingInterval;
+ private String barcode;
+ private String version;
+ private String manufacturer;
+ private Integer batteryStatus;
+ private Integer controllerStatus;
+ private Integer controllerFaultCode;
+
+ public Long getTime() {
+ return time;
+ }
+
+ public void setTime(Long time) {
+ this.time = time;
+ }
+
+ public Short getRelativeSoc() {
+ return relativeSoc;
+ }
+
+ public void setRelativeSoc(Short relativeSoc) {
+ this.relativeSoc = relativeSoc;
+ }
+
+ public Integer getRemainingCap() {
+ return remainingCap;
+ }
+
+ public void setRemainingCap(Integer remainingCap) {
+ this.remainingCap = remainingCap;
+ }
+
+ public Short getAbsoluteSoc() {
+ return absoluteSoc;
+ }
+
+ public void setAbsoluteSoc(Short absoluteSoc) {
+ this.absoluteSoc = absoluteSoc;
+ }
+
+ public Integer getFullCap() {
+ return fullCap;
+ }
+
+ public void setFullCap(Integer fullCap) {
+ this.fullCap = fullCap;
+ }
+
+ public Short getSoh() {
+ return soh;
+ }
+
+ public void setSoh(Short soh) {
+ this.soh = soh;
+ }
+
+ public Integer getInnerTemp() {
+ return innerTemp;
+ }
+
+ public void setInnerTemp(Integer innerTemp) {
+ this.innerTemp = innerTemp;
+ }
+
+ public Integer getRealCurrent() {
+ return realCurrent;
+ }
+
+ public void setRealCurrent(Integer realCurrent) {
+ this.realCurrent = realCurrent;
+ }
+
+ public Integer getVoltage() {
+ return voltage;
+ }
+
+ public void setVoltage(Integer voltage) {
+ this.voltage = voltage;
+ }
+
+ public Integer getCycleIndex() {
+ return cycleIndex;
+ }
+
+ public void setCycleIndex(Integer cycleIndex) {
+ this.cycleIndex = cycleIndex;
+ }
+
+ public List<Integer> getBatterysVol() {
+ return batterysVol;
+ }
+
+ public void setBatterysVol(List<Integer> batterysVol) {
+ this.batterysVol = batterysVol;
+ }
+
+ public Integer getCurrChargingInterval() {
+ return currChargingInterval;
+ }
+
+ public void setCurrChargingInterval(Integer currChargingInterval) {
+ this.currChargingInterval = currChargingInterval;
+ }
+
+ public Integer getMaxChargingInterval() {
+ return maxChargingInterval;
+ }
+
+ public void setMaxChargingInterval(Integer maxChargingInterval) {
+ this.maxChargingInterval = maxChargingInterval;
+ }
+
+ public String getBarcode() {
+ return barcode;
+ }
+
+ public void setBarcode(String barcode) {
+ this.barcode = barcode;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getManufacturer() {
+ return manufacturer;
+ }
+
+ public void setManufacturer(String manufacturer) {
+ this.manufacturer = manufacturer;
+ }
+
+ public Integer getBatteryStatus() {
+ return batteryStatus;
+ }
+
+ public void setBatteryStatus(Integer batteryStatus) {
+ this.batteryStatus = batteryStatus;
+ }
+
+ public Integer getControllerStatus() {
+ return controllerStatus;
+ }
+
+ public void setControllerStatus(Integer controllerStatus) {
+ this.controllerStatus = controllerStatus;
+ }
+
+ public Integer getControllerFaultCode() {
+ return controllerFaultCode;
+ }
+
+ public void setControllerFaultCode(Integer controllerFaultCode) {
+ this.controllerFaultCode = controllerFaultCode;
+ }
+ }
+
private final Map<Integer, ByteBuf> photos = new HashMap<>();
public Gt06ProtocolDecoder(Protocol protocol) {
@@ -96,6 +274,8 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
public static final int MSG_OBD = 0x8C;
public static final int MSG_DTC = 0x65;
public static final int MSG_PID = 0x66;
+ public static final int MSG_BMS_DATA = 0x40;
+ public static final int MSG_MEDIA_DATA = 0x41;
private static boolean isSupported(int type) {
return hasGps(type) || hasLbs(type) || hasStatus(type);
@@ -186,7 +366,8 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
response.writeShort(index);
response.writeShort(Checksum.crc16(Checksum.CRC16_X25,
response.nioBuffer(2, response.writerIndex() - 2)));
- response.writeByte('\r'); response.writeByte('\n'); // ending
+ response.writeByte('\r');
+ response.writeByte('\n'); // ending
channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress()));
}
}
@@ -391,7 +572,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
return position;
}
- private Object decodeBasic(Channel channel, SocketAddress remoteAddress, ByteBuf buf) {
+ private Object decodeBasic(Channel channel, SocketAddress remoteAddress, ByteBuf buf) throws Exception {
int length = buf.readUnsignedByte();
int dataLength = length - 5;
@@ -611,7 +792,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
}
private Object decodeBasicOther(Channel channel, ByteBuf buf,
- DeviceSession deviceSession, int type, int dataLength) {
+ DeviceSession deviceSession, int type, int dataLength) throws Exception {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
@@ -664,6 +845,44 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
buf.readSlice(commandLength - 1).toString(StandardCharsets.US_ASCII));
}
+ } else if (type == MSG_BMS_DATA) {
+ getLastLocation(position, new Date());
+
+ ComplexBMS bms = new ComplexBMS();
+
+ buf.skipBytes(8); // skip sn
+ bms.setTime(buf.readUnsignedInt() * 1000);
+ bms.setRelativeSoc(buf.readUnsignedByte());
+ bms.setRemainingCap(buf.readUnsignedShort());
+ bms.setAbsoluteSoc(buf.readUnsignedByte());
+ bms.setFullCap(buf.readUnsignedShort());
+ bms.setSoh(buf.readUnsignedByte());
+ bms.setInnerTemp(buf.readUnsignedShort());
+ bms.setRealCurrent(buf.readUnsignedShort());
+ bms.setVoltage(buf.readUnsignedShort());
+ bms.setCycleIndex(buf.readUnsignedShort());
+ List<Integer> batterysVol = new LinkedList<>();
+ for (int i = 0; i < 14; i++) {
+ batterysVol.add(buf.readUnsignedShort());
+ }
+ bms.setBatterysVol(batterysVol);
+ bms.setCurrChargingInterval(buf.readUnsignedShort());
+ bms.setMaxChargingInterval(buf.readUnsignedShort());
+ bms.setBarcode(buf.readCharSequence(16, StandardCharsets.US_ASCII).toString().trim());
+ bms.setVersion(Integer.toString(buf.readUnsignedShort()));
+ bms.setManufacturer(buf.readCharSequence(16, StandardCharsets.US_ASCII).toString().trim());
+ bms.setBatteryStatus(buf.readInt());
+
+ bms.setControllerStatus(buf.readInt());
+ bms.setControllerFaultCode(buf.readInt());
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ String bmsStr = objectMapper.writeValueAsString(bms);
+ position.set(Position.KEY_BMS_INFO, bmsStr);
+
+ sendResponse(channel, false, type, buf.getShort(buf.writerIndex() - 6), null);
+
+ return position;
} else if (isSupported(type)) {
if (hasGps(type)) {
@@ -749,7 +968,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
Position position = new Position(getProtocolName());
position.setDeviceId(deviceSession.getDeviceId());
- buf.readUnsignedShort(); // length
+ int dataLength = buf.readUnsignedShort(); // length
int type = buf.readUnsignedByte();
if (type == MSG_STRING_INFO) {
@@ -904,6 +1123,65 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder {
return position;
+ } else {
+ return decodeExtendedOther(channel, buf, deviceSession, type, dataLength);
+ }
+
+ return null;
+ }
+
+ private Object decodeExtendedOther(Channel channel, ByteBuf buf,
+ DeviceSession deviceSession, int type, int dataLength) {
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ if (type == MSG_MEDIA_DATA) {
+
+ buf.skipBytes(8); // skip sn
+
+ long dt = buf.readUnsignedInt() * 1000;
+
+ buf.skipBytes(4 + 4 + 2 + 1 + 1 + 2); // skip gps
+
+ buf.skipBytes(2 + 2 + 2 + 2); // skip cell
+
+ int mediaId = buf.readInt();
+ int mediaLen = buf.readInt();
+ int mediaType = buf.readUnsignedByte();
+ int mediaFormat = buf.readUnsignedByte();
+ int eventType = buf.readUnsignedByte();
+ int mediaPkgIndex = buf.readUnsignedShort();
+ int mediaPkgLen = buf.readableBytes() - (2 + 2 + 2);
+ if (mediaType != 0 || mediaFormat != 0) {
+ sendResponse(channel, true, type, buf.getShort(buf.writerIndex() - 6), null);
+ return null;
+ }
+ ByteBuf photo;
+ if (mediaPkgIndex == 0) {
+ photo = Unpooled.buffer(mediaLen);
+ if (photos.containsKey(mediaId)) {
+ photos.remove(mediaId).release();
+ }
+ photos.put(mediaId, photo);
+ } else {
+ photo = photos.get(mediaId);
+ }
+ if (null != photo) {
+ buf.readBytes(photo, mediaPkgLen);
+ if (photo.writableBytes() <= 0) {
+ Device device = Context.getDeviceManager().getById(deviceSession.getDeviceId());
+ getLastLocation(position, new Date(dt));
+ position.set(Position.KEY_IMAGE, Context.getMediaManager().writeFile(device.getUniqueId(),
+ photo, "jpg"));
+ photos.remove(mediaId).release();
+
+ sendResponse(channel, true, type, buf.getShort(buf.writerIndex() - 6), null);
+
+ return position;
+ }
+ }
+ sendResponse(channel, true, type, buf.getShort(buf.writerIndex() - 6), null);
}
return null;