using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Text.RegularExpressions;
namespace AutomativeLightDetection.Structs
{
public class VbfSetting
{
public string description { get; set; }
public string sw_part_number { get; set; }
public string sw_version { get; set; }
public string sw_part_type { get; set; }
public string data_format_identifier { get; set; }
public string ecu_address { get; set; }
public string verification_block_root_hash { get; set; }
public string verification_block_start { get; set; }
public string verification_block_length { get; set; }
public byte[] sw_signature_dev { get; set; }
public string file_checksum { get; set; }
public byte[] callAddress { get; set; }
public byte[] eraseAddr { get; set; }
public int Index { get; set; }
public List<DataSegment> SegmentList { get; set; }
public static VbfSetting ReadVbfFile(string vbfFileName)
{
try
{
VbfSetting myVbfSetting = new VbfSetting();
//read all data from vbf file
FileStream fs = new FileStream(vbfFileName, FileMode.Open);
byte[] allDataArray = new byte[fs.Length];
int resInt = fs.Read(allDataArray, 0, (int)(fs.Length));
//BinaryReader br = new BinaryReader(fs);
fs.Close();
//find srart index of data
string tempHeaderStr = Encoding.ASCII.GetString(allDataArray.Skip(0).Take(8192).ToArray());
int sCount = 0;
int leftIndex = 0;
int rightIndex = 0;
int dataStartIndex = 0;
for (int i = 0; i < 32; i++)
{
leftIndex = tempHeaderStr.IndexOf("{");
rightIndex = tempHeaderStr.IndexOf("}");
if (leftIndex >= 0 || rightIndex >= 0)
{
if (leftIndex < rightIndex)
{
sCount++;
tempHeaderStr = tempHeaderStr.Substring(leftIndex + 1);
dataStartIndex += leftIndex + 1;
}
else
{
sCount--;
tempHeaderStr = tempHeaderStr.Substring(rightIndex + 1);
dataStartIndex += rightIndex + 1;
}
}
if (sCount <= 0)
{
break;
}
}
//get header String
byte[] headerArray = allDataArray.Skip(0).Take(dataStartIndex).ToArray();
string headerString = Encoding.ASCII.GetString(headerArray);
myVbfSetting.description = ReadParameter("description", headerString);
myVbfSetting.sw_part_number = ReadParameter("sw_part_number", headerString);
myVbfSetting.sw_version = ReadParameter("sw_version", headerString);
myVbfSetting.sw_part_type = ReadParameter("sw_part_type ", headerString);
if(ReadParameter("sw_part_type ", headerString)=="SBL")
{
myVbfSetting.Index = 0;
}
if (ReadParameter("sw_part_type ", headerString) == "EXE")
{
myVbfSetting.Index = 2;
}
if (ReadParameter("sw_part_type ", headerString) == "DATA")
{
myVbfSetting.Index = 1;
}
myVbfSetting.data_format_identifier = ReadParameter("data_format_identifier", headerString);
myVbfSetting.ecu_address = ReadParameter("ecu_address", headerString);
myVbfSetting.verification_block_root_hash = ReadParameter("verification_block_root_hash", headerString);
myVbfSetting.verification_block_start = ReadParameter("verification_block_start", headerString);
myVbfSetting.verification_block_length = ReadParameter("verification_block_length", headerString);
myVbfSetting.sw_signature_dev = stringToHex(ReadParameter("sw_signature_dev", headerString));
myVbfSetting.file_checksum = ReadParameter("file_checksum", headerString);
myVbfSetting.callAddress = stringToHex(ReadParameter("call", headerString));
myVbfSetting.eraseAddr = stringToHex(ReadEraseParameter(headerString));
byte[] dataArray = allDataArray.Skip(dataStartIndex).ToArray();
MemoryStream stream = new MemoryStream(dataArray);
StreamReader reader = new StreamReader(stream);
List<DataSegment> dataSegmentList = new List<DataSegment>();
int segIndex = 0;
while (segIndex < dataArray.Length)
{
DataSegment dataSegment = new DataSegment();
dataSegment.Length = Convert.ToInt32(dataArray[segIndex + 4].ToString("X2") + dataArray[segIndex + 5].ToString("X2") + dataArray[segIndex + 6].ToString("X2") + dataArray[segIndex + 7].ToString("X2"), 16);
dataSegment.StartAddr = dataArray.Skip(segIndex).Take(4).ToArray();
byte[] data= dataArray.Skip(segIndex + 8).Take(dataSegment.Length).ToArray();
dataSegment.SegData= splitPacket(data);
dataSegmentList.Add(dataSegment);
//len + addrlen + crc
segIndex += dataSegment.Length + 8 + 2;
}
myVbfSetting.SegmentList = dataSegmentList;
return myVbfSetting;
}
catch (Exception)
{
throw;
}
}
public static byte[] stringToHex(string value)
{
value=value.Replace("0x", "");
value = value.Replace(",", "");
return Split(value,2);
}
static byte[] Split(string str, int count)
{
var list = new List<byte>();
int length = (int)Math.Ceiling((double)str.Length / count);
for (int i = 0; i < length; i++)
{
int start = count * i;
if (str.Length <= start)
{
break;
}
if (str.Length < start + count)
{
list.Add(Convert.ToByte(str.Substring(start),16));
}
else
{
list.Add(Convert.ToByte(str.Substring(start, count),16));
}
}
return list.ToArray();
}
public static string SubstringSingle(string source, string startStr, string endStr)
{
Regex rg = new Regex("(?<=(" + startStr + "))[.\\s\\S]*?(?=(" + endStr + "))", RegexOptions.Multiline | RegexOptions.Singleline);
return rg.Match(source).Value;
}
private static string ReadEraseParameter(string sourceString)
{
string valueStr = SubstringSingle(sourceString, "erase = {{", "}\\};");
valueStr = valueStr.Trim();
return valueStr;
}
private static string ReadParameter(string parameterName, string sourceString)
{
//Regex regex = new Regex(parameterName + " = (.+);", RegexOptions.Multiline | RegexOptions.Singleline);
//Match match = regex.Match(sourceString);
//string value = match.Groups[1].Value;
string value = SubstringSingle(sourceString, parameterName + " = ", ";");
//remove """"
Regex regex = new Regex("\"*\"");
if (regex.IsMatch(value))
{
value = value.Replace("\"", "");
}
//remove "0x"
regex = new Regex("0x*");
if (regex.IsMatch(value))
{
value = value.Replace("0x", "");
}
return value;
}
/// <summary>
/// 分割数据包
/// </summary>
/// <param name="hexchar">要分割的数据</param>
/// <returns></returns>
static List<MessagePacket> splitPacket(byte[] hexchar)
{
int total = (hexchar.Length / 2048) + 1;//总共的包数
int remainder = hexchar.Length % 2048;//发送最后一个包剩余的数据量
int count = 1;
int k = 1;
List<MessagePacket> packets = new List<MessagePacket>();
for (int index = 1; index <= total; index++)
{
MessagePacket messagePacket = new MessagePacket();
messagePacket.Index = index;
messagePacket.sequence = k;
if (k == 255)
{
k = 0;
}
else
{
k++;
}
int dataIndex = (index - 1) * 2048;//数据所在位置
int TrueLength = (index) * 2048;//传输数据字节位置
byte[] data;
if (index != total)
{
byte[] chunk = new byte[2048];
Buffer.BlockCopy(hexchar, (index - 1) * 2048, chunk, 0, 2048);
messagePacket.DataList = chunk;
}
else
{
byte[] chunk = new byte[remainder];
Buffer.BlockCopy(hexchar, (index - 1) * 2048, chunk, 0, remainder);
messagePacket.DataList = chunk;
}
packets.Add(messagePacket);
}
return packets;
}
}
public class MessagePacket
{
public int sequence { get; set; }//数据包所持有的序号
public int Index { get; set; }//第几个包
public int total { get; set; }//总共数据包的数量
public byte[] DataList { get; set; } //分包的数据
public MessagePacket()
{
}
public MessagePacket(int sequence, int total, int Index, byte[] dataList, int chunkLength)
{
this.sequence = sequence;
this.total = total;
DataList = dataList;
}
}
public class DataSegment
{
public int Length { get; set; }
public byte[] StartAddr { get; set; }
public List<MessagePacket> SegData { get; set; }
}
}