├── 道路运输车辆卫星定位系统北斗兼容车载终端通讯协议技术规范.pdf
├── src
├── Messages
│ ├── PingMessage.cs
│ ├── SignatureMessage.cs
│ ├── ResponseMessage.cs
│ ├── RegisterMessage.cs
│ ├── Message.cs
│ └── PostionMessage.cs
├── Serializes
│ ├── IBitType.cs
│ ├── MessageTypeAttribute.cs
│ ├── PropertySerializeHandler.cs
│ ├── Serializer.cs
│ ├── IReadWriteHandler.cs
│ └── EmitHandler.cs
├── ProtocolProcessError.cs
├── Properties
│ └── AssemblyInfo.cs
├── IMessage.cs
├── BufferUtils.cs
├── JT808.csproj
└── ProtocolBuffer.cs
├── JT808.sln
├── .gitattributes
└── .gitignore
/道路运输车辆卫星定位系统北斗兼容车载终端通讯协议技术规范.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linfx/JT808/HEAD/道路运输车辆卫星定位系统北斗兼容车载终端通讯协议技术规范.pdf
--------------------------------------------------------------------------------
/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/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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/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/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/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/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/.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
--------------------------------------------------------------------------------
/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/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/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/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/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 |
--------------------------------------------------------------------------------