我的【XF.net】常用工具库
【XF.net】库是我这些年工作中,将常见的功能进行一个简单封装的工具库,里面涵盖:通用函数功能如(对象深拷贝,加密/解密/正反序列化/压缩解压等),及相关工控行业的功能如(DBC文件读取,通讯报文解析,BMS程序刷写,数据库访问等)。如果在您日常中代码开发中涉及到这些当面,那就可以尝试使用这个库,这样有些细节您就不需要关心了,下面我就根据这两个方面简单的举例说明使用方法:
首先在Visual Studio的NuGet管理器中安装【XF.net】库:
1.通讯协议报文:
1.1.DBC文件读取:
原始DBC内容: BO_ 123 VehicleStatus: 8 ECU1 SG_ Speed : 0|16@0+ (0.1,0) [0|255] "km/h" ECU1 SG_ EngineRPM : 16|16@0+ (1,0) [0|65535] "RPM" ECU1 SG_ FuelLevel : 32|8@0+ (0.5,0) [0|100] "%" ECU1 CM_ BO_ 123 "车辆状态消息" CM_ SG_ Speed "车速信号" CM_ SG_ EngineRPM "发动机转速信号" CM_ SG_ FuelLevel "燃油液位信号" BO_ 456 DiagnosticData: 8 ECU2 SG_ ErrorCode : 0|32@0+ (1,0) [0|4294967295] "无符号" ECU2 CM_ BO_ 456 "诊断数据消息" CM_ SG_ ErrorCode "错误代码信号"
读取DBC文件:
private static void ReadDbcFile() { System.Text.Encoding encoding = System.Text.Encoding.UTF8; var mesgList = new ReadDbcFile().OpenFileReadMess(@"D:\测试.dbc", string.Empty,ref encoding,true ,out var strDbc); //读取测试.dbc文件,只需要1行代码搞定 //为了方便查看,将读取到的DCB文件中的信号配置使用JSON打印出来: Console.WriteLine(XF.net.Base.Json.JsonExtensions.ToJson(mesgList, false, true)); }
运行效果:
1.2.DBC报文解析:
/// <summary> /// 解析DBC报文参数 /// </summary> private static void DbcParamAnalysis() { var testMsg = new MessageModel() { ID = 123, Data = [1, 2, 3, 4, 5, 6, 7, 8] }; //测试模拟报文 var dicParamData = new ConcurrentDictionary<string, double>(); if (DbcSingleAnalysis.AnalysisDbcSignal(new ReadDbcFile().OpenFileReadMess(@"D:\测试.dbc", string.Empty, ref _encoding, true, out _).First().SignalParamList, testMsg, dicParamData)) { ///解析成功,打印解析后参数值: foreach (var ps in dicParamData) { Console.WriteLine($"参数名称:{ps.Key},数值={ps.Value}"); } } }
运行效果:
1.3.自定义报文参数解析(可以支持跨bit解析):
/// <summary> /// 自定义报文参数解析 /// </summary> public static void MsgParamAnalysis() { var bys = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; Console.WriteLine($"无符号解析报文,从第9bit开始,长度为12bit,系数为1,偏移量为0,小端,解析后值={ProtocolAnalysis.AnalysisBit(bys, 9, 12, 1, 0, false)}"); Console.WriteLine($"有符号解析报文,从第9bit开始,长度为12bit,系数为1,偏移量为0,大端,解析后值={ProtocolAnalysis.AnalysisSignedBit(bys, 9, 12, 1, 0, true)}"); Console.WriteLine($"Float解析报文,从第9bit开始,长度为12bit,系数为1,偏移量为0,小端,解析后值={ProtocolAnalysis.AnalysisSignedBit(bys, 9, 32, 1, 0, false)}"); Console.WriteLine($"Double解析报文,从第9bit开始,长度为12bit,系数为1,偏移量为0,小端,解析后值={ProtocolAnalysis.AnalysisSignedBit(bys, 0, 64, 1, 0, false)}"); }
运行效果:
1.4.更新报文内容:
/// <summary> /// 更新报文数据 /// </summary> private static void UpdateMsgData() { var bys = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; Console.WriteLine($"更新【前】报文:{BitConverter.ToString(bys)}"); ProtocolAnalysis.IntConvertBit(bys, 6, 10, 66, true); Console.WriteLine($"从第6bit开始更新,长度为10bit,更新值是66,更新【后】报文:{BitConverter.ToString(bys)}"); }
运行后效果:
1.5.BMS/ECU基于UDS程序刷写:
namespace XF.net.BmsFlash { /// <summary> /// 读取BMS刷写ASC格式里面的HEX数据 /// </summary> public class ReadHexAscFile { /// <summary> /// 读取(入口) /// </summary> /// <param name="fileAddress">文件地址</param> /// <param name="securityUnLock">安全访问</param> /// <param name="excuteDownloadApplicationSoftware">文件传输过程</param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <returns></returns> public virtual List<FlashMsgModel> Read(string fileAddress,Action<FlashMsgModel> securityUnLock,Action<FlashMsgModel> excuteDownloadApplicationSoftware, uint funCanID= 0x7DF, uint physicalCanID= 0x7C0, uint bmsResp= 0x7C8) /// <summary> /// 1.进入扩展回话 /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void EnterExtendedSession(string[] fDataList ,List<FlashMsgModel> list, uint funCanID,uint physicalCanID,uint bmsResp,float cp) /// <summary> /// 2.停止DTC检查 /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void StopDTC(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) /// <summary> /// 3.禁用非诊断通信 /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void DisableCommunication(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) /// <summary> /// 4.进入编程回话 /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void EnterProgrammingSession(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) /// <summary> /// 7.写指纹 /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void WriteFingerprint(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) /// <summary> /// 8.写程序日期 /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void WriteProgrammingDate(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) /// <summary> /// 9.擦除应用软件内存 /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void EraseApplicationSoftwareMemory(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) /// <summary> /// 11.烧录BMS程序(34,36,37) /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="excuteDownloadApplicationSoftware"></param> /// <param name="cp"></param> public virtual void DownloadApplicationSoftware(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp, Action<FlashMsgModel> excuteDownloadApplicationSoftware,float cp) /// <summary> /// 12.检查程序完整性 /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void CheckAPPDataIntegrity(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) /// <summary> /// 13.检查程序数据依赖 /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void CheckAPPDataDependencies(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) /// <summary> /// 14.重启ECU /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void ECUReset(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) /// <summary> /// 17.开始复位DTC检查 /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void StartSettingDTCs(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) /// <summary> /// 18.进入默认回话 /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void EnterDefaultSession(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) /// <summary> /// 19.清除DTC /// </summary> /// <param name="fDataList"></param> /// <param name="list"></param> /// <param name="funCanID"></param> /// <param name="physicalCanID"></param> /// <param name="bmsResp"></param> /// <param name="cp"></param> public virtual void ClearDTC(string[] fDataList, List<FlashMsgModel> list, uint funCanID, uint physicalCanID, uint bmsResp,float cp) } }
2.常用功能:
2.1.JSON正反序列化:
namespace XF.net.Base.Json { /// <summary> /// System.Text.Json工具 /// </summary> public static class SysTextJsonExtensions { /// <summary> /// 序列化 /// </summary> /// <param name="obj"></param> /// <param name="indented"></param> /// <returns></returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="Exception"></exception> public static string ToSysTextJson(this object obj, bool indented = false) /// <summary> /// 将json字符串序列化成对象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="json"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public static T FromSysTextJson<T>(this string json) /// <summary> /// System.Text.Json序列化成字节数组 /// </summary> /// <param name="obj"></param> /// <param name="indented"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public static byte[] ToSysTextJsonBys(this object obj, bool indented = false) /// <summary> /// 序列化成对象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="jsonUtf8Bytes"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public static T FromSysTextJson<T>(this byte[] jsonUtf8Bytes) }
2.2.XML正反序列化:
namespace XF.net.Base.xml { /// <summary> /// XML序列化与反序列化的扩展方法类 /// </summary> public static class XmlExtensions { /// <summary> /// 将对象执行XML序列化(使用UTF-8编码) /// </summary> /// <param name="obj">要序列化的对象</param> /// <returns>XML序列化的结果</returns> public static string ToXml(this object obj) /// <summary> /// 从XML字符串中反序列化对象(使用UTF-8编码) /// </summary> /// <typeparam name="T">反序列化的结果类型</typeparam> /// <param name="xml">XML字符串</param> /// <returns>反序列化的结果</returns> public static T FromXml<T>(this string xml) /// <summary> /// 从XML字符串中反序列化对象(使用UTF-8编码) /// </summary> /// <param name="s"></param> /// <param name="type">反序列化的结果类型</param> /// <returns></returns> public static object FromXml(this string s, Type type) } }
2.3.Zip:
namespace XF.net.Base.Common { /// <summary> /// 提供一些操作ZIP文件的工具方法 /// </summary> public static class ZipHelper { /// <summary> /// 将ZIP文件解压缩到指定的目录 /// </summary> /// <param name="zipPath">需要解压缩的ZIP文件</param> /// <param name="extractPath">要释放的目录</param> public static void ExtractFiles(string zipPath, string extractPath) /// <summary> /// 读取ZIP到内存字典中 /// </summary> /// <param name="zipPath">需要读取的ZIP文件</param> /// <returns></returns> public static List<Tuple<string, byte[]>> Read(string zipPath) /// <summary> /// 将指定的目录打包成ZIP文件 /// </summary> /// <param name="path"></param> /// <param name="zipPath"></param> public static void Compress(string path, string zipPath)
/// <summary> /// 根据指定的包内文件名及对应的文件内容打包成ZIP文件 /// </summary> /// <param name="files"></param> /// <param name="zipPath"></param> public static void Compress(List<Tuple<string, byte[]>> files, string zipPath) /// <summary> /// 根据指定的包内文件名及对应的文件清单打包成ZIP文件 /// </summary> /// <param name="files">要打包的文件清单,可以为string(指示文件路径)或者byte[](文件内容)</param> /// <param name="zipPath">zip文件的保存路径</param> public static void Compress(List<Tuple<string, object>> files, string zipPath) } }
2.4.结构体转换工具:
namespace XF.net.Base.Common { /// <summary> /// 结构体转换工具 /// </summary> public static class StructHelper { /// <summary> /// 结构体转byte数组 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="structObj"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public static byte[] StructToBytes<T>(T structObj) /// <summary> /// byte数组转结构体 /// </summary> /// <param name="bytes">byte数组</param> /// <returns>转换后的结构体</returns> public static T BytesToStuct<T>(byte[] bytes) /// <summary> /// byte数组转结构体 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="bytes"></param> /// <param name="size"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public static T BytesToStuct<T>(byte[] bytes, int size) }
2.5.数据值转换:
namespace XF.net.Base.Common { public class DataCal { /// <summary> /// 长整形数据转成字节数组 /// 如果是浮点数建议将浮点数乘以系数后转成长整形数据 /// </summary> /// <param name="value"></param> /// <param name="length"></param> /// <returns></returns> public static byte[] LongTobyte(long value, int length) /// <summary> /// 将整数转成对应的数组,就是先将值分解成16进制字串,然后将每个16进制字串存储; /// </summary> /// <param name="value"></param> /// <param name="length"></param> /// <returns></returns> public static byte[] IntTobyte(int value, int length) /// <summary> /// 将字节数组转成整数,也就是拼接字节数组个值,然后将值转成整形; /// </summary> /// <param name="pvData">要转换的字节数组</param> /// <returns>转成整数</returns> public static int ByteToInt(byte[] pvData) /// <summary> /// 将字节数组值转换成整形值; /// </summary> /// <param name="pvData">字节数组</param> /// <param name="pvIndex">字节数组其实索引</param> /// <param name="pvLength">长度</param> /// <returns>字节数组值转换成整形值</returns> public static int ByteToInt(byte[] pvData, int pvIndex, int pvLength) /// <summary> /// 将字节数组值转换成整形值; /// </summary> /// <param name="pvData">字节数组</param> /// <param name="pvIndex">字节数组其实索引</param> /// <param name="pvLength">长度</param> /// <returns>字节数组值转换成整形值</returns> public static int ByteToInt(List<byte> pvData, int pvIndex, int pvLength) /// <summary> /// 字节数组转成长整型 /// </summary> /// <param name="pvData"></param> /// <param name="pvIndex"></param> /// <param name="pvLength"></param> /// <returns></returns> public static long ByteToLong(byte[] pvData, int pvIndex, int pvLength) /// <summary> /// 将字节数组转成长整形 /// </summary> /// <param name="pvData"></param> /// <returns></returns> public static long ByteToLong(byte[] pvData) } }
2.6.CRC16校验和:
namespace XF.net.Base.Common { public static class CheckSumFun { /// <summary> /// 求取crc16校验和 /// </summary> /// <param name="buffer">要校验和的报文</param> /// <param name="index">开始索引</param> /// <param name="len">计算报文数据长度</param> /// <param name="crcHi">计算出校验和的高位字节</param> /// <param name="crcLo">计算出校验和的低位字节</param> public static void CalculateCrc16(IEnumerable<byte> buffer, int index, int len, out byte crcHi, out byte crcLo) } }
2.7.数组池租借:
namespace XF.net.Base.Common { public static class ArrayPoolHelp { /// <summary> /// 租借8字节数组 /// </summary> /// <returns></returns> public static byte[] RentBysSize8() /// <summary> /// 租借64字节数组 /// </summary> /// <returns></returns> public static byte[] RentBysSize64() /// <summary> /// 租借72字节数组 /// </summary> /// <returns></returns> public static byte[] RentBysSize72()
/// <summary> /// 租借字节数组 /// </summary> /// <param name="len"></param> /// <returns></returns> public static byte[] RentBys8(byte len) /// <summary> /// 归还 /// </summary> /// <param name="bys"></param> public static void TryReturn(this byte[] bys) } }
2.8.tcp客户端:
namespace XF.net.Ports { /// <summary> /// tcp客户端 /// </summary> public class XfTcpClient : System.IDisposable { /// <summary> /// 是否连接 /// </summary> public bool IsConnected /// <summary> /// 连接tcp服务器 /// </summary> /// <param name="ip"></param> /// <param name="port"></param> /// <param name="recv"></param> /// <param name="error"></param> /// <returns></returns> public bool Connect(string ip, int port, Action<string, byte[]> recv, Action<Exception, string> error) /// <summary> /// 发送报文 /// </summary> /// <param name="bytes"></param> public void Send(byte[] bytes) /// <summary> /// 释放 /// </summary> public void Dispose() } }
2.9.SqlServer帮助类:
namespace XF.net.DbContext { /// <summary> /// SqlServer帮助类 /// </summary> public class SqlServerHelper : IDbHelper { /// <summary> /// 开始事务 /// </summary> /// <param name="isolation"></param> /// <returns></returns> public override DbTransaction BeginTransaction(IsolationLevel isolation) /// <summary> /// 连接数据库 /// </summary> public override void Connection() /// <summary> /// 连接数据库 /// </summary> /// <param name="connection"></param> /// <exception cref="Exception"></exception> public override void Connection(string connection) /// <summary> /// 创建查询命令对象 /// </summary> /// <returns></returns> public override DbCommand CreateCommand()
/// <summary> /// 释放对象 /// </summary> public override void Dispose() /// <summary> /// 执行查询 /// </summary> /// <param name="sql"></param> /// <param name="isDispose"></param> /// <param name="cmdTimeout"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public override bool ExecuteNonQuery(string sql, bool isDispose = true, int cmdTimeout = CommandTimeout) /// <summary> /// 执行查询,返回首行首列 /// </summary> /// <param name="sql"></param> /// <param name="cmdTimeout"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public override object ExecuteScalar(string sql, int cmdTimeout = CommandTimeout) /// <summary> /// 查询数据 /// </summary> /// <param name="sql"></param> /// <param name="tabName"></param> /// <param name="isDispose"></param> /// <param name="cmdTimeout"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public override DataTable ToDataTable(string sql, string tabName = "xf-tab", bool isDispose = true,int cmdTimeout= CommandTimeout) } }
2.10.sqlite帮助类:
namespace XF.net.DbContext { /// <summary> /// sqlite工具 /// </summary> public class SqliteHelper : IDbHelper { /// <summary> /// 构造函数 /// </summary> public SqliteHelper() /// <summary> /// 创建数据库文件 /// </summary> /// <param name="databaseFileName"></param> public static void CreateFile(string databaseFileName) /// <summary> /// 连接 /// </summary> /// <exception cref="NotImplementedException"></exception> public override void Connection() /// <summary> /// 连接sqlite /// </summary> /// <param name="databaseFileName"></param> /// <exception cref="Exception"></exception> public override void Connection(string databaseFileName) /// <summary> /// 执行SQL语句 /// </summary> /// <param name="sql"></param> /// <param name="isDispose"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public override bool ExecuteNonQuery(/*string databaseFileName, */string sql, bool isDispose = true, int cmdTimeout = CommandTimeout)
/// <summary> /// 事务中执行SQL /// </summary> /// <param name="databaseFileName"></param> /// <param name="sql"></param> /// <param name="tran"></param> /// <param name="isDispose"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public bool ExecuteNonQuery(string databaseFileName, string sql, SqliteTransaction tran, bool isDispose = true, int cmdTimeout = CommandTimeout) /// <summary> /// 执行SQL返回datatable /// </summary> /// <param name="sql"></param> /// <param name="tabName"></param> /// <param name="isDispose"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public override DataTable ToDataTable(/*string databaseFileName, */string sql, string tabName = "xf-tab", bool isDispose = true, int cmdTimeout = CommandTimeout) /// <summary> /// 创建Sql,命令对象 /// </summary> /// <returns></returns> public override DbCommand CreateCommand() /// <summary> /// 创建事务 /// </summary> /// <param name="isolation"></param> /// <returns></returns> public override DbTransaction BeginTransaction(IsolationLevel isolation) /// <summary> /// 执行SQL返回datatable,支持在值类型字段数据中可为空 /// </summary> /// <param name="databaseFileName"></param> /// <param name="sql"></param> /// <param name="tabName"></param> /// <param name="isDispose"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public DataTable ToDataTableNullable(string databaseFileName, string sql, string tabName = "xf-tab", bool isDispose = true, int cmdTimeout = CommandTimeout) /// <summary> /// 执行SQL返回datatable,支持在值类型字段数据中可为空 /// </summary> /// <param name="connection"></param> /// <param name="sql"></param> /// <param name="tabName"></param> /// <param name="isDispose"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public DataTable ToDataTableNullable(SqliteConnection connection, string sql, string tabName = "xf-tab", bool isDispose = true, int cmdTimeout = CommandTimeout) /// <summary> /// 返回结果集中的第一行第一列,忽略其他行或列 /// </summary> /// <param name="sql"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public override object ExecuteScalar(string sql, int cmdTimeout = CommandTimeout) /// <summary> /// 释放资源 /// </summary> public override void Dispose() /// <summary> /// 清除文件占用 /// </summary> public static void ClearAllPools() } }