Bladeren bron

重整新能源协议

tags/1.0.0
SmallChi 6 jaren geleden
bovenliggende
commit
58a67ed5e4
28 gewijzigde bestanden met toevoegingen van 1403 en 13 verwijderingen
  1. +19
    -0
      src/JTNE.Protocol.Test/JTNE.Protocol.Test.csproj
  2. +18
    -0
      src/JTNE.Protocol.Test/JTNEPackageTest.cs
  3. +14
    -0
      src/JTNE.Protocol/Attributes/JTNEBodiesTypeAttribute.cs
  4. +25
    -0
      src/JTNE.Protocol/Attributes/JTNEFormatterAttribute.cs
  5. +20
    -0
      src/JTNE.Protocol/Attributes/JTNEMsgIdDescriptionAttribute.cs
  6. +29
    -0
      src/JTNE.Protocol/Enums/JTNEAskId.cs
  7. +34
    -0
      src/JTNE.Protocol/Enums/JTNEEncryptMethod.cs
  8. +26
    -0
      src/JTNE.Protocol/Enums/JTNEErrorCode.cs
  9. +57
    -0
      src/JTNE.Protocol/Enums/JTNEMsgId.cs
  10. +22
    -0
      src/JTNE.Protocol/Exceptions/JTNEException.cs
  11. +45
    -0
      src/JTNE.Protocol/Extensions/JTNEBCDExtensions.cs
  12. +120
    -0
      src/JTNE.Protocol/Extensions/JTNEBinaryExtensions.cs
  13. +170
    -0
      src/JTNE.Protocol/Extensions/JTNEDateTimeExtensions.cs
  14. +207
    -0
      src/JTNE.Protocol/Extensions/JTNEEnumExtensions.cs
  15. +50
    -0
      src/JTNE.Protocol/Extensions/JTNEFormatterExtensions.cs
  16. +81
    -0
      src/JTNE.Protocol/Extensions/JTNEFormatterResolverExtensions.cs
  17. +130
    -0
      src/JTNE.Protocol/Extensions/JTNEHexExtensions.cs
  18. +70
    -0
      src/JTNE.Protocol/Extensions/JTNEStringExtensions.cs
  19. +45
    -0
      src/JTNE.Protocol/Extensions/JTNEXorExtensions.cs
  20. +12
    -0
      src/JTNE.Protocol/Formatters/IJTNEFormatterOfT.cs
  21. +43
    -0
      src/JTNE.Protocol/Formatters/JTNEPackageFormatter.cs
  22. +1
    -1
      src/JTNE.Protocol/JTNE.Protocol.csproj
  23. +27
    -0
      src/JTNE.Protocol/JTNEArrayPool.cs
  24. +14
    -0
      src/JTNE.Protocol/JTNEBodies.cs
  25. +34
    -0
      src/JTNE.Protocol/JTNEGlobalConfigs.cs
  26. +20
    -9
      src/JTNE.Protocol/JTNEPackage.cs
  27. +49
    -0
      src/JTNE.Protocol/JTNESerializer.cs
  28. +21
    -3
      src/JTNewEnergy.sln

+ 19
- 0
src/JTNE.Protocol.Test/JTNE.Protocol.Test.csproj Bestand weergeven

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\JTNE.Protocol\JTNE.Protocol.csproj" />
</ItemGroup>

</Project>

+ 18
- 0
src/JTNE.Protocol.Test/JTNEPackageTest.cs Bestand weergeven

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;
using JTNE.Protocol.Extensions;

namespace JTNE.Protocol.Test
{
public class JTNEPackageTest
{
[Fact]
public void Test1()
{
var hex = "23 23 05 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 08 12 06 08 12 06 3A 00 01 E9".ToHexBytes();
var package=JTNESerializer.Deserialize(hex);
}
}
}

+ 14
- 0
src/JTNE.Protocol/Attributes/JTNEBodiesTypeAttribute.cs Bestand weergeven

@@ -0,0 +1,14 @@
using System;

namespace JTNE.Protocol.Attributes
{
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class JTNEBodiesTypeAttribute : Attribute
{
public JTNEBodiesTypeAttribute(Type jT808BodiesType)
{
JT808BodiesType = jT808BodiesType;
}
public Type JT808BodiesType { get;}
}
}

+ 25
- 0
src/JTNE.Protocol/Attributes/JTNEFormatterAttribute.cs Bestand weergeven

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol.Attributes
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
public sealed class JTNEFormatterAttribute:Attribute
{
public Type FormatterType { get; private set; }

public object[] Arguments { get; private set; }

public JTNEFormatterAttribute(Type formatterType)
{
this.FormatterType = formatterType;
}

public JTNEFormatterAttribute(Type formatterType, params object[] arguments)
{
this.FormatterType = formatterType;
this.Arguments = arguments;
}
}
}

+ 20
- 0
src/JTNE.Protocol/Attributes/JTNEMsgIdDescriptionAttribute.cs Bestand weergeven

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol.Attributes
{
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class JTNEMsgIdDescriptionAttribute : Attribute
{
public string Code { get; set; }

public string Name { get; set; }

public JTNEMsgIdDescriptionAttribute(string code,string name)
{
Code = code;
Name = name;
}
}
}

+ 29
- 0
src/JTNE.Protocol/Enums/JTNEAskId.cs Bestand weergeven

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol.Enums
{
/// <summary>
/// 应答标志
/// </summary>
public enum JTNEAskId:byte
{
/// <summary>
/// 接收到的信息正确
/// </summary>
Success=0x01,
/// <summary>
/// 设置未成功
/// </summary>
Error=0x02,
/// <summary>
/// VIN重复错误
/// </summary>
VinRepeatError=0x03,
/// <summary>
/// 数据包为命令包,而非应答包
/// </summary>
CMD=0xFE
}
}

