Realtime Push
Realtime Push
Realtime push provides WebSocket updates for enabled accounts. Device status WebSocket messages keep live maps and device lists current, while notification push messages deliver alarms and platform notices. REST v2 APIs remain the authoritative source for reconnect recovery, paging, filtering, and historical data.
Realtime Capabilities
Realtime push can support live fleet screens, alarm panels, and status-driven UI changes without high-frequency polling.
| Client function | Realtime source | Main data | Typical handling |
|---|---|---|---|
| Live map and device list | Device status WebSocket | snapshot or onlyUpdateEvent |
Merge by imei, the API device identifier returned as devices[].imei; update online state, latest coordinates, speed, event, ignition/ACC, mileage, battery, network signal, lock status, and supported sensor fields. |
| Smart lock status screens | Device status WebSocket and notification push | status.lock_status, subLockInfo, lock alarm messages |
Show current open/closed/error state, merge sub-lock records by ble_id, and use alarm push or GET /v2/alarm-points for audit history. |
| Alarm popup and alarm center | Notification push | messagePass.alarm_msg |
Show a notification, append to the alarm panel, and use alert_code with the Event / Alarm Code Definitions table. |
| Map alarm pins | Notification push | alarm_msg.imei, coordinates, speed, mileage, event detail |
Place or update an alarm marker, then refresh the device’s current state if the screen depends on latest status. |
| System or maintenance notices | Notification push | messagePass.message, message_type |
Show a notice, update the message center, or increase unread counters. |
| Reconnect and gap recovery | REST v2 | GET /v2/device-statuses, GET /v2/alarm-points |
Reload canonical current state and alarm records after reconnect or when the browser cache is uncertain. |
Realtime messages are not a complete historical point stream. Use GET /v2/snapshots for route playback and historical analysis.
Connection Lifecycle
| Channel | Endpoint | Registration | Purpose |
|---|---|---|---|
| Device status WebSocket | wss://openapi.tftiot.com:8443/websocketws://<server>:8888/websocket for non-SSL/private environments |
event: "signin" |
Realtime current device status, including snapshot updates. |
| Notification push | WebSocket gateway supplied when realtime notification push is enabled for the account. | type: "registUserMessage" with access-token |
Alarm and platform messages such as messagePass. |
- Authenticate through Open API v2 and keep the returned
idandaccess-token. - Open the WebSocket channel required by the screen.
- Send the channel-specific registration message and wait for a success response before using the stream.
- Decode compressed device status messages when
compressis1. - Reconnect with backoff after close/error, then reload REST state to close any message gap.
Device Status WebSocket
The device status WebSocket is the channel used by Monitor live screens to receive current status changes. It is the realtime companion to GET /v2/device-statuses.
wss://openapi.tftiot.com:8443/websocket
ws://<server>:8888/websocket
After the WebSocket opens, send a sign-in frame. In the example below, replace 12345 with the id returned by POST /v2/auth/action:
{
"event": "signin",
"token": 12345,
"md5-password": "MD5_OF_ACCOUNT_PASSWORD",
"compress": 2,
"parent_id": 12345,
"customer_name": ""
}
| Field | Required | Description |
|---|---|---|
event |
Yes | Use signin. |
token |
Yes | User/account id returned by POST /v2/auth/action as id. This WebSocket field is named token, but the value is the numeric user id, not the REST access-token. |
md5-password |
Yes | MD5 hash of the account password, the same hash used in password-md5 during authentication. Treat the hash as a secret. |
compress |
Recommended | Use 2 to allow compact status payloads. Inspect each returned message; if it contains compress: 1, decode data using the compression format below. |
parent_id |
Recommended | Parent/current account id when applicable. For a normal account, use the same id as token. |
customer_name |
Optional | Use when the account is authenticated through a customer namespace; otherwise send an empty string or omit. |
access_code |
Optional | Only for accounts that have been issued an additional access code. |
A successful device status WebSocket sign-in returns:
{
"event": "signin",
"error": 0,
"token": 12345`n}
Snapshot Messages
Device status messages update one device at a time. Use imei as the merge key and compare timestamp fields such as status.date or status.heartbeat_time before overwriting a newer local status.
| Message event | Meaning | Handling | |
|---|---|---|---|
snapshot |
Current status update for a device. | Decode if compressed, then merge top-level device fields and nested status fields by imei. |
|
onlyUpdateEvent |
Partial status update using the same snapshot field map. | Decode with the same rules and update only the fields present in the message. | |
subLockInfo |
Realtime status list for supported sub-lock accessories. | Decode if compressed, then merge sub_lock_list items by ble_id into the device status cache. |
|
| BLE tire pressure | Device status WebSocket | bleTire, status.ble_tire_pressure_list |
Merge tire readings by parent imei and tire sensor mac. Use GET /v2/tire-ble-mac for configured tire names and positions. |
| BLE temperature/humidity | Device status WebSocket | bleTemp, status.ble_temp_jsonarray_str |
Merge sensor readings by parent imei and ble_id. Use GET /v2/device-ble-temps for configured sensor names and thresholds. |
| Other peripheral sensor events | Device status WebSocket | Hardware-specific realtime data such as BLE door/fuel, driver ID, RS232 fuel/tire, Wi-Fi/network, or environment temperature/humidity when enabled. | Handle only the event types required by the enabled devices. Use REST status recovery when a peripheral message is missing or unsupported. |
Expanded snapshot example
{
"event": "snapshot",
"data": {
"id": 301,
"imei": "860000000000301",
"model": "TLP2-SFB",
"valid": 1,
"device_key": "DEV-301",
"status": {
"online": 1,
"latlng_valid": 1,
"lat": 22.571,
"lng": 113.877,
"speed": 45.6,
"azimuth": 92,
"event": 1,
"date": 1700000000000,
"acc": 1,
"mileage": 6200,
"battery_voltage_percent": 87,
"network_signal": 4,
"lock_status": {
"lock_type": 0,
"lock_msg_date": 1700000000000,
"lock_id": "LOCK-001",
"lat": 22.571,
"lng": 113.877
}
}
}
}
Sub-lock Realtime Status
When sub-lock accessories are enabled, the device status WebSocket can send subLockInfo. Use this message to refresh sub-lock open/closed/error state without polling. Keep the parent device keyed by imei and merge each sub-lock item by ble_id.
{
"event": "subLockInfo",
"data": {
"id": 301,
"imei": "860000000000301",
"model": "TLP2-SFB",
"sub_lock_list": [
{
"ble_id": "A1B2C3D4",
"date": 1700000000000,
"latlng_valid": 1,
"latitude": 22.571,
"longitude": 113.877,
"lock_type": 0,
"rssi": -66,
"voltage": 4.6,
"solar_voltage": 4.6,
"temp": 27,
"is_low_power": 0,
"is_open_lock_cover": 0,
"is_open_back_cover": 0
}
]
}
}
| Field | Description |
|---|---|
data.imei |
API device identifier of the tracker that owns the sub-lock list. |
sub_lock_list[].ble_id |
Sub-lock identifier. Use this as the merge key and as openSubLock.ble_id. |
sub_lock_list[].lock_type |
Sub-lock status/result code. See Smart Locks in the Core API Reference for lock status code meanings. |
sub_lock_list[].date |
Status timestamp in Unix epoch milliseconds. |
latitude, longitude, latlng_valid |
Location reported with the sub-lock event when available. |
rssi, voltage, solar_voltage, temp |
BLE signal, battery/solar voltage, and temperature values. |
is_charging, is_low_power, is_high_temp, is_low_temp, is_open_lock_cover, is_open_back_cover |
Power, temperature, and cover-state flags when supported. |
Compressed subLockInfo
When compress: 1 is returned for subLockInfo, the top-level data string uses comma positions 0=id, 1=imei, 2=model, and 3=sub_lock_list. If a string value needs a literal comma, the comma is escaped as #%@#.
The sub_lock_list value is a nested positional array: multiple sub-lock items are separated by *, and fields inside one item are separated by |.
| Sub-lock index | Field |
|---|---|
0 |
ble_id |
1 |
latlng_valid |
2 |
date |
3, 4 |
latitude, longitude |
5, 6, 7 |
speed, azimuth, altitude |
8 |
lock_type |
9, 10 |
satellite_number, rssi |
11, 12 |
hardware, software |
13, 14, 15 |
voltage, solar_voltage, temp |
16 to 22 |
is_charging, is_charging_over_voltage, is_low_power, is_high_temp, is_low_temp, is_open_lock_cover, is_open_back_cover |
BLE Sensor Realtime Status
BLE sensor WebSocket messages update child sensor data without polling. Keep the parent tracker keyed by imei. For BLE tire pressure, merge each reading by mac; for BLE temperature/humidity, merge each reading by ble_id. REST status remains the recovery source after reconnect.
bleTire example
{
"event": "bleTire",
"data": {
"id": 301,
"imei": "860000000000301",
"model": "TLP2-SFB",
"ble_tire_pressure_list": [
{
"mac": "A1B2C3D4E5F6",
"date": 1700000000000,
"voltage": 2.92,
"airPressure": 245,
"airTemp": 28,
"alarm": 0
}
]
}
}
| Field | Description |
|---|---|
data.imei |
API device identifier of the tracker that owns the tire pressure sensor list. |
ble_tire_pressure_list[].mac |
BLE tire sensor MAC/id. Match it with GET /v2/tire-ble-mac rows. |
ble_tire_pressure_list[].date |
Reading timestamp in Unix epoch milliseconds. |
airPressure |
Tire pressure raw value in kPa. |
airTemp |
Tire air temperature raw value in Celsius. |
voltage |
Sensor battery voltage in volts when reported. |
alarm |
Sensor alarm bitmask/code. Use Tire Leak and TPS Low Battery names from the Event / Alarm Code Definitions table. |
bleTemp example
{
"event": "bleTemp",
"data": {
"id": 301,
"imei": "860000000000301",
"model": "TLP2-SFB",
"ble_temp_list": [
{
"ble_id": "A1B2C3D4",
"date": 1700000000000,
"temp": 4.8,
"humidity": 62,
"battery_percent": 91,
"light_intensity": 1,
"rssi": -63
}
]
}
}
| Field | Description |
|---|---|
data.imei |
API device identifier of the tracker that owns the BLE temperature/humidity list. |
ble_temp_list[].ble_id |
BLE sensor id. Match it with GET /v2/device-ble-temps rows. |
ble_temp_list[].date |
Reading timestamp in Unix epoch milliseconds. |
temp |
Temperature raw value in Celsius. |
humidity |
Relative humidity percentage. |
voltage, battery_percent |
Sensor battery values when reported. |
light_intensity |
Light state when supported: 0 dark, non-zero bright. |
rssi |
BLE signal strength in dBm. |
is_open_box, latitude, longitude |
Optional box/case state and location fields when supported. |
tempAlarmType, humidityAlarmType |
Optional temperature/humidity alarm state/type fields. |
For REST recovery, read GET /v2/device-statuses. Tire pressure returns an array in status.ble_tire_pressure_list. Temperature/humidity returns a JSON string in status.ble_temp_jsonarray_str; parse it before merging by ble_id.
BLE Sensor Compression
When compress: 1 is returned for bleTire or bleTemp, the top-level data string uses comma positions 0=id, 1=imei, 2=model, and 3=sensor_list. If a string value needs a literal comma, the comma is escaped as #%@#.
The nested sensor list uses the same nested array convention as subLockInfo: multiple sensor items are separated by *, and fields inside one item are separated by |.
bleTire top-level index |
Field |
|---|---|
0 |
id |
1 |
imei |
2 |
model |
3 |
ble_tire_pressure_list |
ble_tire_pressure_list item index |
Field |
|---|---|
0 |
imei |
1 |
date |
2 |
mac |
3 |
voltage |
4 |
airPressure |
5 |
airTemp |
6 |
alarm |
7 |
id |
8 |
isHadSendPowerAlert |
9 |
isHadSendTireLeakAlert |
10 |
deviceType |
bleTemp top-level index |
Field |
|---|---|
0 |
id |
1 |
imei |
2 |
model |
3 |
ble_temp_list |
ble_temp_list item index |
Field |
|---|---|
0 |
imei |
1 |
ble_id |
2 |
voltage |
3 |
battery_percent |
4 |
temp |
5 |
humidity |
6 |
is_open_box |
7 |
light_intensity |
8 |
rssi |
9 |
date |
10 |
latitude |
11 |
longitude |
12 |
tempAlarmType |
13 |
humidityAlarmType |
Compression Format
compress: 1 is not gzip, deflate, or binary compression. The data value is a comma-delimited positional string. Decode it by index using the snapshot field index table.
| Rule | Description |
|---|---|
| Delimiter | Split data by comma (,). |
| Escaped comma | If a value contains #%@#, replace each #%@# with a literal comma after splitting. |
| Top-level fields | Indexes 0 to 4 become top-level fields: id, imei, model, valid, device_key. |
| Status fields | Indexes 5 and above become fields inside status. |
| Empty values | Empty strings mean the field was not supplied or is not supported by that device/model. |
| Type conversion | Convert fields marked Integer, Float, or Boolean in the index table. Keep other fields as strings. |
function decodeSnapshot(data, fieldIndex, typeMap) {
const values = String(data).split(",").map(function (value) {
return value.split("#%@#").join(",");
});
const result = {};
const status = {};
Object.keys(fieldIndex).forEach(function (indexText) {
const index = Number(indexText);
if (index >= values.length || values[index] === "") return;
const field = fieldIndex[indexText];
const target = index <= 4 ? result : status;
let value = values[index];
if (typeMap.integer[field]) value = parseInt(value, 10);
else if (typeMap.float[field]) value = parseFloat(value);
else if (typeMap.boolean[field]) value = value === "true";
target[field] = value;
});
result.status = status;
return result;
}
Snapshot Field Index
This table is the public positional map for compressed snapshot and onlyUpdateEvent status messages. Fields may be absent, empty, or unchanged depending on device model, firmware, account permissions, and hardware accessories.
| Index | Field | Decode type | Target |
|---|---|---|---|
0 |
id |
Integer | Top level |
1 |
imei |
String | Top level API device identifier. Match this value to devices[].imei. |
2 |
model |
String | Top level |
3 |
valid |
Integer | Top level |
4 |
device_key |
String | Top level customer-visible device number when configured. Use it for display/reference. |
5 |
online |
Integer | status |
6 |
gpsWorking |
Boolean | status |
7 |
alerts |
Integer | status |
8 |
alerts1 |
Integer | status |
9 |
mileage |
Integer | status |
10 |
antithefted_status |
Integer | status |
11 |
latlng_valid |
Integer | status |
12 |
last_reg_date |
Integer | status |
13 |
lat |
Float | status |
14 |
lng |
Float | status |
15 |
speed |
Float | status |
16 |
azimuth |
Integer | status |
17 |
event |
Integer | status |
18 |
fuel |
Float | status |
19 |
address |
String | status |
20 |
drag_threshold |
Integer | status |
21 |
gps |
Boolean | status |
22 |
date |
Integer | status |
23 |
iop |
Integer | status |
24 |
acc |
Integer | status |
25 |
relay |
Integer | status |
26 |
antithefted |
Integer | status |
27 |
analog1 |
Float | status |
28 |
analog2 |
Float | status |
29 |
altitude |
Float | status |
30 |
acc_switch_time |
Integer | status |
31 |
idle_status |
Integer | status |
32 |
external_power_voltage |
Float | status |
33 |
accumulating_fuel_consumption |
Integer | status |
34 |
instant_fuel_consumption |
Integer | status |
35 |
rpm |
Integer | status |
36 |
air_input |
Integer | status |
37 |
air_pressure |
Integer | status |
38 |
cooling_fluid_temp |
Integer | status |
39 |
air_inflow_temp |
Integer | status |
40 |
engine_load |
String | status |
41 |
throttle_position |
Integer | status |
42 |
remain_fuel_rate |
Integer | status |
43 |
location_date |
Integer | status |
44 |
satellite_count |
Integer | status |
45 |
battery_voltage_percent |
Integer | status |
46 |
is_external_battery_lower |
Integer | status |
47 |
rs232_device_valid |
Integer | status |
48 |
is_inner_battery_lower |
Integer | status |
49 |
temp |
Float | status |
50 |
network_signal |
Integer | status |
51 |
input |
String | status |
52 |
output |
String | status |
53 |
device_temp |
Float | status |
54 |
light_sensor |
Float | status |
55 |
battery_voltage |
Float | status |
56 |
solar_voltage |
Float | status |
57 |
engine_time |
Integer | status |
58 |
is_usb_charging |
Integer | status |
59 |
is_solar_charging |
Integer | status |
60 |
alert_sum |
String | status |
61 |
link_type |
String | status |
62 |
obd_version |
String | status |
63 |
version |
String | status |
64 |
mcu_version |
String | status |
65 |
smart_power_status |
String | status |
66 |
output_12v |
Boolean | status |
67 |
output_vout |
Boolean | status |
68 |
analog3 |
Float | status |
69 |
analog4 |
Float | status |
70 |
analog5 |
Float | status |
71 |
is_smart_upload_support |
Boolean | status |
72 |
support_change_battery |
Boolean | status |
73 |
remain_fuel |
Integer | status |
74 |
cmd_send_status |
String | status |
75 |
lock_status |
String | status |
76 |
external_power_reduce_status |
Integer | status |
77 |
upload_abnormal |
Integer | status |
78 |
obd_total_distance |
Integer | status |
79 |
obd_speed |
Float | status |
80 |
obd_total_engine_hours |
Integer | status |
81 |
obd_total_driver_time |
Integer | status |
82 |
obd_total_engine_idle_time |
Integer | status |
83 |
obd_total_idle_fuel_used |
Float | status |
84 |
ac |
Integer | status |
85 |
relay_status |
Integer | status |
86 |
cur_event |
Integer | status |
87 |
comment |
String | status |
88 |
heartbeat_time |
Integer | status |
89 |
vin |
String | status |
90 |
ignition_source |
Integer | status |
91 |
ex_power_consump_status |
Integer | status |
92 |
has_third_party_obd |
Integer | status |
93 |
remain_fuel_unit |
Integer | status |
94 |
mileage_source |
Integer | status |
95 |
second_heartbeat_time |
String | status |
96 |
remain_power |
Integer | status |
97 |
is_car_charge |
Integer | status |
98 |
dash_board_speed |
Integer | status |
99 |
accelerator_pedal_position |
Integer | status |
100 |
remain_power_min_distance |
Integer | status |
101 |
remain_power_max_distance |
Integer | status |
102 |
car_charge_voltage |
Float | status |
103 |
car_charge_electric_current |
Integer | status |
104 |
car_charge_Power |
Integer | status |
105 |
full_remaining_time |
Integer | status |
106 |
car_battery_effective_capacity |
Integer | status |
107 |
car_battery_initial_capacity |
Integer | status |
108 |
car_total_power_consumption |
Integer | status |
109 |
is_ble_anti_lost_open |
Integer | status |
110 |
humidity |
Float | status |
111 |
light |
String | status |
112 |
driver_id_type |
String | status |
113 |
is_wireless_charging |
Integer | status |
114 |
flash_light_open |
Integer | status |
115 |
logo_light_open |
Integer | status |
116 |
buzzer_open |
Integer | status |
117 |
lost_mode_open |
Integer | status |
118 |
obd_fuel_type |
Integer | status |
119 |
position_type |
Integer | status |
120 |
is_barking |
Integer | status |
Notification Registration
The notification push channel delivers alarm and platform messages. After opening the WebSocket gateway supplied for the enabled account, send this JSON message:
{
"type": "registUserMessage",
"access-token": "ACCESS_TOKEN",
"clientId": "customer-web-operator-01",
"authSeq": "operator-01:1700000000000"
}
| Field | Required | Description |
|---|---|---|
type |
Yes | Use registUserMessage. |
access-token |
Yes | Token returned by Open API v2 authentication. |
clientId |
Recommended | Stable identifier for this browser tab, operator session, service instance, or integration worker. If the same token-authenticated clientId reconnects, the older socket can be closed to avoid duplicate delivery. |
authSeq |
Recommended | Client-generated correlation value for registration attempts. It is useful when matching client logs with support-side logs. |
Registration Responses
| Message | Meaning | Client action |
|---|---|---|
wsAuthAck |
The notification WebSocket was registered successfully for the token owner. | Mark notification push as active for this session. |
wsAuthReject |
The token is invalid, expired, or not accepted from the current source. | Close the socket, refresh the v2 token, and register again. |
{
"type": "wsAuthAck",
"clientId": "customer-web-operator-01",
"user_id": 2048
}
{
"type": "wsAuthReject",
"msg": "Invalid access-token."
}
Notification Message Types
The customer-facing notification payload is delivered as messagePass. The message can contain an alarm_msg object for alarm events, or a plain message field for system, maintenance, or suggestion messages.
| Payload shape | When it appears | Main fields |
|---|---|---|
messagePass + alarm_msg |
A device alarm or event should be shown to the authenticated account. | date, from_id, to_id, alarm_msg |
messagePass + message |
A system, maintenance, or account message is pushed to one user or all connected users. | date, from_id, to_id, id, message, message_type |
Alarm Message Payload
Alarm push is the most important notification payload for tracking platforms. Use alert_code with the Event / Alarm Code Definitions table in the Core API Reference.
{
"type": "messagePass",
"from_id": 1,
"to_id": 2048,
"id": 0,
"date": 1700000009999,
"alarm_msg": {
"imei": "860000000000301",
"device_key": "DEV-301",
"device_name": "Tracker Alpha",
"alert_code": 4096,
"latitude": 22.571,
"longitude": 113.877,
"speed": 88,
"mileage": 6200,
"extra": "geofence name or event-specific detail"
}
}
| Field | Type | Description |
|---|---|---|
type |
String | Business push type. Alarm and notice messages use messagePass. |
date |
Number | 13-digit Unix epoch milliseconds for when the message/event was generated. |
from_id |
Number | Message source category. Alarm notifications use 1. |
to_id |
Number | Target user id, or -1 for broadcast-style messages. |
id |
Number | Message id when available. Some realtime alarm notifications can use 0; do not rely on this as a unique alarm id. |
alarm_msg.imei |
String | API device identifier related to the alarm. Match this value to devices[].imei. |
alarm_msg.device_key |
String | Optional customer-visible device number when configured. Use it for display/reference, not as the Open API imei identifier. |
alarm_msg.device_name |
String | Optional device display name when available. |
alarm_msg.alert_code |
Number | Alarm/event code. Match this value against the Event / Alarm Code Definitions table. |
alarm_msg.latitude, alarm_msg.longitude |
Number | Decimal degrees for the event position. |
alarm_msg.speed |
Number | Speed value reported with the event. Render with the same unit policy used by your platform. |
alarm_msg.mileage |
Number | Mileage value reported with the event when available. |
alarm_msg.extra |
String | Event-specific detail. Some alarm types may return plain text, while complex alarms may return JSON text. Parse defensively. |
alarm_msg.address |
String | Optional. If missing, resolve the address from coordinates on your side when needed. |
System or Maintenance Message Example
{
"type": "messagePass",
"from_id": 0,
"to_id": -1,
"id": 301,
"date": 1700000005678,
"message": "Scheduled maintenance notice",
"message_type": 7
}
Implementation Pattern
- Keep a device map keyed by
devices[].imeifromGET /v2/devices, then keep current status fresh withGET /v2/device-statuses. - Apply
snapshotandonlyUpdateEventmessages to the current-status cache only after decoding and timestamp checks. - When
messagePass.alarm_msgarrives, validatealarm_msg.imei,alert_code,date, and coordinates before updating the UI. - Append alarm notifications to the alarm panel and show map markers when coordinates are usable.
- Use
GET /v2/devicesorGET /v2/devices/{imei}when the screen needs device metadata, configuration, or a newly assigned device object. - Use
GET /v2/alarm-pointsto rebuild the alarm list after reconnect or after the user opens the alarm center. - Debounce UI work if many messages arrive in a short period.
Use status.latlng_valid before moving a map marker. If a pushed point is not valid for display, keep the previous valid map position and still update non-location fields such as online state, battery, ignition, or signal.
Reconnect Recovery
- Reconnect with backoff after a socket close.
- For notification push, refresh the v2 token if registration returns
wsAuthReject. - For device status WebSocket, sign in again after reconnect and wait for
event: "signin"witherror: 0. - Use a stable
clientIdper active notification client to reduce duplicate delivery during reconnects. - While disconnected, poll
GET /v2/device-statusesat a controlled interval for screens that must stay fresh. - After reconnect, reload current device status with
GET /v2/device-statusesand alarm state withGET /v2/alarm-pointsbefore trusting the local browser cache.
Do not use high-frequency REST polling as a substitute for realtime status updates. WebSocket push plus controlled REST recovery is the intended pattern for live screens.