From 681e25e6ea0fc3f6c2bf610b23256bc99eeda343 Mon Sep 17 00:00:00 2001
From: SmallChi <564952747@qq.com>
Date: Thu, 20 Sep 2018 20:39:11 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=95=B4JT809=E5=8D=8F=E8=AE=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 README.md                                     |  15 +-
 .../JT809.Protocol.Test.csproj                |  15 +-
 src/JT809.Protocol.Test/JT809HeaderTest.cs    |  41 ++
 .../JT809MessageBody/JT809_0x1001Test.cs      |  37 ++
 .../JT809Packages/JT809_0x1001PackageTest.cs  |  81 +++
 src/JT809.Protocol.Test/PackageTest.cs        | 117 ----
 src/JT809.Protocol/Enums/ErrorCode.cs         |  12 -
 .../Exceptions/JT809Exception.cs              |  25 -
 src/JT809.Protocol/JT809.Protocol.csproj      |  33 +-
 .../JT809BodiesTypeAttribute.cs               |  14 +
 .../JT809FormatterAttribute.cs                |  25 +
 src/JT809.Protocol/JT809Bodies.cs             |  10 +
 .../JT809BusinessType.cs}                     | 329 +++++------
 .../JT809Enums/JT809ErrorCode.cs              |  17 +
 .../JT809SubBusinessType.cs}                  | 520 +++++++++---------
 .../JT809Exceptions/JT809Exception.cs         |  32 ++
 .../JT809Extensions/JT809BinaryExtensions.cs  | 429 +++++++++++++++
 .../JT809Extensions/JT809EnumExtensions.cs    | 155 ++++++
 .../JT809FormatterExtensions.cs               |  50 ++
 .../JT809FormatterResolverExtensions.cs       |  87 +++
 .../JT809Formatters/IJT809FormatterOfT.cs     |  12 +
 .../JT809Formatters/JT809HeaderFormatter.cs   |  39 ++
 .../JT809_0x1001Formatter.cs                  |  33 ++
 .../JT809Formatters/JT809PackageFormatter.cs  | 209 +++++++
 src/JT809.Protocol/JT809Header.cs             |  52 ++
 ...ryptOpitions.cs => JT809Header_Encrypt.cs} |   4 +-
 src/JT809.Protocol/JT809Header_Version.cs     |  62 +++
 .../JT809MessageBody/JT809_0x1001.cs          |  34 ++
 src/JT809.Protocol/JT809Package.cs            |  33 ++
 src/JT809.Protocol/JT809Serializer.cs         |  64 +++
 30 files changed, 1997 insertions(+), 589 deletions(-)
 create mode 100644 src/JT809.Protocol.Test/JT809HeaderTest.cs
 create mode 100644 src/JT809.Protocol.Test/JT809MessageBody/JT809_0x1001Test.cs
 create mode 100644 src/JT809.Protocol.Test/JT809Packages/JT809_0x1001PackageTest.cs
 delete mode 100644 src/JT809.Protocol.Test/PackageTest.cs
 delete mode 100644 src/JT809.Protocol/Enums/ErrorCode.cs
 delete mode 100644 src/JT809.Protocol/Exceptions/JT809Exception.cs
 create mode 100644 src/JT809.Protocol/JT809Attributes/JT809BodiesTypeAttribute.cs
 create mode 100644 src/JT809.Protocol/JT809Attributes/JT809FormatterAttribute.cs
 create mode 100644 src/JT809.Protocol/JT809Bodies.cs
 rename src/JT809.Protocol/{Enums/BusinessType.cs => JT809Enums/JT809BusinessType.cs} (95%)
 create mode 100644 src/JT809.Protocol/JT809Enums/JT809ErrorCode.cs
 rename src/JT809.Protocol/{Enums/SubBusinessType.cs => JT809Enums/JT809SubBusinessType.cs} (96%)
 create mode 100644 src/JT809.Protocol/JT809Exceptions/JT809Exception.cs
 create mode 100644 src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs
 create mode 100644 src/JT809.Protocol/JT809Extensions/JT809EnumExtensions.cs
 create mode 100644 src/JT809.Protocol/JT809Extensions/JT809FormatterExtensions.cs
 create mode 100644 src/JT809.Protocol/JT809Extensions/JT809FormatterResolverExtensions.cs
 create mode 100644 src/JT809.Protocol/JT809Formatters/IJT809FormatterOfT.cs
 create mode 100644 src/JT809.Protocol/JT809Formatters/JT809HeaderFormatter.cs
 create mode 100644 src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1001Formatter.cs
 create mode 100644 src/JT809.Protocol/JT809Formatters/JT809PackageFormatter.cs
 create mode 100644 src/JT809.Protocol/JT809Header.cs
 rename src/JT809.Protocol/{Enums/EncryptOpitions.cs => JT809Header_Encrypt.cs} (71%)
 create mode 100644 src/JT809.Protocol/JT809Header_Version.cs
 create mode 100644 src/JT809.Protocol/JT809MessageBody/JT809_0x1001.cs
 create mode 100644 src/JT809.Protocol/JT809Package.cs
 create mode 100644 src/JT809.Protocol/JT809Serializer.cs