+ 34
- 0
src/JTNE.Protocol/Enums/JTNEEncryptMethod.cs Bestand weergeven

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol.Enums
{
/// <summary>
/// 数据单元加密方式
/// 0x01:数据不加密;0x02:数据经过 RSA 算法加密;0x03:数据经过 AES128 位算法加密;“0xFE”表示异常,“0xFF”表示无效
/// </summary>
public enum JTNEEncryptMethod:byte
{
/// <summary>
/// 数据不加密
/// </summary>
None = 0x01,
/// <summary>
/// 数据经过 RSA 算法加密
/// </summary>
RSA = 0x02,
/// <summary>
/// 数据经过 AES128 位算法加密
/// </summary>
AES128 = 0x03,
/// <summary>
/// 表示异常
/// </summary>
Exception = 0xFE,
/// <summary>
/// 表示无效
/// </summary>
Invalid = 0xFF
}
}

+ 26
- 0
src/JTNE.Protocol/Enums/JTNEErrorCode.cs Bestand weergeven

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol.Enums
{
/// <summary>
/// 错误代码
/// </summary>
public enum JTNEErrorCode
{
/// <summary>
/// 开始标识错误
/// </summary>
BeginFlagError = 1001,
/// <summary>
/// BCC校验错误
/// </summary>
BCCCodeError = 1002,
/// <summary>
/// 没有标记
/// <see cref="JT808.Protocol.Attributes.JT808FormatterAttribute"/>
/// </summary>
GetFormatterAttributeError = 1003,
}
}

+ 57
- 0
src/JTNE.Protocol/Enums/JTNEMsgId.cs Bestand weergeven

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol.Enums
{
/// <summary>
/// 命令单元
/// </summary>
public enum JTNEMsgId:byte
{
/// <summary>
/// 车辆登入
/// </summary>
login = 0x01,
/// <summary>
/// 实时信息上传
/// </summary>
uploadim = 0x02,
/// <summary>
/// 补传信息上传
/// </summary>
uploadsup = 0x03,
/// <summary>
/// 车辆登出
/// </summary>
loginout = 0x04,
/// <summary>
/// 平台登入
/// </summary>
platformlogin = 0x05,
/// <summary>
/// 平台登出
/// </summary>
platformlogout = 0x06,
/// <summary>
/// 心跳
/// </summary>
heartbeat = 0x07,
/// <summary>
/// 终端校时
/// </summary>
checktime = 0x08,
/// <summary>
/// 查询命令
/// </summary>
query = 0x80,
/// <summary>
/// 设置命令
/// </summary>
settings = 0x81,
/// <summary>
/// 控制命令
/// </summary>
control = 0x82
}
}

+ 22
- 0
src/JTNE.Protocol/Exceptions/JTNEException.cs Bestand weergeven

@@ -0,0 +1,22 @@
using JTNE.Protocol.Enums;
using System;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol.Exceptions
{
public class JTNEException:Exception
{
public JTNEException(JTNEErrorCode errorCode) : base(errorCode.ToString())
{
this.ErrorCode = errorCode;
}

public JTNEException(JTNEErrorCode errorCode, string message) : base(message)
{
this.ErrorCode = errorCode;
}

public JTNEErrorCode ErrorCode { get; }
}
}

+ 45
- 0
src/JTNE.Protocol/Extensions/JTNEBCDExtensions.cs Bestand weergeven

@@ -0,0 +1,45 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

namespace JTNE.Protocol.Extensions
{
public static partial class JTNEBinaryExtensions
{
public static string ReadBCDLittle(ReadOnlySpan<byte> buf, ref int offset, int len)
{
int count = len / 2;
StringBuilder bcdSb = new StringBuilder(count);
for(int i = 0; i < count; i++)
{
bcdSb.Append(buf[offset + i].ToString("X2"));
}
offset = offset + count;
return bcdSb.ToString().TrimStart('0');
}

public static int WriteBCDLittle(byte[] bytes, int offset, string data,int len)
{
string bcdText = data == null ? "" : data;
int startIndex = 0;
int noOfZero = len - bcdText.Length;
if (noOfZero > 0)
{
bcdText = bcdText.Insert(startIndex, new string('0', noOfZero));
}
int byteIndex = 0;
int count = len / 2;
byte[] tempBytes = new byte[count];
while (startIndex < bcdText.Length && byteIndex < count)
{
tempBytes[byteIndex] = Convert.ToByte(bcdText.Substring(startIndex, 2), 16);
startIndex += 2;
byteIndex++;
}
Array.Copy(tempBytes, 0, bytes, offset, tempBytes.Length);
return count;
}
}
}

+ 120
- 0
src/JTNE.Protocol/Extensions/JTNEBinaryExtensions.cs Bestand weergeven

