Skip to main content

EKA-GPS Knowledge Base

EKA-GPS Knowledge Base

Version: 1.v1.6.0-hotfix-10+hotfix.2 | Last Updated: Feb 202626Feb2026


1. Overview

EKA-GPS is a TCP server microservice that receives real-time GPS telemetry from vehicle tracking devices (trucks), persists location data to MySQL, and manages geofencing-based pickup/delivery workflow state via Redis.

It is deployed on a dedicated server and serves as the central ingestion point for all fleet GPS data within the EKA logistics ecosystem.


2. Connection Details

For Third-Party GPS Device Providers

Protocol TCP (raw socket, plain text)
Host ekagps.iotapp.my
Port 6091
Encoding ASCII / UTF-8
Authentication None (open TCP)

The server expects a plain text string sent over a raw TCP socket connection. No HTTP, no WebSocket, no headers.


3. Data Format

Packet Structure

Each GPS update must be a single line, comma-separated, with exactly 10 fields:

IGT,CLIENTCODE-PLATENUMBER,YYYY-MM-DD,HH:MM:SS,IgnitionStatus,Latitude,Longitude,Speed,Direction,PTOStatus

Critical: Packets with fewer or more than 10 fields are silently dropped.

Field Reference

# Field Type Example Notes
1 Provider Code String IGT Fixed identifier from GPS provider
2 Client-Plate String EKJY-JUS9065 CLIENTCODE-PLATENUMBER or just PLATENUMBER if no hyphen
3 Date String 2025-02-26 Format: YYYY-MM-DD
4 Time String 16:30:39 Format: HH:MM:SSmust be Malaysia time (UTC+08:00)
5 Ignition String On / Off Case-sensitive
6 Latitude Float 1.528220 Decimal degrees
7 Longitude Float 103.818243 Decimal degrees
8 Speed Integer 70 Numeric, in km/h
9 Direction String North / South-East Cardinal or intercardinal direction
10 PTO Status String ON / OFF Power Take-Off (hydraulic system)

Client-Plate Parsing Rule

"EKJY - JUS9065"  →  clientCode = "EKJY",  plateNumber = "JUS9065"
"M3"              →  clientCode = null,     plateNumber = "M3"

If the field contains a hyphen (-), it is split into clientCode and plateNumber. Whitespace is trimmed from both.

Example Packets

IGT,EKJY-JUS9065,2025-02-26,16:30:39,On,1.528220,103.818243,70,South-East,OFF
IGT,TSC-MDM7648,2025-02-26,16:30:39,On,2.010985,103.058758,28,South-West,ON
IGT,M3,2025-02-26,13:42:40,Off,2.994904,101.453437,0,North,OFF

4. How to Test Connection

From Linux/Mac (netcat)

echo "IGT,EKJY-JUS9065,2025-02-26,10:00:00,On,1.528220,103.818243,0,North,OFF" | nc ekagps.iotapp.my 6091

From Windows (PowerShell)

$client = New-Object System.Net.Sockets.TcpClient("ekagps.iotapp.my", 6091)
$stream = $client.GetStream()
$data = [System.Text.Encoding]::ASCII.GetBytes("IGT,EKJY-JUS9065,2025-02-26,10:00:00,On,1.528220,103.818243,0,North,OFF")
$stream.Write($data, 0, $data.Length)
$client.Close()

From Node.js

const net = require('net');
const client = new net.Socket();
client.connect(6091, 'ekagps.iotapp.my', () => {
  client.write('IGT,EKJY-JUS9065,2025-02-26,10:00:00,On,1.528220,103.818243,0,North,OFF');
  client.end();
});

On Server (SSH)

node -e "const net=require('net');const c=new net.Socket();c.connect(6091,'127.0.0.1',()=>{c.write('IGT,EKJY-JUS9065,2025-02-26,10:00:00,On,1.528220,103.818243,0,North,OFF');c.end();});c.on('close',()=>console.log('Done'));c.on('error',e=>console.error(e.message));"

5. Server-Side Processing Logic

Step-by-Step Data Flow

GPS Device
    │
    │  TCP packet (raw text, 10 fields)
    ▼
TCP Server @ ekagps.iotapp.my:6091
    │
    ├─ [1] Validate: exactly 10 comma-separated fields?
    │       NO  → Log error, drop packet, close
    │       YES → Continue
    │
    ├─ [2] Parse all fields
    │       • Split Client-Plate by "-" to extract clientCode + plateNumber
    │       • Convert datetime from Malaysia (UTC+08:00) → UTC
    │       • Cast latitude, longitude, speed to numbers
    │
    ├─ [3] Multicast (Production only)
    │       • Forward raw packet to: 10.10.0.81:6091, 10.10.0.160:6091
    │       • Dev/Staging: skipped (TCP_HOST is empty)
    │
    └─ [4] MySQL Insert
            • Table: truck_location
            • ON DUPLICATE KEY UPDATE (keyed by plate_number)
            • Stores latest GPS snapshot per truck

What Gets Stored (truck_location table)

Column Value
provider_code e.g. IGT
client_code e.g. EKJY (or NULL)
plate_number e.g. JUS9065
datetime UTC timestamp
ignition On / Off
latitude float
longitude float
speed integer
direction e.g. South-East
pto_status ON / OFF

6. Architecture & Infrastructure

Tech Stack

Component Technology
Runtime Node.js
TCP Server net (Node.js built-in)
Database MySQL 8 (ekadb schema)
Cache / Pub-Sub Redis 6
Geofencing geolib v3.3.4
Datetime luxon v3.5.0
Process Manager PM2

Production Multicast Targets

Production forwards every GPS packet to two additional servers:

  • 10.10.0.81:6091
  • 10.10.0.160:6091

Key Database Tables

Table Purpose
truck_location Latest GPS snapshot per truck (inserted/updated on every packet)

7. Error Handling & Known Behaviors

Scenario Behavior
Packet has ≠ 10 fields Dropped silently, error logged
No hyphen in Client-Plate field clientCode = null, no crash
Redis down TCP server continues, MySQL writes still work
TCP_HOST empty Multicast skipped, no error
Duplicate plate_number in DB Row updated (not duplicated) via ON DUPLICATE KEY UPDATE
Scanner/bot traffic detected (HTTP, GET, POST, Cookie, SSH, TLS, CONNECT keywords) Connection destroyed immediately, logged as blocked
Socket errors ECONNRESET / EPIPE Silently ignored (expected internet behavior, not real server errors)

8. Version History (Summary)

Version Date Key Change
v1.0.0 Sep 2024 Initial release
v1.3.0 Apr 2025 Redis + geofencing + multicast added
v1.5.0 Apr 2025 Redis pub/sub for status updates
v1.6.0 Apr 2025 Code cleanup and uncommented logic
v1.6.0-hotfix-1 Oct 2025 DB host changed to localhost (security fix)
v1.6.0+hotfix.2 26 Feb 2026 Block scanner/bot traffic (HTTP, GET, POST, SSH, TLS keywords dropped immediately). Silently ignore ECONNRESET and EPIPE socket errors. Deployed to DEV, UAT, production.

9. Monitoring

# View live logs (PM2)
pm2 logs eka-gps

# View last 50 lines
pm2 logs eka-gps --lines 50

# Process status
pm2 status

Normal Startup Log

Server listening on *:6091
Redis clients connected

Normal Data Receipt Log

Client connected: 1.2.3.4 54321
Raw data: IGT,EKJY-JUS9065,2025-02-26,16:30:39,On,1.528220,103.818243,70,South-East,OFF
Data received: { providerCode: 'IGT', plateNumber: 'JUS9065', ... }
Client disconnected