浏览代码

1.增加创建包的扩展方法

2.增加加密接口及默认测试实现
3.增加0x02位置信息上报(待完善)
4.增加头部解包
5.增加CI配置及修改文档
tags/1.0.0
SmallChi 6 年前
父节点
当前提交
d051a9c5b2
共有 18 个文件被更改,包括 576 次插入36 次删除
  1. +15
    -0
      .travis.yml
  2. +45
    -2
      README.md
  3. +33
    -0
      src/JTNE.Protocol.Test/Extensions/JTNEPackageExtensionsTest.cs
  4. +2
    -0
      src/JTNE.Protocol.Test/JTNE.Protocol.Test.csproj
  5. +55
    -0
      src/JTNE.Protocol.Test/JTNEHeaderPackageTest.cs
  6. +66
    -0
      src/JTNE.Protocol.Test/Package/JTNE_0x01_PackageTest.cs
  7. +0
    -8
      src/JTNE.Protocol/Extensions/JTNEPackageExtensions.cs
  8. +56
    -13
      src/JTNE.Protocol/Formatters/JTNEPackageFormatter.cs
  9. +52
    -0
      src/JTNE.Protocol/Formatters/MessageBodyFormatters/JTNE_0x02_0x01_Formatter.cs
  10. +27
    -0
      src/JTNE.Protocol/Formatters/MessageBodyFormatters/JTNE_0x02_Formatter.cs
  11. +12
    -0
      src/JTNE.Protocol/Interfaces/IJTNEEncrypt.cs
  12. +47
    -0
      src/JTNE.Protocol/Internal/Default_AES128EncryptImpl.cs
  13. +32
    -1
      src/JTNE.Protocol/JTNEGlobalConfigs.cs
  14. +2
    -0
      src/JTNE.Protocol/JTNEHeaderPackage.cs
  15. +24
    -0
      src/JTNE.Protocol/MessageBody/JTNE_0x02.cs
  16. +70
    -0
      src/JTNE.Protocol/MessageBody/JTNE_0x02_0x01.cs
  17. +32
    -0
      src/JTNE.Protocol/MessageBody/JTNE_0x02_Body.cs
  18. +6
    -12
      src/JTNewEnergy.sln

+ 15
- 0
.travis.yml 查看文件

@@ -0,0 +1,15 @@
language: csharp
solution: JTNewEnergy.sln
dotnet: 2.2.101
os: linux
mono: none
dist: trusty2
script:
- dotnet restore src/JTNewEnergy.sln
- dotnet build src/JTNE.Protocol.Test/JTNE.Protocol.Test.csproj
- dotnet test src/JTNE.Protocol.Test/JTNE.Protocol.Test.csproj
after_success:
- echo successful build!
branches:
only:
- master

+ 45
- 2
README.md 查看文件

@@ -1,2 +1,45 @@
# GBNewEnergy
GBNewEnergy
# JTNewEnergy协议