@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol.Extensions
{
public static partial class JTNEBinaryExtensions
{
public static int ReadInt32Little(ReadOnlySpan<byte> read, ref int offset)
{
int value = ((read[offset] << 24) | (read[offset + 1] << 16) | (read[offset + 2] << 8) | read[offset + 3]);
offset = offset + 4;
return value;
}

public static uint ReadUInt32Little(ReadOnlySpan<byte> read, ref int offset)
{
uint value =(uint) ((read[offset] << 24) | (read[offset + 1] << 16) | (read[offset + 2] << 8) | read[offset + 3]);
offset = offset + 4;
return value;
}

public static ushort ReadUInt16Little(ReadOnlySpan<byte> read, ref int offset)
{
ushort value = (ushort)((read[offset] << 8) | (read[offset + 1]));
offset = offset + 2;
return value;
}

public static byte ReadByteLittle(ReadOnlySpan<byte> read, ref int offset)
{
byte value = read[offset];
offset = offset + 1;
return value;
}

public static byte[] ReadBytesLittle(ReadOnlySpan<byte> read, ref int offset,int len)
{
ReadOnlySpan<byte> temp = read.Slice(offset, len);
offset = offset + len;
return temp.ToArray();
}

public static byte[] ReadBytesLittle(ReadOnlySpan<byte> read, ref int offset)
{
ReadOnlySpan<byte> temp = read.Slice(offset);
offset = offset + temp.Length;
return temp.ToArray();
}

public static int WriteUInt32Little(byte[] write, int offset, uint data)
{
write[offset] = (byte)(data >> 24);
write[offset + 1] = (byte)(data >> 16);
write[offset + 2] = (byte)(data >> 8);
write[offset + 3] = (byte)data;
return 4;
}

public static int WriteInt32Little(byte[] write, int offset, int data)
{
write[offset] = (byte)(data >> 24);
write[offset + 1] = (byte)(data >> 16);
write[offset + 2] = (byte)(data >> 8);
write[offset + 3] = (byte)data;
return 4;
}

public static int WriteUInt16Little(byte[] write, int offset, ushort data)
{
write[offset] = (byte)(data >> 8);
write[offset + 1] = (byte)data;
return 2;
}

public static int WriteByteLittle(byte[] write, int offset, byte data)
{
write[offset] = data;
return 1;
}

public static int WriteBytesLittle(byte[] write, int offset, byte[] data)
{
Array.Copy(data, 0, write, offset, data.Length);
return data.Length;
}

public static IEnumerable<byte> ToBytes(this string data, Encoding coding)
{
return coding.GetBytes(data);
}

public static IEnumerable<byte> ToBytes(this string data)
{
return ToBytes(data, JTNEGlobalConfigs.Instance.Encoding);
}

public static IEnumerable<byte> ToBytes(this int data, int len)
{
List<byte> bytes = new List<byte>();
int n = 1;
for (int i = 0; i < len; i++)
{
bytes.Add((byte)(data >> 8 * (len - n)));
n++;
}
return bytes;
}

/// <summary>
/// 经纬度
/// </summary>
/// <param name="latlng"></param>
/// <returns></returns>
public static double ToLatLng(this int latlng)
{
return Math.Round(latlng / Math.Pow(10, 6), 6);
}
}
}

+ 170
- 0
src/JTNE.Protocol/Extensions/JTNEDateTimeExtensions.cs Bestand weergeven

@@ -0,0 +1,170 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol.Extensions
{
public static partial class JTNEBinaryExtensions
{
/// <summary>
/// 日期限制于2000年
/// </summary>
private const int DateLimitYear = 2000;

private static readonly DateTime UTCBaseTime = new DateTime(1970, 1, 1);

/// <summary>
///
/// </summary>
/// <param name="buf"></param>
/// <param name="offset"></param>
/// <param name="format">D2: 10 X2:16</param>
/// <returns></returns>
public static DateTime ReadDateTime6Little(ReadOnlySpan<byte> buf, ref int offset,string format= "X2")
{
DateTime d = UTCBaseTime;
try
{
int year = Convert.ToInt32(buf[offset].ToString(format)) + DateLimitYear;
int month = Convert.ToInt32(buf[offset + 1].ToString(format));
int day = Convert.ToInt32(buf[offset + 2].ToString(format));
int hour = Convert.ToInt32(buf[offset + 3].ToString(format));
int minute = Convert.ToInt32(buf[offset + 4].ToString(format));
int second = Convert.ToInt32(buf[offset + 5].ToString(format));
d = new DateTime(year, month, day, hour, minute, second);
}
catch (Exception ex)
{
d = UTCBaseTime;
}
offset = offset + 6;
return d;
}

/// <summary>
///
/// </summary>
/// <param name="buf"></param>
/// <param name="offset"></param>
/// <param name="format">D2: 10 X2:16</param>
/// <returns></returns>
public static DateTime ReadDateTime4Little(ReadOnlySpan<byte> buf, ref int offset, string format = "X2")
{
DateTime d = UTCBaseTime;
try
{
d = new DateTime(
(Convert.ToInt32(buf[offset].ToString(format)) << 8) + Convert.ToByte(buf[offset + 1]),
Convert.ToInt32(buf[offset + 2].ToString(format)),
Convert.ToInt32(buf[offset + 3].ToString(format)));
}
catch (Exception)
{
d = UTCBaseTime;
}
offset = offset + 4;
return d;
}

public static DateTime ReadUTCDateTimeLittle(ReadOnlySpan<byte> buf, ref int offset)
{
ulong result = 0;
for (int i = 0; i < 8; i++)
{
ulong currentData = (ulong)buf[offset + i] << (8 * (8 - i - 1));
result += currentData;
}
offset += 8;
return UTCBaseTime.AddSeconds(result).AddHours(8);
}
/// <summary>
/// hh-mm-ss-msms
/// hh-mm-ss-fff
/// </summary>
/// <param name="buf"></param>
/// <param name="offset"></param>
/// <param name="format"></param>
/// <returns></returns>
public static DateTime ReadDateTime5Little(ReadOnlySpan<byte> buf, ref int offset, string format = "X2")
{

DateTime dateTime = new DateTime(
DateTime.Now.Year,
DateTime.Now.Month,
DateTime.Now.Day,
Convert.ToInt32(buf[offset].ToString(format)),
Convert.ToInt32(buf[offset + 1].ToString(format)),
Convert.ToInt32(buf[offset + 2].ToString(format)),
((buf[offset + 3] << 8) + buf[offset + 4]));
offset = offset + 5;
return dateTime;
}

public static int WriteUTCDateTimeLittle(byte[] bytes, int offset, DateTime date)
{
ulong totalSecends = (ulong)(date.AddHours(-8) - UTCBaseTime).TotalSeconds;
//高位在前
for (int i = 7; i >= 0; i--)
{
bytes[offset + i] = (byte)(totalSecends & 0xFF); //取低8位
totalSecends = totalSecends >> 8;
}
return 8;
}

/// <summary>
///
/// </summary>
/// <param name="memoryOwner"></param>
/// <param name="offset"></param>
/// <param name="date"></param>
/// <param name="fromBase">BCD:10 HEX:16</param>
/// <returns></returns>
public static int WriteDateTime6Little(byte[] bytes, int offset, DateTime date,int fromBase=16)
{
bytes[offset] = Convert.ToByte(date.ToString("yy"), fromBase);
bytes[offset + 1] = Convert.ToByte(date.ToString("MM"), fromBase);
bytes[offset + 2] = Convert.ToByte(date.ToString("dd"), fromBase);
bytes[offset + 3] = Convert.ToByte(date.ToString("HH"), fromBase);
bytes[offset + 4] = Convert.ToByte(date.ToString("mm"), fromBase);
bytes[offset + 5] = Convert.ToByte(date.ToString("ss"), fromBase);
return 6;
}

/// <summary>
/// YYYYMMDD
/// </summary>
/// <param name="bytes"></param>
/// <param name="offset"></param>
/// <param name="date"></param>
/// <param name="fromBase">BCD:10 HEX:16</param>
/// <returns></returns>
public static int WriteDateTime4Little(byte[] bytes, int offset, DateTime date, int fromBase = 16)
{
bytes[offset] = (byte)(date.Year>>8);
bytes[offset + 1] = (byte)(date.Year);
bytes[offset + 2] = Convert.ToByte(date.ToString("MM"), fromBase);
bytes[offset + 3] = Convert.ToByte(date.ToString("dd"), fromBase);
return 4;
}
/// <summary>
/// hh-mm-ss-msms
/// hh-mm-ss-fff
/// </summary>
/// <param name="bytes"></param>
/// <param name="offset"></param>
/// <param name="date"></param>
/// <param name="fromBase"></param>
/// <returns></returns>
public static int WriteDateTime5Little(byte[] bytes, int offset, DateTime date, int fromBase = 16)
{
bytes[offset] = Convert.ToByte(date.ToString("HH"), fromBase);
bytes[offset + 1] = Convert.ToByte(date.ToString("mm"), fromBase);
bytes[offset + 2] = Convert.ToByte(date.ToString("ss"), fromBase);
bytes[offset + 3] = (byte)(date.Millisecond >> 8);
bytes[offset + 4] = (byte)(date.Millisecond);
return 5;
}
}
}

