├── .gitattributes ├── .gitignore ├── JT808.sln ├── src ├── BufferUtils.cs ├── IMessage.cs ├── JT808.csproj ├── Messages │ ├── Message.cs │ ├── PingMessage.cs │ ├── PostionMessage.cs │ ├── RegisterMessage.cs │ ├── ResponseMessage.cs │ └── SignatureMessage.cs ├── Properties │ └── AssemblyInfo.cs ├── ProtocolBuffer.cs ├── ProtocolProcessError.cs └── Serializes │ ├── EmitHandler.cs │ ├── IBitType.cs │ ├── IReadWriteHandler.cs │ ├── MessageTypeAttribute.cs │ ├── PropertySerializeHandler.cs │ └── Serializer.cs └── 道路运输车辆卫星定位系统北斗兼容车载终端通讯协议技术规范.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /JT808.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.14 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JT808", "src\JT808.csproj", "{DB307AB7-382B-440C-8C93-8914B6923B2D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {DB307AB7-382B-440C-8C93-8914B6923B2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {DB307AB7-382B-440C-8C93-8914B6923B2D}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {DB307AB7-382B-440C-8C93-8914B6923B2D}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {DB307AB7-382B-440C-8C93-8914B6923B2D}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /src/BufferUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace JT808 4 | { 5 | class BufferUtils 6 | { 7 | public byte[] Encode(string value) 8 | { 9 | return Encoding.GetEncoding("GBK").GetBytes(value); 10 | } 11 | 12 | public string Decode(byte[] data, int offset, int count) 13 | { 14 | return Encoding.GetEncoding("GBK").GetString(data, offset, count); 15 | } 16 | 17 | public static short SwapInt16(short v) 18 | { 19 | return (short)(((v & 0xff) << 8) | ((v >> 8) & 0xff)); 20 | } 21 | public static ushort SwapUInt16(ushort v) 22 | { 23 | return (ushort)(((v & 0xff) << 8) | ((v >> 8) & 0xff)); 24 | } 25 | public static int SwapInt32(int v) 26 | { 27 | return ((SwapInt16((short)v) & 0xffff) << 0x10) | (SwapInt16((short)(v >> 0x10)) & 0xffff); 28 | } 29 | public static uint SwapUInt32(uint v) 30 | { 31 | return (uint)(((SwapUInt16((ushort)v) & 0xffff) << 0x10) | (SwapUInt16((ushort)(v >> 0x10)) & 0xffff)); 32 | } 33 | public static long SwapInt64(long v) 34 | { 35 | return ((SwapInt32((int)v) & 0xffffffffL) << 0x20) | (SwapInt32((int)(v >> 0x20)) & 0xffffffffL); 36 | } 37 | public static ulong SwapUInt64(ulong v) 38 | { 39 | return (ulong)(((SwapUInt32((uint)v) & 0xffffffffL) << 0x20) | (SwapUInt32((uint)(v >> 0x20)) & 0xffffffffL)); 40 | } 41 | 42 | public static byte GetCRC(byte[] array, int offset, int count) 43 | { 44 | byte crc = 1; 45 | for (int i = offset; i < offset + count; i++) 46 | { 47 | if (i == 1) 48 | crc = array[i]; 49 | else 50 | crc = (byte)(crc ^ array[i]); 51 | } 52 | return crc; 53 | } 54 | 55 | public static bool GetBitValue(uint value, int index) 56 | { 57 | uint tag = 1; 58 | tag = tag << (index); 59 | return (value & tag) > 0; 60 | } 61 | 62 | public static byte GetByteBitValue(params bool[] values) 63 | { 64 | byte result = 0; 65 | for (int i = 0; i < values.Length; i++) 66 | result = (byte)(result | ((values[i] ? 1 : 0) << i)); 67 | return result; 68 | } 69 | 70 | public static ushort GetUShortBitValue(params bool[] values) 71 | { 72 | ushort result = 0; 73 | for (int i = 0; i < values.Length; i++) 74 | result = (ushort)(result | ((values[i] ? 1 : 0) << i)); 75 | return result; 76 | } 77 | 78 | public static uint GetUIntBitValue(params bool[] values) 79 | { 80 | uint result = 0; 81 | for (int i = 0; i < values.Length; i++) 82 | result = (uint)(result | ((values[i] ? (uint)1 : (uint)0) << i)); 83 | return result; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/IMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace JT808 4 | { 5 | public interface IMessage 6 | { 7 | ushort ID { get; set; } 8 | MessageBodyProperty Property { get; set; } 9 | string SIM { get; set; } 10 | ushort No { get; set; } 11 | PacketInfo Packet { get; set; } 12 | void Write(IProtocolBuffer buffer); 13 | void Read(IProtocolBuffer buffer); 14 | object Body { get; set; } 15 | byte CRC { get; set; } 16 | T GetBody(); 17 | } 18 | 19 | public interface IMessageBody 20 | { 21 | void Save(IProtocolBuffer buffer); 22 | void Load(IProtocolBuffer buffer); 23 | } 24 | 25 | public class MessageFactory 26 | { 27 | public static Message DecodeMessage(IProtocolBuffer buffer) 28 | { 29 | Message msg = new Message(); 30 | msg.Read(buffer); 31 | return msg; 32 | } 33 | 34 | public static IProtocolBuffer CreateMessage(ushort businessNO, string sim, Action handler) where T : new() 35 | { 36 | var buffer = ProtocolBufferPool.Default.Pop(); 37 | var msg = new Message 38 | { 39 | No = businessNO, 40 | SIM = sim 41 | }; 42 | T body = new T(); 43 | msg.Body = body; 44 | handler?.Invoke(msg, body); 45 | msg.Write(buffer); 46 | return buffer; 47 | } 48 | 49 | public static ushort GetMessageID() 50 | { 51 | Type type = typeof(T); 52 | Serializes.Serializer serializer = Serializes.SerializerFactory.Defalut.Get(type); 53 | if(serializer == null) 54 | throw new ProtocolProcessError(string.Format("{0} serializer not found!", type)); 55 | return serializer.MessageType.ID; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/JT808.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {DB307AB7-382B-440C-8C93-8914B6923B2D} 8 | Library 9 | Properties 10 | JT808 11 | JT808 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/Messages/Message.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using JT808.Serializes; 3 | 4 | namespace JT808 5 | { 6 | public class Message : IMessage 7 | { 8 | /// 9 | /// 消息ID 10 | /// 11 | public ushort ID { get; set; } 12 | /// 13 | /// 消息体属性 14 | /// 15 | public MessageBodyProperty Property { get; set; } = new MessageBodyProperty(); 16 | /// 17 | /// 终端手机号 18 | /// 19 | public string SIM { get; set; } 20 | /// 21 | /// 消息流水号 22 | /// 23 | public ushort No { get; set; } 24 | /// 25 | /// 消息包封装项 26 | /// 27 | public PacketInfo Packet { get; set; } 28 | /// 29 | /// 消息体 30 | /// 31 | public object Body { get; set; } 32 | /// 33 | /// 校验码 34 | /// 35 | public byte CRC { get; set; } 36 | 37 | public T GetBody() 38 | { 39 | return (T)Body; 40 | } 41 | 42 | public void Read(IProtocolBuffer buffer) 43 | { 44 | //byte crc = Core.GetCRC(buffer.Array, 1, buffer.Length - 3); 45 | //CRC = buffer.Array[buffer.Length - 2]; 46 | //if(CRC != crc) 47 | // throw new ProtocolProcessError("message check CRC error!"); 48 | 49 | buffer.Read(); //read start 标识位 50 | ID = buffer.ReadUInt16(); //read id 消息 ID 51 | Property.Read(buffer); //read property 消息体属性 52 | SIM = buffer.ReadBCD(6); //read sim 终端手机号 53 | No = buffer.ReadUInt16(); //read no 消息流水号 54 | if (Property.IsPacket) //read packet 消息包封装项 55 | { 56 | Packet = new PacketInfo(); 57 | Packet.Load(buffer); 58 | } 59 | if (Property.BodyLength > 0) //read body 消息体 60 | { 61 | IProtocolBuffer bodybuffer = ProtocolBufferPool.Default.Pop(); 62 | try 63 | { 64 | buffer.ReadSubBuffer(bodybuffer, Property.BodyLength); 65 | Serializer serializer = SerializerFactory.Defalut.Get(ID); 66 | if(serializer != null) 67 | { 68 | Body = serializer.CreateObject(); 69 | serializer.Deserialize(Body, bodybuffer); 70 | } 71 | } 72 | finally 73 | { 74 | ProtocolBufferPool.Default.Push(bodybuffer); 75 | } 76 | } 77 | CRC = buffer.Read(); //read crc 检验码 78 | buffer.Read(); //read end 标识位 79 | } 80 | 81 | public void Write(IProtocolBuffer buffer) 82 | { 83 | IProtocolBuffer bodybuffer = null; 84 | try 85 | { 86 | if (Packet != null) 87 | Property.IsPacket = true; 88 | if (Body != null) 89 | { 90 | Serializer serializer = SerializerFactory.Defalut.Get(Body.GetType()); 91 | if (serializer == null) 92 | throw new ProtocolProcessError(string.Format("{0} serializer not found!", Body)); 93 | ID = serializer.MessageType.ID; 94 | if (!serializer.MessageType.NoBody) 95 | { 96 | bodybuffer = ProtocolBufferPool.Default.Pop(); 97 | serializer.Serialize(Body, bodybuffer); 98 | if (bodybuffer.Length > MessageBodyProperty.BODY_LENGTH) 99 | throw new ProtocolProcessError("message body to long!"); 100 | Property.BodyLength = (ushort)bodybuffer.Length; 101 | } 102 | } 103 | buffer.WriteTag(); //write start 104 | buffer.Write(ID); //write id 105 | Property.Write(buffer); //write body property 106 | buffer.WriteBCD(SIM); //write sim 107 | buffer.Write(No); //write no 108 | if (Packet != null) //write packet 109 | Packet.Save(buffer); 110 | if (bodybuffer != null) //write body 111 | buffer.WriteSubBuffer(bodybuffer); 112 | byte crc = BufferUtils.GetCRC(buffer.Array, 1, buffer.Length - 1); 113 | buffer.Write(crc); //write crc 114 | buffer.WriteTag(); //write end 115 | } 116 | finally 117 | { 118 | if (bodybuffer != null) 119 | ProtocolBufferPool.Default.Push(bodybuffer); 120 | } 121 | } 122 | } 123 | 124 | public class MessageBodyProperty 125 | { 126 | public const ushort CUSTOM_HEIGHT = 0x8000; 127 | public const ushort CUSTOM_LOW = 0x4000; 128 | public const ushort IS_PACKET = 0x2000; 129 | public const ushort ENCRYPT_HEIGHT = 0x1000; 130 | public const ushort ENCRYPT_MIDDLE = 0x0400; 131 | public const ushort ENCRYPT_LOW = 0x0200; 132 | public const ushort BODY_LENGTH = 0x01FF; 133 | 134 | //保留位15 135 | public bool CustomHigh { get; set; } 136 | 137 | //保留位14 138 | public bool CustomLow { get; set; } 139 | 140 | //分包位13 141 | public bool IsPacket { get; set; } 142 | 143 | //加密位12 144 | public bool EncryptHigh { get; set; } 145 | 146 | //加密位11 147 | public bool EncryptMiddle { get; set; } 148 | 149 | //加密位10 150 | public bool EncryptLow { get; set; } 151 | 152 | //消息长度9-0 153 | public ushort BodyLength { get; set; } 154 | 155 | public void Read(IProtocolBuffer buffer) 156 | { 157 | ushort value = buffer.ReadUInt16(); 158 | CustomHigh = (CUSTOM_HEIGHT & value) > 0; 159 | CustomLow = (CUSTOM_LOW & value) > 0; 160 | IsPacket = (IS_PACKET & value) > 0; 161 | EncryptHigh = (ENCRYPT_HEIGHT & value) > 0; 162 | EncryptMiddle = (ENCRYPT_MIDDLE & value) > 0; 163 | EncryptLow = (ENCRYPT_LOW & value) > 0; 164 | BodyLength = (ushort)(BODY_LENGTH & value); 165 | } 166 | 167 | public void Write(IProtocolBuffer buffer) 168 | { 169 | ushort value = (ushort)(BodyLength & BODY_LENGTH); 170 | if(CustomHigh) 171 | value |= CUSTOM_HEIGHT; 172 | if(CustomLow) 173 | value |= CUSTOM_LOW; 174 | if(IsPacket) 175 | value |= IS_PACKET; 176 | if(EncryptHigh) 177 | value |= ENCRYPT_HEIGHT; 178 | if(EncryptMiddle) 179 | value |= ENCRYPT_MIDDLE; 180 | if(EncryptLow) 181 | value |= ENCRYPT_LOW; 182 | buffer.Write(value); 183 | } 184 | } 185 | 186 | public class PacketInfo 187 | { 188 | public ushort Count { get; set; } 189 | 190 | public ushort Index { get; set; } 191 | 192 | public void Save(IProtocolBuffer buffer) 193 | { 194 | Count = BufferUtils.SwapUInt16(Count); 195 | Index = BufferUtils.SwapUInt16(Index); 196 | } 197 | 198 | public void Load(IProtocolBuffer buffer) 199 | { 200 | byte[] data = buffer.Read(2); 201 | Count = BitConverter.ToUInt16(data, 0); 202 | Count = BufferUtils.SwapUInt16(Count); 203 | 204 | data = buffer.Read(2); 205 | Index = BitConverter.ToUInt16(data, 0); 206 | Index = BufferUtils.SwapUInt16(Count); 207 | } 208 | } 209 | } -------------------------------------------------------------------------------- /src/Messages/PingMessage.cs: -------------------------------------------------------------------------------- 1 | namespace JT808.Messages 2 | { 3 | [MessageType(NoBody = true, ID = 0x0002)] 4 | public class PingMessage 5 | { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Messages/PostionMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace JT808.Messages 4 | { 5 | /// 6 | /// 位置信息汇报 7 | /// 8 | [MessageType(0x0200)] 9 | public class PostionMessage 10 | { 11 | /// 12 | /// 报警标志 13 | /// 14 | [UIntBitHandler(typeof(PostionWarningMark))] 15 | public PostionWarningMark WarningMark { get; set; } = new PostionWarningMark(); 16 | /// 17 | /// 状态 18 | /// 19 | [UIntBitHandler(typeof(PostionStatus))] 20 | public PostionStatus Status { get; set; } = new PostionStatus(); 21 | /// 22 | /// 纬度 以度为单位的纬度值乘以 10 的 6 次方,精确到百万 分之一度 23 | /// 24 | [UIntHandler] 25 | public uint Latitude { get; set; } 26 | /// 27 | /// 经度 以度为单位的经度值乘以 10 的 6 次方,精确到百万 分之一度 28 | /// 29 | [UIntHandler] 30 | public uint Longitude { get; set; } 31 | /// 32 | /// 海拔高度,单位为米(m) 33 | /// 34 | [UInt16Handler] 35 | public ushort Height { get; set; } 36 | /// 37 | /// 速度 1/10km/h 38 | /// 39 | [UInt16Handler] 40 | public ushort Speed { get; set; } 41 | /// 42 | /// 方向 0-359,正北为 0,顺时针 43 | /// 44 | [UInt16Handler] 45 | public ushort Direction { get; set; } 46 | /// 47 | /// 时间 BCD[6] YY-MM-DD-hh-mm-ss 48 | /// 49 | [TimeBCD] 50 | public DateTime Time { get; set; } 51 | } 52 | 53 | public class PostionWarningMark : IBitCustomType 54 | { 55 | /// 56 | /// 紧急报瞥触动报警开关后触发 57 | /// 58 | public bool TouchAlarmSwitch { get; set; } 59 | /// 60 | /// 超速报警 61 | /// 62 | public bool SpeedLimit { get; set; } 63 | /// 64 | /// 疲劳驾驶 65 | /// 66 | public bool Fatigue { get; set; } 67 | /// 68 | /// 预警 69 | /// 70 | public bool Alert { get; set; } 71 | /// 72 | /// GNSS模块发生故障 73 | /// 74 | public bool GNSSModule { get; set; } 75 | /// 76 | /// GNSS天线未接或被剪断 77 | /// 78 | public bool GNSSCutAntenna { get; set; } 79 | /// 80 | /// GNSS天线短路 81 | /// 82 | public bool GNSSShortCircuit { get; set; } 83 | /// 84 | /// 终端主电源欠压 85 | /// 86 | public bool MainPowerVoltage { get; set; } 87 | /// 88 | /// 终端主电源掉电 89 | /// 90 | public bool MainPowerOff { get; set; } 91 | /// 92 | /// 终端LCD或显示器故障 93 | /// 94 | public bool DisplayTheFault { get; set; } 95 | /// 96 | /// TTS模块故障 97 | /// 98 | public bool TTSModuleFailure { get; set; } 99 | /// 100 | /// 摄像头故障 101 | /// 102 | public bool CameraMalfunction { get; set; } 103 | 104 | public bool Keep12 { get; set; } 105 | public bool Keep13 { get; set; } 106 | public bool Keep14 { get; set; } 107 | public bool Keep15 { get; set; } 108 | public bool Keep16 { get; set; } 109 | public bool Keep17 { get; set; } 110 | 111 | /// 112 | /// 驾驶超时 113 | /// 114 | public bool DrivingTimeoutOfDay { get; set; } 115 | /// 116 | /// 超时停车 117 | /// 118 | public bool StopTimeout { get; set; } 119 | /// 120 | /// 进出区域 121 | /// 122 | public bool InOutArea { get; set; } 123 | /// 124 | /// 进出路线 125 | /// 126 | public bool InOutLine { get; set; } 127 | /// 128 | /// 路段行驶时间 129 | /// 130 | public bool BritainsTime { get; set; } 131 | /// 132 | /// 路线偏离报警 133 | /// 134 | public bool LaneDeparture { get; set; } 135 | /// 136 | /// VSS故障 137 | /// 138 | public bool VSSFault { get; set; } 139 | /// 140 | /// 油量异常 141 | /// 142 | public bool OilFault { get; set; } 143 | /// 144 | /// 被盗 145 | /// 146 | public bool Stolen { get; set; } 147 | /// 148 | /// 非法点火 149 | /// 150 | public bool IllegalIgnition { get; set; } 151 | /// 152 | /// 车辆非法位移 153 | /// 154 | public bool IllegalDisplacement { get; set; } 155 | 156 | public bool Keep29 { get; set; } 157 | public bool Keep30 { get; set; } 158 | public bool Keep31 { get; set; } 159 | 160 | public void Load(object value) 161 | { 162 | uint data = (uint)value; 163 | TouchAlarmSwitch = BufferUtils.GetBitValue(data, 0); 164 | SpeedLimit = BufferUtils.GetBitValue(data, 1); 165 | Fatigue = BufferUtils.GetBitValue(data, 2); 166 | Alert = BufferUtils.GetBitValue(data, 3); 167 | GNSSModule = BufferUtils.GetBitValue(data, 4); 168 | GNSSCutAntenna = BufferUtils.GetBitValue(data, 5); 169 | GNSSShortCircuit = BufferUtils.GetBitValue(data, 6); 170 | MainPowerVoltage = BufferUtils.GetBitValue(data, 7); 171 | MainPowerOff = BufferUtils.GetBitValue(data, 8); 172 | DisplayTheFault = BufferUtils.GetBitValue(data, 9); 173 | TTSModuleFailure = BufferUtils.GetBitValue(data, 10); 174 | CameraMalfunction = BufferUtils.GetBitValue(data, 11); 175 | Keep12 = BufferUtils.GetBitValue(data, 12); 176 | Keep13 = BufferUtils.GetBitValue(data, 13); 177 | Keep14 = BufferUtils.GetBitValue(data, 14); 178 | Keep15 = BufferUtils.GetBitValue(data, 15); 179 | Keep16 = BufferUtils.GetBitValue(data, 16); 180 | Keep17 = BufferUtils.GetBitValue(data, 17); 181 | DrivingTimeoutOfDay = BufferUtils.GetBitValue(data, 18); 182 | StopTimeout = BufferUtils.GetBitValue(data, 19); 183 | InOutArea = BufferUtils.GetBitValue(data, 20); 184 | InOutLine = BufferUtils.GetBitValue(data, 21); 185 | BritainsTime = BufferUtils.GetBitValue(data, 22); 186 | LaneDeparture = BufferUtils.GetBitValue(data, 23); 187 | VSSFault = BufferUtils.GetBitValue(data, 24); 188 | OilFault = BufferUtils.GetBitValue(data, 25); 189 | Stolen = BufferUtils.GetBitValue(data, 26); 190 | IllegalIgnition = BufferUtils.GetBitValue(data, 27); 191 | IllegalDisplacement = BufferUtils.GetBitValue(data, 28); 192 | Keep29 = BufferUtils.GetBitValue(data, 29); 193 | Keep30 = BufferUtils.GetBitValue(data, 30); 194 | Keep31 = BufferUtils.GetBitValue(data, 31); 195 | } 196 | 197 | public object Save() 198 | { 199 | return BufferUtils.GetUIntBitValue(TouchAlarmSwitch, SpeedLimit, Fatigue, Alert, GNSSModule, GNSSCutAntenna, GNSSShortCircuit, 200 | MainPowerVoltage, MainPowerOff, DisplayTheFault, TTSModuleFailure, CameraMalfunction, Keep12, 201 | Keep13, Keep14, Keep15, Keep16, Keep17, DrivingTimeoutOfDay, StopTimeout, InOutArea, InOutLine, 202 | BritainsTime, LaneDeparture, VSSFault, OilFault, Stolen, IllegalIgnition, IllegalDisplacement, 203 | Keep29, Keep30, Keep31); 204 | } 205 | } 206 | 207 | public class PostionStatus : IBitCustomType 208 | { 209 | public bool ACC { get; set; } 210 | 211 | public bool Location { get; set; } 212 | 213 | public bool Latitude { get; set; } 214 | 215 | public bool Longitude { get; set; } 216 | 217 | public bool Operate { get; set; } 218 | 219 | public bool Encryption { get; set; } 220 | 221 | public bool Keep6 { get; set; } 222 | 223 | public bool Keep7 { get; set; } 224 | 225 | public bool Keep8 { get; set; } 226 | 227 | public bool Keep9 { get; set; } 228 | 229 | public bool OilRoad { get; set; } 230 | 231 | public bool ElectricityRoad { get; set; } 232 | 233 | public bool DoorLock { get; set; } 234 | 235 | public bool Keep13 { get; set; } 236 | 237 | public bool Keep14 { get; set; } 238 | 239 | public bool Keep15 { get; set; } 240 | 241 | public bool Keep16 { get; set; } 242 | 243 | public bool Keep17 { get; set; } 244 | 245 | public bool Keep18 { get; set; } 246 | 247 | public bool Keep19 { get; set; } 248 | 249 | public bool Keep20 { get; set; } 250 | 251 | public bool Keep21 { get; set; } 252 | 253 | public bool Keep22 { get; set; } 254 | 255 | public bool Keep23 { get; set; } 256 | 257 | public bool Keep24 { get; set; } 258 | 259 | public bool Keep25 { get; set; } 260 | 261 | public bool Keep26 { get; set; } 262 | 263 | public bool Keep27 { get; set; } 264 | 265 | public bool Keep28 { get; set; } 266 | 267 | public bool Keep29 { get; set; } 268 | 269 | public bool Keep30 { get; set; } 270 | 271 | public bool Keep31 { get; set; } 272 | 273 | public void Load(object value) 274 | { 275 | uint data = (uint)value; 276 | ACC = BufferUtils.GetBitValue(data, 0); 277 | Location = BufferUtils.GetBitValue(data, 1); 278 | Latitude = BufferUtils.GetBitValue(data, 2); 279 | Longitude = BufferUtils.GetBitValue(data, 3); 280 | Operate = BufferUtils.GetBitValue(data, 4); 281 | Encryption = BufferUtils.GetBitValue(data, 5); 282 | Keep6 = BufferUtils.GetBitValue(data, 6); 283 | Keep7 = BufferUtils.GetBitValue(data, 7); 284 | Keep8 = BufferUtils.GetBitValue(data, 8); 285 | Keep9 = BufferUtils.GetBitValue(data, 9); 286 | OilRoad = BufferUtils.GetBitValue(data, 10); 287 | ElectricityRoad = BufferUtils.GetBitValue(data, 11); 288 | DoorLock = BufferUtils.GetBitValue(data, 12); 289 | Keep13 = BufferUtils.GetBitValue(data, 13); 290 | Keep14 = BufferUtils.GetBitValue(data, 14); 291 | Keep15 = BufferUtils.GetBitValue(data, 15); 292 | Keep16 = BufferUtils.GetBitValue(data, 16); 293 | Keep17 = BufferUtils.GetBitValue(data, 17); 294 | Keep18 = BufferUtils.GetBitValue(data, 18); 295 | Keep19 = BufferUtils.GetBitValue(data, 19); 296 | Keep20 = BufferUtils.GetBitValue(data, 20); 297 | Keep21 = BufferUtils.GetBitValue(data, 21); 298 | Keep22 = BufferUtils.GetBitValue(data, 22); 299 | Keep23 = BufferUtils.GetBitValue(data, 23); 300 | Keep24 = BufferUtils.GetBitValue(data, 24); 301 | Keep25 = BufferUtils.GetBitValue(data, 25); 302 | Keep26 = BufferUtils.GetBitValue(data, 26); 303 | Keep27 = BufferUtils.GetBitValue(data, 27); 304 | Keep28 = BufferUtils.GetBitValue(data, 28); 305 | Keep29 = BufferUtils.GetBitValue(data, 29); 306 | Keep30 = BufferUtils.GetBitValue(data, 30); 307 | Keep31 = BufferUtils.GetBitValue(data, 31); 308 | } 309 | 310 | public object Save() 311 | { 312 | return BufferUtils.GetUIntBitValue(ACC, Location, Latitude, Longitude, Operate, Encryption, Keep6, Keep7, Keep8, Keep9, 313 | OilRoad, ElectricityRoad, DoorLock, Keep13, Keep14, Keep15, Keep16, Keep17, Keep18, Keep19, Keep20, Keep21, Keep22, 314 | Keep23, Keep24, Keep25, Keep26, Keep27, Keep28, Keep29, Keep30, Keep31); 315 | } 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /src/Messages/RegisterMessage.cs: -------------------------------------------------------------------------------- 1 | namespace JT808.Messages 2 | { 3 | /// 4 | /// 终端注册 5 | /// 6 | [MessageType(ID = 0x0100)] 7 | public class RegisterMessage 8 | { 9 | /// 10 | /// 省ID 11 | /// 12 | [UInt16Handler] 13 | public ushort Province { get; set; } 14 | /// 15 | /// 市、县域ID 16 | /// 17 | [UInt16Handler] 18 | public ushort City { get; set; } 19 | /// 20 | /// 五个字节,终端制造商编码。 21 | /// 22 | [ASCIIHandler(5)] 23 | public string Provider { get; set; } 24 | /// 25 | /// 终端型号 26 | /// 27 | [ASCIIHandler(8)] 28 | public string DeviceNo { get; set; } 29 | /// 30 | /// 终端ID 31 | /// 32 | [ASCIIHandler(7)] 33 | public string DeviceID { get; set; } 34 | /// 35 | /// 车牌颜色,按照JT/T 415-2006的5.4.12 36 | /// 37 | [ByteHandler] 38 | public byte Color { get; set; } 39 | /// 40 | /// 公安交通管理部门颁发的机动车号牌 41 | /// 42 | [GBKHandler] 43 | public string PlateNo { get; set; } 44 | } 45 | 46 | /// 47 | /// 终端注册应答 48 | /// 49 | [MessageType(0x8100)] 50 | public class RegisterResponseMessage 51 | { 52 | /// 53 | /// 应答流水号 54 | /// 55 | [UInt16Handler] 56 | public ushort No { get; set; } 57 | /// 58 | /// 结果 59 | /// 60 | [ByteHandler] 61 | public RegisterResult Result { get; set; } 62 | /// 63 | /// 鉴权码 64 | /// 65 | [GBKHandler] 66 | public string Signature { get; set; } 67 | } 68 | 69 | [MessageType(NoBody = true, ID = 0x0003)] 70 | public class RegisterCancelMessage 71 | { 72 | } 73 | 74 | public enum RegisterResult : byte 75 | { 76 | 成功 = 0, 77 | 车辆已被注 = 1, 78 | 数据库中无该车辆 = 2, 79 | 终端已被注册 = 3, 80 | 数据库中无该终端 = 4, 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Messages/ResponseMessage.cs: -------------------------------------------------------------------------------- 1 | namespace JT808.Messages 2 | { 3 | /// 4 | /// 平台通用应答 5 | /// 6 | [MessageType(ID = 0x8001)] 7 | public class CenterResponseMessage 8 | { 9 | /// 10 | /// 应答流水号 (对应的终端消息的流水号) 11 | /// 12 | [UInt16Handler] 13 | public ushort No { get; set; } 14 | /// 15 | /// 应答 ID (对应的终端消息的 ID ) 16 | /// 17 | [UInt16Handler] 18 | public ushort ResultID { get; set; } 19 | /// 20 | /// 结果 21 | /// 22 | [ByteHandler] 23 | public ResultType Result { get; set; } 24 | } 25 | 26 | /// 27 | /// 终端通用应答 28 | /// 29 | [MessageType(ID = 0x0001)] 30 | public class ClientResponseMessage 31 | { 32 | /// 33 | /// 应答流水号 34 | /// 35 | [UInt16Handler] 36 | public ushort No { get; set; } 37 | /// 38 | /// 应答 ID 39 | /// 40 | [UInt16Handler] 41 | public ushort ResultID { get; set; } 42 | /// 43 | /// 结果 44 | /// 45 | [ByteHandler] 46 | public ResultType Result { get; set; } 47 | } 48 | 49 | public enum ResultType : byte 50 | { 51 | Success = 0, 52 | Failure = 1, 53 | Error = 2, 54 | NotSupport = 3 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Messages/SignatureMessage.cs: -------------------------------------------------------------------------------- 1 | namespace JT808.Messages 2 | { 3 | /// 4 | /// 终端鉴权 5 | /// 6 | [MessageType(ID = 0x0102)] 7 | public class SignatureMessage 8 | { 9 | [GBKHandler] 10 | public string Signature { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /src/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // 有关程序集的一般信息由以下 5 | // 控制。更改这些特性值可修改 6 | // 与程序集关联的信息。 7 | [assembly: AssemblyTitle("JT808")] 8 | [assembly: AssemblyDescription("道路运输车辆卫星定位系统北斗兼容车载终端通讯协议技术规范")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("JT808")] 12 | [assembly: AssemblyCopyright("Copyright © 2017")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | //将 ComVisible 设置为 false 将使此程序集中的类型 17 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, 18 | //请将此类型的 ComVisible 特性设置为 true。 19 | [assembly: ComVisible(false)] 20 | 21 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 22 | [assembly: Guid("ad6a9116-9faf-475d-8451-4316f2df910f")] 23 | 24 | // 程序集的版本信息由下列四个值组成: 25 | // 26 | // 主版本 27 | // 次版本 28 | // 生成号 29 | // 修订号 30 | // 31 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, 32 | // 方法是按如下所示使用“*”: : 33 | [assembly: AssemblyVersion("1.0.*")] 34 | -------------------------------------------------------------------------------- /src/ProtocolBuffer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Text; 4 | 5 | namespace JT808 6 | { 7 | public interface IProtocolBuffer 8 | { 9 | bool Import(byte value); 10 | int Import(byte[] data, int offset, int count); 11 | 12 | void Reset(); 13 | int Length { get; } 14 | void SetLength(int length); 15 | int Postion { get; set; } 16 | byte[] Array { get; } 17 | 18 | void Write(byte[] data); 19 | void Write(byte data); 20 | void Write(ushort value); 21 | void Write(uint value); 22 | void WriteBCD(string value); 23 | void WriteASCII(string value, int length); 24 | int WriteGBK(string value); 25 | void WriteSubBuffer(IProtocolBuffer buffer); 26 | void WriteTag(); 27 | 28 | byte Read(); 29 | byte[] Read(int length); 30 | ushort ReadUInt16(); 31 | uint ReadUInt(); 32 | string ReadBCD(int length); 33 | string ReadASCII(int length); 34 | string ReadGBK(int length = -1); 35 | void ReadSubBuffer(IProtocolBuffer buffer, int count); 36 | } 37 | 38 | public class ProtocolBuffer : IProtocolBuffer 39 | { 40 | private byte[] mArray = new byte[1024]; 41 | private int mPostion; 42 | private int mLength; 43 | private bool mProtocolStart = false; 44 | public const byte PROTOBUF_TAG = 0x7e; 45 | public const byte REPLACE_TAG = 0x7d; 46 | 47 | public bool Import(byte value) 48 | { 49 | if (value == PROTOBUF_TAG) 50 | { 51 | OnWrite(value); 52 | if (!mProtocolStart) 53 | mProtocolStart = true; 54 | else 55 | { 56 | mPostion = 0; 57 | return true; 58 | } 59 | } 60 | else 61 | { 62 | if (mProtocolStart) 63 | OnWrite(value); 64 | } 65 | return false; 66 | } 67 | 68 | public int Import(byte[] data, int offset, int count) 69 | { 70 | int result = 0; 71 | for (int i = 0; i < count; i++) 72 | { 73 | result++; 74 | byte value = data[offset + i]; 75 | if (Import(value)) 76 | return result; 77 | } 78 | return -1; 79 | } 80 | 81 | private byte OnRead() 82 | { 83 | byte value = mArray[mPostion]; 84 | mPostion++; 85 | return value; 86 | } 87 | 88 | public byte Read() 89 | { 90 | byte value = OnRead(); 91 | if (value == REPLACE_TAG) 92 | { 93 | value = Read(); 94 | if (value == 0x01) 95 | return REPLACE_TAG; 96 | else if (value == 0x02) 97 | return PROTOBUF_TAG; 98 | } 99 | return value; 100 | } 101 | 102 | public byte[] Read(int length) 103 | { 104 | byte[] result = new byte[length]; 105 | for (int i = 0; i < length; i++) 106 | { 107 | result[i] = Read(); 108 | } 109 | return result; 110 | } 111 | 112 | private ProtocolBuffer OnWrite(byte value) 113 | { 114 | mArray[mPostion] = value; 115 | mPostion++; 116 | mLength++; 117 | return this; 118 | } 119 | 120 | public void WriteTag() => OnWrite(PROTOBUF_TAG); 121 | 122 | public void Write(byte data) 123 | { 124 | if (data == PROTOBUF_TAG) 125 | { 126 | OnWrite(REPLACE_TAG).OnWrite(0x02); 127 | } 128 | else if (data == REPLACE_TAG) 129 | { 130 | OnWrite(REPLACE_TAG).OnWrite(0x01); 131 | } 132 | else 133 | { 134 | OnWrite(data); 135 | } 136 | } 137 | 138 | public void Write(byte[] data) 139 | { 140 | for (int i = 0; i < data.Length; i++) 141 | { 142 | Write(data[i]); 143 | } 144 | } 145 | 146 | public int Length { get { return mLength; } } 147 | 148 | public int Postion { get { return mPostion; } set { mPostion = value; } } 149 | 150 | public byte[] Array { get { return mArray; } } 151 | 152 | public void ReadSubBuffer(IProtocolBuffer buffer, int count) 153 | { 154 | Buffer.BlockCopy(mArray, mPostion, buffer.Array, 0, count); 155 | mPostion += count; 156 | buffer.SetLength(count); 157 | buffer.Postion = 0; 158 | } 159 | 160 | public void WriteSubBuffer(IProtocolBuffer buffer) 161 | { 162 | Buffer.BlockCopy(buffer.Array, 0, mArray, mPostion, buffer.Length); 163 | mPostion += buffer.Length; 164 | mLength += buffer.Length; 165 | } 166 | 167 | public void SetLength(int length) 168 | { 169 | mLength = length; 170 | } 171 | 172 | public void Reset() 173 | { 174 | mPostion = 0; 175 | mLength = 0; 176 | mProtocolStart = false; 177 | } 178 | 179 | public void Write(ushort value) 180 | { 181 | value = BufferUtils.SwapUInt16(value); 182 | byte[] data = BitConverter.GetBytes(value); 183 | Write(data); 184 | } 185 | 186 | public void Write(uint value) 187 | { 188 | value = BufferUtils.SwapUInt32(value); 189 | byte[] data = BitConverter.GetBytes(value); 190 | Write(data); 191 | } 192 | 193 | public void WriteBCD(string value) 194 | { 195 | byte[] data = Str2Bcd(value); 196 | Write(data); 197 | } 198 | 199 | public ushort ReadUInt16() 200 | { 201 | byte[] data = Read(2); 202 | ushort result = BitConverter.ToUInt16(data, 0); 203 | return BufferUtils.SwapUInt16(result); 204 | } 205 | 206 | public uint ReadUInt() 207 | { 208 | byte[] data = Read(4); 209 | uint result = BitConverter.ToUInt32(data, 0); 210 | return BufferUtils.SwapUInt32(result); 211 | } 212 | 213 | public string ReadBCD(int length) 214 | { 215 | byte[] data = Read(length); 216 | return Bcd2Str(data); 217 | } 218 | 219 | public byte[] Str2Bcd(string asc) 220 | { 221 | int len = asc.Length; 222 | int mod = len % 2; 223 | if (mod != 0) 224 | { 225 | asc = "0" + asc; 226 | len = asc.Length; 227 | } 228 | byte[] abt = new byte[len]; 229 | if (len >= 2) 230 | { 231 | len = len / 2; 232 | } 233 | byte[] bbt = new byte[len]; 234 | abt = Encoding.ASCII.GetBytes(asc); 235 | int j, k; 236 | for (int p = 0; p < asc.Length / 2; p++) 237 | { 238 | if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) 239 | { 240 | j = abt[2 * p] - '0'; 241 | } 242 | else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) 243 | { 244 | j = abt[2 * p] - 'a' + 0x0a; 245 | } 246 | else 247 | { 248 | j = abt[2 * p] - 'A' + 0x0a; 249 | } 250 | if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) 251 | { 252 | k = abt[2 * p + 1] - '0'; 253 | } 254 | else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) 255 | { 256 | k = abt[2 * p + 1] - 'a' + 0x0a; 257 | } 258 | else 259 | { 260 | k = abt[2 * p + 1] - 'A' + 0x0a; 261 | } 262 | int a = (j << 4) + k; 263 | byte b = (byte)a; 264 | bbt[p] = b; 265 | } 266 | return bbt; 267 | } 268 | 269 | public string Bcd2Str(byte[] bytes) 270 | { 271 | StringBuilder temp = new StringBuilder(bytes.Length * 2); 272 | for (int i = 0; i < bytes.Length; i++) 273 | { 274 | temp.Append((byte)((bytes[i] & 0xf0) >> 4)); 275 | temp.Append((byte)(bytes[i] & 0x0f)); 276 | } 277 | return temp.ToString().Substring(0, 1).Equals("0") ? temp.ToString().Substring(1) : temp.ToString(); 278 | 279 | } 280 | 281 | public void WriteASCII(string value, int length) 282 | { 283 | if (value.Length > length) 284 | value = value.Substring(0, length); 285 | else 286 | { 287 | for (int i = value.Length; i < length; i++) 288 | { 289 | value = " " + value; 290 | } 291 | } 292 | byte[] data = Encoding.ASCII.GetBytes(value); 293 | Write(data); 294 | } 295 | 296 | public string ReadASCII(int length) 297 | { 298 | byte[] data = Read(length); 299 | return Encoding.ASCII.GetString(data); 300 | } 301 | 302 | public int WriteGBK(string value) 303 | { 304 | int postion = mPostion; 305 | byte[] data = Encoding.GetEncoding("GBK").GetBytes(value); 306 | Write(data); 307 | return mPostion - postion; 308 | } 309 | 310 | public string ReadGBK(int length = -1) 311 | { 312 | if (length == -1) 313 | return Encoding.GetEncoding("GBK").GetString(Array, mPostion, mLength - mPostion); 314 | byte[] data = Read(length); 315 | return Encoding.GetEncoding("GBK").GetString(data); 316 | } 317 | 318 | public override string ToString() 319 | { 320 | string hex = BitConverter.ToString(Array, 0, Length).Replace("-", string.Empty); 321 | return hex; 322 | } 323 | } 324 | 325 | public class ProtocolBufferPool 326 | { 327 | static ProtocolBufferPool _default; 328 | ConcurrentStack _pool = new ConcurrentStack(); 329 | 330 | public ProtocolBufferPool() 331 | { 332 | for (int i = 0; i < 1000; i++) 333 | _pool.Push(CreateBuffer()); 334 | } 335 | 336 | public IProtocolBuffer Pop() 337 | { 338 | if(!_pool.TryPop(out IProtocolBuffer result)) 339 | result = CreateBuffer(); 340 | 341 | result.Reset(); 342 | return result; 343 | } 344 | 345 | public void Push(IProtocolBuffer buffer) 346 | { 347 | _pool.Push(buffer); 348 | } 349 | 350 | private IProtocolBuffer CreateBuffer() 351 | { 352 | ProtocolBuffer buffer = new ProtocolBuffer(); 353 | return buffer; 354 | } 355 | 356 | public static ProtocolBufferPool Default 357 | { 358 | get 359 | { 360 | if (_default == null) 361 | _default = new ProtocolBufferPool(); 362 | return _default; 363 | } 364 | } 365 | } 366 | } 367 | -------------------------------------------------------------------------------- /src/ProtocolProcessError.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace JT808 4 | { 5 | public class ProtocolProcessError : Exception 6 | { 7 | public ProtocolProcessError(){ } 8 | 9 | public ProtocolProcessError(string error) : base(error) { } 10 | 11 | public ProtocolProcessError(string error, Exception e) : base(error, e) { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Serializes/EmitHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | 6 | namespace JT808.Serializes 7 | { 8 | public class FieldHandler 9 | { 10 | public FieldHandler(FieldInfo field) 11 | { 12 | mGetValue = ReflectionHandlerFactory.FieldGetHandler(field); 13 | mSetValue = ReflectionHandlerFactory.FieldSetHandler(field); 14 | Field = field; 15 | } 16 | private FieldInfo mField; 17 | public FieldInfo Field 18 | { 19 | get 20 | { 21 | return mField; 22 | } 23 | private set 24 | { 25 | mField = value; 26 | } 27 | } 28 | private GetValueHandler mGetValue; 29 | public GetValueHandler GetValue 30 | { 31 | get 32 | { 33 | return mGetValue; 34 | } 35 | 36 | } 37 | private SetValueHandler mSetValue; 38 | public SetValueHandler SetValue 39 | { 40 | get 41 | { 42 | return mSetValue; 43 | } 44 | 45 | } 46 | } 47 | public class PropertyHandler 48 | { 49 | public PropertyHandler(PropertyInfo property) 50 | { 51 | if (property.CanWrite) 52 | mSetValue = ReflectionHandlerFactory.PropertySetHandler(property); 53 | if (property.CanRead) 54 | mGetValue = ReflectionHandlerFactory.PropertyGetHandler(property); 55 | mProperty = property; 56 | IndexProperty = mProperty.GetGetMethod().GetParameters().Length > 0; 57 | } 58 | private bool mIndexProperty; 59 | public bool IndexProperty 60 | { 61 | get 62 | { 63 | return mIndexProperty; 64 | } 65 | set 66 | { 67 | mIndexProperty = value; 68 | } 69 | } 70 | private PropertyInfo mProperty; 71 | public PropertyInfo Property 72 | { 73 | get 74 | { 75 | return mProperty; 76 | } 77 | set 78 | { 79 | mProperty = value; 80 | } 81 | } 82 | private GetValueHandler mGetValue; 83 | public GetValueHandler Get 84 | { 85 | get 86 | { 87 | return mGetValue; 88 | } 89 | 90 | } 91 | private SetValueHandler mSetValue; 92 | public SetValueHandler Set 93 | { 94 | get 95 | { 96 | return mSetValue; 97 | } 98 | 99 | } 100 | } 101 | public class MethodHandler 102 | { 103 | public MethodHandler(MethodInfo method) 104 | { 105 | mExecute = ReflectionHandlerFactory.MethodHandler(method); 106 | mInfo = method; 107 | } 108 | private MethodInfo mInfo; 109 | public MethodInfo Info 110 | { 111 | get 112 | { 113 | return mInfo; 114 | } 115 | } 116 | private FastMethodHandler mExecute; 117 | public FastMethodHandler Execute 118 | { 119 | get 120 | { 121 | return mExecute; 122 | } 123 | } 124 | } 125 | public class InstanceHandler 126 | { 127 | public InstanceHandler(Type type) 128 | { 129 | mInstance = ReflectionHandlerFactory.InstanceHandler(type); 130 | } 131 | private ObjectInstanceHandler mInstance; 132 | public ObjectInstanceHandler Instance 133 | { 134 | get 135 | { 136 | return mInstance; 137 | } 138 | } 139 | } 140 | public delegate object GetValueHandler(object source); 141 | public delegate object ObjectInstanceHandler(); 142 | public delegate void SetValueHandler(object source, object value); 143 | public delegate object FastMethodHandler(object target, object[] paramters); 144 | public class ReflectionHandlerFactory 145 | { 146 | 147 | #region field handler 148 | 149 | private static Dictionary mFieldGetHandlers = new Dictionary(); 150 | private static Dictionary mFieldSetHandlers = new Dictionary(); 151 | public static GetValueHandler FieldGetHandler(FieldInfo field) 152 | { 153 | GetValueHandler handler; 154 | if (mFieldGetHandlers.ContainsKey(field)) 155 | { 156 | handler = mFieldGetHandlers[field]; 157 | } 158 | else 159 | { 160 | lock (typeof(ReflectionHandlerFactory)) 161 | { 162 | if (mFieldGetHandlers.ContainsKey(field)) 163 | { 164 | handler = mFieldGetHandlers[field]; 165 | } 166 | else 167 | { 168 | handler = CreateFieldGetHandler(field); 169 | mFieldGetHandlers.Add(field, handler); 170 | } 171 | 172 | } 173 | } 174 | return handler; 175 | } 176 | private static GetValueHandler CreateFieldGetHandler(FieldInfo field) 177 | { 178 | DynamicMethod dm = new DynamicMethod("", typeof(object), new Type[] { typeof(object) }, field.DeclaringType); 179 | ILGenerator ilGenerator = dm.GetILGenerator(); 180 | ilGenerator.Emit(OpCodes.Ldarg_0); 181 | ilGenerator.Emit(OpCodes.Ldfld, field); 182 | EmitBoxIfNeeded(ilGenerator, field.FieldType); 183 | ilGenerator.Emit(OpCodes.Ret); 184 | return (GetValueHandler)dm.CreateDelegate(typeof(GetValueHandler)); 185 | } 186 | public static SetValueHandler FieldSetHandler(FieldInfo field) 187 | { 188 | SetValueHandler handler; 189 | if (mFieldSetHandlers.ContainsKey(field)) 190 | { 191 | handler = mFieldSetHandlers[field]; 192 | } 193 | else 194 | { 195 | lock (typeof(ReflectionHandlerFactory)) 196 | { 197 | if (mFieldSetHandlers.ContainsKey(field)) 198 | { 199 | handler = mFieldSetHandlers[field]; 200 | } 201 | else 202 | { 203 | handler = CreateFieldSetHandler(field); 204 | mFieldSetHandlers.Add(field, handler); 205 | } 206 | } 207 | } 208 | return handler; 209 | } 210 | private static SetValueHandler CreateFieldSetHandler(FieldInfo field) 211 | { 212 | DynamicMethod dm = new DynamicMethod("", null, new Type[] { typeof(object), typeof(object) }, field.DeclaringType); 213 | ILGenerator ilGenerator = dm.GetILGenerator(); 214 | ilGenerator.Emit(OpCodes.Ldarg_0); 215 | ilGenerator.Emit(OpCodes.Ldarg_1); 216 | EmitCastToReference(ilGenerator, field.FieldType); 217 | ilGenerator.Emit(OpCodes.Stfld, field); 218 | ilGenerator.Emit(OpCodes.Ret); 219 | return (SetValueHandler)dm.CreateDelegate(typeof(SetValueHandler)); 220 | } 221 | 222 | #endregion 223 | 224 | #region Property Handler 225 | 226 | private static Dictionary mPropertyGetHandlers = new Dictionary(); 227 | private static Dictionary mPropertySetHandlers = new Dictionary(); 228 | public static SetValueHandler PropertySetHandler(PropertyInfo property) 229 | { 230 | SetValueHandler handler; 231 | if (mPropertySetHandlers.ContainsKey(property)) 232 | { 233 | handler = mPropertySetHandlers[property]; 234 | } 235 | else 236 | { 237 | lock (typeof(ReflectionHandlerFactory)) 238 | { 239 | if (mPropertySetHandlers.ContainsKey(property)) 240 | { 241 | handler = mPropertySetHandlers[property]; 242 | } 243 | else 244 | { 245 | handler = CreatePropertySetHandler(property); 246 | mPropertySetHandlers.Add(property, handler); 247 | } 248 | } 249 | } 250 | return handler; 251 | } 252 | private static SetValueHandler CreatePropertySetHandler(PropertyInfo property) 253 | { 254 | DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, null, new Type[] { typeof(object), typeof(object) }, property.DeclaringType.Module); 255 | 256 | ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); 257 | 258 | 259 | ilGenerator.Emit(OpCodes.Ldarg_0); 260 | 261 | 262 | ilGenerator.Emit(OpCodes.Ldarg_1); 263 | 264 | 265 | EmitCastToReference(ilGenerator, property.PropertyType); 266 | 267 | 268 | ilGenerator.EmitCall(OpCodes.Callvirt, property.GetSetMethod(), null); 269 | 270 | 271 | ilGenerator.Emit(OpCodes.Ret); 272 | 273 | 274 | SetValueHandler setter = (SetValueHandler)dynamicMethod.CreateDelegate(typeof(SetValueHandler)); 275 | 276 | return setter; 277 | } 278 | public static GetValueHandler PropertyGetHandler(PropertyInfo property) 279 | { 280 | GetValueHandler handler; 281 | if (mPropertyGetHandlers.ContainsKey(property)) 282 | { 283 | handler = mPropertyGetHandlers[property]; 284 | } 285 | else 286 | { 287 | lock (typeof(ReflectionHandlerFactory)) 288 | { 289 | if (mPropertyGetHandlers.ContainsKey(property)) 290 | { 291 | handler = mPropertyGetHandlers[property]; 292 | } 293 | else 294 | { 295 | handler = CreatePropertyGetHandler(property); 296 | mPropertyGetHandlers.Add(property, handler); 297 | } 298 | } 299 | } 300 | return handler; 301 | } 302 | private static GetValueHandler CreatePropertyGetHandler(PropertyInfo property) 303 | { 304 | 305 | DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object) }, property.DeclaringType.Module); 306 | 307 | ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); 308 | 309 | 310 | ilGenerator.Emit(OpCodes.Ldarg_0); 311 | 312 | 313 | ilGenerator.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null); 314 | 315 | 316 | EmitBoxIfNeeded(ilGenerator, property.PropertyType); 317 | 318 | 319 | ilGenerator.Emit(OpCodes.Ret); 320 | 321 | 322 | GetValueHandler getter = (GetValueHandler)dynamicMethod.CreateDelegate(typeof(GetValueHandler)); 323 | 324 | return getter; 325 | } 326 | #endregion 327 | 328 | #region Method Handler 329 | 330 | private static Dictionary mMethodHandlers = new Dictionary(); 331 | public static FastMethodHandler MethodHandler(MethodInfo method) 332 | { 333 | FastMethodHandler handler = null; 334 | if (mMethodHandlers.ContainsKey(method)) 335 | { 336 | handler = mMethodHandlers[method]; 337 | } 338 | else 339 | { 340 | lock (typeof(ReflectionHandlerFactory)) 341 | { 342 | if (mMethodHandlers.ContainsKey(method)) 343 | { 344 | handler = mMethodHandlers[method]; 345 | } 346 | else 347 | { 348 | handler = CreateMethodHandler(method); 349 | mMethodHandlers.Add(method, handler); 350 | } 351 | } 352 | } 353 | return handler; 354 | } 355 | private static FastMethodHandler CreateMethodHandler(MethodInfo methodInfo) 356 | { 357 | DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object), typeof(object[]) }, methodInfo.DeclaringType.Module); 358 | ILGenerator il = dynamicMethod.GetILGenerator(); 359 | ParameterInfo[] ps = methodInfo.GetParameters(); 360 | Type[] paramTypes = new Type[ps.Length]; 361 | for (int i = 0; i < paramTypes.Length; i++) 362 | { 363 | if (ps[i].ParameterType.IsByRef) 364 | paramTypes[i] = ps[i].ParameterType.GetElementType(); 365 | else 366 | paramTypes[i] = ps[i].ParameterType; 367 | } 368 | LocalBuilder[] locals = new LocalBuilder[paramTypes.Length]; 369 | 370 | for (int i = 0; i < paramTypes.Length; i++) 371 | { 372 | locals[i] = il.DeclareLocal(paramTypes[i], true); 373 | } 374 | for (int i = 0; i < paramTypes.Length; i++) 375 | { 376 | il.Emit(OpCodes.Ldarg_1); 377 | EmitFastInt(il, i); 378 | il.Emit(OpCodes.Ldelem_Ref); 379 | EmitCastToReference(il, paramTypes[i]); 380 | il.Emit(OpCodes.Stloc, locals[i]); 381 | } 382 | if (!methodInfo.IsStatic) 383 | { 384 | il.Emit(OpCodes.Ldarg_0); 385 | } 386 | for (int i = 0; i < paramTypes.Length; i++) 387 | { 388 | if (ps[i].ParameterType.IsByRef) 389 | il.Emit(OpCodes.Ldloca_S, locals[i]); 390 | else 391 | il.Emit(OpCodes.Ldloc, locals[i]); 392 | } 393 | if (methodInfo.IsStatic) 394 | il.EmitCall(OpCodes.Call, methodInfo, null); 395 | else 396 | il.EmitCall(OpCodes.Callvirt, methodInfo, null); 397 | if (methodInfo.ReturnType == typeof(void)) 398 | il.Emit(OpCodes.Ldnull); 399 | else 400 | EmitBoxIfNeeded(il, methodInfo.ReturnType); 401 | 402 | for (int i = 0; i < paramTypes.Length; i++) 403 | { 404 | if (ps[i].ParameterType.IsByRef) 405 | { 406 | il.Emit(OpCodes.Ldarg_1); 407 | EmitFastInt(il, i); 408 | il.Emit(OpCodes.Ldloc, locals[i]); 409 | if (locals[i].LocalType.IsValueType) 410 | il.Emit(OpCodes.Box, locals[i].LocalType); 411 | il.Emit(OpCodes.Stelem_Ref); 412 | } 413 | } 414 | 415 | il.Emit(OpCodes.Ret); 416 | FastMethodHandler invoder = (FastMethodHandler)dynamicMethod.CreateDelegate(typeof(FastMethodHandler)); 417 | return invoder; 418 | } 419 | #endregion 420 | 421 | #region Instance Handler 422 | 423 | private static Dictionary mInstanceHandlers = new Dictionary(); 424 | public static ObjectInstanceHandler InstanceHandler(Type type) 425 | { 426 | ObjectInstanceHandler handler; 427 | if (mInstanceHandlers.ContainsKey(type)) 428 | { 429 | handler = mInstanceHandlers[type]; 430 | } 431 | else 432 | { 433 | lock (typeof(ReflectionHandlerFactory)) 434 | { 435 | if (mInstanceHandlers.ContainsKey(type)) 436 | { 437 | handler = mInstanceHandlers[type]; 438 | } 439 | else 440 | { 441 | handler = CreateInstanceHandler(type); 442 | mInstanceHandlers.Add(type, handler); 443 | } 444 | } 445 | } 446 | return handler; 447 | } 448 | private static ObjectInstanceHandler CreateInstanceHandler(Type type) 449 | { 450 | DynamicMethod method = new DynamicMethod(string.Empty, type, null, type.Module); 451 | ILGenerator il = method.GetILGenerator(); 452 | il.DeclareLocal(type, true); 453 | il.Emit(OpCodes.Newobj, type.GetConstructor(new Type[0])); 454 | il.Emit(OpCodes.Stloc_0); 455 | il.Emit(OpCodes.Ldloc_0); 456 | il.Emit(OpCodes.Ret); 457 | ObjectInstanceHandler creater = (ObjectInstanceHandler)method.CreateDelegate(typeof(ObjectInstanceHandler)); 458 | return creater; 459 | 460 | } 461 | #endregion 462 | 463 | 464 | private static void EmitCastToReference(ILGenerator il, System.Type type) 465 | { 466 | if (type.IsValueType) 467 | { 468 | il.Emit(OpCodes.Unbox_Any, type); 469 | } 470 | else 471 | { 472 | il.Emit(OpCodes.Castclass, type); 473 | } 474 | } 475 | private static void EmitBoxIfNeeded(ILGenerator il, System.Type type) 476 | { 477 | if (type.IsValueType) 478 | { 479 | il.Emit(OpCodes.Box, type); 480 | } 481 | } 482 | private static void EmitFastInt(ILGenerator il, int value) 483 | { 484 | switch (value) 485 | { 486 | case -1: 487 | il.Emit(OpCodes.Ldc_I4_M1); 488 | return; 489 | case 0: 490 | il.Emit(OpCodes.Ldc_I4_0); 491 | return; 492 | case 1: 493 | il.Emit(OpCodes.Ldc_I4_1); 494 | return; 495 | case 2: 496 | il.Emit(OpCodes.Ldc_I4_2); 497 | return; 498 | case 3: 499 | il.Emit(OpCodes.Ldc_I4_3); 500 | return; 501 | case 4: 502 | il.Emit(OpCodes.Ldc_I4_4); 503 | return; 504 | case 5: 505 | il.Emit(OpCodes.Ldc_I4_5); 506 | return; 507 | case 6: 508 | il.Emit(OpCodes.Ldc_I4_6); 509 | return; 510 | case 7: 511 | il.Emit(OpCodes.Ldc_I4_7); 512 | return; 513 | case 8: 514 | il.Emit(OpCodes.Ldc_I4_8); 515 | return; 516 | } 517 | 518 | if (value > -129 && value < 128) 519 | { 520 | il.Emit(OpCodes.Ldc_I4_S, (SByte)value); 521 | } 522 | else 523 | { 524 | il.Emit(OpCodes.Ldc_I4, value); 525 | } 526 | } 527 | } 528 | } 529 | 530 | -------------------------------------------------------------------------------- /src/Serializes/IBitType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JT808 8 | { 9 | public interface IBitCustomType 10 | { 11 | void Load(object value); 12 | 13 | object Save(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Serializes/IReadWriteHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JT808 8 | { 9 | [AttributeUsage(AttributeTargets.Property)] 10 | public abstract class ReadWriteHandlerAttribute : Attribute 11 | { 12 | public abstract object Read(IProtocolBuffer buffer); 13 | 14 | public abstract void Write(object value, IProtocolBuffer buffer); 15 | } 16 | 17 | [AttributeUsage(AttributeTargets.Property)] 18 | public class ByteHandler : ReadWriteHandlerAttribute 19 | { 20 | 21 | public override object Read(IProtocolBuffer buffer) 22 | { 23 | return buffer.Read(); 24 | } 25 | 26 | public override void Write(object value, IProtocolBuffer buffer) 27 | { 28 | buffer.Write((byte)value); 29 | } 30 | } 31 | 32 | [AttributeUsage(AttributeTargets.Property)] 33 | public class BytesHandler : ReadWriteHandlerAttribute 34 | { 35 | 36 | public BytesHandler(int length) 37 | { 38 | Length = length; 39 | } 40 | public int Length { get; set; } 41 | 42 | public override object Read(IProtocolBuffer buffer) 43 | { 44 | return buffer.Read(Length); 45 | } 46 | 47 | public override void Write(object value, IProtocolBuffer buffer) 48 | { 49 | buffer.Write((byte[])value); 50 | } 51 | } 52 | 53 | [AttributeUsage(AttributeTargets.Property)] 54 | public class UInt16Handler : ReadWriteHandlerAttribute 55 | { 56 | 57 | public override object Read(IProtocolBuffer buffer) 58 | { 59 | return buffer.ReadUInt16(); 60 | } 61 | 62 | public override void Write(object value, IProtocolBuffer buffer) 63 | { 64 | buffer.Write((UInt16)value); 65 | } 66 | } 67 | 68 | [AttributeUsage(AttributeTargets.Property)] 69 | public class UIntHandler : ReadWriteHandlerAttribute 70 | { 71 | 72 | public override object Read(IProtocolBuffer buffer) 73 | { 74 | return buffer.ReadUInt(); 75 | } 76 | 77 | public override void Write(object value, IProtocolBuffer buffer) 78 | { 79 | buffer.Write((uint)value); 80 | } 81 | } 82 | 83 | [AttributeUsage(AttributeTargets.Property)] 84 | public class ASCIIHandler : ReadWriteHandlerAttribute 85 | { 86 | public ASCIIHandler(int length) 87 | { 88 | Length = length; 89 | } 90 | public int Length { get; set; } 91 | 92 | public override object Read(IProtocolBuffer buffer) 93 | { 94 | return buffer.ReadASCII(Length).TrimStart(' '); 95 | } 96 | 97 | public override void Write(object value, IProtocolBuffer buffer) 98 | { 99 | buffer.WriteASCII((string)value, Length); 100 | } 101 | } 102 | 103 | [AttributeUsage(AttributeTargets.Property)] 104 | public class CBDHandler : ReadWriteHandlerAttribute 105 | { 106 | public CBDHandler(int length) 107 | { 108 | Length = length; 109 | } 110 | 111 | public int Length { get; set; } 112 | 113 | public override object Read(IProtocolBuffer buffer) 114 | { 115 | return buffer.ReadBCD(Length); 116 | } 117 | 118 | public override void Write(object value, IProtocolBuffer buffer) 119 | { 120 | buffer.WriteBCD((string)value); 121 | } 122 | } 123 | 124 | [AttributeUsage(AttributeTargets.Property)] 125 | public class GBKHandler : ReadWriteHandlerAttribute 126 | { 127 | public GBKHandler(int length = -1) 128 | { 129 | Length = length; 130 | } 131 | 132 | public int Length { get; set; } 133 | 134 | public override object Read(IProtocolBuffer buffer) 135 | { 136 | return buffer.ReadGBK(Length); 137 | } 138 | 139 | public override void Write(object value, IProtocolBuffer buffer) 140 | { 141 | buffer.WriteGBK((string)value); 142 | } 143 | } 144 | 145 | [AttributeUsage(AttributeTargets.Property)] 146 | public class TimeBCD : ReadWriteHandlerAttribute 147 | { 148 | public override object Read(IProtocolBuffer buffer) 149 | { 150 | string value = buffer.ReadBCD(6); 151 | int year = int.Parse("20" + value.Substring(0, 2)); 152 | int month = int.Parse(value.Substring(2, 2)); 153 | int day = int.Parse(value.Substring(4, 2)); 154 | int hh = int.Parse(value.Substring(6, 2)); 155 | int mm = int.Parse(value.Substring(8, 2)); 156 | int ss = int.Parse(value.Substring(10, 2)); 157 | return new DateTime(year, month, day, hh, mm, ss); 158 | } 159 | 160 | public override void Write(object value, IProtocolBuffer buffer) 161 | { 162 | string time = ((DateTime)value).ToString("yyMMddHHmmss"); 163 | buffer.WriteBCD(time); 164 | } 165 | } 166 | 167 | 168 | [AttributeUsage(AttributeTargets.Property)] 169 | public class ByteBitHandler : ReadWriteHandlerAttribute 170 | { 171 | public ByteBitHandler(Type type) 172 | { 173 | mType = type; 174 | } 175 | private Type mType; 176 | 177 | public override object Read(IProtocolBuffer buffer) 178 | { 179 | byte data = buffer.Read(); 180 | IBitCustomType result = (IBitCustomType)Activator.CreateInstance(mType); 181 | result.Load(data); 182 | return result; 183 | } 184 | 185 | public override void Write(object value, IProtocolBuffer buffer) 186 | { 187 | byte data = (byte)((IBitCustomType)value).Save(); 188 | buffer.Write(data); 189 | } 190 | 191 | } 192 | 193 | [AttributeUsage(AttributeTargets.Property)] 194 | public class UInt16BitHandler : ReadWriteHandlerAttribute 195 | { 196 | public UInt16BitHandler(Type type) 197 | { 198 | mType = type; 199 | } 200 | private Type mType; 201 | 202 | public override object Read(IProtocolBuffer buffer) 203 | { 204 | UInt16 data = buffer.ReadUInt16(); 205 | IBitCustomType result = (IBitCustomType)Activator.CreateInstance(mType); 206 | result.Load(data); 207 | return result; 208 | } 209 | 210 | public override void Write(object value, IProtocolBuffer buffer) 211 | { 212 | UInt16 data = (UInt16)((IBitCustomType)value).Save(); 213 | buffer.Write(data); 214 | } 215 | 216 | } 217 | 218 | [AttributeUsage(AttributeTargets.Property)] 219 | public class UIntBitHandler : ReadWriteHandlerAttribute 220 | { 221 | public UIntBitHandler(Type type) 222 | { 223 | mType = type; 224 | } 225 | private Type mType; 226 | 227 | public override object Read(IProtocolBuffer buffer) 228 | { 229 | uint data = buffer.ReadUInt(); 230 | IBitCustomType result = (IBitCustomType)Activator.CreateInstance(mType); 231 | result.Load(data); 232 | return result; 233 | } 234 | 235 | public override void Write(object value, IProtocolBuffer buffer) 236 | { 237 | uint data = (uint)((IBitCustomType)value).Save(); 238 | buffer.Write(data); 239 | } 240 | 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/Serializes/MessageTypeAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace JT808 4 | { 5 | [AttributeUsage(AttributeTargets.Class)] 6 | public class MessageTypeAttribute : Attribute 7 | { 8 | public MessageTypeAttribute() 9 | { 10 | } 11 | 12 | public MessageTypeAttribute(ushort id) 13 | { 14 | ID = id; 15 | } 16 | 17 | public ushort ID { get; set; } 18 | 19 | public bool NoBody { get; set; } = false; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Serializes/PropertySerializeHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace JT808.Serializes 8 | { 9 | class PropertySerializeHandler 10 | { 11 | public PropertySerializeHandler(System.Reflection.PropertyInfo property, ReadWriteHandlerAttribute readwritehandler) 12 | { 13 | Handler = new PropertyHandler(property); 14 | ReadWriteHandler = readwritehandler; 15 | } 16 | 17 | public PropertyHandler Handler { get; private set; } 18 | 19 | public ReadWriteHandlerAttribute ReadWriteHandler { get; private set; } 20 | 21 | public void Read(object target, IProtocolBuffer buffer) 22 | { 23 | object value = ReadWriteHandler.Read(buffer); 24 | Handler.Set(target, value); 25 | } 26 | 27 | public void Write(object target, IProtocolBuffer buffer) 28 | { 29 | object value = Handler.Get(target); 30 | if (value == null) 31 | throw new ProtocolProcessError(string.Format("{0}.{1} value can't be null!", Handler.Property.DeclaringType, Handler.Property.PropertyType)); 32 | ReadWriteHandler.Write(value, buffer); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Serializes/Serializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace JT808.Serializes 5 | { 6 | public class Serializer 7 | { 8 | public Serializer(Type bodyType, MessageTypeAttribute msgType) 9 | { 10 | mBodyType = bodyType; 11 | MessageType = msgType; 12 | Init(); 13 | } 14 | 15 | private Type mBodyType; 16 | 17 | private List mProperties = new List(); 18 | 19 | private void Init() 20 | { 21 | try 22 | { 23 | foreach (System.Reflection.PropertyInfo p in mBodyType.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)) 24 | { 25 | ReadWriteHandlerAttribute[] rwha = (ReadWriteHandlerAttribute[])p.GetCustomAttributes(typeof(ReadWriteHandlerAttribute), true); 26 | if (rwha != null && rwha.Length > 0) 27 | { 28 | PropertySerializeHandler handler = new PropertySerializeHandler(p, rwha[0]); 29 | mProperties.Add(handler); 30 | } 31 | } 32 | } 33 | catch (Exception e_) 34 | { 35 | throw new ProtocolProcessError(string.Format("{0} init error {1}", mBodyType.Name, e_.Message), e_); 36 | } 37 | } 38 | 39 | public MessageTypeAttribute MessageType { get; set; } 40 | 41 | public void Deserialize(object obj, IProtocolBuffer buffer) 42 | { 43 | if (obj is IMessageBody) 44 | { 45 | ((IMessageBody)obj).Load(buffer); 46 | } 47 | else 48 | { 49 | foreach (PropertySerializeHandler item in mProperties) 50 | { 51 | item.Read(obj, buffer); 52 | } 53 | } 54 | } 55 | 56 | public void Serialize(object obj, IProtocolBuffer buffer) 57 | { 58 | if (obj is IMessageBody) 59 | ((IMessageBody)obj).Save(buffer); 60 | else 61 | { 62 | foreach (PropertySerializeHandler item in mProperties) 63 | { 64 | item.Write(obj, buffer); 65 | } 66 | } 67 | } 68 | 69 | public object CreateObject() 70 | { 71 | return Activator.CreateInstance(mBodyType); 72 | } 73 | 74 | } 75 | 76 | public class SerializerFactory 77 | { 78 | Dictionary mTypeSerializersMap = new Dictionary(); 79 | Dictionary mIDSerializersMap = new Dictionary(); 80 | 81 | private void Register(Type type, MessageTypeAttribute msgType) 82 | { 83 | Serializer serializer = new Serializer(type, msgType); 84 | mTypeSerializersMap[type] = serializer; 85 | mIDSerializersMap[serializer.MessageType.ID] = serializer; 86 | } 87 | 88 | public Serializer Get(ushort id) 89 | { 90 | mIDSerializersMap.TryGetValue(id, out Serializer result); 91 | return result; 92 | } 93 | 94 | public Serializer Get(Type type) 95 | { 96 | mTypeSerializersMap.TryGetValue(type, out Serializer result); 97 | return result; 98 | } 99 | 100 | public static void Init() 101 | { 102 | SerializerFactory factory = Defalut; 103 | } 104 | 105 | private static SerializerFactory mDefault = null; 106 | 107 | public static SerializerFactory Defalut 108 | { 109 | get 110 | { 111 | if (mDefault == null) 112 | { 113 | mDefault = new SerializerFactory(); 114 | foreach (Type type in typeof(SerializerFactory).Assembly.GetTypes()) 115 | { 116 | MessageTypeAttribute[] mta = (MessageTypeAttribute[])type.GetCustomAttributes(typeof(MessageTypeAttribute), false); 117 | if (mta != null && mta.Length > 0) 118 | { 119 | mDefault.Register(type, mta[0]); 120 | } 121 | } 122 | } 123 | return mDefault; 124 | } 125 | 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /道路运输车辆卫星定位系统北斗兼容车载终端通讯协议技术规范.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linfx/JT808/6f9ad00171fd1ab4e9e40a1e3239d5f9fb3cf998/道路运输车辆卫星定位系统北斗兼容车载终端通讯协议技术规范.pdf --------------------------------------------------------------------------------