npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

codecs-sdk

v0.2.2

Published

* Codec 8 * Codec 8 Extended * Codec 16 * Codec 12 * Codec 13 * Codec 14

Downloads

95

Readme

Codecs

  • Codec 8
  • Codec 8 Extended
  • Codec 16
  • Codec 12
  • Codec 13
  • Codec 14

Usage

To use this library correctly and parse packets related to above codecs you have to consider three parts of each packet whether it TCP or UDP packets:

  • Header
  • Body ( AVL Records )
  • Footer
// TCP
export class TcpPacketHeader {
  preamble: number;
  length: number;
}
export const parseTCPPacketHeader = (reader: BinaryReader): TcpPacketHeader => {
  const preamble = reader.readInt32(); // or convertBytesToInt(reader.readBytes(4));
  const length = reader.readInt32(); // or convertBytesToInt(reader.readBytes(4));
  const codecId = convertBytesToInt(reader.readBytes(1));
  return {
    preamble,
    length,
  };
};


// UDP
export class UdpPacketHeader {
  preamble: number;
  packetId: number;
  packetType: number;
  avlPacketId: number;
  imeiLength: number;
  imei: any;
  codecId: number;
}
export const parseUDPPacketHeader = (reader: BinaryReader): UdpPacketHeader => {
  const preamble = convertBytesToInt(reader.readBytes(2));
  const packetId = convertBytesToInt(reader.readBytes(2));
  const packetType = convertBytesToInt(reader.readBytes(1));
  const avlPacketId = convertBytesToInt(reader.readBytes(1));
  const imeiLength = convertBytesToInt(reader.readBytes(2));
  const imei = convertBytesToInt(reader.readBytes(imeiLength));
  const codecId = convertBytesToInt(reader.readBytes(1));
  return {
    preamble,
    packetId,
    packetType,
    avlPacketId,
    imeiLength,
    imei,
    codecId,
  };
};
export const parseTCPPacketFooter = (reader: BinaryReader): TcpPacketFooter => {
  const crc = reader.readInt32();
  return { crc };
};
export const calculateCRC = (
  buffer,
  offset = 0,
  polynom = 0xa001,
  preset = 0,
) => {
  preset &= 0xffff;
  polynom &= 0xffff;

  let crc = preset;
  for (let i = 0; i < buffer.length; i++) {
    const data = buffer[(i + offset) % buffer.length] & 0xff;
    crc ^= data;
    for (let j = 0; j < 8; j++) {
      if ((crc & 0x0001) != 0) {
        crc = (crc >> 1) ^ polynom;
      } else {
        crc = crc >> 1;
      }
    }
  }
  return crc & 0xffff;
};


if(crcParsedFromPacet != calculateCRC(packetData)) 
  throw new Error(`Packet does not consist of the correct data as CRC-16 checking failed`)

In the following section you will find an implementation example which clarify the packets

Codec 8