+ 207
- 0
src/JTNE.Protocol/Extensions/JTNEEnumExtensions.cs Bestand weergeven

@@ -0,0 +1,207 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;

namespace JTNE.Protocol.Extensions
{
/// <summary>
/// 枚举扩展
/// </summary>
public static class JT808EnumExtensions
{
/// <summary>
/// 转为整型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static int ToValue<T>(this T t) where T : struct
{
return Convert.ToInt32(t);
}

/// <summary>
/// 转为 u16 整型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static ushort ToUInt16Value<T>(this T t) where T : struct
{
return Convert.ToUInt16(t);
}

/// <summary>
/// 转为Byte
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static byte ToByteValue<T>(this T t) where T : struct
{
return Convert.ToByte(t);
}

/// <summary>
/// 转为整型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static string ToValueString<T>(this T t) where T : struct
{
return Convert.ToInt32(t).ToString();
}

/// <summary>
/// 字符转枚举
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T ToEnum<T>(this string value) where T : struct
{
return (T)Enum.Parse(typeof(T), value);
}

/// <summary>
/// 获取枚举字符串
/// </summary>
/// <param name="valueEnum"></param>
public static string GetName(this Enum valueEnum)
{
return valueEnum.ToString();
}

/// <summary>
/// 获取DescriptionAttribute特性枚举值的描述
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string GetDescription(this Enum value)
{
var attribute = value.GetAttribute<DescriptionAttribute>();
return attribute == null ? value.ToString() : attribute.Description;
}

/// <summary>
/// 验证是否是枚举类型
/// </summary>
/// <typeparam name="TEnum"></typeparam>
/// <param name="enumValue"></param>
/// <returns></returns>
public static bool IsEnumValid<TEnum>(this int enumValue)
{
return Enum.IsDefined(typeof(TEnum), enumValue);
}

/// <summary>
/// 获取DescriptionAttribute特性枚举及描述
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static Dictionary<string, string> GetDescriptionAttributeDictionary(this Enum value)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
var fields = value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public);
foreach (var fi in fields)
{
DescriptionAttribute attr = Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute), false) as DescriptionAttribute;
dictionary.Add(fi.Name, attr != null ? attr.Description : "");
}
return dictionary;
}

/// <summary>
/// 获取DisplayNameAttribute特性枚举值的描述
/// </summary>
/// <param name="obj">枚举值</param>
/// <returns></returns>
public static string GetDisplayName(this Enum value)
{
var attribute = value.GetAttribute<DisplayNameAttribute>();
return attribute == null ? value.ToString() : attribute.DisplayName;
}

/// <summary>
/// 获取DisplayNameAttribute特性枚举及描述
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static Dictionary<string, string> GetDisplayNameAttributeDictionary(this Enum value)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
var fields = value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public);
foreach (var fi in fields)
{
DisplayNameAttribute attr = Attribute.GetCustomAttribute(fi, typeof(DisplayNameAttribute), false) as DisplayNameAttribute;
dictionary.Add(fi.Name, attr != null ? attr.DisplayName : "");
}
return dictionary;
}

/// <summary>
/// 获取枚举对应特性
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
public static T GetAttribute<T>(this Enum value) where T : Attribute
{
try
{
var type = value.GetType();
var memberInfo = type.GetMember(value.ToString());
var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false);
return (T)attributes[0];
}
catch
{
return default;
}
}

/// <summary>
/// 根据值获取对应枚举类型集合
/// </summary>
/// <typeparam name="T">具体枚举类型</typeparam>
/// <param name="value">枚举值</param>
/// <param name="digit">位数(8,16,32)</param>
/// <param name="ignoreUnknown">是否忽略未知数据</param>
/// <returns></returns>
public static IEnumerable<T> GetEnumTypes<T>(this int value, int digit, bool ignoreUnknown=false) where T : Enum
{
List<T> values = new List<T>();
for (int i = 0; i < digit; i++)
{
if (Math.Pow(2, i) <= value) continue;
values.Add((T)Enum.ToObject(typeof(T), (int)Math.Pow(2, i - 1)));
value = value - (int)Math.Pow(2, i - 1);
i = 0;
if (value <= 0) break;
}
if (ignoreUnknown)
{
List<T> results = new List<T>();
foreach (var item in values)
{
foreach (string itemChild in Enum.GetNames(typeof(T)))
{
if (item.ToString() == itemChild)
{
results.Add(item);
break;
}
}
}
return results;
}
else
{
return values;
}
}
}
}