[![MIT Licence](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/SmallChi/JTNewEnergy/blob/master/LICENSE)[![Build Status](https://travis-ci.org/SmallChi/JTNewEnergy.svg?branch=master)](https://travis-ci.org/SmallChi/JTNewEnergy)


## 前提条件

1. 掌握进制转换:二进制转十六进制;
2. 掌握BCD编码、Hex编码;
3. 掌握各种位移、异或;
4. 掌握常用反射;
5. 掌握快速ctrl+c、ctrl+v;
6. 掌握以上装逼技能,就可以开始搬砖了。

## JTNewEnergy数据结构解析

### 数据包[JTNEPackage]

| 起始标识1|起始标识2 | 命令标识 | 应答标志 | 车辆识别码 | 数据加密方式 |数据单元长度| 数据体|校验码|
| :---------:| :---------: | :---------: | :-------: | :-------: |:-------: |:-------: |:-------: |:-------:|
| BeginFlag1 | BeginFlag2 | MsgId | AskId | VIN |EncryptMethod|DataUnitLength|JTNEBodies|BCCCode|
| 0x23(#) | 0x23(#) | - | - | - |- |- |- |- |

#### 消息体属性[JTNEBodies]

> 根据对应消息ID:MsgId

## JTNewEnergy终端通讯协议消息对照表

| 序号 | 消息ID | 完成情况 | 测试情况 | 消息体名称 |
| :---: | :-----------: | :------: | :------: | :----------------------------: |
| 1 | 0x01 | √ | √ | 车辆登入 |
| 2 | 0x02 | x | x | 实时信息上传 |
| 3 | 0x03 | x | x | 补传信息上传 |
| 4 | 0x04 | √ | √ | 车辆登出 |
| 5 | 0x05 | √ | √ | 平台登入 |
| 6 | 0x06 | √ | √ | 平台登出 |
| 7 | 0x07 | √ | √ | 心跳 |
| 8 | 0x08 | √ | √ | 终端校时 |
| 9 | 0x09~0x7F | - | - | 上行数据系统预留 |
| 10 | 0x80 | x | x | 查询命令 |
| 11 | 0x81 | x | x | 设置命令 |
| 12 | 0x82 | x | x | 车载终端控制命令 |
| 13 | 0x83~0xBF | - | - | 下行数据系统预留 |
| 14 | 0xC0~0xFE | - | - | 平台交换自定义数据 |

+ 33
- 0
src/JTNE.Protocol.Test/Extensions/JTNEPackageExtensionsTest.cs 查看文件

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

namespace JTNE.Protocol.Test.Extensions
{
public class JTNEPackageExtensionsTest
{
[Fact]
public void Test1()
{
JTNEPackage jTNEPackage= JTNEMsgId.login.Create("123456789", JTNEAskId.CMD, new JTNE_0x01
{
PDATime = DateTime.Parse("2019-01-22 23:55:56"),
LoginNum = 1,
BatteryLength = 0x04,
SIM = "12345678998765432100",
BatteryNos = new List<string>()
{
"1234",
"4567",
"9870"
}
});
var hex = JTNESerializer.Serialize(jTNEPackage).ToHexString();
Assert.Equal("232301FE313233343536373839000000000000000001002A130116173738000131323334353637383939383736353433323130300304313233343435363739383730FD", hex);
}
}
}

+ 2
- 0
src/JTNE.Protocol.Test/JTNE.Protocol.Test.csproj 查看文件

@@ -4,6 +4,8 @@
<TargetFramework>netcoreapp2.2</TargetFramework>

<IsPackable>false</IsPackable>

<LangVersion>7.1</LangVersion>
</PropertyGroup>

<ItemGroup>


+ 55
- 0
src/JTNE.Protocol.Test/JTNEHeaderPackageTest.cs 查看文件

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

namespace JTNE.Protocol.Test
{
public class JTNEHeaderPackageTest
{
[Fact]
public void Test1()
{
JTNEHeaderPackage jTNEHeaderPackage = new JTNEHeaderPackage();
jTNEHeaderPackage.VIN = "123456789";
jTNEHeaderPackage.AskId = JTNEAskId.CMD.ToByteValue();
jTNEHeaderPackage.MsgId = JTNEMsgId.login.ToByteValue();
JTNE_0x01 jTNE_0X01 = new JTNE_0x01();
jTNE_0X01.PDATime = DateTime.Parse("2019-01-22 23:55:56");
jTNE_0X01.LoginNum = 1;
jTNE_0X01.BatteryLength = 0x04;
jTNE_0X01.SIM = "12345678998765432100";
jTNE_0X01.BatteryNos = new List<string>()
{
"1234",
"4567",
"9870"
};
jTNEHeaderPackage.Bodies = JTNESerializer.Serialize(jTNE_0X01);
var hex = JTNESerializer.Serialize(jTNEHeaderPackage).ToHexString();
Assert.Equal("232301FE313233343536373839000000000000000001002A130116173738000131323334353637383939383736353433323130300304313233343435363739383730FD", hex);
}

[Fact]
public void Test2()
{
var data= "232301FE313233343536373839000000000000000001002A130116173738000131323334353637383939383736353433323130300304313233343435363739383730FD".ToHexBytes();
JTNEHeaderPackage jTNEHeaderPackage = JTNESerializer.Deserialize<JTNEHeaderPackage>(data);
Assert.Equal(JTNEAskId.CMD.ToByteValue(), jTNEHeaderPackage.AskId);
Assert.Equal(JTNEMsgId.login.ToByteValue(), jTNEHeaderPackage.MsgId);
Assert.Equal("123456789", jTNEHeaderPackage.VIN);
JTNE_0x01 jTNE_0X01 = JTNESerializer.Deserialize<JTNE_0x01>(jTNEHeaderPackage.Bodies);
Assert.Equal(DateTime.Parse("2019-01-22 23:55:56"), jTNE_0X01.PDATime);
Assert.Equal(1, jTNE_0X01.LoginNum);
Assert.Equal(0x04, jTNE_0X01.BatteryLength);
Assert.Equal("12345678998765432100", jTNE_0X01.SIM);
Assert.Equal(3, jTNE_0X01.BatteryCount);
Assert.Equal("1234", jTNE_0X01.BatteryNos[0]);
Assert.Equal("4567", jTNE_0X01.BatteryNos[1]);
Assert.Equal("9870", jTNE_0X01.BatteryNos[2]);
}
}
}

+ 66
- 0
src/JTNE.Protocol.Test/Package/JTNE_0x01_PackageTest.cs 查看文件

@@ -5,6 +5,7 @@ using System.Text;
using Xunit;
using JTNE.Protocol.Enums;
using JTNE.Protocol.MessageBody;
using JTNE.Protocol.Internal;

namespace JTNE.Protocol.Test.Package
{
@@ -52,5 +53,70 @@ namespace JTNE.Protocol.Test.Package
Assert.Equal("4567", jTNE_0X01.BatteryNos[1]);
Assert.Equal("9870", jTNE_0X01.BatteryNos[2]);
}

[Fact]
public void Test3()
{
JTNEGlobalConfigs.Instance.SetDataBodiesEncrypt((msgId)=>
{
switch (msgId)
{
case 0x03:
return new Default_AES128EncryptImpl();
default:
return default;
}
});
JTNEPackage jTNEPackage = new JTNEPackage();
jTNEPackage.AskId = JTNEAskId.CMD.ToByteValue();
jTNEPackage.MsgId = JTNEMsgId.login.ToByteValue();
jTNEPackage.VIN = "123456789";
jTNEPackage.EncryptMethod = JTNEEncryptMethod.AES128.ToByteValue();
JTNE_0x01 jTNE_0X01 = new JTNE_0x01();
jTNE_0X01.PDATime = DateTime.Parse("2019-01-22 23:55:56");
jTNE_0X01.LoginNum = 1;
jTNE_0X01.BatteryLength = 0x04;
jTNE_0X01.SIM = "12345678998765432100";
jTNE_0X01.BatteryNos = new List<string>()
{
"1234",
"4567",
"9870"
};
jTNEPackage.Bodies = jTNE_0X01;
var hex = JTNESerializer.Serialize(jTNEPackage).ToHexString();
Assert.Equal("232301FE31323334353637383900000000000000000300307C9AAF67FB9408A75FAFC1C87F1E2AECD79DDAB8219016A5DD0911283922805EF450045EA3611C0D5CFBFD8F2581CEED30", hex);
}

[Fact]
public void Test4()
{
JTNEGlobalConfigs.Instance.SetDataBodiesEncrypt((msgId) =>
{
switch (msgId)
{
case 0x03:
return new Default_AES128EncryptImpl();
default:
return default;
}
});
var data = "232301FE31323334353637383900000000000000000300307C9AAF67FB9408A75FAFC1C87F1E2AECD79DDAB8219016A5DD0911283922805EF450045EA3611C0D5CFBFD8F2581CEED30".ToHexBytes();
JTNEPackage jTNEPackage = JTNESerializer.Deserialize(data);
Assert.Equal(JTNEAskId.CMD.ToByteValue(), jTNEPackage.AskId);
Assert.Equal(JTNEMsgId.login.ToByteValue(), jTNEPackage.MsgId);
Assert.Equal("123456789", jTNEPackage.VIN);
Assert.Equal(JTNEEncryptMethod.AES128.ToByteValue(), jTNEPackage.EncryptMethod);

JTNE_0x01 jTNE_0X01 = jTNEPackage.Bodies as JTNE_0x01;
Assert.Equal(DateTime.Parse("2019-01-22 23:55:56"), jTNE_0X01.PDATime);
Assert.Equal(1, jTNE_0X01.LoginNum);
Assert.Equal(0x04, jTNE_0X01.BatteryLength);
Assert.Equal("12345678998765432100", jTNE_0X01.SIM);
Assert.Equal(3, jTNE_0X01.BatteryCount);
Assert.Equal("1234", jTNE_0X01.BatteryNos[0]);
Assert.Equal("4567", jTNE_0X01.BatteryNos[1]);
Assert.Equal("9870", jTNE_0X01.BatteryNos[2]);
}
}
}

+ 0
- 8
src/JTNE.Protocol/Extensions/JTNEPackageExtensions.cs 查看文件

@@ -27,8 +27,6 @@ namespace JTNE.Protocol.Extensions
jTNEPackage.MsgId = msgId.ToByteValue();
jTNEPackage.Bodies = bodies;
jTNEPackage.VIN = vin;
// todo:加密处理

return jTNEPackage;
}

@@ -45,8 +43,6 @@ namespace JTNE.Protocol.Extensions
jTNEPackage.AskId = askId.ToByteValue();
jTNEPackage.MsgId = msgId.ToByteValue();
jTNEPackage.VIN = vin;
// todo:加密处理

return jTNEPackage;
}