diff --git a/README.md b/README.md
index 1161da5..e3207e0 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,13 @@
-# JT809
-JT809
+# JT809协议开发
+
+### 瞎逼逼:
+
+&emsp;&emsp;现在有了[JT808](https://github.com/SmallChi/GPSPlatform/blob/master/JT808.md)的基础,对JT809就只剩搬砖了。
+
+> 该JT809协议是参考[MessagePack-CSharp](https://github.com/neuecc/MessagePack-CSharp)一款二进制序列化器,站在巨人的肩膀上搬砖就是爽歪歪。
+
+## JT809终端通讯协议消息对照表
+
+|序号|消息体名称|消息ID|完成情况|
+|:------:|:------:|:------:|:------:|
+|  1  |  主链路登录请求消息 | 0x1001  |  √  |
diff --git a/src/JT809.Protocol.Test/JT809.Protocol.Test.csproj b/src/JT809.Protocol.Test/JT809.Protocol.Test.csproj
index 0970015..0553d6f 100644
--- a/src/JT809.Protocol.Test/JT809.Protocol.Test.csproj
+++ b/src/JT809.Protocol.Test/JT809.Protocol.Test.csproj
@@ -1,15 +1,22 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
 
     <IsPackable>false</IsPackable>
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
-    <PackageReference Include="xunit" Version="2.3.1" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
+    <Compile Remove="PackageTest.cs" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
+    <PackageReference Include="xunit" Version="2.4.0" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+    </PackageReference>
     <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
   </ItemGroup>
 
diff --git a/src/JT809.Protocol.Test/JT809HeaderTest.cs b/src/JT809.Protocol.Test/JT809HeaderTest.cs
new file mode 100644
index 0000000..7cdd98b
--- /dev/null
+++ b/src/JT809.Protocol.Test/JT809HeaderTest.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xunit;
+using JT809.Protocol;
+using JT809.Protocol.JT809Extensions;
+
+namespace JT809.Protocol.Test
+{
+    public  class JT809HeaderTest
+    {
+        [Fact]
+        public void Test1()
+        {
+            JT809Header jT809Header = new JT809Header();
+            jT809Header.MsgLength = 24;
+            jT809Header.MsgSN = 1024;
+            jT809Header.MsgID = JT809Enums.JT809BusinessType.DOWN_BASE_MSG;
+            jT809Header.MsgGNSSCENTERID = 1200;
+            jT809Header.Version = new JT809Header_Version();
+            jT809Header.EncryptFlag = JT809Header_Encrypt.None;
+            jT809Header.EncryptKey = 0;
+            var hex = JT809Serializer.Serialize(jT809Header).ToHexString();
+            //"00 00 00 18 00 00 04 00 96 00 00 00 04 B0 01 00 00 00 00 00 00 00"
+        }
+
+        [Fact]
+        public void Test2()
+        {
+            var bytes = "00 00 00 18 00 00 04 00 96 00 00 00 04 B0 01 00 00 00 00 00 00 00".ToHexBytes();
+            JT809Header jT809Header= JT809Serializer.Deserialize<JT809Header>(bytes);
+            Assert.Equal((uint)24, jT809Header.MsgLength);
+            Assert.Equal((uint)1024, jT809Header.MsgSN);
+            Assert.Equal(JT809Enums.JT809BusinessType.DOWN_BASE_MSG, jT809Header.MsgID);
+            Assert.Equal((uint)1200, jT809Header.MsgGNSSCENTERID);
+            Assert.Equal(new JT809Header_Version().ToString(), jT809Header.Version.ToString());
+            Assert.Equal(JT809Header_Encrypt.None, jT809Header.EncryptFlag);
+            Assert.Equal((uint)0, jT809Header.EncryptKey);
+        }
+    }
+}
diff --git a/src/JT809.Protocol.Test/JT809MessageBody/JT809_0x1001Test.cs b/src/JT809.Protocol.Test/JT809MessageBody/JT809_0x1001Test.cs
new file mode 100644
index 0000000..246115f
--- /dev/null
+++ b/src/JT809.Protocol.Test/JT809MessageBody/JT809_0x1001Test.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xunit;
+using JT809.Protocol;
+using JT809.Protocol.JT809Extensions;
+using JT809.Protocol.JT809MessageBody;
+using JT809.Protocol.JT809Exceptions;
+
+namespace JT809.Protocol.Test.JT809MessageBody
+{
+    public class JT809_0x1001Test
+    {
+        [Fact]
+        public void Test1()
+        {
+            JT809_0x1001 jT809_0X1001 = new JT809_0x1001();
+            jT809_0X1001.UserId = 20180920;
+            jT809_0X1001.Password = "20180920";
+            jT809_0X1001.DownLinkIP = "127.0.0.1";
+            jT809_0X1001.DownLinkPort = 809;
+            var hex = JT809Serializer.Serialize(jT809_0X1001).ToHexString();
+            //"01 33 EF B8 32 30 31 38 30 39 32 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31 32 37 2E 30 2E 30 2E 31 03 29"
+        }
+
+        [Fact]
+        public void Test2()
+        {
+            var bytes = "01 33 EF B8 32 30 31 38 30 39 32 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31 32 37 2E 30 2E 30 2E 31 03 29".ToHexBytes();
+            JT809_0x1001 jT809_0X1001 = JT809Serializer.Deserialize<JT809_0x1001>(bytes);
+            Assert.Equal((uint)20180920, jT809_0X1001.UserId);
+            Assert.Equal("20180920", jT809_0X1001.Password);
+            Assert.Equal("127.0.0.1", jT809_0X1001.DownLinkIP);
+            Assert.Equal((ushort)809,jT809_0X1001.DownLinkPort);
+        }
+    }
+}
diff --git a/src/JT809.Protocol.Test/JT809Packages/JT809_0x1001PackageTest.cs b/src/JT809.Protocol.Test/JT809Packages/JT809_0x1001PackageTest.cs
new file mode 100644
index 0000000..b9717db
--- /dev/null
+++ b/src/JT809.Protocol.Test/JT809Packages/JT809_0x1001PackageTest.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xunit;
+using JT809.Protocol;
+using JT809.Protocol.JT809Extensions;
+using JT809.Protocol.JT809MessageBody;
+
+namespace JT809.Protocol.Test.JT809Packages
+{
+    public class JT809_0x1001PackageTest
+    {
+        [Fact]
+        public void Test1()
+        {
+            JT809Package jT809Package = new JT809Package();
+            jT809Package.Header = new JT809Header
+            {
+                MsgSN= 133,
+                EncryptKey=9999,
+                MsgID= JT809Enums.JT809BusinessType.UP_CONNECT_REQ,
+                MsgGNSSCENTERID= 20180920,
+            };
+            JT809_0x1001 jT809_0X1001 = new JT809_0x1001();
+            jT809_0X1001.UserId = 20180920;
+            jT809_0X1001.Password = "20180920";
+            jT809_0X1001.DownLinkIP = "127.0.0.1";
+            jT809_0X1001.DownLinkPort = 809;
+            jT809Package.Bodies = jT809_0X1001;
+            var hex = JT809Serializer.Serialize(jT809Package).ToHexString();
+            //"5B 
+            //00 00 00 48 
+            //00 00 00 85 
+            //10 01 
+            //01 33 EF B8 
+            //01 00 00 
+            //00 
+            //00 00 27 0F 
+            //01 33 EF B8 
+            //32 30 31 38 30 39 32 30 
+            //31 32 37 2E 30 2E 30 2E 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
+            //03 29 
+            //6A 91 
+            //5D"
+        }
+
+        [Fact]
+        public void Test2()
+        {
+            var bytes = "5B 00 00 00 48 00 00 00 85 10 01 01 33 EF B8 01 00 00 00 00 00 27 0F 01 33 EF B8 32 30 31 38 30 39 32 30 31 32 37 2E 30 2E 30 2E 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 29 6A 91 5D".ToHexBytes();
+            JT809Package jT809Package = JT809Serializer.Deserialize(bytes);
+            Assert.Equal((uint)72, jT809Package.Header.MsgLength);
+            Assert.Equal((uint)133, jT809Package.Header.MsgSN);
+            Assert.Equal((uint)9999, jT809Package.Header.EncryptKey);
+            Assert.Equal((uint)20180920, jT809Package.Header.MsgGNSSCENTERID);
+            Assert.Equal(JT809Enums.JT809BusinessType.UP_CONNECT_REQ, jT809Package.Header.MsgID);
+            Assert.Equal(new JT809Header_Version().ToString(), jT809Package.Header.Version.ToString());
+            JT809_0x1001 jT809_0X1001 = (JT809_0x1001)jT809Package.Bodies;
+            Assert.Equal((uint)20180920, jT809_0X1001.UserId);
+            Assert.Equal("20180920", jT809_0X1001.Password);
+            Assert.Equal("127.0.0.1", jT809_0X1001.DownLinkIP);
+            Assert.Equal((ushort)809, jT809_0X1001.DownLinkPort);
+        }
+
+        [Fact]
+        public void Test3()
+        {
+            //字符'0':char c = '0'; 它的ASCII码实际上是48。
+            //字符'\0' : ASCII码为0,表示一个字符串结束的标志。
+            //"5B 00 00 00 48 00 00 00 85 10 01 01 33 EF B8 01 00 00 00 00 00 27 0F 30 01 33 EF B8 32 30 31 38 30 39 32 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31 32 37 2E 30 2E 30 2E 31 03 29 7D 38 5D"
+            var data="32 30 31 38 30 39 32 30".ToHexBytes();
+            var str = Encoding.GetEncoding("GBK").GetString(data);
+            var data1 = "31 32 37 2E 30 2E 30 2E 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00".ToHexBytes();
+            var str1 = Encoding.GetEncoding("GBK").GetString(data1);
+            var test1 = Encoding.GetEncoding("GBK").GetBytes("\0\0\0\0\0\0127.0.0.1");
+            var test2 = Encoding.GetEncoding("GBK").GetBytes("127.0.0.1\0\0\0\0\0\0");
+            var test3 = Encoding.GetEncoding("GBK").GetBytes("000000127.0.0.1");
+            var test4 = Encoding.GetEncoding("GBK").GetBytes("127.0.0.1000000");
+        }
+    }
+}
diff --git a/src/JT809.Protocol.Test/PackageTest.cs b/src/JT809.Protocol.Test/PackageTest.cs
deleted file mode 100644
index e1e86fb..0000000
--- a/src/JT809.Protocol.Test/PackageTest.cs
+++ /dev/null
@@ -1,117 +0,0 @@
-using System;
-using System.Text;
-using JT809.Protocol.Configs;
-using JT809.Protocol.ProtocolPacket;
-using JT809.Protocol.ProtocolPacket.Bodies.Master;
-using Xunit;
-
-namespace JT809.Protocol.Test.ProtocolPacket
-{
-    public class PackageTest
-    {
-        readonly static JT809Config JT809Config = new JT809Config
-        {
-            
-        };
-
-       [Fact]
-        public void CreatePackageTest()
-        {
-           var body_UP_CONNECT_REQ= new Body_UP_CONNECT_REQ(20140813,
-               Encoding.UTF8.GetBytes("20140813"),
-               Encoding.UTF8.GetBytes("20140813"),
-               809);
-            Package package = Package.GeneratePackage(Enums.BusinessType.UP_CONNECT_REQ,
-               body_UP_CONNECT_REQ,
-                JT809Config);         
-            var data = package.Buffer.ToHexString();
-            Package package1 = new Package(package.Buffer);
-            package1.Buffer.ToHexString();
-        }
-
-        [Fact]
-        public void TestMethod1()
-        {
-            //5B 
-            //00 00 00 48 
-            //00 00 00 85 
-            //10 01 
-            //01 33 53 D5 
-            //01 00 00 
-            //00 
-            //00 00 27 0F 
-            //01 33 53 0D 32 30 31 34 30 38 31 33 31 32 37 2E 30 2E 30 2E 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 29 51 83 
-            //5D
-
-            //UP-CONNECT-REQ
-            byte[] login = new byte[]{
-                91,
-                00,00,00,48,
-                00,00,00,85,
-                10,01,
-                01,33,53,213,
-                01,00,00,
-                00,00,00,
-                27,15,01,33,
-                53,13,32,30,
-                31,34,30,38,
-                31,33,31,32,
-                37,46,30,46,
-                30,46,31,00,
-                00,00,00,00,
-                00,00,00,00,
-                00,00,00,00,
-                00,00,00,00,
-                00,00,
-                00,00,
-                00,00,03,29,
-                51,83,
-                93 };
-            Package package = new Package(login);
-        }
-
-        [Fact]
-        public void CrcTest()
-        {
-            byte[] login = new byte[] {51,83};
-
-            
-            var CRC16 = BitConverter.ToUInt16(login, 0);
-            byte[] login1 = new byte[] { 83, 51 };
-            var CRC161 = BitConverter.ToUInt16(login1, 0);
-        }
-
-        [Fact]
-        public void MSG_GNSSCENTERIDTest()
-        {//8449
-            UInt64 result = 0;
-            //00, 01, D7, 28
-            //01 ,33 ,53 ,0xD5
-            //00 01 D7 27
-            //00 00 27 0F
-            //5B 
-            
-            byte[] data = new byte[] { 00 ,0x8A ,0xDA ,0xEB };
-            int length = 4;
-            //00 << 8*(4-0-1)=>00 << 24
-            //01 << 8*(4-1-1)=>01 << 16
-            //0xD7 << 8*(4-2-1)=>0xD7 << 8
-            //27 << 8*(4-3-1)=>27 << 0
-            //var a1 = 27 << 0;
-            //for (int i = 0; i < length; i++)
-            //{
-
-            //    UInt64 currentData = (UInt64)data[i] << (8 * (length - i - 1));
-            //    result += currentData;
-            //}
-            uint value = 20141013;
-            var a1 = (byte)(value >> 24);
-            var a2 = (byte)(value >> 16);
-            var a3 = (byte)(value >> 8);
-            var a4 = (byte)(value);
-            //01 51 83 213
-            var b = (uint)(data[3] | data[2] << 8 | data[1] << 16 | data[0] << 24);
-            var a=result.ToString();
-        }
-    }
-}
diff --git a/src/JT809.Protocol/Enums/ErrorCode.cs b/src/JT809.Protocol/Enums/ErrorCode.cs
deleted file mode 100644
index d4481e3..0000000
--- a/src/JT809.Protocol/Enums/ErrorCode.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace JT809.Protocol.Enums
-{
-    public enum ErrorCode
-    {
-        CRC16CheckInvalid = 1001,
-        HeaderLengthNotEqualBodyLength=1002
-    }
-}
diff --git a/src/JT809.Protocol/Exceptions/JT809Exception.cs b/src/JT809.Protocol/Exceptions/JT809Exception.cs
deleted file mode 100644
index 96a9d17..0000000
--- a/src/JT809.Protocol/Exceptions/JT809Exception.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using JT809.Protocol.Enums;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace JT809.Protocol.Exceptions
-{
-    public class JT809Exception:Exception
-    {
-        private readonly ErrorCode errorCode;
-
-        public JT809Exception(ErrorCode errorCode) : base(errorCode.ToString())
-        {
-            this.errorCode = errorCode;
-        }
-
-        public JT809Exception(ErrorCode errorCode, string message) : base(message)
-        {
-            this.errorCode = errorCode;
-        }
-
-
-        public ErrorCode ErrorCode => errorCode;
-    }
-}
diff --git a/src/JT809.Protocol/JT809.Protocol.csproj b/src/JT809.Protocol/JT809.Protocol.csproj
index 4543a1c..7b668e3 100644
--- a/src/JT809.Protocol/JT809.Protocol.csproj
+++ b/src/JT809.Protocol/JT809.Protocol.csproj
@@ -1,7 +1,8 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
+    <LangVersion>latest</LangVersion>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@@ -9,20 +10,44 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <Compile Remove="Configs\**" />
     <Compile Remove="Encrypt\**" />
+    <Compile Remove="JT809Enums\**" />
     <Compile Remove="Escape\**" />
-    <Compile Remove="ProtocolPacket\Message\**" />
+    <Compile Remove="ProtocolPacket\**" />
+    <EmbeddedResource Remove="Configs\**" />
     <EmbeddedResource Remove="Encrypt\**" />
+    <EmbeddedResource Remove="JT809Enums\**" />
     <EmbeddedResource Remove="Escape\**" />
-    <EmbeddedResource Remove="ProtocolPacket\Message\**" />
+    <EmbeddedResource Remove="ProtocolPacket\**" />
+    <None Remove="Configs\**" />
     <None Remove="Encrypt\**" />
+    <None Remove="JT809Enums\**" />
     <None Remove="Escape\**" />
-    <None Remove="ProtocolPacket\Message\**" />
+    <None Remove="ProtocolPacket\**" />
   </ItemGroup>
 
   <ItemGroup>
+    <Compile Remove="Constants.cs" />
     <Compile Remove="IEncrypt.cs" />
     <Compile Remove="IEscape.cs" />
   </ItemGroup>
 
+  <ItemGroup>
+    <Compile Include="JT809Enums\JT809ErrorCode.cs" />
+    <Compile Include="JT809Enums\JT809BusinessType.cs" />
+    <Compile Include="JT809Enums\JT809SubBusinessType.cs" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
+    <PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
+    <PackageReference Include="System.Memory" Version="4.5.1" />
+    <PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.0" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="JT809Properties\" />
+  </ItemGroup>
+
 </Project>
diff --git a/src/JT809.Protocol/JT809Attributes/JT809BodiesTypeAttribute.cs b/src/JT809.Protocol/JT809Attributes/JT809BodiesTypeAttribute.cs
new file mode 100644
index 0000000..bf0e710
--- /dev/null
+++ b/src/JT809.Protocol/JT809Attributes/JT809BodiesTypeAttribute.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace JT809.Protocol.JT809Attributes
+{
+    [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
+    public sealed class JT809BodiesTypeAttribute : Attribute
+    {
+        public JT809BodiesTypeAttribute(Type jT809BodiesType)
+        {
+            JT809BodiesType = jT809BodiesType;
+        }
+        public Type JT809BodiesType { get;}
+    }
+}
diff --git a/src/JT809.Protocol/JT809Attributes/JT809FormatterAttribute.cs b/src/JT809.Protocol/JT809Attributes/JT809FormatterAttribute.cs
new file mode 100644
index 0000000..af1287b
--- /dev/null
+++ b/src/JT809.Protocol/JT809Attributes/JT809FormatterAttribute.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol.JT809Attributes
+{
+    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
+    public  sealed  class JT809FormatterAttribute:Attribute
+    {
+        public Type FormatterType { get; private set; }
+
+        public object[] Arguments { get; private set; }
+
+        public JT809FormatterAttribute(Type formatterType)
+        {
+            this.FormatterType = formatterType;
+        }
+
+        public JT809FormatterAttribute(Type formatterType, params object[] arguments)
+        {
+            this.FormatterType = formatterType;
+            this.Arguments = arguments;
+        }
+    }
+}
diff --git a/src/JT809.Protocol/JT809Bodies.cs b/src/JT809.Protocol/JT809Bodies.cs
new file mode 100644
index 0000000..69d1d77
--- /dev/null
+++ b/src/JT809.Protocol/JT809Bodies.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol
+{
+    public abstract class JT809Bodies
+    {
+    }
+}
diff --git a/src/JT809.Protocol/Enums/BusinessType.cs b/src/JT809.Protocol/JT809Enums/JT809BusinessType.cs
similarity index 95%
rename from src/JT809.Protocol/Enums/BusinessType.cs
rename to src/JT809.Protocol/JT809Enums/JT809BusinessType.cs
index 4e735d2..40c418b 100644
--- a/src/JT809.Protocol/Enums/BusinessType.cs
+++ b/src/JT809.Protocol/JT809Enums/JT809BusinessType.cs
@@ -1,163 +1,166 @@
-using System.ComponentModel;
-
-namespace JT809.Protocol.Enums
-{
-    /// <summary>
-    /// 业务数据类型标识
-    /// 数据交换一协议规定的业务数据类型名称和标识常量定义见表 73。业务数据类型标识的命名规则如下:
-    /// a) 上级平台向下级平台发送的请求消息,一般以“DOWN_”开头,以后缀_REQ 结尾;而下级平台向上级平台发送的请求消息一般以“UP_”开头,以后缀_REQ 结尾;
-    /// b) 当上下级平台之间有应答消息情况下,应答消息可继续沿用对应的请求消息开头标识符,而通过后缀 RSP 来标识结尾。
-    /// </summary>
-    public enum BusinessType : ushort
-    {
-        #region 链路管理类
-        ///<summary>
-        ///主链路登录请求消息  
-        ///</summary>
-        [Description("主链路登录请求消息")]
-        UP_CONNECT_REQ = 0x1001,
-        ///<summary>
-        ///主链路登录应答消息  
-        ///</summary>
-        [Description("主链路登录应答消息")]
-        UP_CONNECT_RSP = 0x1002,
-        ///<summary>
-        ///主链路注销请求消息  
-        ///</summary>
-        [Description("主链路注销请求消息")]
-        UP_DISCONNECT_REQ = 0x1003,
-        ///<summary>
-        ///主链路注销应答消息  
-        ///</summary>
-        [Description("主链路注销应答消息")]
-        UP_DISCONNECT_RSP = 0x1004,
-        ///<summary>
-        ///主链路连接保持请求消息  
-        ///</summary>
-        [Description("主链路连接保持请求消息")]
-        UP_LINKTEST_REQ = 0x1005,
-        ///<summary>
-        ///主链路连接保持应答消息  
-        ///</summary>
-        [Description("主链路连接保持应答消息")]
-        UP_LINKTEST_RSP = 0x1006,
-        ///<summary>
-        ///主链路断开通知消息  
-        ///</summary>
-        [Description("主链路断开通知消息")]
-        UP_DISCONNECT_INFORM = 0x1007,
-        ///<summary>
-        ///下级平台主动关闭链路通知消息  
-        ///</summary>
-        [Description("下级平台主动关闭链路通知消息")]
-        UP_CLOSELINK_INFORM = 0x1008,
-        ///<summary>
-        ///从链路连接请求消息  
-        ///</summary>
-        [Description("从链路连接请求消息")]
-        DOWN_CONNECT_REQ = 0x9001,
-        ///<summary>
-        ///从链路连接应答消息  
-        ///</summary>
-        [Description("从链路连接应答消息")]
-        DOWN_CONNECT_RSP = 0x9002,
-        ///<summary>
-        ///从链路注销请求消息  
-        ///</summary>
-        [Description("从链路注销请求消息")]
-        DOWN_DISCONNECT_REQ = 0x9003,
-        ///<summary>
-        ///从链路注销应答消息  
-        ///</summary>
-        [Description("从链路注销应答消息")]
-        DOWN_DISCONNECT_RSP = 0x9004,
-        ///<summary>
-        ///从链路连接保持请求消息  
-        ///</summary>
-        [Description("从链路连接保持请求消息")]
-        DOWN_LINKTEST_REQ = 0x9005,
-        ///<summary>
-        ///从链路连接保持应答消息  
-        ///</summary>
-        [Description("从链路连接保持应答消息")]
-        DOWN_LINKTEST_RSP = 0x9006,
-        ///<summary>
-        ///从链路断开通知消息  
-        ///</summary>
-        [Description("从链路断开通知消息")]
-        DOWN_DISCONNECT_INFORM = 0x9007,
-        ///<summary>
-        ///上级平台主动关闭链路通知消息  
-        ///</summary>
-        [Description("上级平台主动关闭链路通知消息")]
-        DOWN_CLOSELINK_INFORM = 0x9008,
-        #endregion
-        #region 信息统计类
-        ///<summary>
-        ///接收定位信息数量通知消息  
-        ///</summary>
-        [Description("接收定位信息数量通知消息")]
-        DOWN_TOTAL_RECV_BACK_MSG = 0x9101,
-        #endregion
-        #region 车辆动态信息交换
-        ///<summary>
-        ///主链路动态信息交换消息  
-        ///</summary>
-        [Description("主链路动态信息交换消息")]
-        UP_EXG_MSG = 0x1200,
-        ///<summary>
-        ///从链路动态信息交换消息  
-        ///</summary>
-        [Description("从链路动态信息交换消息")]
-        DOWN_EXG_MSG = 0x9200,
-        #endregion
-        #region 平台间信息交互类
-        ///<summary>
-        ///主链路平台间信息交互消息  
-        ///</summary>
-        [Description("主链路平台间信息交互消息")]
-        UP_PLATFORM_MSG = 0x1300,
-        ///<summary>
-        ///从链路平台间信息交互消息  
-        ///</summary>
-        [Description("从链路平台间信息交互消息")]
-        DOWN_PLATFORM_MSG = 0x9300,
-        #endregion
-        #region 车辆报警信息交互类
-        ///<summary>
-        ///主链路报警信息交互消息  
-        ///</summary>
-        [Description("主链路报警信息交互消息")]
-        UP_WARN_MSG = 0x1400,
-        ///<summary>
-        ///从链路报警信息交互消息  
-        ///</summary>
-        [Description("从链路报警信息交互消息")]
-        DOWN_WARN_MSG = 0x9400,
-        #endregion
-        #region 车辆监管类 
-        ///<summary>
-        ///主链路车辆监管消息  
-        ///</summary>
-        [Description("主链路车辆监管消息")]
-        UP_CTRL_MSG = 0x1500,
-        ///<summary>
-        ///从链路车辆监管消息  
-        ///</summary>
-        [Description("从链路车辆监管消息")]
-        DOWN_CTRL_MSG = 0x9500,
-        #endregion
-        #region 车辆静态信息交换类
-        ///<summary>
-        ///主链路静态信息交换消息  
-        ///</summary>
-        [Description("主链路静态信息交换消息")]
-        UP_BASE_MSG = 0x1600,
-        ///<summary>
-        ///从链路静态信息交换消息  
-        ///</summary>
-        [Description("从链路静态信息交换消息")]
-        DOWN_BASE_MSG = 0x9600,
-        #endregion
-    }
-}
+using JT809.Protocol.JT809Attributes;
+using JT809.Protocol.JT809MessageBody;
+using System.ComponentModel;
+
+namespace JT809.Protocol.JT809Enums
+{
+    /// <summary>
+    /// 业务数据类型标识
+    /// 数据交换一协议规定的业务数据类型名称和标识常量定义见表 73。业务数据类型标识的命名规则如下:
+    /// a) 上级平台向下级平台发送的请求消息,一般以“DOWN_”开头,以后缀_REQ 结尾;而下级平台向上级平台发送的请求消息一般以“UP_”开头,以后缀_REQ 结尾;
+    /// b) 当上下级平台之间有应答消息情况下,应答消息可继续沿用对应的请求消息开头标识符,而通过后缀 RSP 来标识结尾。
+    /// </summary>
+    public enum JT809BusinessType : ushort
+    {
+        #region 链路管理类
+        ///<summary>
+        ///主链路登录请求消息  
+        ///</summary>
+        [Description("主链路登录请求消息")]
+        [JT809BodiesType(typeof(JT809_0x1001))]
+        UP_CONNECT_REQ = 0x1001,
+        ///<summary>
+        ///主链路登录应答消息  
+        ///</summary>
+        [Description("主链路登录应答消息")]
+        UP_CONNECT_RSP = 0x1002,
+        ///<summary>
+        ///主链路注销请求消息  
+        ///</summary>
+        [Description("主链路注销请求消息")]
+        UP_DISCONNECT_REQ = 0x1003,
+        ///<summary>
+        ///主链路注销应答消息  
+        ///</summary>
+        [Description("主链路注销应答消息")]
+        UP_DISCONNECT_RSP = 0x1004,
+        ///<summary>
+        ///主链路连接保持请求消息  
+        ///</summary>
+        [Description("主链路连接保持请求消息")]
+        UP_LINKTEST_REQ = 0x1005,
+        ///<summary>
+        ///主链路连接保持应答消息  
+        ///</summary>
+        [Description("主链路连接保持应答消息")]
+        UP_LINKTEST_RSP = 0x1006,
+        ///<summary>
+        ///主链路断开通知消息  
+        ///</summary>
+        [Description("主链路断开通知消息")]
+        UP_DISCONNECT_INFORM = 0x1007,
+        ///<summary>
+        ///下级平台主动关闭链路通知消息  
+        ///</summary>
+        [Description("下级平台主动关闭链路通知消息")]
+        UP_CLOSELINK_INFORM = 0x1008,
+        ///<summary>
+        ///从链路连接请求消息  
+        ///</summary>
+        [Description("从链路连接请求消息")]
+        DOWN_CONNECT_REQ = 0x9001,
+        ///<summary>
+        ///从链路连接应答消息  
+        ///</summary>
+        [Description("从链路连接应答消息")]
+        DOWN_CONNECT_RSP = 0x9002,
+        ///<summary>
+        ///从链路注销请求消息  
+        ///</summary>
+        [Description("从链路注销请求消息")]
+        DOWN_DISCONNECT_REQ = 0x9003,
+        ///<summary>
+        ///从链路注销应答消息  
+        ///</summary>
+        [Description("从链路注销应答消息")]
+        DOWN_DISCONNECT_RSP = 0x9004,
+        ///<summary>
+        ///从链路连接保持请求消息  
+        ///</summary>
+        [Description("从链路连接保持请求消息")]
+        DOWN_LINKTEST_REQ = 0x9005,
+        ///<summary>
+        ///从链路连接保持应答消息  
+        ///</summary>
+        [Description("从链路连接保持应答消息")]
+        DOWN_LINKTEST_RSP = 0x9006,
+        ///<summary>
+        ///从链路断开通知消息  
+        ///</summary>
+        [Description("从链路断开通知消息")]
+        DOWN_DISCONNECT_INFORM = 0x9007,
+        ///<summary>
+        ///上级平台主动关闭链路通知消息  
+        ///</summary>
+        [Description("上级平台主动关闭链路通知消息")]
+        DOWN_CLOSELINK_INFORM = 0x9008,
+        #endregion
+        #region 信息统计类
+        ///<summary>
+        ///接收定位信息数量通知消息  
+        ///</summary>
+        [Description("接收定位信息数量通知消息")]
+        DOWN_TOTAL_RECV_BACK_MSG = 0x9101,
+        #endregion
+        #region 车辆动态信息交换
+        ///<summary>
+        ///主链路动态信息交换消息  
+        ///</summary>
+        [Description("主链路动态信息交换消息")]
+        UP_EXG_MSG = 0x1200,
+        ///<summary>
+        ///从链路动态信息交换消息  
+        ///</summary>
+        [Description("从链路动态信息交换消息")]
+        DOWN_EXG_MSG = 0x9200,
+        #endregion
+        #region 平台间信息交互类
+        ///<summary>
+        ///主链路平台间信息交互消息  
+        ///</summary>
+        [Description("主链路平台间信息交互消息")]
+        UP_PLATFORM_MSG = 0x1300,
+        ///<summary>
+        ///从链路平台间信息交互消息  
+        ///</summary>
+        [Description("从链路平台间信息交互消息")]
+        DOWN_PLATFORM_MSG = 0x9300,
+        #endregion
+        #region 车辆报警信息交互类
+        ///<summary>
+        ///主链路报警信息交互消息  
+        ///</summary>
+        [Description("主链路报警信息交互消息")]
+        UP_WARN_MSG = 0x1400,
+        ///<summary>
+        ///从链路报警信息交互消息  
+        ///</summary>
+        [Description("从链路报警信息交互消息")]
+        DOWN_WARN_MSG = 0x9400,
+        #endregion
+        #region 车辆监管类 
+        ///<summary>
+        ///主链路车辆监管消息  
+        ///</summary>
+        [Description("主链路车辆监管消息")]
+        UP_CTRL_MSG = 0x1500,
+        ///<summary>
+        ///从链路车辆监管消息  
+        ///</summary>
+        [Description("从链路车辆监管消息")]
+        DOWN_CTRL_MSG = 0x9500,
+        #endregion
+        #region 车辆静态信息交换类
+        ///<summary>
+        ///主链路静态信息交换消息  
+        ///</summary>
+        [Description("主链路静态信息交换消息")]
+        UP_BASE_MSG = 0x1600,
+        ///<summary>
+        ///从链路静态信息交换消息  
+        ///</summary>
+        [Description("从链路静态信息交换消息")]
+        DOWN_BASE_MSG = 0x9600,
+        #endregion
+    }
+}
diff --git a/src/JT809.Protocol/JT809Enums/JT809ErrorCode.cs b/src/JT809.Protocol/JT809Enums/JT809ErrorCode.cs
new file mode 100644
index 0000000..81f5c68
--- /dev/null
+++ b/src/JT809.Protocol/JT809Enums/JT809ErrorCode.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol.JT809Enums
+{
+    public enum JT809ErrorCode
+    {
+        CRC16CheckInvalid = 1001,
+        HeaderLengthNotEqualBodyLength=1002,
+        GetFormatterError=1003,
+        SerializeError=1004,
+        DeserializeError=1005,
+        HeaderParseError=1006,
+        BodiesParseError=1007
+    }
+}
diff --git a/src/JT809.Protocol/Enums/SubBusinessType.cs b/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs
similarity index 96%
rename from src/JT809.Protocol/Enums/SubBusinessType.cs
rename to src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs
index 18ca14a..3ef3ca0 100644
--- a/src/JT809.Protocol/Enums/SubBusinessType.cs
+++ b/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs
@@ -1,260 +1,260 @@
-using System.ComponentModel;
-
-namespace JT809.Protocol.Enums
-{
-    ///<summary>
-    ///子业务类型标识
-    ///</summary>
-    public enum SubBusinessType : ushort
-    {
-        #region 主链路动态信息交换消息 UP_EXG_MSG
-        /// <summary>
-        /// 上传车辆注册信息
-        /// </summary>
-        [Description("上传车辆注册信息")]
-        UP_EXG_MSG_REGISTER = 0x1201,
-        ///<summary>
-        ///实时上传车辆定位信息  
-        ///</summary>
-        [Description("实时上传车辆定位信息")]
-        UP_EXG_MSG_REAL_LOCATION = 0x1202,
-        ///<summary>
-        ///车辆定位信息自动补报	
-        ///</summary>
-        [Description("车辆定位信息自动补报")]
-        UP_EXG_MSG_HISTORY_LOCATION = 0x1203,
-        ///<summary>
-        ///启动车辆定位信息交换应答	
-        ///</summary>
-        [Description("启动车辆定位信息交换应答")]
-        UP_EXG_MSG_RETURN_STARTUP_ACK = 0x1205,
-        ///<summary>
-        ///结束车辆定位信息交换应答	
-        ///</summary>
-        [Description("结束车辆定位信息交换应答")]
-        UP_EXG_MSG_RETURN_END_ACK = 0x1206,
-        ///<summary>
-        ///申请交换指定车辆定位信息请求	
-        ///</summary>
-        [Description("申请交换指定车辆定位信息请求")]
-        UP_EXG_MSG_APPLY_FOR_MONITOR_STARTUP = 0x1207,
-        ///<summary>
-        ///取消交换指定车辆定位信息请求	
-        ///</summary>
-        [Description("取消交换指定车辆定位信息请求")]
-        UP_EXG_MSG_APPLY_FOR_MONITOR_END = 0x1208,
-        ///<summary>
-        ///补发车辆定位信息请求	
-        ///</summary>
-        [Description("补发车辆定位信息请求")]
-        UP_EXG_MSG_APPLY_HISGNSSDATA_REQ = 0x1209,
-        ///<summary>
-        ///上报车辆驾驶员身份识别信息应答	
-        ///</summary>
-        [Description("上报车辆驾驶员身份识别信息应答")]
-        UP_EXG_MSG_REPORT_DRIVER_INFO_ACK = 0x120A,
-        ///<summary>
-        ///上报车辆电子运单应答	
-        ///</summary>
-        [Description("上报车辆电子运单应答")]
-        UP_EXG_MSG_TAKE_EWAYBILL_ACK = 0x120B,
-        ///<summary>
-        ///主动上报驾驶员身份信息	
-        ///</summary>
-        [Description("主动上报驾驶员身份信息")]
-        UP_EXG_MSG_REPORT_DRIVER_INFO = 0x120C,
-        ///<summary>
-        ///主动上报车辆电子运单信息	
-        ///</summary>
-        [Description("主动上报车辆电子运单信息")]
-        UP_EXG_MSG_REPORT_EWAYBILL_INFO = 0x120D,
-        #endregion
-
-        #region 从链路动态信息交换消息 DOWN_EXG_MSG
-        ///<summary>
-        ///交换车辆定位信息	
-        ///</summary>
-        [Description("交换车辆定位信息")]
-        DOWN_EXG_MSG_CAR_LOCATION = 0x9202,
-        ///<summary>
-        ///车辆定位信息交换补发	
-        ///</summary>
-        [Description("车辆定位信息交换补发")]
-        DOWN_EXG_MSG_HISTORY_ARCOSSAREA = 0x9203,
-        ///<summary>
-        ///交换车辆静态信息	
-        ///</summary>
-        [Description("交换车辆静态信息")]
-        DOWN_EXG_MSG_CAR_INFO = 0x9204,
-        ///<summary>
-        ///启动车辆定位信息交换请求	
-        ///</summary>
-        [Description("启动车辆定位信息交换请求")]
-        DOWN_EXG_MSG_RETURN_STARTUP = 0x9205,
-        ///<summary>
-        ///结束车辆定位信息交换请求	
-        ///</summary>
-        [Description("结束车辆定位信息交换请求")]
-        DOWN_EXG_MSG_RETURN_END = 0x9206,
-        ///<summary>
-        ///申请交换指定车辆定位信息应答	
-        ///</summary>
-        [Description("申请交换指定车辆定位信息应答")]
-        DOWN_EXG_MSG_APPLY_FOR_MONITOR_STARTUP_ACK = 0x9207,
-        ///<summary>
-        ///取消交换指定车辆定位信息应答	
-        ///</summary>
-        [Description("取消交换指定车辆定位信息应答")]
-        DOWN_EXG_MSG_APPLY_FOR_MONITOR_END_ACK = 0x9208,
-        ///<summary>
-        ///补发车辆定位信息应答	
-        ///</summary>
-        [Description("补发车辆定位信息应答")]
-        DOWN_EXG_MSG_APPLY_HISGNSSDATA_ACK = 0x9209,
-        ///<summary>
-        ///上报车辆驾驶员身份识别信息请求	
-        ///</summary>
-        [Description("上报车辆驾驶员身份识别信息请求")]
-        DOWN_EXG_MSG_REPORT_DRIVER_INFO = 0x920A,
-        ///<summary>
-        ///上报车辆电子运单请求	
-        ///</summary>
-        [Description("上报车辆电子运单请求")]
-        DOWN_EXG_MSG_TAKE_EWAYBILL_REQ = 0x920B,
-        #endregion
-
-        #region 主链路平台信息交互消息 UP_PLATFORM_MSG
-        ///<summary>
-        ///平台查岗应答	
-        ///</summary>
-        [Description("平台查岗应答")]
-        UP_PLATFORM_MSG_POST_QUERY_ACK = 0x1301,
-        ///<summary>
-        ///下发平台间报文应答	
-        ///</summary>
-        [Description("下发平台间报文应答")]
-        UP_PLATFORM_MSG_INFO_ACK = 0x1302,
-        #endregion
-
-        #region 从链路平台信息交互消息 DOWN_PLATFORM_MSG
-        ///<summary>
-        ///平台查岗请求	
-        ///</summary>
-        [Description("平台查岗请求")]
-        DOWN_PLATFORM_MSG_POST_QUERY_REQ = 0x9301,
-        ///<summary>
-        ///下发平台间报文请求	
-        ///</summary>
-        [Description("下发平台间报文请求")]
-        DOWN_PLATFORM_MSG_INFO_REQ = 0x9302,
-        #endregion
-
-        #region 主链路报警信息交互消息 UP_WARN_MSG
-        ///<summary>
-        ///报警督办应答	
-        ///</summary>
-        [Description("报警督办应答")]
-        UP_WARN_MSG_URGE_TODO_ACK = 0x1401,
-        ///<summary>
-        ///上报报警信息	
-        ///</summary>
-        [Description("上报报警信息")]
-        UP_WARN_MSG_ADPT_INFO = 0x1402,
-        ///<summary>
-        ///主动上报报警处理结果信息	
-        ///</summary>
-        [Description("主动上报报警处理结果信息")]
-        UP_WARN_MSG_ADPT_TODO_INFO = 0x1403,
-        #endregion
-
-        #region 从链路报警信息交互消息 DOWN_WARN_MSG
-        ///<summary>
-        ///报警督办请求	
-        ///</summary>
-        [Description("报警督办请求")]
-        DOWN_WARN_MSG_URGE_TODO_REQ = 0x9401,
-        ///<summary>
-        ///报警预警	
-        ///</summary>
-        [Description("报警预警")]
-        DOWN_WARN_MSG_INFORM_TIPS = 0x9402,
-        ///<summary>
-        ///实时交换报警信息 	
-        ///</summary>
-        [Description("实时交换报警信息")]
-        DOWN_WARN_MSG_EXG_INFORM = 0x9403,
-        #endregion
-
-        #region 主链路车辆监管消息 UP_CTRL_MSG
-        ///<summary>
-        ///车辆单向监听应答	
-        ///</summary>
-        [Description("车辆单向监听应答")]
-        UP_CTRL_MSG_MONITOR_VEHICLE_ACK = 0x1501,
-        ///<summary>
-        ///车辆拍照应答	
-        ///</summary>
-        [Description("车辆拍照应答")]
-        UP_CTRL_MSG_TAKE_PHOTO_ACK = 0x1502,
-        ///<summary>
-        ///下发车辆报文应答	
-        ///</summary>
-        [Description("下发车辆报文应答")]
-        UP_CTRL_MSG_TEXT_INFO_ACK = 0x1503,
-        ///<summary>
-        ///上报车辆行驶记录应答	
-        ///</summary>
-        [Description("上报车辆行驶记录应答")]
-        UP_CTRL_MSG_TAKE_TRAVEL_ACK = 0x1504,
-        ///<summary>
-        ///车辆应急接入监管平台应答消息	
-        ///</summary>
-        [Description("车辆应急接入监管平台应答消息")]
-        UP_CTRL_MSG_EMERGENCY_MONITORING_ACK = 0x1505,
-        #endregion
-
-        #region 从链路车辆监管消息 DOWN_CTRL_MSG
-        ///<summary>
-        ///车辆单向监听请求	
-        ///</summary>
-        [Description("车辆单向监听请求")]
-        DOWN_CTRL_MSG_MONITOR_VEHICLE_REQ = 0x9501,
-        ///<summary>
-        ///车辆拍照请求	
-        ///</summary>
-        [Description("车辆拍照请求")]
-        DOWN_CTRL_MSG_TAKE_PHOTO_REQ = 0x9502,
-        ///<summary>
-        ///下发车辆报文请求	
-        ///</summary>
-        [Description("下发车辆报文请求")]
-        DOWN_CTRL_MSG_TEXT_INFO = 0x9503,
-        ///<summary>
-        ///上报车辆行驶记录请求	
-        ///</summary>
-        [Description("上报车辆行驶记录请求")]
-        DOWN_CTRL_MSG_TAKE_TRAVEL_REQ = 0x9504,
-        ///<summary>
-        ///车辆应急接入监管平台请求消息	
-        ///</summary>
-        [Description("车辆应急接入监管平台请求消息")]
-        DOWN_CTRL_MSG_EMERGENCY_MONITORING_REQ = 0x9505,
-        #endregion
-
-        #region 主链路静态信息交换消息 UP_BASE_MSG
-        ///<summary>
-        ///补报车辆静态信息应答	
-        ///</summary>
-        [Description("补报车辆静态信息应答")]
-        UP_BASE_MSG_VEHICLE_ADDED_ACK = 0x1601,
-        #endregion
-
-        #region 从链路静态信息交换消息 DOWN_BASE_MSG
-        ///<summary>
-        ///补报车辆静态信息请求	
-        ///</summary>
-        [Description("补报车辆静态信息请求")]
-        DOWN_BASE_MSG_VEHICLE_ADDED = 0x9601,
-        #endregion
-    }
-}
+using System.ComponentModel;
+
+namespace JT809.Protocol.JT809Enums
+{
+    ///<summary>
+    ///子业务类型标识
+    ///</summary>
+    public enum JT809SubBusinessType : ushort
+    {
+        #region 主链路动态信息交换消息 UP_EXG_MSG
+        /// <summary>
+        /// 上传车辆注册信息
+        /// </summary>
+        [Description("上传车辆注册信息")]
+        UP_EXG_MSG_REGISTER = 0x1201,
+        ///<summary>
+        ///实时上传车辆定位信息  
+        ///</summary>
+        [Description("实时上传车辆定位信息")]
+        UP_EXG_MSG_REAL_LOCATION = 0x1202,
+        ///<summary>
+        ///车辆定位信息自动补报	
+        ///</summary>
+        [Description("车辆定位信息自动补报")]
+        UP_EXG_MSG_HISTORY_LOCATION = 0x1203,
+        ///<summary>
+        ///启动车辆定位信息交换应答	
+        ///</summary>
+        [Description("启动车辆定位信息交换应答")]
+        UP_EXG_MSG_RETURN_STARTUP_ACK = 0x1205,
+        ///<summary>
+        ///结束车辆定位信息交换应答	
+        ///</summary>
+        [Description("结束车辆定位信息交换应答")]
+        UP_EXG_MSG_RETURN_END_ACK = 0x1206,
+        ///<summary>
+        ///申请交换指定车辆定位信息请求	
+        ///</summary>
+        [Description("申请交换指定车辆定位信息请求")]
+        UP_EXG_MSG_APPLY_FOR_MONITOR_STARTUP = 0x1207,
+        ///<summary>
+        ///取消交换指定车辆定位信息请求	
+        ///</summary>
+        [Description("取消交换指定车辆定位信息请求")]
+        UP_EXG_MSG_APPLY_FOR_MONITOR_END = 0x1208,
+        ///<summary>
+        ///补发车辆定位信息请求	
+        ///</summary>
+        [Description("补发车辆定位信息请求")]
+        UP_EXG_MSG_APPLY_HISGNSSDATA_REQ = 0x1209,
+        ///<summary>
+        ///上报车辆驾驶员身份识别信息应答	
+        ///</summary>
+        [Description("上报车辆驾驶员身份识别信息应答")]
+        UP_EXG_MSG_REPORT_DRIVER_INFO_ACK = 0x120A,
+        ///<summary>
+        ///上报车辆电子运单应答	
+        ///</summary>
+        [Description("上报车辆电子运单应答")]
+        UP_EXG_MSG_TAKE_EWAYBILL_ACK = 0x120B,
+        ///<summary>
+        ///主动上报驾驶员身份信息	
+        ///</summary>
+        [Description("主动上报驾驶员身份信息")]
+        UP_EXG_MSG_REPORT_DRIVER_INFO = 0x120C,
+        ///<summary>
+        ///主动上报车辆电子运单信息	
+        ///</summary>
+        [Description("主动上报车辆电子运单信息")]
+        UP_EXG_MSG_REPORT_EWAYBILL_INFO = 0x120D,
+        #endregion
+
+        #region 从链路动态信息交换消息 DOWN_EXG_MSG
+        ///<summary>
+        ///交换车辆定位信息	
+        ///</summary>
+        [Description("交换车辆定位信息")]
+        DOWN_EXG_MSG_CAR_LOCATION = 0x9202,
+        ///<summary>
+        ///车辆定位信息交换补发	
+        ///</summary>
+        [Description("车辆定位信息交换补发")]
+        DOWN_EXG_MSG_HISTORY_ARCOSSAREA = 0x9203,
+        ///<summary>
+        ///交换车辆静态信息	
+        ///</summary>
+        [Description("交换车辆静态信息")]
+        DOWN_EXG_MSG_CAR_INFO = 0x9204,
+        ///<summary>
+        ///启动车辆定位信息交换请求	
+        ///</summary>
+        [Description("启动车辆定位信息交换请求")]
+        DOWN_EXG_MSG_RETURN_STARTUP = 0x9205,
+        ///<summary>
+        ///结束车辆定位信息交换请求	
+        ///</summary>
+        [Description("结束车辆定位信息交换请求")]
+        DOWN_EXG_MSG_RETURN_END = 0x9206,
+        ///<summary>
+        ///申请交换指定车辆定位信息应答	
+        ///</summary>
+        [Description("申请交换指定车辆定位信息应答")]
+        DOWN_EXG_MSG_APPLY_FOR_MONITOR_STARTUP_ACK = 0x9207,
+        ///<summary>
+        ///取消交换指定车辆定位信息应答	
+        ///</summary>
+        [Description("取消交换指定车辆定位信息应答")]
+        DOWN_EXG_MSG_APPLY_FOR_MONITOR_END_ACK = 0x9208,
+        ///<summary>
+        ///补发车辆定位信息应答	
+        ///</summary>
+        [Description("补发车辆定位信息应答")]
+        DOWN_EXG_MSG_APPLY_HISGNSSDATA_ACK = 0x9209,
+        ///<summary>
+        ///上报车辆驾驶员身份识别信息请求	
+        ///</summary>
+        [Description("上报车辆驾驶员身份识别信息请求")]
+        DOWN_EXG_MSG_REPORT_DRIVER_INFO = 0x920A,
+        ///<summary>
+        ///上报车辆电子运单请求	
+        ///</summary>
+        [Description("上报车辆电子运单请求")]
+        DOWN_EXG_MSG_TAKE_EWAYBILL_REQ = 0x920B,
+        #endregion
+
+        #region 主链路平台信息交互消息 UP_PLATFORM_MSG
+        ///<summary>
+        ///平台查岗应答	
+        ///</summary>
+        [Description("平台查岗应答")]
+        UP_PLATFORM_MSG_POST_QUERY_ACK = 0x1301,
+        ///<summary>
+        ///下发平台间报文应答	
+        ///</summary>
+        [Description("下发平台间报文应答")]
+        UP_PLATFORM_MSG_INFO_ACK = 0x1302,
+        #endregion
+
+        #region 从链路平台信息交互消息 DOWN_PLATFORM_MSG
+        ///<summary>
+        ///平台查岗请求	
+        ///</summary>
+        [Description("平台查岗请求")]
+        DOWN_PLATFORM_MSG_POST_QUERY_REQ = 0x9301,
+        ///<summary>
+        ///下发平台间报文请求	
+        ///</summary>
+        [Description("下发平台间报文请求")]
+        DOWN_PLATFORM_MSG_INFO_REQ = 0x9302,
+        #endregion
+
+        #region 主链路报警信息交互消息 UP_WARN_MSG
+        ///<summary>
+        ///报警督办应答	
+        ///</summary>
+        [Description("报警督办应答")]
+        UP_WARN_MSG_URGE_TODO_ACK = 0x1401,
+        ///<summary>
+        ///上报报警信息	
+        ///</summary>
+        [Description("上报报警信息")]
+        UP_WARN_MSG_ADPT_INFO = 0x1402,
+        ///<summary>
+        ///主动上报报警处理结果信息	
+        ///</summary>
+        [Description("主动上报报警处理结果信息")]
+        UP_WARN_MSG_ADPT_TODO_INFO = 0x1403,
+        #endregion
+
+        #region 从链路报警信息交互消息 DOWN_WARN_MSG
+        ///<summary>
+        ///报警督办请求	
+        ///</summary>
+        [Description("报警督办请求")]
+        DOWN_WARN_MSG_URGE_TODO_REQ = 0x9401,
+        ///<summary>
+        ///报警预警	
+        ///</summary>
+        [Description("报警预警")]
+        DOWN_WARN_MSG_INFORM_TIPS = 0x9402,
+        ///<summary>
+        ///实时交换报警信息 	
+        ///</summary>
+        [Description("实时交换报警信息")]
+        DOWN_WARN_MSG_EXG_INFORM = 0x9403,
+        #endregion
+
+        #region 主链路车辆监管消息 UP_CTRL_MSG
+        ///<summary>
+        ///车辆单向监听应答	
+        ///</summary>
+        [Description("车辆单向监听应答")]
+        UP_CTRL_MSG_MONITOR_VEHICLE_ACK = 0x1501,
+        ///<summary>
+        ///车辆拍照应答	
+        ///</summary>
+        [Description("车辆拍照应答")]
+        UP_CTRL_MSG_TAKE_PHOTO_ACK = 0x1502,
+        ///<summary>
+        ///下发车辆报文应答	
+        ///</summary>
+        [Description("下发车辆报文应答")]
+        UP_CTRL_MSG_TEXT_INFO_ACK = 0x1503,
+        ///<summary>
+        ///上报车辆行驶记录应答	
+        ///</summary>
+        [Description("上报车辆行驶记录应答")]
+        UP_CTRL_MSG_TAKE_TRAVEL_ACK = 0x1504,
+        ///<summary>
+        ///车辆应急接入监管平台应答消息	
+        ///</summary>
+        [Description("车辆应急接入监管平台应答消息")]
+        UP_CTRL_MSG_EMERGENCY_MONITORING_ACK = 0x1505,
+        #endregion
+
+        #region 从链路车辆监管消息 DOWN_CTRL_MSG
+        ///<summary>
+        ///车辆单向监听请求	
+        ///</summary>
+        [Description("车辆单向监听请求")]
+        DOWN_CTRL_MSG_MONITOR_VEHICLE_REQ = 0x9501,
+        ///<summary>
+        ///车辆拍照请求	
+        ///</summary>
+        [Description("车辆拍照请求")]
+        DOWN_CTRL_MSG_TAKE_PHOTO_REQ = 0x9502,
+        ///<summary>
+        ///下发车辆报文请求	
+        ///</summary>
+        [Description("下发车辆报文请求")]
+        DOWN_CTRL_MSG_TEXT_INFO = 0x9503,
+        ///<summary>
+        ///上报车辆行驶记录请求	
+        ///</summary>
+        [Description("上报车辆行驶记录请求")]
+        DOWN_CTRL_MSG_TAKE_TRAVEL_REQ = 0x9504,
+        ///<summary>
+        ///车辆应急接入监管平台请求消息	
+        ///</summary>
+        [Description("车辆应急接入监管平台请求消息")]
+        DOWN_CTRL_MSG_EMERGENCY_MONITORING_REQ = 0x9505,
+        #endregion
+
+        #region 主链路静态信息交换消息 UP_BASE_MSG
+        ///<summary>
+        ///补报车辆静态信息应答	
+        ///</summary>
+        [Description("补报车辆静态信息应答")]
+        UP_BASE_MSG_VEHICLE_ADDED_ACK = 0x1601,
+        #endregion
+
+        #region 从链路静态信息交换消息 DOWN_BASE_MSG
+        ///<summary>
+        ///补报车辆静态信息请求	
+        ///</summary>
+        [Description("补报车辆静态信息请求")]
+        DOWN_BASE_MSG_VEHICLE_ADDED = 0x9601,
+        #endregion
+    }
+}
diff --git a/src/JT809.Protocol/JT809Exceptions/JT809Exception.cs b/src/JT809.Protocol/JT809Exceptions/JT809Exception.cs
new file mode 100644
index 0000000..4001415
--- /dev/null
+++ b/src/JT809.Protocol/JT809Exceptions/JT809Exception.cs
@@ -0,0 +1,32 @@
+using JT809.Protocol.JT809Enums;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol.JT809Exceptions
+{
+    public class JT809Exception:Exception
+    {
+        public JT809Exception(JT809ErrorCode errorCode) : base(errorCode.ToString())
+        {
+            ErrorCode = errorCode;
+        }
+
+        public JT809Exception(JT809ErrorCode errorCode, string message) : base(message)
+        {
+            ErrorCode = errorCode;
+        }
+
+        public JT809Exception(JT809ErrorCode errorCode, Exception ex) : base(ex.Message, ex)
+        {
+            ErrorCode = errorCode;
+        }
+
+        public JT809Exception(JT809ErrorCode errorCode, string message, Exception ex) : base(ex.Message, ex)
+        {
+            ErrorCode = errorCode;
+        }
+
+        public JT809ErrorCode ErrorCode { get;}
+    }
+}
diff --git a/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs b/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs
new file mode 100644
index 0000000..c7f5eb2
--- /dev/null
+++ b/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs
@@ -0,0 +1,429 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Buffers.Binary;
+using System.Buffers;
+
+namespace JT809.Protocol.JT809Extensions
+{
+    public  static  class JT809BinaryExtensions
+    {
+        /// <summary>
+        /// 日期限制于2000年
+        /// </summary>
+        private const int DateLimitYear = 2000;
+
+        private const ushort cnCRC_CCITT = 0x1021; //CRC校验多项式
+
+        private static ulong[] CRC = new ulong[256]; //建立CRC16表 
+
+        static JT809BinaryExtensions()
+        {
+            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
+            encoding = Encoding.GetEncoding("GBK");
+            ushort i, j;
+            ushort nData;
+            ushort nAccum;
+            for (i = 0; i < 256; i++)
+            {
+                nData = (ushort)(i << 8);
+                nAccum = 0;
+                for (j = 0; j < 8; j++)
+                {
+                    if (((nData ^ nAccum) & 0x8000) > 0)
+                        nAccum = (ushort)((nAccum << 1) ^ cnCRC_CCITT);
+                    else
+                        nAccum <<= 1;
+                    nData <<= 1;
+                }
+                CRC[i] = (ulong)nAccum;
+            }
+        }
+
+        private static Encoding encoding;
+
+        public static int ReadBCD32(this byte data, byte dig)
+        {
+            int result = Convert.ToInt32(data.ToString("X"));
+            return result * (int)Math.Pow(100, dig - 1);
+        }
+
+        public static long ReadBCD64(this byte data, byte dig)
+        {
+            long result = Convert.ToInt64(data.ToString("X"));
+            return result * (long)Math.Pow(100, dig - 1);
+        }
+
+        public static string ReadStringLittle(ReadOnlySpan<byte> read, ref int offset, int len)
+        {
+            string value = encoding.GetString(read.Slice(offset, len).ToArray());
+            offset += value.Length;
+            return value.Trim('\0');
+        }
+
+        public static string ReadStringLittle(ReadOnlySpan<byte> read, ref int offset)
+        {
+            string value = encoding.GetString(read.Slice(offset).ToArray());
+            offset += value.Length;
+            return value.Trim('\0');
+        }
+
+        //public static void WriteLatLng(byte[] write, int offset,double latlng)
+        //{
+        //    WriteLittle(write, (int)(Math.Pow(10, 6) * latlng), offset, 4);
+        //}
+
+        public static long ReadBCD(ReadOnlySpan<byte> buf,ref int offset, int len)
+        {
+            long result = 0;
+            try
+            {
+                for (int i = offset; i < offset + len; i++)
+                {
+                    result += buf[i].ReadBCD64((byte)(offset + len - i));
+                }
+            }
+            catch
+            {
+            }
+            offset = offset + len;
+            return result;
+        }
+
+        public static DateTime ReadDateTimeLittle(ReadOnlySpan<byte> buf,ref int offset)
+        {
+            DateTime dateTime= new DateTime(
+                (buf[offset]).ReadBCD32(1) + DateLimitYear,
+                (buf[offset + 1]).ReadBCD32(1),
+                (buf[offset + 2]).ReadBCD32(1),
+                (buf[offset + 3]).ReadBCD32(1),
+                (buf[offset + 4]).ReadBCD32(1),
+                (buf[offset + 5]).ReadBCD32(1));
+            offset = offset + 6;
+            return dateTime;
+        }
+
+        public static DateTime ReadDateLittle(ReadOnlySpan<byte> buf, ref int offset)
+        {
+            DateTime dateTime = new DateTime(
+                    ((buf[offset] << 8) | (buf[offset + 1])),
+                    (buf[offset + 2]).ReadBCD32(1),
+                    (buf[offset + 3]).ReadBCD32(1));
+            offset = offset + 4;
+            return dateTime;
+        }
+
+        public static int ReadInt32Little(ReadOnlySpan<byte> read, ref int offset)
+        {
+            int value= (read[offset] << 24) | (read[offset + 1] << 16) | (read[offset + 2] << 8) | read[offset + 3];
+            offset = offset + 4;
+            return value;
+        }
+
+        public static uint ReadUInt32Little(ReadOnlySpan<byte> read, ref int offset)
+        {
+            uint value =(uint) ((read[offset] << 24) | (read[offset + 1] << 16) | (read[offset + 2] << 8) | read[offset + 3]);
+            offset = offset + 4;
+            return value;
+        }
+
+        public static ushort ReadUInt16Little(ReadOnlySpan<byte> read, ref int offset)
+        {
+            ushort value = (ushort)((read[offset] << 8) | (read[offset + 1]));
+            offset = offset + 2;
+            return value;
+        }
+
+        public static byte ReadByteLittle(ReadOnlySpan<byte> read, ref int offset)
+        {
+            byte value = read[offset];
+            offset = offset + 1;
+            return value;
+        }
+
+        public static byte[] ReadBytesLittle(ReadOnlySpan<byte> read, ref int offset,int len)
+        {
+            ReadOnlySpan<byte> temp = read.Slice(offset, len);
+            offset = offset + len;
+            return temp.ToArray();
+        }
+
+        public static int WriteLittle(ref byte[] write, int offset, DateTime date)
+        {
+            write[offset] = ((byte)(date.Year - DateLimitYear)).ToBcdByte();
+            write[offset + 1] = ((byte)(date.Month)).ToBcdByte();
+            write[offset + 2] = ((byte)(date.Day)).ToBcdByte();
+            write[offset + 3] = ((byte)(date.Hour)).ToBcdByte();
+            write[offset + 4] = ((byte)(date.Minute)).ToBcdByte();
+            write[offset + 5] = ((byte)(date.Second)).ToBcdByte();
+            return 6;
+        }
+
+        public static int WriteDateTime6Little(IMemoryOwner<byte> memoryOwner, int offset, DateTime date)
+        {
+            memoryOwner.Memory.Span[offset] = ((byte)(date.Year - DateLimitYear)).ToBcdByte();
+            memoryOwner.Memory.Span[offset + 1] = ((byte)(date.Month)).ToBcdByte();
+            memoryOwner.Memory.Span[offset + 2] = ((byte)(date.Day)).ToBcdByte();
+            memoryOwner.Memory.Span[offset + 3] = ((byte)(date.Hour)).ToBcdByte();
+            memoryOwner.Memory.Span[offset + 4] = ((byte)(date.Minute)).ToBcdByte();
+            memoryOwner.Memory.Span[offset + 5] = ((byte)(date.Second)).ToBcdByte();
+            return 6;
+        }
+
+        public static int WriteDateLittle(ref byte[] write, int offset, DateTime date)
+        {
+            write[offset] = (byte)(date.Year >> 8);
+            write[offset + 1] = (byte)date.Year;
+            write[offset + 2] = ((byte)(date.Month)).ToBcdByte();
+            write[offset + 3] = ((byte)(date.Day)).ToBcdByte();
+            return 4;
+        }
+
+        public static int WriteDateTime4Little(IMemoryOwner<byte> memoryOwner, int offset, DateTime date)
+        {
+            memoryOwner.Memory.Span[offset] = (byte)(date.Year >> 8);
+            memoryOwner.Memory.Span[offset + 1] = (byte)date.Year;
+            memoryOwner.Memory.Span[offset + 2] = ((byte)(date.Month)).ToBcdByte();
+            memoryOwner.Memory.Span[offset + 3] = ((byte)(date.Day)).ToBcdByte();
+            return 4;
+        }
+
+        public static int WriteLittle(ref byte[] write, int offset, int data)
+        {
+            write[offset] = (byte)(data >> 24);
+            write[offset + 1] = (byte)(data >> 16);
+            write[offset + 2] = (byte)(data >> 8);
+            write[offset + 3] = (byte)data;
+            return 4;
+        }
+
+        public static int WriteInt32Little(IMemoryOwner<byte> memoryOwner, int offset, int data)
+        {
+            memoryOwner.Memory.Span[offset] = (byte)(data >> 24);
+            memoryOwner.Memory.Span[offset + 1] = (byte)(data >> 16);
+            memoryOwner.Memory.Span[offset + 2] = (byte)(data >> 8);
+            memoryOwner.Memory.Span[offset + 3] = (byte)data;
+            return 4;
+        }
+
+        public static int WriteUInt32Little(IMemoryOwner<byte> memoryOwner, int offset, uint data)
+        {
+            memoryOwner.Memory.Span[offset] = (byte)(data >> 24);
+            memoryOwner.Memory.Span[offset + 1] = (byte)(data >> 16);
+            memoryOwner.Memory.Span[offset + 2] = (byte)(data >> 8);
+            memoryOwner.Memory.Span[offset + 3] = (byte)data;
+            return 4;
+        }
+
+        public static int WriteUInt16Little(ref byte[] write, int offset, ushort data)
+        {
+            write[offset] = (byte)(data >> 8);
+            write[offset + 1] = (byte)data;
+            return 2;
+        }
+
+        public static int WriteUInt16Little(IMemoryOwner<byte> memoryOwner, int offset, ushort data)
+        {
+            memoryOwner.Memory.Span[offset] = (byte)(data >> 8);
+            memoryOwner.Memory.Span[offset + 1] = (byte)data;
+            return 2;
+        }
+
+        public static int WriteLittle(ref byte[] write, int offset, byte data)
+        {
+            write[offset] = data;
+            return 1;
+        }
+
+        public static int WriteByteLittle(IMemoryOwner<byte> memoryOwner, int offset, byte data)
+        {
+            memoryOwner.Memory.Span[offset] = data;
+            return 1;
+        }
+
+        public static int WriteBytesLittle(IMemoryOwner<byte> memoryOwner, int offset, byte[] data)
+        {
+            CopyTo(data, memoryOwner.Memory.Span, offset);
+            return data.Length;
+        }
+
+        public static int WriteLittle(ref byte[] write, int offset, byte[] data)
+        {
+            Buffer.BlockCopy(data, 0, write, offset, data.Length);
+            return data.Length;
+        }
+
+        public static int WriteLittle(ref byte[] write, int offset, string data)
+        {
+            byte[] codeBytes = encoding.GetBytes(data);
+            Buffer.BlockCopy(codeBytes, 0, write, offset, codeBytes.Length);
+            return codeBytes.Length;
+        }
+
+        public static int WriteStringLittle(IMemoryOwner<byte> memoryOwner, int offset, string data)
+        {
+            byte[] codeBytes = encoding.GetBytes(data);
+            CopyTo(codeBytes, memoryOwner.Memory.Span, offset);
+            return codeBytes.Length;
+        }
+
+        public static int WriteBCDLittle(ref byte[] write, int offset, string data, int digit, int len)
+        {
+            ReadOnlySpan<char> bcd = data.PadLeft(len, '0').AsSpan();
+            for (int i = 0; i < digit; i++)
+            {
+                write[offset + i] = Convert.ToByte(bcd.Slice(i * 2, 2).ToString(), 16);
+            }
+            return digit;
+        }
+
+        public static int WriteBCDLittle(IMemoryOwner<byte> memoryOwner, int offset, string data, int digit, int len)
+        {
+            ReadOnlySpan<char> bcd = data.PadLeft(len, '0').AsSpan();
+            for (int i = 0; i < digit; i++)
+            {
+                memoryOwner.Memory.Span[offset + i] = Convert.ToByte(bcd.Slice(i * 2, 2).ToString(), 16);
+            }
+            return digit;
+        }
+
+        public static IEnumerable<byte> ToBytes(this string data, Encoding coding)
+        {
+            return coding.GetBytes(data);
+        }
+
+        public static IEnumerable<byte> ToBytes(this string data)
+        {
+            return ToBytes(data, encoding);
+        }
+
+        public static IEnumerable<byte> ToBytes(this int data, int len)
+        {
+            List<byte> bytes = new List<byte>();
+            int n = 1;
+            for (int i = 0; i < len; i++)
+            {
+                bytes.Add((byte)(data >> 8 * (len - n)));
+                n++;
+            }
+            return bytes;
+        }
+
+        /// <summary>
+        /// 从数据头到校验码前的 CRC 1 G-CCITT 的校验值,遵循人端排序方式的规定。
+        /// </summary>
+        /// <param name="packege"></param>
+        /// <param name="ucbuf"></param>
+        /// <param name="offset"></param>
+        /// <param name="iLen"></param>
+        /// <returns></returns>
+        public static ushort ToCRC16_CCITT(this Span<byte> ucbuf, int offset, int iLen)
+        {
+            ushort checkCode = 0xFFFF;
+            for (int j = offset; j < iLen; ++j)
+            {
+                checkCode = (ushort)((checkCode << 8) ^ (ushort)CRC[(checkCode >> 8) ^ ucbuf[j]]);
+            }
+            return checkCode;
+        }
+
+        /// <summary>
+        /// 从数据头到校验码前的 CRC 1 G-CCITT 的校验值,遵循人端排序方式的规定。
+        /// </summary>
+        /// <param name="packege"></param>
+        /// <param name="ucbuf"></param>
+        /// <param name="offset"></param>
+        /// <param name="iLen"></param>
+        /// <returns></returns>
+        public static ushort ToCRC16_CCITT(this ReadOnlySpan<byte> ucbuf, int offset, int iLen)
+        {
+            ushort checkCode = 0xFFFF;
+            for (int j = offset; j < iLen; ++j)
+            {
+                checkCode = (ushort)((checkCode << 8) ^ (ushort)CRC[(checkCode >> 8) ^ ucbuf[j]]);
+            }
+            return checkCode;
+        }
+
+        public static byte ToBcdByte(this byte buf)
+        {
+            return (byte)Convert.ToInt32(buf.ToString(), 16);
+        }
+
+        /// <summary>
+        /// 经纬度
+        /// </summary>
+        /// <param name="latlng"></param>
+        /// <returns></returns>
+        public static double ToLatLng(this int latlng)
+        {
+            return Math.Round(latlng / Math.Pow(10, 6), 6);
+        }
+
+        public static void CopyTo(Span<byte> source, Span<byte> destination, int offset)
+        {
+            for (int i = 0; i < source.Length; i++)
+            {
+                destination[offset + i] = source[i];
+            }
+        }
+
+        /// <summary>
+        /// 字节数组转16进制字符串
+        /// </summary>
+        /// <param name="bytes"></param>
+        /// <param name="separator">默认 " "</param>
+        /// <returns></returns>
+        public static string ToHexString(this byte[] bytes, string separator = " ")
+        {
+            return string.Join(separator, bytes.Select(s => s.ToString("X2")));
+        }
+
+        /// <summary>
+        /// 16进制字符串转16进制数组
+        /// </summary>
+        /// <param name="hexString"></param>
+        /// <param name="separator"></param>
+        /// <returns></returns>
+        public static byte[] ToHexBytes(this string hexString, string separator = " ")
+        {
+            return hexString.Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries).Select(s => Convert.ToByte(s, 16)).ToArray();
+        }
+
+        /// <summary>
+        /// 16进制字符串转16进制数组
+        /// </summary>
+        /// <param name="hexString"></param>
+        /// <returns></returns>
+        public static byte[] ToStr2HexBytes(this string hexString)
+        {
+            //byte[] buf = new byte[hexString.Length / 2];
+            //for (int i = 0; i < hexString.Length; i++)
+            //{
+            //    if (i % 2 == 0)
+            //    {
+            //        buf[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16) ;
+            //    }
+
+            //}
+            byte[] buf = new byte[hexString.Length / 2];
+            ReadOnlySpan<char> readOnlySpan = hexString.AsSpan();
+            for (int i = 0; i < hexString.Length; i++)
+            {
+                if (i % 2 == 0)
+                {
+                    buf[i / 2] = Convert.ToByte(readOnlySpan.Slice(i, 2).ToString(), 16);
+                }
+            }
+            return buf;
+            //List<byte> bytes = new List<byte>();
+            //while (hexString.Length>0)
+            //{
+            //    bytes.Add(Convert.ToByte(hexString.AsSpan(0, 2).ToString(), 16));
+            //    hexString = hexString.Remove(0,2);
+            //}
+            //return Regex.Replace(hexString, @"(\w{2})", "$1 ").Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).Select(s => Convert.ToByte(s, 16)).ToArray();
+        }
+    }
+}
diff --git a/src/JT809.Protocol/JT809Extensions/JT809EnumExtensions.cs b/src/JT809.Protocol/JT809Extensions/JT809EnumExtensions.cs
new file mode 100644
index 0000000..6030d16
--- /dev/null
+++ b/src/JT809.Protocol/JT809Extensions/JT809EnumExtensions.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Reflection;
+
+namespace JT809.Protocol.JT809Extensions
+{
+    /// <summary>
+    /// 枚举扩展
+    /// </summary>
+    public static class JT809EnumExtensions
+    {
+        /// <summary>
+        /// 转为整型
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="t"></param>
+        /// <returns></returns>
+        public static int ToValue<T>(this T t) where T : struct
+        {
+            return Convert.ToInt32(t);
+        }
+
+        /// <summary>
+        /// 转为Byte
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="t"></param>
+        /// <returns></returns>
+        public static byte ToByteValue<T>(this T t) where T : struct
+        {
+            return Convert.ToByte(t);
+        }
+
+        /// <summary>
+        /// 转为整型
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="t"></param>
+        /// <returns></returns>
+        public static string ToValueString<T>(this T t) where T : struct
+        {
+            return Convert.ToInt32(t).ToString();
+        }
+
+        /// <summary>
+        /// 字符转枚举
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static T ToEnum<T>(this string value) where T : struct
+        {
+            return (T)Enum.Parse(typeof(T), value);
+        }
+
+        /// <summary>
+        /// 获取枚举字符串
+        /// </summary>
+        /// <param name="valueEnum"></param>
+        public static string GetName(this Enum valueEnum)
+        {
+            return valueEnum.ToString();
+        }
+
+        /// <summary>
+        /// 获取DescriptionAttribute特性枚举值的描述
+        /// </summary>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static string GetDescription(this Enum value)
+        {
+            var attribute = value.GetAttribute<DescriptionAttribute>();
+            return attribute == null ? value.ToString() : attribute.Description;
+        }
+
+        /// <summary>
+        /// 验证是否是枚举类型
+        /// </summary>
+        /// <typeparam name="TEnum"></typeparam>
+        /// <param name="enumValue"></param>
+        /// <returns></returns>
+        public static bool IsEnumValid<TEnum>(this int enumValue)
+        {
+            return Enum.IsDefined(typeof(TEnum), enumValue);
+        }
+
+        /// <summary>
+        /// 获取DescriptionAttribute特性枚举及描述
+        /// </summary>
+        /// <param name="type"></param>
+        /// <returns></returns>
+        public static Dictionary<string, string> GetDescriptionAttributeDictionary(this Enum value)
+        {
+            Dictionary<string, string> dictionary = new Dictionary<string, string>();
+            var fields = value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public);
+            foreach (var fi in fields)
+            {
+                DescriptionAttribute attr = Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute), false) as DescriptionAttribute;
+                dictionary.Add(fi.Name, attr != null ? attr.Description : "");
+            }
+            return dictionary;
+        }
+
+        /// <summary>
+        /// 获取DisplayNameAttribute特性枚举值的描述
+        /// </summary>
+        /// <param name="obj">枚举值</param>
+        /// <returns></returns>
+        public static string GetDisplayName(this Enum value)
+        {
+            var attribute = value.GetAttribute<DisplayNameAttribute>();
+            return attribute == null ? value.ToString() : attribute.DisplayName;
+        }
+
+        /// <summary>
+        /// 获取DisplayNameAttribute特性枚举及描述
+        /// </summary>
+        /// <param name="type"></param>
+        /// <returns></returns>
+        public static Dictionary<string, string> GetDisplayNameAttributeDictionary(this Enum value)
+        {
+            Dictionary<string, string> dictionary = new Dictionary<string, string>();
+            var fields = value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public);
+            foreach (var fi in fields)
+            {
+                DisplayNameAttribute attr = Attribute.GetCustomAttribute(fi, typeof(DisplayNameAttribute), false) as DisplayNameAttribute;
+                dictionary.Add(fi.Name, attr != null ? attr.DisplayName : "");
+            }
+            return dictionary;
+        }
+
+        /// <summary>
+        /// 获取枚举对应特性
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static T GetAttribute<T>(this Enum value) where T : Attribute
+        {
+            try
+            {
+                var type = value.GetType();
+                var memberInfo = type.GetMember(value.ToString());
+                var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false);
+                return (T)attributes[0];
+            }
+            catch
+            {
+                return default;
+            }
+        }
+    }
+}
diff --git a/src/JT809.Protocol/JT809Extensions/JT809FormatterExtensions.cs b/src/JT809.Protocol/JT809Extensions/JT809FormatterExtensions.cs
new file mode 100644
index 0000000..baf2e40
--- /dev/null
+++ b/src/JT809.Protocol/JT809Extensions/JT809FormatterExtensions.cs
@@ -0,0 +1,50 @@
+using JT809.Protocol.JT809Attributes;
+using JT809.Protocol.JT809Enums;
+using JT809.Protocol.JT809Exceptions;
+using JT809.Protocol.JT809Formatters;
+using System;
+using System.Reflection;
+
+namespace JT809.Protocol.JT809Extensions
+{
+    public  static class JT809FormatterExtensions
+    {
+        public static IJT809Formatter<T> GetFormatter<T>()
+        {
+            IJT809Formatter<T> formatter;
+            var attr = typeof(T).GetTypeInfo().GetCustomAttribute<JT809FormatterAttribute>();
+            if (attr == null)
+            {
+                throw new JT809Exception(JT809ErrorCode.GetFormatterError, $"该类{typeof(T).FullName}没有标记JT809FormatterAttribute");
+            }
+            if (attr.Arguments == null)
+            {
+                formatter = (IJT809Formatter<T>)Activator.CreateInstance(attr.FormatterType);
+            }
+            else
+            {
+                formatter = (IJT809Formatter<T>)Activator.CreateInstance(attr.FormatterType, attr.Arguments);
+            }
+            return formatter;
+        }
+
+        public static object GetFormatter(Type formatterType)
+        {
+            object formatter;
+            var attr = formatterType.GetTypeInfo().GetCustomAttribute<JT809FormatterAttribute>();
+            if (attr == null)
+            {
+                throw new JT809Exception(JT809ErrorCode.GetFormatterError,$"该类{formatterType.FullName}没有标记JT809FormatterAttribute");
+            }
+            if (attr.Arguments == null)
+            {
+                formatter = Activator.CreateInstance(attr.FormatterType);
+            }
+            else
+            {
+                formatter = Activator.CreateInstance(attr.FormatterType, attr.Arguments);
+            }
+            return formatter;
+        }
+    }
+}
diff --git a/src/JT809.Protocol/JT809Extensions/JT809FormatterResolverExtensions.cs b/src/JT809.Protocol/JT809Extensions/JT809FormatterResolverExtensions.cs
new file mode 100644
index 0000000..96cf1c3
--- /dev/null
+++ b/src/JT809.Protocol/JT809Extensions/JT809FormatterResolverExtensions.cs
@@ -0,0 +1,87 @@
+using JT809.Protocol.JT809Formatters;
+using System;
+using System.Buffers;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Text;
+
+namespace JT809.Protocol.JT809Extensions
+{
+    /// <summary>
+    /// 
+    /// <para>ref http://adamsitnik.com/Span/#span-must-not-be-a-generic-type-argument </para>
+    /// <para>ref http://adamsitnik.com/Span/ </para>
+    /// <para>ref MessagePack.Formatters.DynamicObjectTypeFallbackFormatter </para>
+    /// </summary>
+    public static class JT809FormatterResolverExtensions
+    {
+        delegate int JT809SerializeMethod(object dynamicFormatter, IMemoryOwner<byte> memoryOwner, int offset, object value);
+
+        delegate dynamic JT809DeserializeMethod(object dynamicFormatter, ReadOnlySpan<byte> bytes,  out int readSize);
+
+        static readonly ConcurrentDictionary<Type, (object Value, JT809SerializeMethod SerializeMethod)> jT809Serializers = new ConcurrentDictionary<Type, (object Value, JT809SerializeMethod SerializeMethod)>();
+
+        static readonly ConcurrentDictionary<Type, (object Value, JT809DeserializeMethod DeserializeMethod)> jT809Deserializes = new ConcurrentDictionary<Type, (object Value, JT809DeserializeMethod DeserializeMethod)>();
+
+        //T Deserialize(ReadOnlySpan<byte> bytes, out int readSize);
+        //int Serialize(IMemoryOwner<byte> memoryOwner, int offset, T value);
+
+        public static int JT809DynamicSerialize(object objFormatter, IMemoryOwner<byte> memoryOwner, int offset, dynamic value)
+        {
+            Type type = value.GetType();
+            var ti = type.GetTypeInfo();
+            (object Value, JT809SerializeMethod SerializeMethod) formatterAndDelegate;
+            if (!jT809Serializers.TryGetValue(type, out formatterAndDelegate))
+            {
+                var t = type;
+                {
+                    var formatterType = typeof(IJT809Formatter<>).MakeGenericType(t);
+                    var param0 = Expression.Parameter(typeof(object), "formatter");
+                    var param1 = Expression.Parameter(typeof(IMemoryOwner<byte>), "memoryOwner");
+                    var param2 = Expression.Parameter(typeof(int), "offset");
+                    var param3 = Expression.Parameter(typeof(object), "value");
+                    var serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(IMemoryOwner<byte>), typeof(int), t});
+                    var body = Expression.Call(
+                        Expression.Convert(param0, formatterType),
+                        serializeMethodInfo,
+                        param1,
+                        param2,
+                        ti.IsValueType ? Expression.Unbox(param3, t) : Expression.Convert(param3, t));
+                    var lambda = Expression.Lambda<JT809SerializeMethod>(body, param0, param1, param2, param3).Compile();
+                    formatterAndDelegate = (objFormatter, lambda);
+                }
+                jT809Serializers.TryAdd(t, formatterAndDelegate);
+            }
+            return formatterAndDelegate.SerializeMethod(formatterAndDelegate.Value, memoryOwner, offset, value);
+        }
+
+        public static dynamic JT809DynamicDeserialize(object objFormatter,ReadOnlySpan<byte> bytes, out int readSize)
+        {
+            var type = objFormatter.GetType();
+            (object Value, JT809DeserializeMethod DeserializeMethod) formatterAndDelegate;
+            if (!jT809Deserializes.TryGetValue(type, out formatterAndDelegate))
+            {
+                var t = type;
+                {
+                    var formatterType = typeof(IJT809Formatter<>).MakeGenericType(t);
+                    ParameterExpression param0 = Expression.Parameter(typeof(object), "formatter");
+                    ParameterExpression param1 = Expression.Parameter(typeof(ReadOnlySpan<byte>), "bytes");
+                    ParameterExpression param2 = Expression.Parameter(typeof(int).MakeByRefType(), "readSize");
+                    var deserializeMethodInfo = type.GetRuntimeMethod("Deserialize", new[] { typeof(ReadOnlySpan<byte>), typeof(int).MakeByRefType() });
+                    var body = Expression.Call(
+                        Expression.Convert(param0, type),
+                        deserializeMethodInfo,
+                        param1,
+                        param2
+                        );
+                    var lambda = Expression.Lambda<JT809DeserializeMethod>(body, param0, param1, param2).Compile();
+                    formatterAndDelegate = (objFormatter, lambda);
+                }
+                jT809Deserializes.TryAdd(t, formatterAndDelegate);
+            }
+            return formatterAndDelegate.DeserializeMethod(formatterAndDelegate.Value, bytes,  out readSize);
+        }
+    }
+}
diff --git a/src/JT809.Protocol/JT809Formatters/IJT809FormatterOfT.cs b/src/JT809.Protocol/JT809Formatters/IJT809FormatterOfT.cs
new file mode 100644
index 0000000..11c45fd
--- /dev/null
+++ b/src/JT809.Protocol/JT809Formatters/IJT809FormatterOfT.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Buffers;
+
+namespace JT809.Protocol.JT809Formatters
+{
+    public interface IJT809Formatter<T>
+    {
+        T Deserialize(ReadOnlySpan<byte> bytes, out int readSize);
+
+        int Serialize(IMemoryOwner<byte> memoryOwner, int offset, T value);
+    }
+}
diff --git a/src/JT809.Protocol/JT809Formatters/JT809HeaderFormatter.cs b/src/JT809.Protocol/JT809Formatters/JT809HeaderFormatter.cs
new file mode 100644
index 0000000..71088fd
--- /dev/null
+++ b/src/JT809.Protocol/JT809Formatters/JT809HeaderFormatter.cs
@@ -0,0 +1,39 @@
+using JT809.Protocol.JT809Enums;
+using JT809.Protocol.JT809Extensions;
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol.JT809Formatters
+{
+    public class JT809HeaderFormatter : IJT809Formatter<JT809Header>
+    {
+        public JT809Header Deserialize(ReadOnlySpan<byte> bytes, out int readSize)
+        {
+            int offset = 0;
+            JT809Header jT809Header = new JT809Header();
+            jT809Header.MsgLength = JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset);
+            jT809Header.MsgSN= JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset);
+            jT809Header.MsgID = (JT809BusinessType)JT809BinaryExtensions.ReadUInt16Little(bytes, ref offset);
+            jT809Header.MsgGNSSCENTERID = JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset);
+            jT809Header.Version = new JT809Header_Version(JT809BinaryExtensions.ReadBytesLittle(bytes, ref offset, JT809Header_Version.FixedByteLength));
+            jT809Header.EncryptFlag= (JT809Header_Encrypt)JT809BinaryExtensions.ReadByteLittle(bytes, ref offset);
+            jT809Header.EncryptKey= JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset);
+            readSize = offset;
+            return jT809Header;
+        }
+
+        public int Serialize(IMemoryOwner<byte> memoryOwner, int offset, JT809Header value)
+        {
+            offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.MsgLength);
+            offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.MsgSN);
+            offset += JT809BinaryExtensions.WriteUInt16Little(memoryOwner, offset, (ushort)value.MsgID);
+            offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.MsgGNSSCENTERID);
+            offset += JT809BinaryExtensions.WriteBytesLittle(memoryOwner, offset, value.Version.Buffer);
+            offset += JT809BinaryExtensions.WriteByteLittle(memoryOwner, offset, (byte)value.EncryptFlag);
+            offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.EncryptKey);
+            return offset;
+        }
+    }
+}
diff --git a/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1001Formatter.cs b/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1001Formatter.cs
new file mode 100644
index 0000000..3663856
--- /dev/null
+++ b/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1001Formatter.cs
@@ -0,0 +1,33 @@
+using JT809.Protocol.JT809Extensions;
+using JT809.Protocol.JT809MessageBody;
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol.JT809Formatters.JT809MessageBodyFormatters
+{
+    public class JT809_0x1001Formatter : IJT809Formatter<JT809_0x1001>
+    {
+        public JT809_0x1001 Deserialize(ReadOnlySpan<byte> bytes, out int readSize)
+        {
+            int offset = 0;
+            JT809_0x1001 jT809_0X1001 = new JT809_0x1001();
+            jT809_0X1001.UserId = JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset);
+            jT809_0X1001.Password = JT809BinaryExtensions.ReadStringLittle(bytes, ref offset, 8);
+            jT809_0X1001.DownLinkIP = JT809BinaryExtensions.ReadStringLittle(bytes, ref offset, 32);
+            jT809_0X1001.DownLinkPort = JT809BinaryExtensions.ReadUInt16Little(bytes, ref offset);
+            readSize = offset;
+            return jT809_0X1001;
+        }
+
+        public int Serialize(IMemoryOwner<byte> memoryOwner, int offset, JT809_0x1001 value)
+        {
+            offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.UserId);
+            offset += JT809BinaryExtensions.WriteStringLittle(memoryOwner, offset, value.Password.PadRight(8,'\0'));
+            offset += JT809BinaryExtensions.WriteStringLittle(memoryOwner, offset, value.DownLinkIP.PadRight(32, '\0'));
+            offset += JT809BinaryExtensions.WriteUInt16Little(memoryOwner, offset, value.DownLinkPort);
+            return offset;
+        }
+    }
+}
diff --git a/src/JT809.Protocol/JT809Formatters/JT809PackageFormatter.cs b/src/JT809.Protocol/JT809Formatters/JT809PackageFormatter.cs
new file mode 100644
index 0000000..5961670
--- /dev/null
+++ b/src/JT809.Protocol/JT809Formatters/JT809PackageFormatter.cs
@@ -0,0 +1,209 @@
+using JT809.Protocol.JT809Attributes;
+using JT809.Protocol.JT809Enums;
+using JT809.Protocol.JT809Exceptions;
+using JT809.Protocol.JT809Extensions;
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol.JT809Formatters
+{
+    public class JT809PackageFormatter : IJT809Formatter<JT809Package>
+    {
+        public JT809Package Deserialize(ReadOnlySpan<byte> bytes, out int readSize)
+        {
+            int offset = 0;
+            JT809Package jT809Package = new JT809Package();
+            // 转义还原——>验证校验码——>解析消息
+            // 1. 解码(转义还原)
+            ReadOnlySpan<byte> buffer = JT809DeEscape(bytes);
+            // 2. 验证校验码
+            //  2.1. 获取校验位索引
+            int checkIndex = buffer.Length - 3;
+            //  2.2. 获取校验码
+            int crcCodeOffset = 0;
+            jT809Package.CRCCode = JT809BinaryExtensions.ReadUInt16Little(buffer.Slice(checkIndex,2),ref crcCodeOffset);
+            //  2.3. 从消息头到校验码前一个字节
+            ushort checkCode = buffer.ToCRC16_CCITT(1, checkIndex);
+            //  2.4. 验证校验码
+            if (jT809Package.CRCCode != checkCode)
+            {
+                throw new JT809Exception(JT809ErrorCode.CRC16CheckInvalid,$"{jT809Package.CRCCode.ToString()}!={checkCode.ToString()}");
+            }
+            jT809Package.BeginFlag = JT809BinaryExtensions.ReadByteLittle(buffer, ref offset);
+            // 3.初始化消息头
+            try
+            {
+                jT809Package.Header = JT809FormatterExtensions.GetFormatter<JT809Header>().Deserialize(buffer.Slice(offset, JT809Header.FixedByteLength), out readSize);
+            }
+            catch (Exception ex)
+            {
+                throw new JT809Exception(JT809ErrorCode.HeaderParseError, $"offset>{offset.ToString()}", ex);
+            }
+            offset += readSize;
+            // 4.是否加密
+            switch (jT809Package.Header.EncryptFlag)
+            {
+                case JT809Header_Encrypt.None:
+                    break;
+                case JT809Header_Encrypt.Common:
+#warning 加密尚未实现
+                    
+                    break;
+            }
+            // 5.数据体处理
+            //  5.1 判断是否有数据体(总长度-固定长度)> 0
+            if ((jT809Package.Header.MsgLength - JT809Package.FixedByteLength) > 0)
+            {
+                //JT809.Protocol.JT809Enums.JT809BusinessType 映射对应消息特性
+                JT809BodiesTypeAttribute jT809BodiesTypeAttribute = jT809Package.Header.MsgID.GetAttribute<JT809BodiesTypeAttribute>();
+                if (jT809BodiesTypeAttribute != null)
+                {
+                    try
+                    {
+                        var a = buffer.Slice(offset);
+                        var b = buffer.Slice(offset,checkIndex - offset);
+                        //5.2 处理消息体
+                        jT809Package.Bodies = JT809FormatterResolverExtensions.JT809DynamicDeserialize(JT809FormatterExtensions.GetFormatter(jT809BodiesTypeAttribute.JT809BodiesType), buffer.Slice(offset, checkIndex - offset), out readSize);
+                    }
+                    catch (Exception ex)
+                    {
+                        throw new JT809Exception(JT809ErrorCode.BodiesParseError,$"offset>{offset.ToString()}", ex);
+                    }
+                }
+            }
+            jT809Package.EndFlag = buffer[buffer.Length - 1];
+            readSize = buffer.Length;
+            return jT809Package;
+        }
+
+        public int Serialize(IMemoryOwner<byte> memoryOwner, int offset, JT809Package value)
+        {
+            // 1. 先序列化数据体,根据数据体的长度赋值给头部,在序列化头部。
+            int messageBodyOffset = 0;
+            JT809BodiesTypeAttribute jT809BodiesTypeAttribute = value.Header.MsgID.GetAttribute<JT809BodiesTypeAttribute>();
+            if (jT809BodiesTypeAttribute != null)
+            {
+                if (value.Bodies != null)
+                {
+                    // 1.1 处理数据体
+                    messageBodyOffset = JT809FormatterResolverExtensions.JT809DynamicSerialize(JT809FormatterExtensions.GetFormatter(jT809BodiesTypeAttribute.JT809BodiesType), memoryOwner, messageBodyOffset, value.Bodies);
+                }
+            }
+            byte[] messageBodyData=null;
+            if (messageBodyOffset != 0)
+            {
+                // 1.2 数据加密
+                switch (value.Header.EncryptFlag)
+                {
+                    case JT809Header_Encrypt.None:
+                        break;
+                    case JT809Header_Encrypt.Common:
+#warning 加密尚未实现
+                        
+                        break;
+                }
+                // 1.3 数据内容进行转义
+                messageBodyData = JT809Escape(memoryOwner.Memory.Slice(0, messageBodyOffset).Span);
+            }
+            // ------------------------------------开始组包
+            // 1.起始符
+            offset += JT809BinaryExtensions.WriteByteLittle(memoryOwner, offset, value.BeginFlag);
+            // 2.赋值头数据长度
+            if (messageBodyOffset != 0)
+            {
+                value.Header.MsgLength = (uint)(JT809Package.FixedByteLength + messageBodyData.Length);
+            }
+            else
+            {
+                value.Header.MsgLength = JT809Package.FixedByteLength;
+            }
+            // 2.1写入头部数据
+            offset = JT809FormatterExtensions.GetFormatter<JT809Header>().Serialize(memoryOwner, offset, value.Header);
+            if (messageBodyOffset != 0)
+            {
+                // 3. 写入数据体
+                JT809BinaryExtensions.CopyTo(messageBodyData, memoryOwner.Memory.Span, offset);
+                offset += messageBodyData.Length;
+                messageBodyData = null;
+            }
+            // 4.校验码
+            offset += JT809BinaryExtensions.WriteUInt16Little(memoryOwner, offset, memoryOwner.Memory.Span.ToCRC16_CCITT(1, offset));
+            // 5.终止符
+            offset += JT809BinaryExtensions.WriteByteLittle(memoryOwner, offset, value.EndFlag);
+            return offset;
+        }
+
+        private static ReadOnlySpan<byte> JT809DeEscape(ReadOnlySpan<byte> buffer)
+        {
+            List<byte> dataList = new List<byte>();
+            dataList.Add(buffer[0]);
+            for (int i = 1; i < buffer.Length - 1; i++)
+            {
+                byte first = buffer[i];
+                byte second = buffer[i + 1];
+                if (first == 0x5a && second == 0x01)
+                {
+                    dataList.Add(0x5b);
+                    i++;
+                }
+                else if (first == 0x5a && second == 0x02)
+                {
+                    dataList.Add(0x5a);
+                    i++;
+                }
+                else if (first == 0x5e && second == 0x01)
+                {
+                    dataList.Add(0x5d);
+                    i++;
+                }
+                else if (first == 0x5e && second == 0x02)
+                {
+                    dataList.Add(0x5e);
+                    i++;
+                }
+                else
+                {
+                    dataList.Add(first);
+                }
+            }
+            dataList.Add(buffer[buffer.Length - 1]);
+            return dataList.ToArray();
+        }
+
+        private static byte[] JT809Escape(Span<byte> buf)
+        {
+            List<byte> dataList = new List<byte>();
+            dataList.Add(buf[0]);
+            for (int i = 1; i < buf.Length - 1; i++)
+            {
+                var item = buf[i];
+                switch (item)
+                {
+                    case 0x5b:
+                        dataList.Add(0x5a);
+                        dataList.Add(0x01);
+                        break;
+                    case 0x5a:
+                        dataList.Add(0x5a);
+                        dataList.Add(0x02);
+                        break;
+                    case 0x5d:
+                        dataList.Add(0x5e);
+                        dataList.Add(0x01);
+                        break;
+                    case 0x5e:
+                        dataList.Add(0x5e);
+                        dataList.Add(0x02);
+                        break;
+                    default:
+                        dataList.Add(item);
+                        break;
+                }
+            }
+            dataList.Add(buf[buf.Length - 1]);
+            return dataList.ToArray();
+        }
+    }
+}
diff --git a/src/JT809.Protocol/JT809Header.cs b/src/JT809.Protocol/JT809Header.cs
new file mode 100644
index 0000000..76e4c7c
--- /dev/null
+++ b/src/JT809.Protocol/JT809Header.cs
@@ -0,0 +1,52 @@
+using JT809.Protocol.JT809Attributes;
+using JT809.Protocol.JT809Enums;
+using JT809.Protocol.JT809Formatters;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol
+{
+    [JT809Formatter(typeof(JT809HeaderFormatter))]
+    public class JT809Header
+    {
+        /// <summary>
+        /// 固定为22个字节长度
+        /// <para>MSG LENGTH + MSG_SN + MSG_ID + MSG_GNSSCENTERID + VERSION_FLAG + ENCRYPT_FLAG + ENCRYPT_KEY</para>
+        /// <para>4 + 4 + 2 + 4 + 3 + 1 + 4 = 22</para>
+        /// </summary>
+        public const int FixedByteLength = 22;
+        /// <summary>
+        /// 数据长度(包括头标识、数据头、数据体和尾标识)
+        /// <para>头标识 + 数据头 + 数据体 + 尾标识</para>
+        /// <para>1 + 22 + n + 1</para>
+        /// </summary>
+        public uint MsgLength { get; set; }
+        /// <summary>
+        /// 报文序列号 a
+        /// </summary>
+        public uint MsgSN { get; set; }
+        /// <summary>
+        /// 业务数据类型
+        /// </summary>
+        public JT809BusinessType MsgID { get; set; }
+        /// <summary>
+        /// 下级平台接入码,上级平台给下级平台分配唯一标识码。
+        /// </summary>
+        public uint MsgGNSSCENTERID { get; set; }
+        /// <summary>
+        /// 协议版本好标识,上下级平台之间采用的标准协议版
+        /// 编号;长度为 3 个字节来表示,0x01 0x02 0x0F 标识
+        /// 的版本号是 v1.2.15,以此类推。
+        /// </summary>
+        public JT809Header_Version Version { get; set; } = new JT809Header_Version();
+        /// <summary>
+        /// 报文加密标识位 b: 0 表示报文不加密,1 表示报文加密。
+        /// </summary>
+        public JT809Header_Encrypt EncryptFlag { get; set; } = JT809Header_Encrypt.None;
+        /// <summary>
+        /// 数据加密的密匙,长度为 4 个字节
+        /// </summary>
+        public uint EncryptKey { get; set; }
+    }
+}
diff --git a/src/JT809.Protocol/Enums/EncryptOpitions.cs b/src/JT809.Protocol/JT809Header_Encrypt.cs
similarity index 71%
rename from src/JT809.Protocol/Enums/EncryptOpitions.cs
rename to src/JT809.Protocol/JT809Header_Encrypt.cs
index fa8dc90..49ae3d1 100644
--- a/src/JT809.Protocol/Enums/EncryptOpitions.cs
+++ b/src/JT809.Protocol/JT809Header_Encrypt.cs
@@ -1,9 +1,9 @@
-namespace JT809.Protocol.Enums
+namespace JT809.Protocol
 {
     /// <summary>
     /// 报文加密标识位 b: 0 表示报文不加密,1 表示报文加密。
     /// </summary>
-    public enum EncryptOpitions : byte
+    public enum JT809Header_Encrypt:byte
     {
         None = 0X00,
         Common = 0X01,
diff --git a/src/JT809.Protocol/JT809Header_Version.cs b/src/JT809.Protocol/JT809Header_Version.cs
new file mode 100644
index 0000000..f7958f5
--- /dev/null
+++ b/src/JT809.Protocol/JT809Header_Version.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol
+{
+    public class JT809Header_Version
+    {
+        public byte[] Buffer { get; } = new byte[3];
+        private const int MajorIndex = 0;
+        private const int MinorIndex = 1;
+        private const int BuildIndex = 2;
+        public const int FixedByteLength = 3;
+
+        public byte Major
+        {
+            get { return Buffer[MajorIndex]; }
+            private set { Buffer[MajorIndex] = value; }
+        }
+
+        public byte Minor
+        {
+            get { return Buffer[MinorIndex]; }
+            private set { Buffer[MinorIndex] = value; }
+        }
+
+        public byte Build
+        {
+            get { return Buffer[BuildIndex]; }
+            private set { Buffer[BuildIndex] = value; }
+        }
+
+        /// <summary>
+        /// 默认1.0.0版本
+        /// </summary>
+        public JT809Header_Version()
+        {
+            Major = 1;
+            Minor = 0;
+            Build = 0;
+        }
+
+        public JT809Header_Version(byte major, byte minor, byte buid)
+        {
+            Major = major;
+            Minor = minor;
+            Build = buid;
+        }
+
+        public JT809Header_Version(byte[] bytes)
+        {
+            Major = bytes[0];
+            Minor = bytes[1];
+            Build = bytes[2];
+        }
+
+        public override string ToString()
+        {
+            return $"{Major}.{Minor}.{Build}";
+        }
+    }
+}
diff --git a/src/JT809.Protocol/JT809MessageBody/JT809_0x1001.cs b/src/JT809.Protocol/JT809MessageBody/JT809_0x1001.cs
new file mode 100644
index 0000000..e629d6c
--- /dev/null
+++ b/src/JT809.Protocol/JT809MessageBody/JT809_0x1001.cs
@@ -0,0 +1,34 @@
+using JT809.Protocol.JT809Attributes;
+using JT809.Protocol.JT809Formatters.JT809MessageBodyFormatters;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol.JT809MessageBody
+{
+    /// <summary>
+    /// 主链路登录请求消息
+    /// </summary>
+    [JT809Formatter(typeof(JT809_0x1001Formatter))]
+    public class JT809_0x1001: JT809Bodies
+    {
+        /// <summary>
+        /// 用户名
+        /// </summary>
+        public uint UserId { get; set; }
+        /// <summary>
+        /// 密码
+        /// 8位
+        /// </summary>
+        public string Password { get; set; }
+        /// <summary>
+        /// 下级平台提供对应的从链路服务端 IP 地址
+        /// 32位
+        /// </summary>
+        public string DownLinkIP { get; set; }
+        /// <summary>
+        /// 下级平台提供对应的从链路服务器端口号
+        /// </summary>
+        public ushort DownLinkPort { get; set; }
+    }
+}
diff --git a/src/JT809.Protocol/JT809Package.cs b/src/JT809.Protocol/JT809Package.cs
new file mode 100644
index 0000000..ae98417
--- /dev/null
+++ b/src/JT809.Protocol/JT809Package.cs
@@ -0,0 +1,33 @@
+using JT809.Protocol.JT809Attributes;
+using JT809.Protocol.JT809Formatters;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol
+{
+    [JT809Formatter(typeof(JT809PackageFormatter))]
+    public class JT809Package
+    {
+        public const byte BEGINFLAG = 0X5B;
+
+        public const byte ENDFLAG = 0X5D;
+
+        /// <summary>
+        /// 固定为26个字节长度
+        /// <para>Head flag + Message Header + CRC Code + End Flag</para>
+        /// <para>1 + 22 + 2 + 1 = 26</para>
+        /// </summary>
+        public const int FixedByteLength = 26;
+
+        public byte BeginFlag { get; set; } = BEGINFLAG;
+
+        public JT809Header Header { get; set; }
+
+        public JT809Bodies Bodies { get; set; }
+
+        public ushort CRCCode { get; set; }
+
+        public byte EndFlag { get; set; } = ENDFLAG;
+    }
+}
diff --git a/src/JT809.Protocol/JT809Serializer.cs b/src/JT809.Protocol/JT809Serializer.cs
new file mode 100644
index 0000000..fe3d632
--- /dev/null
+++ b/src/JT809.Protocol/JT809Serializer.cs
@@ -0,0 +1,64 @@
+using JT809.Protocol.JT809Enums;
+using JT809.Protocol.JT809Exceptions;
+using JT809.Protocol.JT809Extensions;
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT809.Protocol
+{
+    public static class JT809Serializer
+    {
+        public static byte[] Serialize(JT809Package jT809Package)
+        {
+            var formatter = JT809FormatterExtensions.GetFormatter<JT809Package>();
+            var pool = MemoryPool<byte>.Shared;
+            IMemoryOwner<byte> buffer = pool.Rent(4096);
+            try
+            {
+                var len = formatter.Serialize(buffer, 0, jT809Package);
+                return buffer.Memory.Slice(0, len).ToArray();
+            }
+            finally
+            {
+                // 源码:System.Memory.MemoryPool 
+                // private static readonly MemoryPool<T> s_shared = new ArrayMemoryPool<T>();
+                // 单例内存池 不需要手动释放资源
+                buffer.Dispose();
+            }
+        }
+
+        public static JT809Package Deserialize(ReadOnlySpan<byte> bytes)
+        {
+            var formatter = JT809FormatterExtensions.GetFormatter<JT809Package>();
+            return formatter.Deserialize(bytes, out int readSize);
+        }
+
+        public static byte[] Serialize<T>(T obj)
+        {
+            var formatter = JT809FormatterExtensions.GetFormatter<T>();
+            var pool = MemoryPool<byte>.Shared;
+            IMemoryOwner<byte> buffer = pool.Rent(10240);
+            try
+            {
+                var len = formatter.Serialize(buffer, 0, obj);
+                return buffer.Memory.Slice(0, len).ToArray();
+            }
+            finally
+            {
+                // 源码:System.Memory.MemoryPool 
+                // private static readonly MemoryPool<T> s_shared = new ArrayMemoryPool<T>();
+                // 单例内存池 不需要手动释放资源
+                buffer.Dispose();
+            }
+        }
+
+        public static T Deserialize<T>(ReadOnlySpan<byte> bytes)
+        {
+            var formatter = JT809FormatterExtensions.GetFormatter<T>();
+            int readSize;
+            return formatter.Deserialize(bytes, out readSize);
+        }
+    }
+}