+ 50
- 0
src/JTNE.Protocol/Extensions/JTNEFormatterExtensions.cs Bestand weergeven

@@ -0,0 +1,50 @@
using System;
using System.Reflection;
using JTNE.Protocol.Formatters;
using JTNE.Protocol.Enums;
using JTNE.Protocol.Attributes;
using JTNE.Protocol.Exceptions;

namespace JTNE.Protocol.Extensions
{
public static class JTNEFormatterExtensions
{
public static IJTNEFormatter<T> GetFormatter<T>()
{
IJTNEFormatter<T> formatter;
var attr = typeof(T).GetTypeInfo().GetCustomAttribute<JTNEFormatterAttribute>();
if (attr == null)
{
return default;
}
if (attr.Arguments == null)
{
formatter = (IJTNEFormatter<T>)Activator.CreateInstance(attr.FormatterType);
}
else
{
formatter = (IJTNEFormatter<T>)Activator.CreateInstance(attr.FormatterType, attr.Arguments);
}
return formatter;
}

public static object GetFormatter(Type formatterType)
{
object formatter;
var attr = formatterType.GetTypeInfo().GetCustomAttribute<JTNEFormatterAttribute>();
if (attr == null)
{
throw new JTNEException(JTNEErrorCode.GetFormatterAttributeError, formatterType.FullName);
}
if (attr.Arguments == null)
{
formatter = Activator.CreateInstance(attr.FormatterType);
}
else
{
formatter = Activator.CreateInstance(attr.FormatterType, attr.Arguments);
}
return formatter;
}
}
}

+ 81
- 0
src/JTNE.Protocol/Extensions/JTNEFormatterResolverExtensions.cs Bestand weergeven

@@ -0,0 +1,81 @@
using JTNE.Protocol.Formatters;
using System;
using System.Collections.Concurrent;
using System.Linq.Expressions;
using System.Reflection;

namespace JTNE.Protocol.Extensions
{
/// <summary>
///
/// ref http://adamsitnik.com/Span/#span-must-not-be-a-generic-type-argument
/// ref http://adamsitnik.com/Span/
/// ref:MessagePack.Formatters.DynamicObjectTypeFallbackFormatter
/// </summary>
public static class JTNEFormatterResolverExtensions
{
delegate int JTNESerializeMethod(object dynamicFormatter, ref byte[] bytes, int offset, object value);

delegate dynamic JTNEDeserializeMethod(object dynamicFormatter, ReadOnlySpan<byte> bytes, out int readSize);

static readonly ConcurrentDictionary<Type, (object Value, JTNESerializeMethod SerializeMethod)> jTNESerializers = new ConcurrentDictionary<Type, (object Value, JTNESerializeMethod SerializeMethod)>();

static readonly ConcurrentDictionary<Type, (object Value, JTNEDeserializeMethod DeserializeMethod)> jTNEDeserializes = new ConcurrentDictionary<Type, (object Value, JTNEDeserializeMethod DeserializeMethod)>();

public static int JTNEDynamicSerialize(object objFormatter, ref byte[] bytes, int offset, dynamic value)
{
Type type = value.GetType();
var ti = type.GetTypeInfo();
(object Value, JTNESerializeMethod SerializeMethod) formatterAndDelegate;
if (!jTNESerializers.TryGetValue(type, out formatterAndDelegate))
{
var t = type;
{
var formatterType = typeof(IJTNEFormatter<>).MakeGenericType(t);
var param0 = Expression.Parameter(typeof(object), "formatter");
var param1 = Expression.Parameter(typeof(byte[]).MakeByRefType(), "bytes");
var param2 = Expression.Parameter(typeof(int), "offset");
var param3 = Expression.Parameter(typeof(object), "value");
var serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(byte[]).MakeByRefType(), typeof(int), t});
var body = Expression.Call(
Expression.Convert(param0, formatterType),
serializeMethodInfo,
param1,
param2,
ti.IsValueType ? Expression.Unbox(param3, t) : Expression.Convert(param3, t));
var lambda = Expression.Lambda<JTNESerializeMethod>(body, param0, param1, param2, param3).Compile();
formatterAndDelegate = (objFormatter, lambda);
}
jTNESerializers.TryAdd(t, formatterAndDelegate);
}
return formatterAndDelegate.SerializeMethod(formatterAndDelegate.Value,ref bytes, offset, value);
}

public static dynamic JTNEDynamicDeserialize(object objFormatter,ReadOnlySpan<byte> bytes, out int readSize)
{
var type = objFormatter.GetType();
(object Value, JTNEDeserializeMethod DeserializeMethod) formatterAndDelegate;
if (!jTNEDeserializes.TryGetValue(type, out formatterAndDelegate))
{
var t = type;
{
var formatterType = typeof(IJTNEFormatter<>).MakeGenericType(t);
ParameterExpression param0 = Expression.Parameter(typeof(object), "formatter");
ParameterExpression param1 = Expression.Parameter(typeof(ReadOnlySpan<byte>), "bytes");
ParameterExpression param2 = Expression.Parameter(typeof(int).MakeByRefType(), "readSize");
var deserializeMethodInfo = type.GetRuntimeMethod("Deserialize", new[] { typeof(ReadOnlySpan<byte>), typeof(int).MakeByRefType() });
var body = Expression.Call(
Expression.Convert(param0, type),
deserializeMethodInfo,
param1,
param2
);
var lambda = Expression.Lambda<JTNEDeserializeMethod>(body, param0, param1, param2).Compile();
formatterAndDelegate = (objFormatter, lambda);
}
jTNEDeserializes.TryAdd(t, formatterAndDelegate);
}
return formatterAndDelegate.DeserializeMethod(formatterAndDelegate.Value, bytes, out readSize);
}
}
}

