JT/T808 is a C# library for serializing, deserializing, and testing the JT/T808 vehicle-telemetry protocol (including extensions such as JT1078, SuBiao, YueBiao, GPS51, etc.). It includes helpers for packet framing, escaping/unescaping, CRC checking, message registration, and extension point support for vendor-specific messages.
Before using this library you should be comfortable with:
- Binary / hexadecimal conversions
- BCD and hex encodings
- Bit shifts and XOR operations
- Reflection usage in .NET
- Working with JObject (Newtonsoft.Json) if inspecting JSON
- Basic use of Span
- Familiarity with .NET and C# coding patterns
Packet layout (JT808Package):
| Begin | Header (JT808Header) | Body / Sub-packet bodies | Checksum | End |
|---|---|---|---|---|
| 0x7E | - | - | - | 0x7E |
JT808Header fields:
- Message ID (MsgId)
- Message body property (JT808HeaderMessageBodyProperty)
- Protocol version (ProtocolVersion, 2019 spec)
- Terminal phone number (TerminalPhoneNo)
- Message serial number (MsgNum)
- Total package count (PackgeCount, if fragmented)
- Package index (PackageIndex, if fragmented)
Message body property includes:
- Version flag (VersionFlag)
- IsPackge (IsPackge)
- Encryption (Encrypt)
- Data length (DataLength)
When sending the packet body (everything between the head and tail 0x7E), two bytes must be escaped:
- 0x7E -> 0x7D 0x02
- 0x7D -> 0x7D 0x01
This escaping ensures TCP message boundaries for JT808 messages.
Example 1 — Building a 0x0200 location report:
JT808Package jT808Package = new JT808Package();
jT808Package.Header = new JT808Header
{
MsgId = (ushort)JT808.Protocol.Enums.JT808MsgId._0x0200,
ManualMsgNum = 126,
TerminalPhoneNo = "123456789012"
};
JT808_0x0200 jT808_0x0200 = new JT808_0x0200();
jT808_0x0200.AlarmFlag = 1;
jT808_0x0200.Altitude = 40;
jT808_0x0200.GPSTime = DateTime.Parse("2018-10-15 10:10:10");
jT808_0x0200.Lat = 12222222;
jT808_0x0200.Lng = 132444444;
jT808_0x0200.Speed = 60;
jT808_0x0200.Direction = 0;
jT808_0x0200.StatusFlag = 2;
jT808_0x0200.BasicLocationAttachData = new Dictionary<byte, JT808_0x0200_BodyBase>();
jT808_0x0200.BasicLocationAttachData.Add(JT808Constants.JT808_0x0200_0x01, new JT808_0x0200_0x01
{
Mileage = 100
});
jT808_0x0200.BasicLocationAttachData.Add(JT808Constants.JT808_0x0200_0x02, new JT808_0x0200_0x02
{
Oil = 125
});
jT808Package.Bodies = jT808_0x0200;
byte[] data = JT808Serializer.Serialize(jT808Package);
var hex = data.ToHexString();
// Example output (hex):
// 7E 02 00 00 26 12 34 56 78 90 12 00 7D 02 ... 13 7E- Original frame contains escape sequences (0x7D 0x02, 0x7D 0x01).
- Replace 0x7D 0x02 -> 0x7E and 0x7D 0x01 -> 0x7D.
- After unescaping, parse header fields and body according to message ID and body length.
byte[] bytes = "7E 02 00 00 26 12 34 56 78 90 12 00 7D 02 ... 13 7E".ToHexBytes();
var jT808Package = JT808Serializer.Deserialize(bytes);
// Header assertions
Assert.Equal(Enums.JT808MsgId._0x0200, jT808Package.Header.MsgId);
Assert.Equal(38, jT808Package.Header.MessageBodyProperty.DataLength);
Assert.Equal(126, jT808Package.Header.MsgNum);
Assert.Equal("123456789012", jT808Package.Header.TerminalPhoneNo);
Assert.False(jT808Package.Header.MessageBodyProperty.IsPackge);
// Body assertions
JT808_0x0200 jT808_0x0200 = (JT808_0x0200)jT808Package.Bodies;
Assert.Equal((uint)1, jT808_0x0200.AlarmFlag);
Assert.Equal((uint)40, jT808_0x0200.Altitude);
Assert.Equal(DateTime.Parse("2018-10-15 10:10:10"), jT808_0x0200.GPSTime);
Assert.Equal(12222222, jT808_0x0200.Lat);
Assert.Equal(132444444, jT808_0x0200.Lng);
Assert.Equal(60, jT808_0x0200.Speed);
Assert.Equal(0, jT808_0x0200.Direction);
Assert.Equal((uint)2, jT808_0x0200.StatusFlag);
// Attachments
Assert.Equal(100, ((JT808_0x0200_0x01)jT808_0x0200.BasicLocationAttachData[JT808Constants.JT808_0x0200_0x01]).Mileage);
Assert.Equal(125, ((JT808_0x0200_0x02)jT808_0x0200.BasicLocationAttachData[JT808Constants.JT808_0x0200_0x02]).Oil);- You can create different IJT808Config implementations (e.g., DT1Config, DT2Config).
- Register external assemblies to add custom message IDs and formatters.
- You may skip CRC validation in config (useful for testing).
- Use MsgIdFactory.SetMap() and FormatterFactory.SetMap() to add or override mappings per device type.
- Multiple device types with overlapping custom attachment IDs: use per-device factory or separate GlobalConfigBase instances to avoid ID collisions.
- Fragmented multimedia data: merge sub-packets (Max message body size is 1023 bytes). The library includes a default merger that caches and merges fragments; tweak or replace IMerger for special needs.
- Vendor devices that do not follow the standard (e.g., different attachment formats or incorrect version flags): the library provides mechanisms to register custom parsers or to coerce version flags for compatibility.
- Automatic merging of fragmented packages (merger timeout defaults to 5 minutes).
- See JT808SerializerTest.MergerTest for usage and test coverage.
You can install core and extension packages via NuGet:
- Install-Package JT808
- Install-Package JT808.Protocol.Extensions.JT1078
- Install-Package JT808.Protocol.Extensions.SuBiao
- Install-Package JT808.Protocol.Extensions.YueBiao
- Install-Package JT808.Protocol.Extensions.GPS51
This repository includes BenchmarkDotNet reports (for reference only). Results will vary depending on environment and .NET runtime.
The repository contains comprehensive message ID tables for:
- JT808 base messages (0x0001 — 0xFFFF)
- JT1078 extensions (video-related)
- SuBiao (active safety) extensions
- YueBiao (Guangdong) active safety extensions
See the repo for the full tables and mapping details. If you want, I can translate all tables into English verbatim (they are long), or include them as separate downloadable files.
Dependency injection example:
IServiceCollection services = new ServiceCollection();
services.AddJT808Configure()
.AddJT1078Configure();
// Register global assemblies
JT808Serializer.Instance.Register(JT808_JT1078_Constants.GetCurrentAssembly());The repository contains a Simples test demo folder (Simples/Demo1..DemoN) that demonstrates:
- Custom message registration
- Merger behavior
- Compatibility handling between 2011 and 2019 specs
- Multi-protocol device handling