@@ -67,8 +63,6 @@ namespace JTNE.Protocol.Extensions
jTNEPackage.MsgId = msgId;
jTNEPackage.Bodies = bodies;
jTNEPackage.VIN = vin;
// todo:加密处理

return jTNEPackage;
}

@@ -85,8 +79,6 @@ namespace JTNE.Protocol.Extensions
jTNEPackage.AskId = askId.ToByteValue();
jTNEPackage.MsgId = msgId;
jTNEPackage.VIN = vin;
// todo:加密处理

return jTNEPackage;
}
}


+ 56
- 13
src/JTNE.Protocol/Formatters/JTNEPackageFormatter.cs 查看文件

@@ -41,7 +41,7 @@ namespace JTNE.Protocol.Formatters
jTNEPackage.DataUnitLength = JTNEBinaryExtensions.ReadUInt16Little(bytes, ref offset);
// 8.数据体
// 8.1.根据数据加密方式进行解码
// todo: 8.2.解析出对应数据体
// 8.2.解析出对应数据体
if (jTNEPackage.DataUnitLength > 0)
{
Type jTNEBodiesImplType = JTNEMsgIdFactory.GetBodiesImplTypeByMsgId(jTNEPackage.MsgId);
@@ -50,10 +50,25 @@ namespace JTNE.Protocol.Formatters
int bodyReadSize = 0;
try
{
jTNEPackage.Bodies = JTNEFormatterResolverExtensions.JTNEDynamicDeserialize(
JTNEFormatterExtensions.GetFormatter(jTNEBodiesImplType),
bytes.Slice(offset, jTNEPackage.DataUnitLength),
out bodyReadSize);
if (jTNEPackage.EncryptMethod == 0x01)
{
jTNEPackage.Bodies = JTNEFormatterResolverExtensions.JTNEDynamicDeserialize(
JTNEFormatterExtensions.GetFormatter(jTNEBodiesImplType),
bytes.Slice(offset, jTNEPackage.DataUnitLength),
out bodyReadSize);
}
else
{
if (JTNEGlobalConfigs.Instance.DataBodiesEncrypt != null)
{
var data = JTNEGlobalConfigs.Instance.DataBodiesEncrypt(jTNEPackage.EncryptMethod)
.Decrypt(bytes.Slice(offset, jTNEPackage.DataUnitLength).ToArray());
jTNEPackage.Bodies = JTNEFormatterResolverExtensions.JTNEDynamicDeserialize(
JTNEFormatterExtensions.GetFormatter(jTNEBodiesImplType),
data,
out bodyReadSize);
}
}
}
catch (Exception ex)
{
@@ -82,9 +97,8 @@ namespace JTNE.Protocol.Formatters
offset += JTNEBinaryExtensions.WriteStringPadRightLittle(bytes, offset, value.VIN, 17);
// 6.数据加密方式
offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.EncryptMethod);
// 7.记录存储数据长度的当前偏移量
// 7.记录当前偏移量
int tmpOffset = offset;
offset += FixedDataBodyLength;
// 8.数据体
Type jTNEBodiesImplType = JTNEMsgIdFactory.GetBodiesImplTypeByMsgId(value.MsgId);
int messageBodyOffset = 0;
@@ -92,17 +106,46 @@ namespace JTNE.Protocol.Formatters
{
if (value.Bodies != null)
{
// 8.1 处理数据体
// todo: 8.2.判断是否有加密
// 8.1.处理数据体
// 8.2.判断是否有加密
messageBodyOffset = JTNEFormatterResolverExtensions.JTNEDynamicSerialize(
JTNEFormatterExtensions.GetFormatter(jTNEBodiesImplType),
ref bytes,
offset,
offset + FixedDataBodyLength,
value.Bodies);
// 9.通过tmpOffset反写数据单元长度
JTNEBinaryExtensions.WriteUInt16Little(bytes, tmpOffset, (ushort)(messageBodyOffset - offset));
offset = messageBodyOffset;
if (value.EncryptMethod == 0x01)
{
// 9.通过tmpOffset反写数据单元长度
JTNEBinaryExtensions.WriteUInt16Little(bytes, tmpOffset, (ushort)(messageBodyOffset - offset- FixedDataBodyLength));
offset = messageBodyOffset;
}
else
{
if (JTNEGlobalConfigs.Instance.DataBodiesEncrypt != null)
{
// 8.1.先进行分割数据体
var bodiesData = bytes.AsSpan(tmpOffset+ FixedDataBodyLength, messageBodyOffset - offset - FixedDataBodyLength).ToArray();
// 8.2.将数据体进行加密
var data = JTNEGlobalConfigs.Instance.DataBodiesEncrypt(value.EncryptMethod)
.Encrypt(bodiesData);
// 9.通过tmpOffset反写加密后数据单元长度
JTNEBinaryExtensions.WriteUInt16Little(bytes, tmpOffset, (ushort)data.Length);
// 8.3.写入加密后的数据体
offset += FixedDataBodyLength;
offset += JTNEBinaryExtensions.WriteBytesLittle(bytes, offset, data);
}
}
}
else
{
// 9.数据单元长度
offset += JTNEBinaryExtensions.WriteUInt16Little(bytes, offset, 0);
}
}
else
{
// 9.数据单元长度
offset += JTNEBinaryExtensions.WriteUInt16Little(bytes, offset, 0);
}
// 10.校验码
var bccCode = bytes.ToXor(2, offset);


+ 52
- 0
src/JTNE.Protocol/Formatters/MessageBodyFormatters/JTNE_0x02_0x01_Formatter.cs 查看文件

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

namespace JTNE.Protocol.Formatters.MessageBodyFormatters
{
public class JTNE_0x02_0x01_Formatter : IJTNEFormatter<JTNE_0x02_0x01>
{
public JTNE_0x02_0x01 Deserialize(ReadOnlySpan<byte> bytes, out int readSize)
{
int offset = 0;
JTNE_0x02_0x01 jTNE_0X02_0X01 = new JTNE_0x02_0x01();
jTNE_0X02_0X01.TypeCode = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
jTNE_0X02_0X01.CarStatus= JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
jTNE_0X02_0X01.ChargeStatus = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
jTNE_0X02_0X01.OperationMode = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
jTNE_0X02_0X01.Speed = JTNEBinaryExtensions.ReadUInt16Little(bytes, ref offset);
jTNE_0X02_0X01.TotalDis = JTNEBinaryExtensions.ReadUInt32Little(bytes, ref offset);
jTNE_0X02_0X01.TotalVoltage= JTNEBinaryExtensions.ReadUInt16Little(bytes, ref offset);
jTNE_0X02_0X01.TotalTemp = JTNEBinaryExtensions.ReadUInt16Little(bytes, ref offset);
jTNE_0X02_0X01.SOC = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
jTNE_0X02_0X01.DCStatus = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
jTNE_0X02_0X01.Stall = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
jTNE_0X02_0X01.Resistance = JTNEBinaryExtensions.ReadUInt16Little(bytes, ref offset);
jTNE_0X02_0X01.Accelerator = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
jTNE_0X02_0X01.Brakes = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset);
readSize = offset;
return jTNE_0X02_0X01;
}

public int Serialize(ref byte[] bytes, int offset, JTNE_0x02_0x01 value)
{
offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.TypeCode);
offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.CarStatus);
offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.ChargeStatus);
offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.OperationMode);
offset += JTNEBinaryExtensions.WriteUInt16Little(bytes, offset, value.Speed);
offset += JTNEBinaryExtensions.WriteUInt32Little(bytes, offset, value.TotalDis);
offset += JTNEBinaryExtensions.WriteUInt16Little(bytes, offset, value.TotalVoltage);
offset += JTNEBinaryExtensions.WriteUInt16Little(bytes, offset, value.TotalTemp);
offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.SOC);
offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.DCStatus);
offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.Stall);
offset += JTNEBinaryExtensions.WriteUInt16Little(bytes, offset, value.Resistance);
offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.Accelerator);
offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.Brakes);
return offset;
}
}
}