+ 130
- 0
src/JTNE.Protocol/Extensions/JTNEHexExtensions.cs Bestand weergeven

@@ -0,0 +1,130 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace JTNE.Protocol.Extensions
{
/// <summary>
///
/// ref:"www.codeproject.com/tips/447938/high-performance-csharp-byte-array-to-hex-string-t"
/// </summary>
public static partial class JTNEBinaryExtensions
{
public static string ToHexString(this byte[] source)
{
return HexUtil.DoHexDump(source,0, source.Length).ToUpper();
}

public static int WriteHexStringLittle(byte[] bytes, int offset, string data, int len)
{
if (data == null) data = "";
data = data.Replace(" ", "");
int startIndex = 0;
if (data.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
{
startIndex = 2;
}
int length = len;
if (length == -1)
{
length = (data.Length - startIndex) / 2;
}
int noOfZero = length * 2 + startIndex - data.Length;
if (noOfZero > 0)
{
data = data.Insert(startIndex, new string('0', noOfZero));
}
int byteIndex = 0;
while (startIndex < data.Length && byteIndex < length)
{
bytes[offset+byteIndex] = Convert.ToByte(data.Substring(startIndex, 2), 16);
startIndex += 2;
byteIndex++;
}
return length;
}

/// <summary>
/// 16进制字符串转16进制数组
/// </summary>
/// <param name="hexString"></param>
/// <param name="separator"></param>
/// <returns></returns>
public static byte[] ToHexBytes(this string hexString)
{
hexString = hexString.Replace(" ", "");
byte[] buf = new byte[hexString.Length / 2];
ReadOnlySpan<char> readOnlySpan = hexString.AsSpan();
for (int i = 0; i < hexString.Length; i++)
{
if (i % 2 == 0)
{
buf[i / 2] = Convert.ToByte(readOnlySpan.Slice(i, 2).ToString(), 16);
}
}
return buf;
}

public static string ReadHexStringLittle(ReadOnlySpan<byte> read, ref int offset, int len)
{
ReadOnlySpan<byte> source = read.Slice(offset, len);
string hex = HexUtil.DoHexDump(read, offset, len);
offset += len;
return hex;
}

/// <summary>
/// ref dotnetty
/// </summary>
static class HexUtil
{
static readonly char[] HexdumpTable = new char[256 * 4];

static HexUtil()
{
char[] digits = "0123456789abcdef".ToCharArray();
for (int i = 0; i < 256; i++)
{
HexdumpTable[i << 1] = digits[(int)((uint)i >> 4 & 0x0F)];
HexdumpTable[(i << 1) + 1] = digits[i & 0x0F];
}
}

public static string DoHexDump(ReadOnlySpan<byte> buffer, int fromIndex, int length)
{
if (length == 0)
{
return "";
}
int endIndex = fromIndex + length;
var buf = new char[length << 1];
int srcIdx = fromIndex;
int dstIdx = 0;
for (; srcIdx < endIndex; srcIdx++, dstIdx += 2)
{
Array.Copy(HexdumpTable, buffer[srcIdx] << 1,buf, dstIdx, 2);
}
return new string(buf);
}

public static string DoHexDump(byte[] array, int fromIndex, int length)
{
if (length == 0)
{
return "";
}
int endIndex = fromIndex + length;
var buf = new char[length << 1];
int srcIdx = fromIndex;
int dstIdx = 0;
for (; srcIdx < endIndex; srcIdx++, dstIdx += 2)
{
Array.Copy(HexdumpTable, (array[srcIdx] & 0xFF) << 1, buf, dstIdx, 2);
}
return new string(buf);
}
}
}
}

+ 70
- 0
src/JTNE.Protocol/Extensions/JTNEStringExtensions.cs Bestand weergeven

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Buffers.Binary;
using System.Buffers;

namespace JTNE.Protocol.Extensions
{
public static partial class JTNEBinaryExtensions
{
public static string ReadStringLittle(ReadOnlySpan<byte> read, ref int offset, int len)
{
string value = JTNEGlobalConfigs.Instance.Encoding.GetString(read.Slice(offset, len).ToArray());
offset += len;
return value.Trim('\0');
}

public static string ReadStringLittle(ReadOnlySpan<byte> read, ref int offset)
{
string value = JTNEGlobalConfigs.Instance.Encoding.GetString(read.Slice(offset).ToArray());
offset += value.Length;
return value.Trim('\0');
}

public static int WriteStringLittle(byte[] bytes, int offset, string data)
{
byte[] codeBytes = JTNEGlobalConfigs.Instance.Encoding.GetBytes(data);
Array.Copy(codeBytes, 0, bytes, offset, codeBytes.Length);
return codeBytes.Length;
}

public static int WriteStringLittle(byte[] bytes, int offset, string data, int len)
{
byte[] tempBytes = null;
if (string.IsNullOrEmpty(data))
{
tempBytes = new byte[0];
}
else
{
tempBytes = JTNEGlobalConfigs.Instance.Encoding.GetBytes(data);
}
byte[] rBytes = new byte[len];
for (int i = 0; i < tempBytes.Length; i++)
{
if (i >= len) break;
rBytes[i] = tempBytes[i];
}
Array.Copy(rBytes, 0, bytes, offset, rBytes.Length);
return rBytes.Length;
}

public static int WriteStringPadLeftLittle(byte[] bytes, int offset, string data, int len)
{
data = data.PadLeft(len, '\0');
byte[] codeBytes = JTNEGlobalConfigs.Instance.Encoding.GetBytes(data);
Array.Copy(codeBytes, 0, bytes, offset, codeBytes.Length);
return codeBytes.Length;
}

public static int WriteStringPadRightLittle(byte[] bytes, int offset, string data, int len)
{
data = data.PadRight(len, '\0');
byte[] codeBytes = JTNEGlobalConfigs.Instance.Encoding.GetBytes(data);
Array.Copy(codeBytes, 0, bytes, offset, codeBytes.Length);
return codeBytes.Length;
}
}
}

+ 45
- 0
src/JTNE.Protocol/Extensions/JTNEXorExtensions.cs Bestand weergeven

@@ -0,0 +1,45 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

namespace JTNE.Protocol.Extensions
{
public static partial class JTNEBinaryExtensions
{
/// <summary>
/// 异或
/// </summary>
/// <param name="buf"></param>
/// <param name="offset"></param>
/// <param name="len"></param>
/// <returns></returns>
public static byte ToXor(this byte[] buf, int offset, int len)
{
byte result = buf[offset];
for (int i = offset + 1; i < len; i++)
{
result = (byte)(result ^ buf[i]);
}
return result;
}

/// <summary>
/// 异或
/// </summary>
/// <param name="buf"></param>
/// <param name="offset"></param>
/// <param name="len"></param>
/// <returns></returns>
public static byte ToXor(this ReadOnlySpan<byte> buf, int offset, int len)
{
byte result = buf[offset];
for (int i = offset + 1; i < len; i++)
{
result = (byte)(result ^ buf[i]);
}
return result;
}
}
}

+ 12
- 0
src/JTNE.Protocol/Formatters/IJTNEFormatterOfT.cs Bestand weergeven

@@ -0,0 +1,12 @@
using System;
using System.Buffers;

namespace JTNE.Protocol.Formatters
{
public interface IJTNEFormatter<T>
{
T Deserialize(ReadOnlySpan<byte> bytes, out int readSize);

int Serialize(ref byte[] bytes, int offset, T value);
}
}

+ 43
- 0
src/JTNE.Protocol/Formatters/JTNEPackageFormatter.cs Bestand weergeven

@@ -0,0 +1,43 @@
using JTNE.Protocol.Enums;
using JTNE.Protocol.Exceptions;
using JTNE.Protocol.Extensions;
using System;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol.Formatters
{
public class JTNEPackageFormatter : IJTNEFormatter<JTNEPackage>
{
public JTNEPackage Deserialize(ReadOnlySpan<byte> bytes, out int readSize)
{
int offset = 0;
// 1.进行固定头校验
if (bytes[offset] != JTNEPackage.BeginFlag && bytes[offset+1] == JTNEPackage.BeginFlag)
throw new JTNEException(JTNEErrorCode.BeginFlagError, $"{bytes[offset]},{bytes[offset + 1]}");
// 2.进行BCC校验码
// 校验位 = 报文长度 - 最后一位(校验位)
byte bCCCode = bytes[bytes.Length - 1];
byte bCCCode2 = bytes.ToXor(2, bytes.Length - 1);
if (bCCCode != bCCCode2)
throw new JTNEException(JTNEErrorCode.BCCCodeError, $"request:{bCCCode}!=calculate:{bCCCode2}");
JTNEPackage jTNEPackage = new JTNEPackage();
offset += 2;
jTNEPackage.MsgId = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
jTNEPackage.AskId = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
jTNEPackage.VIN = JTNEBinaryExtensions.ReadStringLittle(bytes, ref offset,17);
jTNEPackage.EncryptMethod = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
jTNEPackage.DataUnitLength = JTNEBinaryExtensions.ReadUInt16Little(bytes, ref offset);
//todo:解码
jTNEPackage.Bodies = JTNEBinaryExtensions.ReadBytesLittle(bytes, ref offset, jTNEPackage.DataUnitLength);
jTNEPackage.BCCCode = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
readSize = offset;
return jTNEPackage;
}

public int Serialize(ref byte[] bytes, int offset, JTNEPackage value)
{
throw new NotImplementedException();
}
}
}

+ 1
- 1
src/JTNE.Protocol/JTNE.Protocol.csproj Bestand weergeven

@@ -18,7 +18,7 @@
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>D:\My Project\JTNewEnergy\src\JTNE.Protocol\JTNE.Protocol.xml</DocumentationFile>
<DocumentationFile></DocumentationFile>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">


+ 27
- 0
src/JTNE.Protocol/JTNEArrayPool.cs Bestand weergeven

@@ -0,0 +1,27 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol
{
internal static class JTNEArrayPool
{
private readonly static ArrayPool<byte> ArrayPool;

static JTNEArrayPool()
{
ArrayPool = ArrayPool<byte>.Create();
}

public static byte[] Rent(int minimumLength)
{
return ArrayPool.Rent(minimumLength);
}

public static void Return(byte[] array, bool clearArray = false)
{
ArrayPool.Return(array, clearArray);
}
}
}

+ 14
- 0
src/JTNE.Protocol/JTNEBodies.cs Bestand weergeven

@@ -0,0 +1,14 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol
{
/// <summary>
/// 数据体
/// </summary>
public abstract class JTNEBodies
{
}
}

+ 34
- 0
src/JTNE.Protocol/JTNEGlobalConfigs.cs Bestand weergeven

@@ -0,0 +1,34 @@
using System;
using System.Text;

namespace JTNE.Protocol
{
/// <summary>
///
/// </summary>
public class JTNEGlobalConfigs
{
private static readonly Lazy<JTNEGlobalConfigs> instance = new Lazy<JTNEGlobalConfigs>(() => new JTNEGlobalConfigs());

private JTNEGlobalConfigs()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Encoding = Encoding.UTF8;
}
/// <summary>
/// 字符串编码
/// </summary>
public Encoding Encoding { get; }

/// <summary>
///
/// </summary>
public static JTNEGlobalConfigs Instance
{
get
{
return instance.Value;
}
}
}
}

