From e60ecc5f2bc8bb6c53e95c4db2e68cbca79c6e54 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 6 Oct 2015 15:58:35 +1300 Subject: Implement Cityeasy protocol commands --- src/org/traccar/WebDataHandler.java | 5 +- src/org/traccar/helper/Checksum.java | 171 ++++++++++++++++++++ src/org/traccar/helper/Crc.java | 174 --------------------- src/org/traccar/model/Command.java | 2 + src/org/traccar/protocol/ApelProtocolDecoder.java | 6 +- .../traccar/protocol/AplicomProtocolDecoder.java | 4 +- .../traccar/protocol/CastelProtocolDecoder.java | 6 +- src/org/traccar/protocol/CityeasyProtocol.java | 7 + .../traccar/protocol/CityeasyProtocolDecoder.java | 16 +- .../traccar/protocol/CityeasyProtocolEncoder.java | 65 ++++++++ .../traccar/protocol/GpsGateProtocolDecoder.java | 4 +- src/org/traccar/protocol/Gt06ProtocolDecoder.java | 4 +- src/org/traccar/protocol/Gt06ProtocolEncoder.java | 4 +- src/org/traccar/protocol/KhdProtocolDecoder.java | 4 +- src/org/traccar/protocol/KhdProtocolEncoder.java | 4 +- .../traccar/protocol/LaipacProtocolDecoder.java | 4 +- .../traccar/protocol/MeiligaoProtocolDecoder.java | 6 +- .../traccar/protocol/NavigilProtocolDecoder.java | 4 +- 18 files changed, 284 insertions(+), 206 deletions(-) create mode 100644 src/org/traccar/helper/Checksum.java delete mode 100644 src/org/traccar/helper/Crc.java create mode 100644 src/org/traccar/protocol/CityeasyProtocolEncoder.java (limited to 'src/org') diff --git a/src/org/traccar/WebDataHandler.java b/src/org/traccar/WebDataHandler.java index f273385f6..c6e120bbc 100644 --- a/src/org/traccar/WebDataHandler.java +++ b/src/org/traccar/WebDataHandler.java @@ -19,7 +19,8 @@ import java.util.Calendar; import java.util.Formatter; import java.util.Locale; import java.util.TimeZone; -import org.traccar.helper.Crc; + +import org.traccar.helper.Checksum; import org.traccar.model.Device; import org.traccar.model.Event; import org.traccar.model.Position; @@ -52,7 +53,7 @@ public class WebDataHandler extends BaseDataHandler { f.format("%1$td%1$tm%1$ty,,", calendar); } - s.append(Crc.nmeaChecksum(s.toString())); + s.append(Checksum.nmeaChecksum(s.toString())); return s.toString(); } diff --git a/src/org/traccar/helper/Checksum.java b/src/org/traccar/helper/Checksum.java new file mode 100644 index 000000000..99d7e2ddb --- /dev/null +++ b/src/org/traccar/helper/Checksum.java @@ -0,0 +1,171 @@ +/* + * Copyright 2012 - 2015 Anton Tananaev (anton.tananaev@gmail.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.helper; + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.zip.CRC32; + +public class Checksum { + + private static final int CRC16_CCITT_TABLE_REVERSE[] = { + 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, + 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, + 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, + 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, + 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, + 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, + 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, + 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, + 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, + 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, + 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, + 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, + 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, + 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, + 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, + 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, + 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, + 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, + 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, + 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, + 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, + 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, + 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, + 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, + 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, + 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, + 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, + 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, + 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, + 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, + 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, + 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 + }; + + private static final int CRC16_CCITT_TABLE[] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 + }; + + private static final int CRC16_CCITT_START = 0xFFFF; + private static final int CRC16_CCITT_XOROUT = 0xFFFF; + + private static int crc16Unreflected(ByteBuffer buf, int crc_in, int[] table) { + int crc16 = crc_in; + while (buf.hasRemaining()) { + crc16 = table[((crc16 >> 8) ^ buf.get()) & 0xff] ^ (crc16 << 8); + } + return crc16 & 0xFFFF; + } + + private static int crc16Reflected(ByteBuffer buf, int crc_in, int[] table) { + int crc16 = crc_in; + while (buf.hasRemaining()) { + crc16 = table[(crc16 ^ buf.get()) & 0xff] ^ (crc16 >> 8); + } + return crc16 & 0xFFFF; + } + + public static int crc16Ccitt(ByteBuffer buf) { + return crc16Reflected(buf, CRC16_CCITT_START, CRC16_CCITT_TABLE_REVERSE) ^ CRC16_CCITT_XOROUT; + } + + public static int crc16X25Ccitt(ByteBuffer buf) { + return crc16Unreflected(buf, CRC16_CCITT_START, CRC16_CCITT_TABLE); + } + + public static int crc16Ccitt(ByteBuffer buf, int seed, int xorout) { + return crc16Reflected(buf, seed, CRC16_CCITT_TABLE_REVERSE) ^ xorout; + } + + public static int crc32(ByteBuffer buf) { + CRC32 checksum = new CRC32(); + while (buf.hasRemaining()) { + checksum.update(buf.get()); + } + return (int) checksum.getValue(); + } + + public static int xorChecksum(ByteBuffer buf) { + int checksum = 0; + while (buf.hasRemaining()) { + checksum ^= buf.get(); + } + return checksum; + } + + public static String nmeaChecksum(String msg) { + int checksum = 0; + byte bytes[] = msg.getBytes(Charset.defaultCharset()); + for (int i = 1; i < msg.length(); i++) { + checksum ^= bytes[i]; + } + return String.format("*%02x", checksum).toUpperCase(); + } + + public static long luhnChecksum(long imei) { + long checksum = 0; + long remain = imei; + + for (int i = 0; remain != 0; i++) { + long digit = remain % 10; + + if ((i % 2) == 0) { + digit *= 2; + if (digit >= 10) { + digit = 1 + (digit % 10); + } + } + + checksum += digit; + remain /= 10; + } + + return (10 - (checksum % 10)) % 10; + } + +} diff --git a/src/org/traccar/helper/Crc.java b/src/org/traccar/helper/Crc.java deleted file mode 100644 index 3df6ffd71..000000000 --- a/src/org/traccar/helper/Crc.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2012 Anton Tananaev (anton.tananaev@gmail.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.helper; - -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.util.zip.CRC32; - -/** - * CRC functions - */ -public class Crc { - - private static final int crc16CcittTableReverse[] = { - 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, - 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, - 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, - 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, - 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, - 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, - 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, - 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, - 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, - 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, - 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, - 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, - 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, - 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, - 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, - 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, - 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, - 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, - 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, - 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, - 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, - 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, - 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, - 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, - 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, - 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, - 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, - 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, - 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, - 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, - 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, - 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 - }; - - private static final int crc16CcittTable[] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 - }; - - private static final int crc16CcittStart = 0xFFFF; - private static final int crc16CcittXorout = 0xFFFF; - - private static int crc16Unreflected(ByteBuffer buf, int crc_in, int[] table) { - int crc16 = crc_in; - while (buf.hasRemaining()) { - crc16 = table[((crc16 >> 8) ^ buf.get()) & 0xff] ^ (crc16 << 8); - } - return crc16 & 0xFFFF; - } - - private static int crc16Reflected(ByteBuffer buf, int crc_in, int[] table) { - int crc16 = crc_in; - while (buf.hasRemaining()) { - crc16 = table[(crc16 ^ buf.get()) & 0xff] ^ (crc16 >> 8); - } - return crc16 & 0xFFFF; - } - - public static int crc16Ccitt(ByteBuffer buf) { - return crc16Reflected(buf, crc16CcittStart, crc16CcittTableReverse) ^ crc16CcittXorout; - } - - public static int crc16X25Ccitt(ByteBuffer buf) { - return crc16Unreflected(buf, crc16CcittStart, crc16CcittTable); - } - - public static int crc16CcittSeed(ByteBuffer buf, int seed) { - return crc16Reflected(buf, seed, crc16CcittTableReverse) ^ crc16CcittXorout; - } - - public static int crc32(ByteBuffer buf) { - CRC32 checksum = new CRC32(); - while (buf.hasRemaining()) { - checksum.update(buf.get()); - } - return (int) checksum.getValue(); - } - - public static int xorChecksum(ByteBuffer buf) { - int checksum = 0; - while (buf.hasRemaining()) { - checksum ^= buf.get(); - } - return checksum; - } - - public static String nmeaChecksum(String msg) { - int checksum = 0; - byte bytes[] = msg.getBytes(Charset.defaultCharset()); - for (int i = 1; i < msg.length(); i++) { - checksum ^= bytes[i]; - } - return String.format("*%02x", checksum).toUpperCase(); - } - - public static long luhnChecksum(long imei) { - long checksum = 0; - long remain = imei; - - for (int i = 0; remain != 0; i++) { - long digit = remain % 10; - - if ((i % 2) == 0) { - digit *= 2; - if (digit >= 10) { - digit = 1 + (digit % 10); - } - } - - checksum += digit; - remain /= 10; - } - - return (10 - (checksum % 10)) % 10; - } - -} diff --git a/src/org/traccar/model/Command.java b/src/org/traccar/model/Command.java index 13187808f..56e709150 100644 --- a/src/org/traccar/model/Command.java +++ b/src/org/traccar/model/Command.java @@ -35,9 +35,11 @@ public class Command implements Factory { public static final String TYPE_ENGINE_RESUME = "engineResume"; public static final String TYPE_ALARM_ARM = "alarmArm"; public static final String TYPE_ALARM_DISARM = "alarmDisarm"; + public static final String TYPE_SET_TIMEZONE = "setTimezone"; public static final String KEY_UNIQUE_ID = "uniqueId"; public static final String KEY_FREQUENCY = "frequency"; + public static final String KEY_TIMEZONE = "timezone"; public static final String KEY_DEVICE_PASSWORD = "devicePassword"; } diff --git a/src/org/traccar/protocol/ApelProtocolDecoder.java b/src/org/traccar/protocol/ApelProtocolDecoder.java index c3e16a7dc..7b89d374e 100644 --- a/src/org/traccar/protocol/ApelProtocolDecoder.java +++ b/src/org/traccar/protocol/ApelProtocolDecoder.java @@ -26,7 +26,7 @@ import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.helper.Log; import org.traccar.helper.UnitsConverter; import org.traccar.model.Event; @@ -75,7 +75,7 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder { ChannelBuffer request = ChannelBuffers.directBuffer(ByteOrder.LITTLE_ENDIAN, 8); request.writeShort(type); request.writeShort(0); - request.writeInt(Crc.crc32(request.toByteBuffer(0, 4))); + request.writeInt(Checksum.crc32(request.toByteBuffer(0, 4))); channel.write(request); } @@ -88,7 +88,7 @@ public class ApelProtocolDecoder extends BaseProtocolDecoder { request.writeShort(6); request.writeInt((int) lastIndex); request.writeShort(512); - request.writeInt(Crc.crc32(request.toByteBuffer(0, 10))); + request.writeInt(Checksum.crc32(request.toByteBuffer(0, 10))); channel.write(request); } } diff --git a/src/org/traccar/protocol/AplicomProtocolDecoder.java b/src/org/traccar/protocol/AplicomProtocolDecoder.java index a4d177ed0..aa9dd57d1 100644 --- a/src/org/traccar/protocol/AplicomProtocolDecoder.java +++ b/src/org/traccar/protocol/AplicomProtocolDecoder.java @@ -24,7 +24,7 @@ import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.Context; import org.traccar.helper.ChannelBufferTools; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.helper.UnitsConverter; import org.traccar.model.Event; import org.traccar.model.Position; @@ -40,7 +40,7 @@ public class AplicomProtocolDecoder extends BaseProtocolDecoder { private static final long IMEI_BASE_TC65I_V11 = 0x14143B4000000L; private static boolean validateImei(long imei) { - return Crc.luhnChecksum(imei / 10) == imei % 10; + return Checksum.luhnChecksum(imei / 10) == imei % 10; } private static long imeiFromUnitId(long unitId) { diff --git a/src/org/traccar/protocol/CastelProtocolDecoder.java b/src/org/traccar/protocol/CastelProtocolDecoder.java index ceed8f5ef..f93b9762c 100644 --- a/src/org/traccar/protocol/CastelProtocolDecoder.java +++ b/src/org/traccar/protocol/CastelProtocolDecoder.java @@ -26,7 +26,7 @@ import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.helper.UnitsConverter; import org.traccar.model.Event; import org.traccar.model.Position; @@ -95,7 +95,7 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder { response.writeByte(version); response.writeBytes(id); response.writeShort(ChannelBuffers.swapShort(MSG_HEARTBEAT_RESPONSE)); - response.writeShort(Crc.crc16Ccitt(response.toByteBuffer(0, response.writerIndex()))); + response.writeShort(Checksum.crc16Ccitt(response.toByteBuffer(0, response.writerIndex()))); response.writeByte(0x0D); response.writeByte(0x0A); channel.write(response, remoteAddress); } @@ -123,7 +123,7 @@ public class CastelProtocolDecoder extends BaseProtocolDecoder { response.writeInt(0xFFFFFFFF); response.writeShort(0); response.writeInt((int) (System.currentTimeMillis() / 1000)); - response.writeShort(Crc.crc16Ccitt(response.toByteBuffer(0, response.writerIndex()))); + response.writeShort(Checksum.crc16Ccitt(response.toByteBuffer(0, response.writerIndex()))); response.writeByte(0x0D); response.writeByte(0x0A); channel.write(response, remoteAddress); } diff --git a/src/org/traccar/protocol/CityeasyProtocol.java b/src/org/traccar/protocol/CityeasyProtocol.java index 69f7ad5ac..1049e48eb 100644 --- a/src/org/traccar/protocol/CityeasyProtocol.java +++ b/src/org/traccar/protocol/CityeasyProtocol.java @@ -20,6 +20,7 @@ import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; import org.traccar.BaseProtocol; import org.traccar.TrackerServer; +import org.traccar.model.Command; import java.util.List; @@ -27,6 +28,11 @@ public class CityeasyProtocol extends BaseProtocol { public CityeasyProtocol() { super("cityeasy"); + setSupportedCommands( + Command.TYPE_POSITION_SINGLE, + Command.TYPE_POSITION_PERIODIC, + Command.TYPE_POSITION_STOP, + Command.TYPE_SET_TIMEZONE); } @Override @@ -36,6 +42,7 @@ public class CityeasyProtocol extends BaseProtocol { protected void addSpecificHandlers(ChannelPipeline pipeline) { pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 2, 2, -4, 0)); pipeline.addLast("objectDecoder", new CityeasyProtocolDecoder(CityeasyProtocol.this)); + pipeline.addLast("objectEncoder", new CityeasyProtocolEncoder()); } }); } diff --git a/src/org/traccar/protocol/CityeasyProtocolDecoder.java b/src/org/traccar/protocol/CityeasyProtocolDecoder.java index 4cb0562a6..457ba9c5d 100644 --- a/src/org/traccar/protocol/CityeasyProtocolDecoder.java +++ b/src/org/traccar/protocol/CityeasyProtocolDecoder.java @@ -25,7 +25,7 @@ import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.helper.ChannelBufferTools; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.model.Event; import org.traccar.model.Position; @@ -51,8 +51,14 @@ public class CityeasyProtocolDecoder extends BaseProtocolDecoder { "(\\d+)" + // Cell ".*"); - private static final int MSG_LOCATION_REPORT = 0x0003; - private static final int MSG_LOCATION_INQUIRY_RESPONSE = 0x0004; + public static final int MSG_ADDRESS_REQUEST = 0x0001; + public static final int MSG_STATUS = 0x0002; + public static final int MSG_LOCATION_REPORT = 0x0003; + public static final int MSG_LOCATION_REQUEST = 0x0004; + public static final int MSG_LOCATION_INTERVAL = 0x0005; + public static final int MSG_PHONE_NUMBER = 0x0006; + public static final int MSG_MONITORING = 0x0007; + public static final int MSG_TIMEZONE = 0x0008; @Override protected Object decode( @@ -66,14 +72,14 @@ public class CityeasyProtocolDecoder extends BaseProtocolDecoder { String imei = ChannelBufferTools.readHexString(buf, 14); if (!identify(imei, channel, null, false)) { - if (!identify(imei + Crc.luhnChecksum(Long.parseLong(imei)), channel)) { + if (!identify(imei + Checksum.luhnChecksum(Long.parseLong(imei)), channel)) { return null; } } int type = buf.readUnsignedShort(); - if (type == MSG_LOCATION_REPORT || type == MSG_LOCATION_INQUIRY_RESPONSE) { + if (type == MSG_LOCATION_REPORT || type == MSG_LOCATION_REQUEST) { String sentence = buf.toString(buf.readerIndex(), buf.readableBytes() - 8, Charset.defaultCharset()); Matcher parser = pattern.matcher(sentence); diff --git a/src/org/traccar/protocol/CityeasyProtocolEncoder.java b/src/org/traccar/protocol/CityeasyProtocolEncoder.java new file mode 100644 index 000000000..9d15e9d5d --- /dev/null +++ b/src/org/traccar/protocol/CityeasyProtocolEncoder.java @@ -0,0 +1,65 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.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.protocol; + +import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBuffers; +import org.traccar.BaseProtocolEncoder; +import org.traccar.helper.Checksum; +import org.traccar.model.Command; + +public class CityeasyProtocolEncoder extends BaseProtocolEncoder { + + private ChannelBuffer encodeContent(int type, ChannelBuffer content) { + + ChannelBuffer buf = ChannelBuffers.dynamicBuffer(); + + buf.writeByte('S'); + buf.writeByte('S'); + buf.writeShort(2 + 2 + 2 + content.readableBytes() + 4 + 2 + 2); + buf.writeShort(type); + buf.writeBytes(content); + buf.writeInt(0x0B); + buf.writeShort(Checksum.crc16Ccitt(buf.toByteBuffer(), 0, 0)); + buf.writeByte('\r'); + buf.writeByte('\n'); + + return buf; + } + + @Override + protected Object encodeCommand(Command command) { + + ChannelBuffer content = ChannelBuffers.dynamicBuffer(); + + switch (command.getType()) { + case Command.TYPE_POSITION_SINGLE: + return encodeContent(CityeasyProtocolDecoder.MSG_LOCATION_REQUEST, content); + case Command.TYPE_POSITION_PERIODIC: + case Command.TYPE_POSITION_STOP: + content.writeShort(((Number) command.getAttributes().getOrDefault(Command.KEY_FREQUENCY, 0)).intValue()); + return encodeContent(CityeasyProtocolDecoder.MSG_LOCATION_INTERVAL, content); + case Command.TYPE_SET_TIMEZONE: + int timezone = ((Number) command.getAttributes().getOrDefault(Command.KEY_TIMEZONE, 0)).intValue(); + content.writeByte(timezone < 0 ? 1 : 0); + content.writeShort(Math.abs(timezone) / 60); + return encodeContent(CityeasyProtocolDecoder.MSG_TIMEZONE, content); + } + + return null; + } + +} diff --git a/src/org/traccar/protocol/GpsGateProtocolDecoder.java b/src/org/traccar/protocol/GpsGateProtocolDecoder.java index 9e583aebd..3994587bf 100644 --- a/src/org/traccar/protocol/GpsGateProtocolDecoder.java +++ b/src/org/traccar/protocol/GpsGateProtocolDecoder.java @@ -24,7 +24,7 @@ import java.util.regex.Pattern; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.model.Position; public class GpsGateProtocolDecoder extends BaseProtocolDecoder { @@ -48,7 +48,7 @@ public class GpsGateProtocolDecoder extends BaseProtocolDecoder { private void send(Channel channel, String message) { if (channel != null) { - channel.write(message + Crc.nmeaChecksum(message) + "\r\n"); + channel.write(message + Checksum.nmeaChecksum(message) + "\r\n"); } } diff --git a/src/org/traccar/protocol/Gt06ProtocolDecoder.java b/src/org/traccar/protocol/Gt06ProtocolDecoder.java index e6acc5e1b..ab5c80cf6 100644 --- a/src/org/traccar/protocol/Gt06ProtocolDecoder.java +++ b/src/org/traccar/protocol/Gt06ProtocolDecoder.java @@ -23,7 +23,7 @@ import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.Context; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.helper.UnitsConverter; import org.traccar.model.Event; import org.traccar.model.Position; @@ -81,7 +81,7 @@ public class Gt06ProtocolDecoder extends BaseProtocolDecoder { response.writeByte(0x05); // size response.writeByte(type); response.writeShort(index); - response.writeShort(Crc.crc16Ccitt(response.toByteBuffer(2, 4))); + response.writeShort(Checksum.crc16Ccitt(response.toByteBuffer(2, 4))); response.writeByte(0x0D); response.writeByte(0x0A); // ending channel.write(response); } diff --git a/src/org/traccar/protocol/Gt06ProtocolEncoder.java b/src/org/traccar/protocol/Gt06ProtocolEncoder.java index e842c3a69..9a1bb4571 100644 --- a/src/org/traccar/protocol/Gt06ProtocolEncoder.java +++ b/src/org/traccar/protocol/Gt06ProtocolEncoder.java @@ -18,7 +18,7 @@ package org.traccar.protocol; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.traccar.BaseProtocolEncoder; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.model.Command; public class Gt06ProtocolEncoder extends BaseProtocolEncoder { @@ -40,7 +40,7 @@ public class Gt06ProtocolEncoder extends BaseProtocolEncoder { buf.writeShort(0); // message index - buf.writeShort(Crc.crc16Ccitt(buf.toByteBuffer(2, buf.writerIndex() - 2))); + buf.writeShort(Checksum.crc16Ccitt(buf.toByteBuffer(2, buf.writerIndex() - 2))); buf.writeByte('\r'); buf.writeByte('\n'); diff --git a/src/org/traccar/protocol/KhdProtocolDecoder.java b/src/org/traccar/protocol/KhdProtocolDecoder.java index 6d634e744..3ad6761cd 100644 --- a/src/org/traccar/protocol/KhdProtocolDecoder.java +++ b/src/org/traccar/protocol/KhdProtocolDecoder.java @@ -25,7 +25,7 @@ import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.helper.ChannelBufferTools; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.helper.UnitsConverter; import org.traccar.model.Event; import org.traccar.model.Position; @@ -136,7 +136,7 @@ public class KhdProtocolDecoder extends BaseProtocolDecoder { response.writeByte(buf.readUnsignedByte()); response.writeByte(type); response.writeByte(0); // reserved - response.writeByte(Crc.xorChecksum(response.toByteBuffer())); + response.writeByte(Checksum.xorChecksum(response.toByteBuffer())); response.writeByte(0x0D); // ending channel.write(response); diff --git a/src/org/traccar/protocol/KhdProtocolEncoder.java b/src/org/traccar/protocol/KhdProtocolEncoder.java index 68196d65c..ca2407743 100644 --- a/src/org/traccar/protocol/KhdProtocolEncoder.java +++ b/src/org/traccar/protocol/KhdProtocolEncoder.java @@ -18,7 +18,7 @@ package org.traccar.protocol; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.traccar.BaseProtocolEncoder; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.model.Command; public class KhdProtocolEncoder extends BaseProtocolEncoder { @@ -38,7 +38,7 @@ public class KhdProtocolEncoder extends BaseProtocolEncoder { buf.writeInt(0); // terminal id - buf.writeByte(Crc.xorChecksum(buf.toByteBuffer())); + buf.writeByte(Checksum.xorChecksum(buf.toByteBuffer())); buf.writeByte(0x0D); // ending return buf; diff --git a/src/org/traccar/protocol/LaipacProtocolDecoder.java b/src/org/traccar/protocol/LaipacProtocolDecoder.java index f3884650d..57dd797eb 100644 --- a/src/org/traccar/protocol/LaipacProtocolDecoder.java +++ b/src/org/traccar/protocol/LaipacProtocolDecoder.java @@ -24,7 +24,7 @@ import java.util.regex.Pattern; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.model.Position; public class LaipacProtocolDecoder extends BaseProtocolDecoder { @@ -121,7 +121,7 @@ public class LaipacProtocolDecoder extends BaseProtocolDecoder { if (type.equals("0") && Character.isLowerCase(status.charAt(0))) { response = "$EAVACK,0," + checksum; - response += Crc.nmeaChecksum(response); + response += Checksum.nmeaChecksum(response); } else if (type.equals("S") || type.equals("T")) { response = "$AVCFG,00000000,t*21"; } else if (type.equals("3")) { diff --git a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java b/src/org/traccar/protocol/MeiligaoProtocolDecoder.java index e50b4f60b..51587f3b5 100644 --- a/src/org/traccar/protocol/MeiligaoProtocolDecoder.java +++ b/src/org/traccar/protocol/MeiligaoProtocolDecoder.java @@ -27,7 +27,7 @@ import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.Context; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.model.Event; import org.traccar.model.Position; @@ -100,7 +100,7 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder { if (id.length() == 14) { // Try to recreate full IMEI number // Sometimes first digit is cut, so this won't work - if (identify(id + Crc.luhnChecksum(Long.valueOf(id)), channel, null, false)) { + if (identify(id + Checksum.luhnChecksum(Long.valueOf(id)), channel, null, false)) { return true; } } @@ -121,7 +121,7 @@ public class MeiligaoProtocolDecoder extends BaseProtocolDecoder { buf.writeBytes(id); buf.writeShort(type); buf.writeBytes(msg); - buf.writeShort(Crc.crc16X25Ccitt(buf.toByteBuffer())); + buf.writeShort(Checksum.crc16X25Ccitt(buf.toByteBuffer())); buf.writeByte('\r'); buf.writeByte('\n'); diff --git a/src/org/traccar/protocol/NavigilProtocolDecoder.java b/src/org/traccar/protocol/NavigilProtocolDecoder.java index 686c8a691..24c6618bb 100644 --- a/src/org/traccar/protocol/NavigilProtocolDecoder.java +++ b/src/org/traccar/protocol/NavigilProtocolDecoder.java @@ -22,7 +22,7 @@ import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; -import org.traccar.helper.Crc; +import org.traccar.helper.Checksum; import org.traccar.helper.UnitsConverter; import org.traccar.model.Event; import org.traccar.model.Position; @@ -68,7 +68,7 @@ public class NavigilProtocolDecoder extends BaseProtocolDecoder { header.writeShort(MESSAGE_ACKNOWLEDGEMENT); header.writeShort(header.capacity() + data.capacity()); header.writeShort(0); - header.writeShort(Crc.crc16X25Ccitt(data.toByteBuffer())); + header.writeShort(Checksum.crc16X25Ccitt(data.toByteBuffer())); header.writeInt(0); header.writeInt((int) (System.currentTimeMillis() / 1000) + LEAP_SECONDS_DELTA); -- cgit v1.2.3