+ 27
- 0
src/JTNE.Protocol/Formatters/MessageBodyFormatters/JTNE_0x02_Formatter.cs 查看文件

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

namespace JTNE.Protocol.Formatters.MessageBodyFormatters
{
public class JTNE_0x02_Formatter : IJTNEFormatter<JTNE_0x02>
{
public JTNE_0x02 Deserialize(ReadOnlySpan<byte> bytes, out int readSize)
{
int offset = 0;
JTNE_0x02 jTNE_0X02 = new JTNE_0x02();
readSize = offset;
return jTNE_0X02;
}

public int Serialize(ref byte[] bytes, int offset, JTNE_0x02 value)
{
return offset;
}
}
}

+ 12
- 0
src/JTNE.Protocol/Interfaces/IJTNEEncrypt.cs 查看文件

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

namespace JTNE.Protocol.Interfaces
{
public interface IJTNEEncrypt
{
byte[] Encrypt(byte[] buffer);
byte[] Decrypt(byte[] buffer);
}
}

+ 47
- 0
src/JTNE.Protocol/Internal/Default_AES128EncryptImpl.cs 查看文件

@@ -0,0 +1,47 @@
using JTNE.Protocol.Interfaces;
using System.IO;
using System.Security.Cryptography;

namespace JTNE.Protocol.Internal
{
public class Default_AES128EncryptImpl : IJTNEEncrypt
{
public string PrivateKey => "test";

public byte[] SaltBytes => new byte[9] { 13, 34, 27, 67, 189, 255, 104, 219, 122 };

public byte[] Encrypt(byte[] buffer)
{
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(PrivateKey, SaltBytes);
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(),CryptoStreamMode.Write))
{
cs.Write(buffer, 0, buffer.Length);
cs.Close();
return ms.ToArray();
}
}
}

