From 8532bffcec8e239c6699845e09e63da927f51d9a Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 18 Sep 2022 10:47:58 -0700 Subject: Refactor NDTPv6 protocol --- .../org/traccar/protocol/NDTPv6FrameDecoder.java | 32 --- .../java/org/traccar/protocol/NDTPv6Protocol.java | 26 -- .../traccar/protocol/NDTPv6ProtocolDecoder.java | 309 --------------------- .../traccar/protocol/NDTPv6ProtocolEncoder.java | 38 --- .../org/traccar/protocol/NdtpV6FrameDecoder.java | 32 +++ .../java/org/traccar/protocol/NdtpV6Protocol.java | 39 +++ .../traccar/protocol/NdtpV6ProtocolDecoder.java | 203 ++++++++++++++ .../traccar/protocol/NdtpV6ProtocolEncoder.java | 42 +++ 8 files changed, 316 insertions(+), 405 deletions(-) delete mode 100644 src/main/java/org/traccar/protocol/NDTPv6FrameDecoder.java delete mode 100644 src/main/java/org/traccar/protocol/NDTPv6Protocol.java delete mode 100644 src/main/java/org/traccar/protocol/NDTPv6ProtocolDecoder.java delete mode 100644 src/main/java/org/traccar/protocol/NDTPv6ProtocolEncoder.java create mode 100644 src/main/java/org/traccar/protocol/NdtpV6FrameDecoder.java create mode 100644 src/main/java/org/traccar/protocol/NdtpV6Protocol.java create mode 100644 src/main/java/org/traccar/protocol/NdtpV6ProtocolDecoder.java create mode 100644 src/main/java/org/traccar/protocol/NdtpV6ProtocolEncoder.java (limited to 'src') diff --git a/src/main/java/org/traccar/protocol/NDTPv6FrameDecoder.java b/src/main/java/org/traccar/protocol/NDTPv6FrameDecoder.java deleted file mode 100644 index c869b11a4..000000000 --- a/src/main/java/org/traccar/protocol/NDTPv6FrameDecoder.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 - 2018 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.buffer.ByteBuf; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import org.traccar.BaseFrameDecoder; - -public class NDTPv6FrameDecoder extends BaseFrameDecoder { - - @Override - protected Object decode( - ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception { - - return buf; - } - -} diff --git a/src/main/java/org/traccar/protocol/NDTPv6Protocol.java b/src/main/java/org/traccar/protocol/NDTPv6Protocol.java deleted file mode 100644 index 78dc11b50..000000000 --- a/src/main/java/org/traccar/protocol/NDTPv6Protocol.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 2020 - NDTP v6 Protocol - */ -package org.traccar.protocol; - -import org.traccar.BaseProtocol; -import org.traccar.PipelineBuilder; -import org.traccar.TrackerServer; -import org.traccar.config.Config; - -import javax.inject.Inject; - -public class NDTPv6Protocol extends BaseProtocol { - - @Inject - public NDTPv6Protocol(Config config) { - addServer( - new TrackerServer(config, getName(), false) { - @Override - protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) { - pipeline.addLast(new NDTPv6ProtocolDecoder(NDTPv6Protocol.this)); - } - } - ); - } -} diff --git a/src/main/java/org/traccar/protocol/NDTPv6ProtocolDecoder.java b/src/main/java/org/traccar/protocol/NDTPv6ProtocolDecoder.java deleted file mode 100644 index 788afd65b..000000000 --- a/src/main/java/org/traccar/protocol/NDTPv6ProtocolDecoder.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * 2020 - NDTP v6 Protocol Decoder - */ -package org.traccar.protocol; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; - -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Date; - -import org.traccar.BaseProtocolDecoder; -import org.traccar.NetworkMessage; -import org.traccar.Protocol; -import org.traccar.helper.BitUtil; -import org.traccar.helper.Checksum; -import org.traccar.model.Position; -import org.traccar.session.DeviceSession; - -public class NDTPv6ProtocolDecoder extends BaseProtocolDecoder { - - public NDTPv6ProtocolDecoder(Protocol protocol) { - super(protocol); - } - - private static final byte[] SIGNATURE = {0x7E, 0x7E}; - - private static final int NPL_FLAG_CRC = 2; - private static final int NPH_RESULT_OK = 0x00000000; - private static final int NPL_TYPE_NPH = 2; - private static final int NPL_ADDRESS_SERVER = 0; - - /* common packets for all services */ - private static final int NPH_RESULT = 0; - - /* NPH service types */ - private static final int NPH_SRV_GENERIC_CONTROLS = 0; - private static final int NPH_SRV_NAVDATA = 1; - - /* NPH_SRV_GENERIC_CONTROLS packets */ - private static final int NPH_SGC_RESULT = NPH_RESULT; - private static final int NPH_SGC_CONN_REQUEST = 100; - - /* NPH_SRV_NAVDATA packets */ - private static final int NPH_SND_RESULT = NPH_RESULT; - - private static void sendResultResponse( - Channel channel, - short serviceId, - int requestId, - int nphSendResult, - int nphResult - ) { - // Формирование пакета данных - byte[] serviceIdBytes = ByteBuffer - .allocate(2) - .order(ByteOrder.LITTLE_ENDIAN) - .putShort(serviceId) - .array(); - byte[] nphSendResultBytes = ByteBuffer - .allocate(4) - .order(ByteOrder.LITTLE_ENDIAN) - .putInt(nphSendResult) - .array(); - byte[] requestIdBytes = ByteBuffer - .allocate(4) - .order(ByteOrder.LITTLE_ENDIAN) - .putInt(requestId) - .array(); - byte[] nphResultBytes = ByteBuffer - .allocate(4) - .order(ByteOrder.LITTLE_ENDIAN) - .putInt(nphResult) - .array(); - - byte[] allByteArray = new byte[serviceIdBytes.length + - requestIdBytes.length + - nphSendResultBytes.length + - nphResultBytes.length]; - - System.arraycopy(serviceIdBytes, 0, allByteArray, 0, serviceIdBytes.length); - System.arraycopy( - nphSendResultBytes, - 0, - allByteArray, - serviceIdBytes.length, - nphSendResultBytes.length - ); - System.arraycopy( - requestIdBytes, - 0, - allByteArray, - serviceIdBytes.length + nphSendResultBytes.length, - requestIdBytes.length - ); - System.arraycopy( - nphResultBytes, - 0, - allByteArray, - serviceIdBytes.length + requestIdBytes.length + nphSendResultBytes.length, - nphResultBytes.length - ); - - // ПАКЕТ ОТВЕТА КЛИЕНТУ - ByteBuf response = Unpooled.buffer(); - // NPL - response.writeBytes(SIGNATURE); - response.writeShortLE(allByteArray.length); // Размер данных - response.writeShortLE(NPL_FLAG_CRC); // Флаги - - response.writeShort( - Checksum.crc16(Checksum.CRC16_MODBUS, ByteBuffer.wrap(allByteArray)) - ); // CRC - response.writeByte(NPL_TYPE_NPH); // Тип - response.writeIntLE(NPL_ADDRESS_SERVER); // peer_address - response.writeShortLE(0); // request_id - - response.writeBytes(allByteArray); - - channel.writeAndFlush( - new NetworkMessage(response, channel.remoteAddress()) - ); - } - - private static final short MAIN_NAV_DATA = 0; - private static final short ADDITIONAL_NAV_DATA = 2; - - private void decodeData(ByteBuf buf, Position position, int dataType) { - if (dataType == NPH_SRV_NAVDATA) { - short cellType; - short cellNumber; - - cellType = buf.readUnsignedByte(); // Тип ячейки - cellNumber = buf.readUnsignedByte(); // Номер ячейки - if (cellType == MAIN_NAV_DATA && (cellNumber == 0 || cellNumber == 1)) { - position.setTime(new Date(buf.readUnsignedIntLE() * 1000)); // Значение реального времени unix - position.setLongitude(buf.readIntLE() / 10000000.0); // Долгота в градусах, умноженная на 10 000 000 - position.setLatitude(buf.readIntLE() / 10000000.0); // Широта в градусах, умноженная на 10 000 000 - - short flags = buf.readUnsignedByte(); // Достоверность навигационных данных: - // bit7 - достоверность нав. данных (1 - достоверны, 0 – нет); - // bit6 - полушарие долготы (1 – E, 0 – W); - // bit5 - полушарие широты (1 – N, 0 – S); - // bit4 - флаг работы от встроенного аккумулятора; - // bit3 – флаг первоначального включения; - // bit2 – состояние SOS (1 – SOS, 0 – нет SOS); - // bit1 – флаг тревожной информации (один из параметров - // находится в диапазоне тревоги) - position.setValid(BitUtil.check(flags, 7)); - if (BitUtil.check(flags, 1)) { - position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); - } - position.set(Position.KEY_BATTERY, buf.readUnsignedByte() * 20); // Напряжение батареи, 1бит = 20мВ - position.set(Position.KEY_OBD_SPEED, buf.readUnsignedShortLE()); // Средняя скорость за период в км/ч - position.setSpeed(buf.readUnsignedShortLE() / 1.85); // Максимальная скорость за период в км/ч - - int course = buf.readUnsignedShortLE(); // Направление движения - position.setCourse(course); - - position.set(Position.KEY_DISTANCE, buf.readUnsignedShortLE()); // Пройденный путь, м - position.setAltitude(buf.readShortLE()); // Высота над уровнем моря в метрах (-18000 - +18000) - position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); // Количество видимых спутников - position.set(Position.KEY_PDOP, buf.readUnsignedByte()); // PDOP - } - cellType = buf.readUnsignedByte(); // Тип ячейки - cellNumber = buf.readUnsignedByte(); // Номер ячейки - if (cellType == ADDITIONAL_NAV_DATA && cellNumber == 0) { - int analogIn1 = buf.readUnsignedShortLE(); // Значение 0 аналогового входа в 16 битном формате - //(analogIn1 - отражает напряжение на батерии для радиоборта) - int analogIn2 = buf.readUnsignedShortLE(); // Значение 1 аналогового входа в 16 битном формате - int analogIn3 = buf.readUnsignedShortLE(); // Значение 2 аналогового входа в 16 битном формате - int analogIn4 = buf.readUnsignedShortLE(); // Значение 3 аналогового входа в 16 битном формате - - buf.readUnsignedByte(); // Значение цифровых входов - buf.readUnsignedByte(); // Состояние дискретных выходов - buf.readUnsignedShortLE(); // Количество импульсов на дискретном входе 0 с предыдущей нав. отметки - buf.readUnsignedShortLE(); // Количество импульсов на дискретном входе 1 с предыдущей нав. отметки - buf.readUnsignedShortLE(); // Количество импульсов на дискретном входе 2 с предыдущей нав. отметки - buf.readUnsignedShortLE(); // Количество импульсов на дискретном входе 3 с предыдущей нав. отметки - buf.readUnsignedIntLE(); // Длина трека с момента первого включения - - position.set(Position.KEY_ANTENNA, buf.readUnsignedByte()); // Сила GSM сигнала - position.set(Position.KEY_GPS, buf.readUnsignedByte()); // Состояние GPRS подключения - position.set(Position.KEY_ACCELERATION, buf.readUnsignedByte()); // Акселерометр - энергия - position.set(Position.KEY_POWER, buf.readUnsignedByte() * 200); // Напряжение борт. сети (1бит - 200мв) - - position.set(Position.PREFIX_ADC + 1, analogIn1 * 1); - position.set(Position.PREFIX_ADC + 2, analogIn2 * 1); - position.set(Position.PREFIX_ADC + 3, analogIn3 * 1); - position.set(Position.PREFIX_ADC + 4, analogIn4 * 1); - - // Расчет уровня батареи - // float Voltage = 5 / 4096 * analogIn1; // Вольтаж - - float batteryLevel = (analogIn1 - 3600) / 6; - - if (batteryLevel > 100) { - batteryLevel = 100; - } - if (batteryLevel < 0) { - batteryLevel = 0; - } - - position.set(Position.KEY_BATTERY_LEVEL, batteryLevel); - } - } - } - - @Override - protected Object decode( - Channel channel, - SocketAddress remoteAddress, - Object msg - ) - throws Exception { - ByteBuf buf = (ByteBuf) msg; - - DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); - - // Заголовок NPL - buf.skipBytes(2); // Сигнатура (7e 7e) - buf.readUnsignedShortLE(); // Размер данных (nph + размер массива данных) - buf.readUnsignedShortLE(); // Флаги соединения (2 - проверять crc) - buf.readUnsignedShortLE(); // CRC (Modbus) - buf.readUnsignedByte(); // Тип пакета (nph) - buf.readUnsignedIntLE(); // Адрес участника соединения - buf.readUnsignedShortLE(); // Идентификатор NPL - - // Заголовок NPH - int serviceId = buf.readUnsignedShortLE(); // Идентификатор услуги (NPH_SRV_NAVDATA) service_id - int serviceType = buf.readUnsignedShortLE(); // Тип пакета - buf.readUnsignedShortLE(); // Флаг (1 - требуется подтверждение) NPH_FLAG_REQUEST - long requestId = buf.readUnsignedIntLE(); // Идентификатор nph - - if ( - deviceSession == null && - serviceId == NPH_SRV_GENERIC_CONTROLS && - serviceType == NPH_SGC_CONN_REQUEST - ) { // Регистрация устройства - buf.readUnsignedShortLE(); // Версия протокола NDTP (старший номер) - buf.readUnsignedShortLE(); // Версия протокола NDTP (младший номер) - buf.readUnsignedShortLE(); // Опции соединения (connection_flags) - // Определяет настройки соединения, - // которые будут использоваться после установки соединения. - // На данный момент их две: - // - бит0: шифровать пакеты (0 - нет, 1 — да) - // - бит1: рассчитывать CRC пакетов (0 - нет, 1 — да) - // - бит2: подключение симулятора (0 — подключается обычный клиент, - // 1 подключается симулятор) - // - бит3: тип алгоритма шифрования. - // - 0 - blowfish - // - 1 – ГОСТ - // - бит8: наличие поля IMEI (0 - нет, 1 — да) - // - бит9: наличие поля IMSI (0 - нет, 1 — да) - // - остальные биты не используются. - int deviceId = buf.readUnsignedShortLE(); - Position position = new Position(getProtocolName()); - deviceSession = - getDeviceSession(channel, remoteAddress, String.valueOf(deviceId)); - position.setDeviceId(deviceSession.getDeviceId()); - - if (channel != null) { - sendResultResponse( - channel, - (short) serviceId, - (int) requestId, - NPH_SND_RESULT, - NPH_RESULT_OK - ); - } - - position.set(Position.KEY_RESULT, String.valueOf(NPH_SGC_RESULT)); - position.setTime(new Date()); - getLastLocation(position, new Date()); - position.setValid(false); - - return position; - } - - if (serviceId == NPH_SRV_NAVDATA) { - deviceSession = getDeviceSession(channel, remoteAddress); - if (deviceSession == null) { - return null; - } - - Position position = new Position(getProtocolName()); - position.setDeviceId(deviceSession.getDeviceId()); - - if (channel != null) { - sendResultResponse( - channel, - (short) serviceId, - (int) requestId, - NPH_SND_RESULT, - NPH_RESULT_OK - ); - } - - decodeData(buf, position, NPH_SRV_NAVDATA); - - return position; - } - - return null; - } -} diff --git a/src/main/java/org/traccar/protocol/NDTPv6ProtocolEncoder.java b/src/main/java/org/traccar/protocol/NDTPv6ProtocolEncoder.java deleted file mode 100644 index af0dd58f9..000000000 --- a/src/main/java/org/traccar/protocol/NDTPv6ProtocolEncoder.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 2020 - NDTP v6 Protocol Encoder - */ -package org.traccar.protocol; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import java.nio.charset.StandardCharsets; -import org.traccar.BaseProtocolEncoder; -import org.traccar.Protocol; -import org.traccar.model.Command; - -public class NDTPv6ProtocolEncoder extends BaseProtocolEncoder { - - public NDTPv6ProtocolEncoder(Protocol protocol) { - super(protocol); - } - - private ByteBuf encodeCommand(String commandString) { - ByteBuf buffer = Unpooled.buffer(); - buffer.writeBytes(commandString.getBytes(StandardCharsets.US_ASCII)); - return buffer; - } - - @Override - protected Object encodeCommand(Command command) { - switch (command.getType()) { - case Command.TYPE_IDENTIFICATION: - return encodeCommand("BB+IDNT"); - case Command.TYPE_REBOOT_DEVICE: - return encodeCommand("BB+RESET"); - case Command.TYPE_POSITION_SINGLE: - return encodeCommand("BB+RRCD"); - default: - return null; - } - } -} diff --git a/src/main/java/org/traccar/protocol/NdtpV6FrameDecoder.java b/src/main/java/org/traccar/protocol/NdtpV6FrameDecoder.java new file mode 100644 index 000000000..5b610013a --- /dev/null +++ b/src/main/java/org/traccar/protocol/NdtpV6FrameDecoder.java @@ -0,0 +1,32 @@ +/* + * Copyright 2022 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.buffer.ByteBuf; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import org.traccar.BaseFrameDecoder; + +public class NdtpV6FrameDecoder extends BaseFrameDecoder { + + @Override + protected Object decode( + ChannelHandlerContext ctx, Channel channel, ByteBuf buf) throws Exception { + + return buf; + } + +} diff --git a/src/main/java/org/traccar/protocol/NdtpV6Protocol.java b/src/main/java/org/traccar/protocol/NdtpV6Protocol.java new file mode 100644 index 000000000..ce0dbbef2 --- /dev/null +++ b/src/main/java/org/traccar/protocol/NdtpV6Protocol.java @@ -0,0 +1,39 @@ +/* + * Copyright 2022 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.StringEncoder; +import org.traccar.BaseProtocol; +import org.traccar.PipelineBuilder; +import org.traccar.TrackerServer; +import org.traccar.config.Config; + +import javax.inject.Inject; + +public class NdtpV6Protocol extends BaseProtocol { + + @Inject + public NdtpV6Protocol(Config config) { + addServer(new TrackerServer(config, getName(), false) { + @Override + protected void addProtocolHandlers(PipelineBuilder pipeline, Config config) { + pipeline.addLast(new StringEncoder()); + pipeline.addLast(new NdtpV6ProtocolDecoder(NdtpV6Protocol.this)); + } + }); + } + +} diff --git a/src/main/java/org/traccar/protocol/NdtpV6ProtocolDecoder.java b/src/main/java/org/traccar/protocol/NdtpV6ProtocolDecoder.java new file mode 100644 index 000000000..35cb0bae8 --- /dev/null +++ b/src/main/java/org/traccar/protocol/NdtpV6ProtocolDecoder.java @@ -0,0 +1,203 @@ +/* + * Copyright 2022 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.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import org.traccar.BaseProtocolDecoder; +import org.traccar.NetworkMessage; +import org.traccar.Protocol; +import org.traccar.helper.BitUtil; +import org.traccar.helper.Checksum; +import org.traccar.helper.UnitsConverter; +import org.traccar.model.Position; +import org.traccar.session.DeviceSession; + +import java.net.SocketAddress; +import java.util.Date; + +public class NdtpV6ProtocolDecoder extends BaseProtocolDecoder { + + public NdtpV6ProtocolDecoder(Protocol protocol) { + super(protocol); + } + + private static final byte[] SIGNATURE = {0x7E, 0x7E}; + + private static final int NPL_FLAG_CRC = 2; + private static final int NPH_RESULT_OK = 0x00000000; + private static final int NPL_TYPE_NPH = 2; + private static final int NPL_ADDRESS_SERVER = 0; + + private static final int NPH_RESULT = 0; + + private static final int NPH_SRV_GENERIC_CONTROLS = 0; + private static final int NPH_SRV_NAVDATA = 1; + + private static final int NPH_SGC_RESULT = NPH_RESULT; + private static final int NPH_SGC_CONN_REQUEST = 100; + + private static final int NPH_SND_RESULT = NPH_RESULT; + + private void sendResponse( + Channel channel, int serviceId, long requestId) { + + ByteBuf content = Unpooled.buffer(); + content.writeShortLE(serviceId); + content.writeIntLE(NPH_SND_RESULT); + content.writeIntLE((int) requestId); + content.writeIntLE(NPH_RESULT_OK); + + ByteBuf response = Unpooled.buffer(); + response.writeBytes(SIGNATURE); + response.writeShortLE(content.readableBytes()); + response.writeShortLE(NPL_FLAG_CRC); // flags + response.writeShort(Checksum.crc16(Checksum.CRC16_MODBUS, content.nioBuffer())); + response.writeByte(NPL_TYPE_NPH); // type + response.writeIntLE(NPL_ADDRESS_SERVER); // peer address + response.writeShortLE(0); // request id + response.writeBytes(content); + content.release(); + + channel.writeAndFlush(new NetworkMessage(response, channel.remoteAddress())); + } + + private static final short MAIN_NAV_DATA = 0; + private static final short ADDITIONAL_NAV_DATA = 2; + + private void decodeData(ByteBuf buf, Position position) { + + short itemType; + short itemIndex; + + itemType = buf.readUnsignedByte(); + itemIndex = buf.readUnsignedByte(); + if (itemType == MAIN_NAV_DATA && (itemIndex == 0 || itemIndex == 1)) { + + position.setTime(new Date(buf.readUnsignedIntLE() * 1000)); + position.setLongitude(buf.readIntLE() / 10000000.0); + position.setLatitude(buf.readIntLE() / 10000000.0); + + short flags = buf.readUnsignedByte(); + position.setValid(BitUtil.check(flags, 7)); + if (BitUtil.check(flags, 1)) { + position.set(Position.KEY_ALARM, Position.ALARM_GENERAL); + } + + position.set(Position.KEY_BATTERY, buf.readUnsignedByte() * 20); + position.set(Position.KEY_OBD_SPEED, buf.readUnsignedShortLE()); + position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShortLE())); + position.setCourse(buf.readUnsignedShortLE()); + + position.set(Position.KEY_ODOMETER, buf.readUnsignedShortLE()); + position.setAltitude(buf.readShortLE()); + position.set(Position.KEY_SATELLITES, buf.readUnsignedByte()); + position.set(Position.KEY_PDOP, buf.readUnsignedByte()); + } + + itemType = buf.readUnsignedByte(); + itemIndex = buf.readUnsignedByte(); + if (itemType == ADDITIONAL_NAV_DATA && itemIndex == 0) { + + position.set(Position.KEY_BATTERY_LEVEL, Math.max((buf.readUnsignedShortLE() - 3600) / 6, 100)); + position.set(Position.PREFIX_ADC + 2, buf.readUnsignedShortLE()); + position.set(Position.PREFIX_ADC + 3, buf.readUnsignedShortLE()); + position.set(Position.PREFIX_ADC + 4, buf.readUnsignedShortLE()); + + buf.readUnsignedByte(); // inputs + buf.readUnsignedByte(); // outputs + buf.readUnsignedShortLE(); // in1 count + buf.readUnsignedShortLE(); // in2 count + buf.readUnsignedShortLE(); // in3 count + buf.readUnsignedShortLE(); // in4 count + buf.readUnsignedIntLE(); // track length + + position.set(Position.KEY_ANTENNA, buf.readUnsignedByte()); + position.set(Position.KEY_GPS, buf.readUnsignedByte()); + position.set(Position.KEY_ACCELERATION, buf.readUnsignedByte()); + position.set(Position.KEY_POWER, buf.readUnsignedByte() * 200); + } + } + + @Override + protected Object decode( + Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + + ByteBuf buf = (ByteBuf) msg; + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress); + + buf.skipBytes(2); // signature + buf.readUnsignedShortLE(); // length + buf.readUnsignedShortLE(); // connection flags + buf.readUnsignedShortLE(); // checksum + buf.readUnsignedByte(); // type + buf.readUnsignedIntLE(); // address + buf.readUnsignedShortLE(); // identification + + int serviceId = buf.readUnsignedShortLE(); + int serviceType = buf.readUnsignedShortLE(); + buf.readUnsignedShortLE(); // request flags + long requestId = buf.readUnsignedIntLE(); + + if (deviceSession == null && serviceId == NPH_SRV_GENERIC_CONTROLS && serviceType == NPH_SGC_CONN_REQUEST) { + + buf.readUnsignedShortLE(); // version major + buf.readUnsignedShortLE(); // version minor + buf.readUnsignedShortLE(); // connection flags + + int deviceId = buf.readUnsignedShortLE(); + Position position = new Position(getProtocolName()); + deviceSession = getDeviceSession(channel, remoteAddress, String.valueOf(deviceId)); + position.setDeviceId(deviceSession.getDeviceId()); + + if (channel != null) { + sendResponse(channel, serviceId, requestId); + } + + position.set(Position.KEY_RESULT, String.valueOf(NPH_SGC_RESULT)); + position.setTime(new Date()); + getLastLocation(position, new Date()); + position.setValid(false); + + return position; + + } + + if (serviceId == NPH_SRV_NAVDATA) { + + deviceSession = getDeviceSession(channel, remoteAddress); + if (deviceSession == null) { + return null; + } + + Position position = new Position(getProtocolName()); + position.setDeviceId(deviceSession.getDeviceId()); + + if (channel != null) { + sendResponse(channel, serviceId, requestId); + } + + decodeData(buf, position); + + return position; + } + + return null; + } + +} diff --git a/src/main/java/org/traccar/protocol/NdtpV6ProtocolEncoder.java b/src/main/java/org/traccar/protocol/NdtpV6ProtocolEncoder.java new file mode 100644 index 000000000..7aac8658a --- /dev/null +++ b/src/main/java/org/traccar/protocol/NdtpV6ProtocolEncoder.java @@ -0,0 +1,42 @@ +/* + * Copyright 2022 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 org.traccar.BaseProtocolEncoder; +import org.traccar.Protocol; +import org.traccar.model.Command; + +public class NdtpV6ProtocolEncoder extends BaseProtocolEncoder { + + public NdtpV6ProtocolEncoder(Protocol protocol) { + super(protocol); + } + + @Override + protected Object encodeCommand(Command command) { + switch (command.getType()) { + case Command.TYPE_IDENTIFICATION: + return "BB+IDNT"; + case Command.TYPE_REBOOT_DEVICE: + return "BB+RESET"; + case Command.TYPE_POSITION_SINGLE: + return "BB+RRCD"; + default: + return null; + } + } + +} -- cgit v1.2.3