atlibx
v1.13.0
Published
ATLIBX is a collection of internal utilities with no external dependencies (zero-dependency) designed for performance and cross-service use
Readme
atlibx
atlibx is a high-performance, zero-dependency Teltonika IoT protocol parser library for Node.js environments. It provides full support for Teltonika Codec 8, Codec 8 Extended, and Codec 12 (decoder & command encoder), ensuring lightweight, type-safe, and cross-service compatibility.
Key Features
- Zero External Dependencies: Built using native Node.js
BufferAPIs. - Teltonika Codec 8 & 8 Extended Support: Efficient AVL data record parsing.
- Teltonika Codec 12 Support: Complete two-way GPRS command encoding & response decoding with CRC-16/IBM validation.
- First-Class TypeScript Support: Strict typing for parsed AVL records and Codec 12 messages.
- Modern Standards: Built exclusively for ES Modules (Node.js >= 22.0.0).
Installation
Install via your preferred package manager:
# pnpm
pnpm add atlibx
# npm
npm install atlibx
# yarn
yarn add atlibxUsage
1. Parsing Codec 8 & Codec 8 Extended (AVL Data)
import { TeltonikaParser } from 'atlibx/parser' // or import from 'atlibx'
const buffer = getTcpSocketBuffer()
const parser = new TeltonikaParser(buffer)
if (!parser.isImei) {
const avl = parser.getAvl()
console.log(`Codec ID: 0x${avl.codec_id.toString(16)}`)
console.log(`Parsed ${avl.number_of_data} record(s):`)
for (const record of avl.records) {
console.log('Timestamp:', record.timestamp)
console.log('GPS:', record.gps.latitude, record.gps.longitude)
console.log('IO Elements:', record.io.elements)
}
// Advance buffer by consumed bytes
buffer = buffer.subarray(parser.consumed)
}2. Codec 12 (Command & Response Communication)
Teltonika Codec 12 is a two-way GPRS binary protocol used for sending remote commands to IoT devices (e.g., setdigout 1, getinfo, getver, cpureset) and receiving execution responses back over TCP.
Architecture Protocol Flow
+---------------------+ +---------------------+
| TCP Server | | Teltonika Device |
| (Sender & Receiver) | | (Command Executor) |
+---------------------+ +---------------------+
| |
|<----- 1. Connection & IMEI Handshake ------|
|------ 2. Accept IMEI (0x01) -------------->|
| |
|====== 3. Send Codec 12 Command ===========>|
| encodeCodec12Command("setdigout 1") |
| (Message Type: 0x05 - Command) |
| |
|<===== 4. Receive Codec 12 Response ========|
| decodeCodec12(frame) |
| (Message Type: 0x01 - Response) |
| -> "setdigout 1 ok" |A. Complete Implementation Scenario: Command Sender & Receiver Server
Below is a complete Node.js/TypeScript scenario demonstrating how a TCP server handles IMEI authentication, routes incoming packets (Codec 8/8E AVL vs Codec 12 responses), sends GPRS commands to connected devices via encodeCodec12Command(), and decodes responses using decodeCodec12().
import net from 'node:net'
import { TeltonikaParser, encodeCodec12Command, decodeCodec12 } from 'atlibx/parser'
import type { Codec12Message } from 'atlibx/parser'
// Map of active connected devices by IMEI
const activeDevices = new Map<string, net.Socket>()
// Create TCP server for Teltonika devices
const server = net.createServer((socket) => {
let imei: string | null = null
let buffer = Buffer.alloc(0)
socket.on('data', (chunk: Buffer) => {
buffer = Buffer.concat([buffer, chunk])
// 1. Handshake Phase: Teltonika sends 2-byte IMEI length + IMEI ASCII string
if (!imei) {
if (buffer.length < 2) return
const imeiLength = buffer.readUInt16BE(0)
if (buffer.length >= 2 + imeiLength) {
imei = buffer.subarray(2, 2 + imeiLength).toString('ascii')
console.log(`[TCP] Device connected | IMEI: ${imei}`)
activeDevices.set(imei, socket)
// Respond with 0x01 byte to accept device connection
socket.write(Buffer.from([0x01]))
// Slice out IMEI handshake from buffer
buffer = buffer.subarray(2 + imeiLength)
} else {
return
}
}
// 2. Data Packet Phase: Process frames starting with Preamble (0x00000000)
while (buffer.length >= 12) {
const preamble = buffer.readUInt32BE(0)
if (preamble !== 0) {
console.error(`[TCP] Invalid preamble from ${imei}. Closing socket.`)
socket.destroy()
return
}
const dataLength = buffer.readUInt32BE(4)
const totalFrameSize = dataLength + 12
if (buffer.length < totalFrameSize) {
// Incomplete packet in buffer; wait for more TCP chunks
break
}
const frameBuffer = buffer.subarray(0, totalFrameSize)
const codecId = frameBuffer.readUInt8(8)
if (codecId === 0x0c) {
// === CODEC 12: Device Command Response Receiver ===
try {
const response: Codec12Message = decodeCodec12(frameBuffer)
console.log(`[Codec 12 Receiver] Response from ${imei}:`, {
type: response.message_type === 0x01 ? 'RESPONSE' : 'COMMAND',
message: response.message,
hex: response.message_hex,
})
// Process or dispatch the command execution result
handleDeviceResponse(imei, response)
} catch (err) {
console.error(`[Codec 12] Decode error from ${imei}:`, err)
}
} else if (codecId === 0x08 || codecId === 0x8e) {
// === CODEC 8 / 8E: Telematic AVL Data Records ===
const parser = new TeltonikaParser(frameBuffer)
const avl = parser.getAvl()
console.log(`[AVL] Parsed ${avl.number_of_data} record(s) from ${imei}`)
// Acknowledge AVL record reception with 4-byte uint32 count
const ack = Buffer.alloc(4)
ack.writeUInt32BE(avl.number_of_data, 0)
socket.write(ack)
}
// Advance buffer past the processed frame
buffer = buffer.subarray(totalFrameSize)
}
})
socket.on('close', () => {
if (imei) {
console.log(`[TCP] Device disconnected | IMEI: ${imei}`)
activeDevices.delete(imei)
}
})
socket.on('error', (err) => {
console.error(`[TCP] Socket error (${imei}):`, err.message)
})
})
/**
* === CODEC 12: Command Sender ===
* Encodes a text GPRS command into Codec 12 frame and sends it over TCP socket.
*/
export function sendCodec12Command(imei: string, command: string): boolean {
const socket = activeDevices.get(imei)
if (!socket || socket.destroyed) {
console.error(`[Codec 12 Sender] Cannot send command: Device ${imei} is offline`)
return false
}
// Encode text command string into binary Codec 12 TCP frame (Type 0x05)
const commandFrame = encodeCodec12Command(command)
// Write frame to active TCP socket
socket.write(commandFrame)
console.log(`[Codec 12 Sender] Sent command "${command}" to IMEI: ${imei}`)
return true
}
function handleDeviceResponse(imei: string, response: Codec12Message) {
// Application-level handler for Codec 12 responses
console.log(`[App] Execution response from IMEI ${imei}: "${response.message}"`)
}
// Start TCP Server on port 5000
server.listen(5000, () => {
console.log('[TCP Server] Listening on port 5000 for Teltonika devices...')
})B. Standalone Decoder & Encoder APIs
1. Decoding Response from Device
import { TeltonikaParser, decodeCodec12 } from 'atlibx/parser'
// Option 1: Using standalone decoder function directly on raw frame Buffer
const responseMsg = decodeCodec12(rawFrameBuffer)
console.log('Message:', responseMsg.message) // e.g., "setdigout 1 ok"
// Option 2: Via TeltonikaParser instance
const parser = new TeltonikaParser(buffer)
if (!parser.isImei && buffer.readUInt8(8) === 0x0c) {
const response = parser.getCodec12()
console.log('Device Response:', response.message)
buffer = buffer.subarray(parser.consumed)
}2. Encoding Command to Send to Device
import { encodeCodec12Command } from 'atlibx/parser'
// Encode plain string command into a binary Codec 12 TCP frame
const frame = encodeCodec12Command('setdigout 1')
// Send frame directly over TCP socket
socket.write(frame)3. CRC-16/IBM Checksum Utility
import { crc16Ibm } from 'atlibx/parser'
const checksum = crc16Ibm(dataBuffer)
console.log('CRC-16/IBM:', checksum.toString(16))Exports
The library can be imported via root atlibx or subpath atlibx/parser:
import { TeltonikaParser, decodeCodec12, encodeCodec12Command, crc16Ibm } from 'atlibx/parser'
import type { TeltonikaAvlData, TeltonikaRecord, Codec12Message, Codec12MessageType } from 'atlibx/parser'Technical Specifications
- Runtime: Node.js >= 22.0.0
- Module System: ES Modules (ESM)
- Dependencies: 0 external dependencies
License
This project is licensed under the ISC License.