public byte[] Decrypt(byte[] buffer)
{
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(PrivateKey, SaltBytes);
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(),CryptoStreamMode.Write))
{
cs.Write(buffer, 0, buffer.Length);
cs.Close();
return ms.ToArray();
}
}
}
}
}

+ 32
- 1
src/JTNE.Protocol/JTNEGlobalConfigs.cs 查看文件

@@ -35,7 +35,6 @@ namespace JTNE.Protocol
return instance.Value;
}
}

/// <summary>
/// 设备流水号
/// </summary>
@@ -51,6 +50,18 @@ namespace JTNE.Protocol
/// </summary>
public bool SkipCRCCode { get; private set; }
/// <summary>
/// 消息数据体加密算法
/// RSA=>IJTNEEncryptImpl
/// AES=>IJTNEEncryptImpl
/// </summary>
public Func<byte,IJTNEEncrypt> DataBodiesEncrypt { get; private set; }
/// <summary>
/// 平台登入加密算法
/// RSA=>IJTNEEncryptImpl
/// AES=>IJTNEEncryptImpl
/// </summary>
public Func<byte, IJTNEEncrypt> PlatformLoginEncrypt { get; private set; }
/// <summary>
/// 注册自定义消息
/// </summary>
/// <typeparam name="TJTNEBodies"></typeparam>
@@ -105,5 +116,25 @@ namespace JTNE.Protocol
instance.Value.PlatformMsgSNDistributed = platformMsgSNDistributed;
return instance.Value;
}
/// <summary>
/// 设置消息数据体加密算法
/// </summary>
/// <param name="dataBodiesEncrypt"></param>
/// <returns></returns>
public JTNEGlobalConfigs SetDataBodiesEncrypt(Func<byte, IJTNEEncrypt> dataBodiesEncrypt)
{
instance.Value.DataBodiesEncrypt = dataBodiesEncrypt;
return instance.Value;
}
/// <summary>
/// 设置平台登入加密算法
/// </summary>
/// <param name="platformLoginEncrypt"></param>
/// <returns></returns>
public JTNEGlobalConfigs SetPlatformLoginEncrypt(Func<byte, IJTNEEncrypt> platformLoginEncrypt)
{
instance.Value.PlatformLoginEncrypt = platformLoginEncrypt;
return instance.Value;
}
}
}