+ 20
- 9
src/JTNE.Protocol/JTNEPackage.cs Bestand weergeven

@@ -1,4 +1,6 @@
using System;
using JTNE.Protocol.Attributes;
using JTNE.Protocol.Formatters;
using System;
using System.IO;

namespace JTNE.Protocol
@@ -6,23 +8,31 @@ namespace JTNE.Protocol
/// <summary>
/// 新能源包
/// </summary>
[JTNEFormatter(typeof(JTNEPackageFormatter))]
public class JTNEPackage
{
/// <summary>
/// 固定为24个字节长度
/// </summary>
public const int HeaderFixedByteLength = 24;
//public const int HeaderFixedByteLength = 24;

public const byte BeginFlag = 0x23;
/// <summary>
/// 起始符1
/// </summary>
public byte BeginFlag1 { get; set; } = 0x23;
/// <summary>
/// 起始符
/// 0x23
/// 起始符2
/// </summary>
public string BeginFlag { get; set; } = "##";
public byte BeginFlag2 { get; set; } = 0x23;
/// <summary>
/// 命令标识
/// <see cref="JTNE.Protocol.Enums.JTNEMsgId"/>
/// </summary>
public byte MsgId { get; set; }
/// <summary>
/// 应答标志
/// <see cref="JTNE.Protocol.Enums.JTNEAskId"/>
/// </summary>
public byte AskId { get; set; }
/// <summary>
@@ -32,16 +42,17 @@ namespace JTNE.Protocol
/// <summary>
/// 数据加密方式
/// 0x01:数据不加密;0x02:数据经过 RSA 算法加密;0x03:数据经过 AES128 位算法加密;“0xFE”表示异常,“0xFF”表示无效
/// <see cref="JTNE.Protocol.Enums.JTNEEncryptMethod"/>
/// </summary>
public byte EncryptMethod { get; set; }
/// <summary>
/// 数据单元长度是数据单元的总字节数,有效值范围:0-65531
/// </summary>
public ushort DataUnitLength { get; set; }
///// <summary>
///// 数据体
///// </summary>
//public NEBodies Bodies { get; protected set; }
/// <summary>
/// 数据体
/// </summary>
public byte[] Bodies { get; set; }
/// <summary>
/// 采用BCC(异或检验)法,校验范围从命令单元的第一个字节开始,同后一个字节异或,直到校验码前一个字节为止,
/// 校验码占用一个字节,当数据单元存在加密时,应先加密后检验,先校验后解密


+ 49
- 0
src/JTNE.Protocol/JTNESerializer.cs Bestand weergeven

@@ -0,0 +1,49 @@
using JTNE.Protocol.Extensions;
using System;

namespace JTNE.Protocol
{
/// <summary>
///
/// </summary>
public static class JTNESerializer
{
public static byte[] Serialize(JTNEPackage jTNEPackage, int minBufferSize = 1024)
{
return Serialize<JTNEPackage>(jTNEPackage, minBufferSize);
}

public static JTNEPackage Deserialize(ReadOnlySpan<byte> bytes)
{
return Deserialize<JTNEPackage>(bytes);
}

public static byte[] Serialize<T>(T obj, int minBufferSize = 1024)
{
var formatter = JTNEFormatterExtensions.GetFormatter<T>();
byte[] buffer = JTNEArrayPool.Rent(minBufferSize);
try
{
var len = formatter.Serialize(ref buffer, 0, obj);
return buffer.AsSpan(0, len).ToArray();
}
finally
{
JTNEArrayPool.Return(buffer);
}
}

public static T Deserialize<T>(ReadOnlySpan<byte> bytes)
{
var formatter = JTNEFormatterExtensions.GetFormatter<T>();
int readSize;
return formatter.Deserialize(bytes,out readSize);
}

public static dynamic Deserialize(ReadOnlySpan<byte> bytes,Type type)
{
var formatter = JTNEFormatterExtensions.GetFormatter(type);
return JTNEFormatterResolverExtensions.JTNEDynamicDeserialize(formatter,bytes,out int readSize);
}
}
}

+ 21
- 3
src/JTNewEnergy.sln Bestand weergeven

@@ -1,9 +1,15 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28407.52
# Visual Studio 15
VisualStudioVersion = 15.0.28307.271
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JTNE.Protocol", "JTNE.Protocol\JTNE.Protocol.csproj", "{5B164F58-141D-474E-A82E-672A1C252029}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JTNE.Protocol", "JTNE.Protocol\JTNE.Protocol.csproj", "{5B164F58-141D-474E-A82E-672A1C252029}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GBNewEnergy.Protocol", "GBNewEnergy.Protocol\GBNewEnergy.Protocol.csproj", "{2E21E873-F9EA-4B98-80D6-9719DC924350}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JTNE.Protocol.Test", "JTNE.Protocol.Test\JTNE.Protocol.Test.csproj", "{30BB532E-4E49-4BB4-A1D4-61DC40F320DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GBNewEnergy.Protocol.Test", "GBNewEnergy.Protocol.Test\GBNewEnergy.Protocol.Test.csproj", "{E8A2DBC3-3384-408F-A9D0-247723EFE383}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -15,6 +21,18 @@ Global
{5B164F58-141D-474E-A82E-672A1C252029}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B164F58-141D-474E-A82E-672A1C252029}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B164F58-141D-474E-A82E-672A1C252029}.Release|Any CPU.Build.0 = Release|Any CPU
{2E21E873-F9EA-4B98-80D6-9719DC924350}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2E21E873-F9EA-4B98-80D6-9719DC924350}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2E21E873-F9EA-4B98-80D6-9719DC924350}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2E21E873-F9EA-4B98-80D6-9719DC924350}.Release|Any CPU.Build.0 = Release|Any CPU
{30BB532E-4E49-4BB4-A1D4-61DC40F320DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{30BB532E-4E49-4BB4-A1D4-61DC40F320DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{30BB532E-4E49-4BB4-A1D4-61DC40F320DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{30BB532E-4E49-4BB4-A1D4-61DC40F320DB}.Release|Any CPU.Build.0 = Release|Any CPU
{E8A2DBC3-3384-408F-A9D0-247723EFE383}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E8A2DBC3-3384-408F-A9D0-247723EFE383}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8A2DBC3-3384-408F-A9D0-247723EFE383}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8A2DBC3-3384-408F-A9D0-247723EFE383}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE


Laden…
Annuleren
Opslaan