const createCodec8Packet = () => {
  /**
   * Preamble – the packet starts with four zero bytes.
   Data Field Length – size is calculated starting from Codec ID to Number of Data 2.
   Codec ID – in Codec8 it is always 0x08.
   Number of Data 1 – a number which defines how many records are in the packet.
   AVL Data – actual data in the packet (more information below).
   Number of Data 2 – a number which defines how many records are in the packet. This number must be the same as “Number of Data 1”.
   CRC-16 – calculated from Codec ID to the Second Number of Data. CRC (Cyclic Redundancy Check) is an error-detecting code using for detect accidental changes to RAW data. For calculation we are using CRC-16/IBM.
   */
  const Preamble = '00000000'; // 4 bytes of zeros
  const Data_Field_Length = '0000009C'; // 4 bytes
  const Codec_ID = '08'; // 1 byte
  const Number_Of_Data_1 = '01'; // 1 byte

  /**
   * Note: for FMB630, FMB640 and FM63XY, minimum AVL record size is 45 bytes (all IO elements disabled). Maximum AVL record size is 255 bytes. Maximum AVL packet size is 512 bytes.
   * For other devices, the minimum AVL record size is 45 bytes (all IO elements disabled). Maximum AVL packet size is 1280 bytes.
   */
  const getAvlTestData = () => {
    /**
     * Timestamp – a difference, in milliseconds, between the current time and midnight, January, 1970 UTC (UNIX time).
     Priority – field which define AVL data priority (more information below).
     GPS Element – location information of the AVL data (more information below).
     IO Element – additional configurable information from device (more information below).
     *
     * */
    const Timestamp = '00000176BB09C2CD'; // 8 bytes
    const Priority = '00'; // 1 byte

    const getGpsElementTestData = () => {
      /**
       * Longitude – east – west position.
       Latitude – north – south position.
       Altitude – meters above sea level.
       Angle – degrees from north pole.
       Satellites – number of satellites in use.
       Speed – speed calculated from satellites.
       Note: Speed will be 0x0000 if GPS data is invalid.
       */

      // Longitude and latitude are integer values built from degrees, minutes, seconds and milliseconds by formula:
      // ( d + (m / 60) + (s / 3600) + (ms / 3600000 ) * p
      // Where:
      // d – Degrees; m – Minutes; s – Seconds; ms – Milliseconds; p – Precision (10000000)
      // If longitude is in west or latitude in south, multiply result by –1.
      //
      // Note:
      // To determine if the coordinate is negative, convert it to binary format and check the very first bit. If it is 0, coordinate is positive, if it is 1, coordinate is negative.
      // Example:
      // Received value: 20 9C CA 80 converted to BIN: 00100000 10011100 11001010 10000000 first bit is 0, which means coordinate is positive converted to DEC: 547146368. For more information see two‘s complement arithmetic.
      const Longitude = '05DBE638'; // 4 bytes
      const Latitude = '1B231893'; // 4 bytes
      const Altitude = '006A'; // 2 bytes
      const Angle = '010B'; // 2 bytes
      const Satellites = '13'; // 1 byte
      const Speed = '0000'; // 2 bytes
      return Longitude + Latitude + Altitude + Angle + Satellites + Speed;
    };

    const GPS_Element = getGpsElementTestData(); // 15 bytes

    const getIoElementsTestData = () => {
      /**
       *  Event IO ID – if data is acquired on event – this field defines which IO property has changed and generated an event. For example, when if Ignition state changed and it generate event, Event IO ID will be 0xEF (AVL ID: 239). If it’s not eventual record – the value is 0.
       N – a total number of properties coming with record (N = N1 + N2 + N4 + N8).
       N1 – number of properties, which length is 1 byte.
       N2 – number of properties, which length is 2 bytes.
       N4 – number of properties, which length is 4 bytes.
       N8 – number of properties, which length is 8 bytes.
       N’th IO ID - AVL ID.
       N’th IO Value - AVL ID value.
       */
      const Event_IO_ID = '00'; // 1 byte
      const N_Of_Total_IO = '25'; // 1 byte
      const N1_Of_One_Byte_IO = '10'; // 1 byte
      const First_IO_ID = '01'; // 1 byte
      const First_IO_Value = '00'; // 1 byte
      const N =
        Event_IO_ID +
        N_Of_Total_IO +
        N1_Of_One_Byte_IO +
        First_IO_ID +
        First_IO_Value;
      // ----------------------------------
      // N1

      const N1Th_IO_ID = '02'; // 1 byte
      const N1Th_IO_Value = '00'; // 1 byte
      const N2_Of_Two_Bytes = '03'; // 1 byte
      const N1_First_IO_ID = '01'; // 1 byte
      const N1_First_IO_Value = '0400'; // 2 byte

      const N1 =
        N1Th_IO_ID +
        N1Th_IO_Value +
        N2_Of_Two_Bytes +
        N1_First_IO_ID +
        N1_First_IO_Value;

      // ----------------------------------
      // N2
      const N2Th_IO_ID = 'B3'; // 1 byte
      const N2Th_IO_Value = '00B4'; // 2 byte
      const N4_Of_Four_Bytes = '00'; // 1 byte
      const N2_First_IO_ID = '32'; // 1 byte
      const N2_First_IO_Value = '00330016'; // 4 byte

      const N2 =
        N2Th_IO_ID +
        N2Th_IO_Value +
        N4_Of_Four_Bytes +
        N2_First_IO_ID +
        N2_First_IO_Value;

      // ----------------------------------
      // N4

      const N4Th_IO_ID = '04'; // 1 byte
      const N4Th_IO_Value = '4703F000'; // 4 byte
      const N8_Of_Eight_Bytes = '15'; // 1 byte
      const N4_First_IO_ID = '04'; // 1 byte
      const N4_First_IO_Value = 'B201C800EF009001'; // 8 byte

      const N4 =
        N4Th_IO_ID +
        N4Th_IO_Value +
        N8_Of_Eight_Bytes +
        N4_First_IO_ID +
        N4_First_IO_Value;

      // ----------------------------------
      // N8
      const N8_IO_ID = '0F'; // 1 byte
      const N8_IO_Value = '0900270A000A0B00'; // 8 byte

      const N8 = N8_IO_ID + N8_IO_Value;
      return N + N1 + N2 + N4 + N8;
    };
    const IoElements =
      getIoElementsTestData() +
      '17F5000A432683440000B50008B6000642620918000046009DCE274DECFC53EDFF9BEEFF1202F1000056C2CD000096F104DA0000D546CACF39A3DB3839343435303233DC3132313930303533DD3437330000000000'; // x bytes
    return Timestamp + Priority + GPS_Element + IoElements;
  };
  const Avl_Data = getAvlTestData(); // 45 - 256 bytes at most

  const Number_Of_Data_2 = '01'; // 1 byte
  const CRC_16 = '000013D1'; // Last 4 bytes
  return (
        Preamble +
        Data_Field_Length +
        Codec_ID +
        Number_Of_Data_1 +
        Avl_Data +
        Number_Of_Data_2 +
        CRC_16
    );
};
  • So the above formed packet shall be converted to buffer and send it to parser as following:
const buff = Buffer.from(packet, 'hex');
const reader = new BinaryReader(buff);
const header = parseTCPPacketHeader(reader);
const codec: DdsBaseClass = new Codec8(reader);
const body = codec.decode();
const footer = parseTCPPacketFooter(reader);

console.log({ header, body, footer});