+ 2
- 0
src/JTNE.Protocol/JTNEHeaderPackage.cs 查看文件

@@ -7,6 +7,8 @@ namespace JTNE.Protocol
{
/// <summary>
/// 新能源包
/// 只做简单的头部解析不做复杂的业务逻辑
/// 例如:不同的厂商可能加密方式不同,所以消息数据体不做加解密的判断。
/// </summary>
[JTNEFormatter(typeof(JTNEHeaderPackageFormatter))]
public class JTNEHeaderPackage


+ 24
- 0
src/JTNE.Protocol/MessageBody/JTNE_0x02.cs 查看文件

@@ -0,0 +1,24 @@
using JTNE.Protocol.Attributes;
using JTNE.Protocol.Formatters.MessageBodyFormatters;
using System;
using System.Collections.Generic;
using System.Text;

namespace JTNE.Protocol.MessageBody
{
/// <summary>
/// 实时信息上报
/// </summary>
[JTNEFormatter(typeof(JTNE_0x02_Formatter))]
public class JTNE_0x02 : JTNEBodies
{
/// <summary>
/// 公共值
/// </summary>
public Dictionary<byte, JTNE_0x02_Body> Values { get; set; }
/// <summary>
/// 自定义值
/// </summary>
public Dictionary<byte, JTNE_0x02_Body> CusotmValues { get; set; }
}
}

+ 70
- 0
src/JTNE.Protocol/MessageBody/JTNE_0x02_0x01.cs 查看文件

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Text;
using JTNE.Protocol.Attributes;
using JTNE.Protocol.Formatters.MessageBodyFormatters;

namespace JTNE.Protocol.MessageBody
{
/// <summary>
/// 整车数据
/// </summary>
[JTNEFormatter(typeof(JTNE_0x02_0x01_Formatter))]
public class JTNE_0x02_0x01 : JTNE_0x02_Body
{
public override byte TypeCode { get; set; } = 0x01;

/// <summary>
/// 车辆状态
/// </summary>
public byte CarStatus { get; set; }
/// <summary>
/// 充放电状态
/// </summary>
public byte ChargeStatus { get; set; }
/// <summary>
/// 运行模式
/// </summary>
public byte OperationMode { get; set; }
/// <summary>
/// 车速
/// </summary>
public ushort Speed { get; set; }
/// <summary>
/// 累计里程
/// </summary>
public uint TotalDis { get; set; }
/// <summary>
/// 总电压
/// </summary>
public ushort TotalVoltage { get; set; }
/// <summary>
/// 总电流
/// </summary>
public ushort TotalTemp { get; set; }
/// <summary>
/// SOC
/// </summary>
public byte SOC { get; set; }
/// <summary>
/// DC-DC 状态
/// </summary>
public byte DCStatus { get; set; }
/// <summary>
/// 档位
/// </summary>
public byte Stall { get; set; }
/// <summary>
/// 绝缘电阻
/// </summary>
public ushort Resistance { get; set; }
/// <summary>
/// 加速踏板行程值
/// </summary>
public byte Accelerator { get; set; }
/// <summary>
/// 制动踏板状态
/// </summary>
public byte Brakes { get; set; }
}
}

+ 32
- 0
src/JTNE.Protocol/MessageBody/JTNE_0x02_Body.cs 查看文件

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

namespace JTNE.Protocol.MessageBody
{
public abstract class JTNE_0x02_Body
{
public abstract byte TypeCode { get; set; }

/// <summary>
/// 整车数据
/// </summary>
public const byte JTNE_0x02_0x01 = 0x01;
/// <summary>
/// 驱动电机数据
/// </summary>
public const byte JTNE_0x02_0x02 = 0x02;

static JTNE_0x02_Body()
{
// todo:实时位置信息上报
Keys = new Dictionary<byte, Type>();
Keys.Add(JTNE_0x02_0x01, typeof(JTNE_0x02_0x01));

}

internal static Dictionary<byte, Type> Keys;


}
}

+ 6
- 12
src/JTNewEnergy.sln 查看文件

@@ -5,11 +5,9 @@ VisualStudioVersion = 15.0.28307.271
MinimumVisualStudioVersion = 10.0.40219.1
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}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JTNE.Protocol.Test", "JTNE.Protocol.Test\JTNE.Protocol.Test.csproj", "{30BB532E-4E49-4BB4-A1D4-61DC40F320DB}"
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}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GBNewEnergy.Protocol", "GBNewEnergy.Protocol\GBNewEnergy.Protocol.csproj", "{5F7A89EB-2417-420A-839D-A878A648BAE1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,18 +19,14 @@ 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
{5F7A89EB-2417-420A-839D-A878A648BAE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F7A89EB-2417-420A-839D-A878A648BAE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F7A89EB-2417-420A-839D-A878A648BAE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F7A89EB-2417-420A-839D-A878A648BAE1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE


正在加载...
取消
保存