PageRenderTime 61ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/src/org/traccar/protocol/NavigilProtocolDecoder.java

https://bitbucket.org/josedaudi_/traccar
Java | 317 lines | 225 code | 77 blank | 15 comment | 15 complexity | 4e20f7e234a0222a0589fa18b98c7d47 MD5 | raw file
  1. /*
  2. * Copyright 2013 Anton Tananaev (anton@traccar.org)
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.traccar.protocol;
  17. import org.jboss.netty.buffer.ChannelBuffer;
  18. import org.jboss.netty.buffer.ChannelBuffers;
  19. import org.jboss.netty.channel.Channel;
  20. import org.traccar.BaseProtocolDecoder;
  21. import org.traccar.DeviceSession;
  22. import org.traccar.helper.Checksum;
  23. import org.traccar.helper.Log;
  24. import org.traccar.helper.UnitsConverter;
  25. import org.traccar.model.Position;
  26. import java.net.SocketAddress;
  27. import java.nio.ByteOrder;
  28. import java.util.Date;
  29. public class NavigilProtocolDecoder extends BaseProtocolDecoder {
  30. public NavigilProtocolDecoder(NavigilProtocol protocol) {
  31. super(protocol);
  32. }
  33. private static final int LEAP_SECONDS_DELTA = 25;
  34. public static final int MSG_ERROR = 2;
  35. public static final int MSG_INDICATION = 4;
  36. public static final int MSG_CONN_OPEN = 5;
  37. public static final int MSG_CONN_CLOSE = 6;
  38. public static final int MSG_SYSTEM_REPORT = 7;
  39. public static final int MSG_UNIT_REPORT = 8;
  40. public static final int MSG_GEOFENCE_ALARM = 10;
  41. public static final int MSG_INPUT_ALARM = 11;
  42. public static final int MSG_TG2_REPORT = 12;
  43. public static final int MSG_POSITION_REPORT = 13;
  44. public static final int MSG_POSITION_REPORT_2 = 15;
  45. public static final int MSG_SNAPSHOT4 = 17;
  46. public static final int MSG_TRACKING_DATA = 18;
  47. public static final int MSG_MOTION_ALARM = 19;
  48. public static final int MSG_ACKNOWLEDGEMENT = 255;
  49. private static Date convertTimestamp(long timestamp) {
  50. return new Date((timestamp - LEAP_SECONDS_DELTA) * 1000);
  51. }
  52. private int senderSequenceNumber = 1;
  53. private void sendAcknowledgment(Channel channel, int sequenceNumber) {
  54. ChannelBuffer data = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 4);
  55. data.writeShort(sequenceNumber);
  56. data.writeShort(0); // OK
  57. ChannelBuffer header = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 20);
  58. header.writeByte(1); header.writeByte(0);
  59. header.writeShort(senderSequenceNumber++);
  60. header.writeShort(MSG_ACKNOWLEDGEMENT);
  61. header.writeShort(header.capacity() + data.capacity());
  62. header.writeShort(0);
  63. header.writeShort(Checksum.crc16(Checksum.CRC16_CCITT_FALSE, data.toByteBuffer()));
  64. header.writeInt(0);
  65. header.writeInt((int) (System.currentTimeMillis() / 1000) + LEAP_SECONDS_DELTA);
  66. if (channel != null) {
  67. channel.write(ChannelBuffers.copiedBuffer(header, data));
  68. }
  69. }
  70. private Position parseUnitReport(
  71. DeviceSession deviceSession, ChannelBuffer buf, int sequenceNumber) {
  72. Position position = new Position();
  73. position.setProtocol(getProtocolName());
  74. position.setValid(true);
  75. position.set(Position.KEY_INDEX, sequenceNumber);
  76. position.setDeviceId(deviceSession.getDeviceId());
  77. buf.readUnsignedShort(); // report trigger
  78. position.set(Position.KEY_FLAGS, buf.readUnsignedShort());
  79. position.setLatitude(buf.readInt() * 0.0000001);
  80. position.setLongitude(buf.readInt() * 0.0000001);
  81. position.setAltitude(buf.readUnsignedShort());
  82. position.set(Position.KEY_SATELLITES, buf.readUnsignedShort());
  83. position.set(Position.KEY_SATELLITES_VISIBLE, buf.readUnsignedShort());
  84. position.set("gpsAntennaState", buf.readUnsignedShort());
  85. position.setSpeed(buf.readUnsignedShort() * 0.194384);
  86. position.setCourse(buf.readUnsignedShort());
  87. position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
  88. position.set(Position.KEY_DISTANCE, buf.readUnsignedInt());
  89. position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.001);
  90. position.set(Position.KEY_CHARGE, buf.readUnsignedShort());
  91. position.setTime(convertTimestamp(buf.readUnsignedInt()));
  92. return position;
  93. }
  94. private Position parseTg2Report(
  95. DeviceSession deviceSession, ChannelBuffer buf, int sequenceNumber) {
  96. Position position = new Position();
  97. position.setProtocol(getProtocolName());
  98. position.setValid(true);
  99. position.set(Position.KEY_INDEX, sequenceNumber);
  100. position.setDeviceId(deviceSession.getDeviceId());
  101. buf.readUnsignedShort(); // report trigger
  102. buf.readUnsignedByte(); // reserved
  103. buf.readUnsignedByte(); // assisted GPS age
  104. position.setTime(convertTimestamp(buf.readUnsignedInt()));
  105. position.setLatitude(buf.readInt() * 0.0000001);
  106. position.setLongitude(buf.readInt() * 0.0000001);
  107. position.setAltitude(buf.readUnsignedShort());
  108. position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
  109. position.set(Position.KEY_SATELLITES_VISIBLE, buf.readUnsignedByte());
  110. position.setSpeed(buf.readUnsignedShort() * 0.194384);
  111. position.setCourse(buf.readUnsignedShort());
  112. position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
  113. position.set("maximumSpeed", buf.readUnsignedShort());
  114. position.set("minimumSpeed", buf.readUnsignedShort());
  115. position.set(Position.PREFIX_IO + 1, buf.readUnsignedShort()); // VSAUT1 voltage
  116. position.set(Position.PREFIX_IO + 2, buf.readUnsignedShort()); // VSAUT2 voltage
  117. position.set(Position.PREFIX_IO + 3, buf.readUnsignedShort()); // solar voltage
  118. position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.001);
  119. return position;
  120. }
  121. private Position parsePositionReport(
  122. DeviceSession deviceSession, ChannelBuffer buf, int sequenceNumber, long timestamp) {
  123. Position position = new Position();
  124. position.setProtocol(getProtocolName());
  125. position.set(Position.KEY_INDEX, sequenceNumber);
  126. position.setDeviceId(deviceSession.getDeviceId());
  127. position.setTime(convertTimestamp(timestamp));
  128. position.setLatitude(buf.readMedium() * 0.00002);
  129. position.setLongitude(buf.readMedium() * 0.00002);
  130. position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
  131. position.setCourse(buf.readUnsignedByte() * 2);
  132. short flags = buf.readUnsignedByte();
  133. position.setValid((flags & 0x80) == 0x80 && (flags & 0x40) == 0x40);
  134. buf.readUnsignedByte(); // reserved
  135. return position;
  136. }
  137. private Position parsePositionReport2(
  138. DeviceSession deviceSession, ChannelBuffer buf, int sequenceNumber, long timestamp) {
  139. Position position = new Position();
  140. position.setProtocol(getProtocolName());
  141. position.set(Position.KEY_INDEX, sequenceNumber);
  142. position.setDeviceId(deviceSession.getDeviceId());
  143. position.setTime(convertTimestamp(timestamp));
  144. position.setLatitude(buf.readInt() * 0.0000001);
  145. position.setLongitude(buf.readInt() * 0.0000001);
  146. buf.readUnsignedByte(); // report trigger
  147. position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
  148. short flags = buf.readUnsignedByte();
  149. position.setValid((flags & 0x80) == 0x80 && (flags & 0x40) == 0x40);
  150. position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
  151. position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
  152. return position;
  153. }
  154. private Position parseSnapshot4(
  155. DeviceSession deviceSession, ChannelBuffer buf, int sequenceNumber) {
  156. Position position = new Position();
  157. position.setProtocol(getProtocolName());
  158. position.set(Position.KEY_INDEX, sequenceNumber);
  159. position.setDeviceId(deviceSession.getDeviceId());
  160. buf.readUnsignedByte(); // report trigger
  161. buf.readUnsignedByte(); // position fix source
  162. buf.readUnsignedByte(); // GNSS fix quality
  163. buf.readUnsignedByte(); // GNSS assistance age
  164. long flags = buf.readUnsignedInt();
  165. position.setValid((flags & 0x0400) == 0x0400);
  166. position.setTime(convertTimestamp(buf.readUnsignedInt()));
  167. position.setLatitude(buf.readInt() * 0.0000001);
  168. position.setLongitude(buf.readInt() * 0.0000001);
  169. position.setAltitude(buf.readUnsignedShort());
  170. position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
  171. position.set(Position.KEY_SATELLITES_VISIBLE, buf.readUnsignedByte());
  172. position.setSpeed(buf.readUnsignedShort() * 0.194384);
  173. position.setCourse(buf.readUnsignedShort() * 0.1);
  174. position.set("maximumSpeed", buf.readUnsignedByte());
  175. position.set("minimumSpeed", buf.readUnsignedByte());
  176. position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
  177. position.set(Position.PREFIX_IO + 1, buf.readUnsignedByte()); // supply voltage 1
  178. position.set(Position.PREFIX_IO + 2, buf.readUnsignedByte()); // supply voltage 2
  179. position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.001);
  180. return position;
  181. }
  182. private Position parseTrackingData(
  183. DeviceSession deviceSession, ChannelBuffer buf, int sequenceNumber, long timestamp) {
  184. Position position = new Position();
  185. position.setProtocol(getProtocolName());
  186. position.set(Position.KEY_INDEX, sequenceNumber);
  187. position.setDeviceId(deviceSession.getDeviceId());
  188. position.setTime(convertTimestamp(timestamp));
  189. buf.readUnsignedByte(); // tracking mode
  190. short flags = buf.readUnsignedByte();
  191. position.setValid((flags & 0x01) == 0x01);
  192. buf.readUnsignedShort(); // duration
  193. position.setLatitude(buf.readInt() * 0.0000001);
  194. position.setLongitude(buf.readInt() * 0.0000001);
  195. position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedByte()));
  196. position.setCourse(buf.readUnsignedByte() * 2.0);
  197. position.set(Position.KEY_SATELLITES, buf.readUnsignedByte());
  198. position.set(Position.KEY_BATTERY, buf.readUnsignedShort() * 0.001);
  199. position.set(Position.KEY_ODOMETER, buf.readUnsignedInt());
  200. return position;
  201. }
  202. @Override
  203. protected Object decode(
  204. Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
  205. ChannelBuffer buf = (ChannelBuffer) msg;
  206. buf.readUnsignedByte(); // protocol version
  207. buf.readUnsignedByte(); // version id
  208. int sequenceNumber = buf.readUnsignedShort();
  209. int messageId = buf.readUnsignedShort();
  210. buf.readUnsignedShort(); // length
  211. int flags = buf.readUnsignedShort();
  212. buf.readUnsignedShort(); // checksum
  213. DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, String.valueOf(buf.readUnsignedInt()));
  214. if (deviceSession == null) {
  215. return null;
  216. }
  217. long timestamp = buf.readUnsignedInt();
  218. if ((flags & 0x1) == 0x0) {
  219. sendAcknowledgment(channel, sequenceNumber);
  220. }
  221. switch (messageId) {
  222. case MSG_UNIT_REPORT:
  223. return parseUnitReport(deviceSession, buf, sequenceNumber);
  224. case MSG_TG2_REPORT:
  225. return parseTg2Report(deviceSession, buf, sequenceNumber);
  226. case MSG_POSITION_REPORT:
  227. return parsePositionReport(deviceSession, buf, sequenceNumber, timestamp);
  228. case MSG_POSITION_REPORT_2:
  229. return parsePositionReport2(deviceSession, buf, sequenceNumber, timestamp);
  230. case MSG_SNAPSHOT4:
  231. return parseSnapshot4(deviceSession, buf, sequenceNumber);
  232. case MSG_TRACKING_DATA:
  233. return parseTrackingData(deviceSession, buf, sequenceNumber, timestamp);
  234. default:
  235. Log.warning(new UnsupportedOperationException(String.valueOf(messageId)));
  236. break;
  237. }
  238. return null;
  239. }
  240. }