private void AnalysisMessage(string cacheResult) { dbcMessage = new DBCMessage(); cacheResult = cacheResult.Substring(cacheResult.IndexOf('_') + 1).TrimStart(); dbcMessage.FrameID = int.Parse(cacheResult.Substring(0, cacheResult.IndexOf(' '))); cacheResult = cacheResult.Substring(cacheResult.IndexOf(' ') + 1).TrimStart(); dbcMessage.FrameName = cacheResult.Substring(0, cacheResult.IndexOf(':')); cacheResult = cacheResult.Substring(cacheResult.IndexOf(':') + 1).TrimStart(); dbcMessage.MessageLen = int.Parse(cacheResult.Substring(0, cacheResult.IndexOf(' '))); cacheResult = cacheResult.Substring(cacheResult.IndexOf(' ') + 1).TrimStart(); dbcMessage.Sender = cacheResult.Substring(0).TrimEnd(); dbcMessageList.Add(dbcMessage); }
/// <summary> /// Parse the given DBCFile string into the librarys. /// </summary> /// <param name="s">The string to parse.</param> private void Parse(string s) { NS_Lib = new Dictionary <string, int>(); BS_Lib = new Dictionary <string, int>(); MsgSendTypes = new Dictionary <int, string>(); ecus = new Dictionary <string, DBCECU>(); messages = new Dictionary <string, DBCMessage>(); attributes = new Dictionary <string, Dictionary <string, List <string> > >(); signalGroups = new Dictionary <string, List <IDBCSignal> >(); #region --- Strings for matches --- string NS = @"NS_[\t ]*:[\r\t ]*\n(\t[\w]+[\r\t ]*\n)*"; string BU = @"BU_\s *:(\s +.*)*"; string BOline = @"BO_\s+\d+\s+\w+:\s*\d+\s+\w+"; string SGline = @"SG_\s+\w+\s*\w*\s*:\s*\d+\|\d+@[01][+-]\s+\([\d.-]*,[\d.-]*\)\s+\[.*\|.*\]\s+"".*""(\s+\w+,*\s*)+"; string BO = BOline + @"\s+(" + SGline + @")*"; string CM = @"CM_\s+\w+\s+\w+(\s+\w+)*\s+""([^""]*)*"""; string BA_DEF = @"BA_DEF_\s+.*;"; string BA_DEF_DEF = @"BA_DEF_DEF_\s+.*;"; string BA = @"BA_\s+.*;"; string VAL = @"VAL_\s+.*;"; //string SIG_GROUP = @""; #endregion // init some values string[] tmp = new string[0]; int i = -1, DataLength = 0; string ECU_Name = "", Msg_Name = "", Snl_name = "", MsgIDHex = ""; string AttributeName = "", AttributeValue = ""; try { #region --- New Symbols --- foreach (Match m in Regex.Matches(s, NS)) { // Remove NS_ and split by whitespace string[] keys = m.Value.Split('\n'); // Add to NS lib if not already there for (int ki = 1; ki < keys.Length; ki++) { if (!NS_Lib.ContainsKey(keys[ki]) && !string.IsNullOrEmpty(keys[ki])) { NS_Lib.Add(keys[ki], NS_Lib.Count); } } } #endregion #region --- ECUs --- foreach (Match m in Regex.Matches(s, BU)) { // Remove BU_ and split by whitespace tmp = Regex.Split(m.Value.Replace("BU_", ""), @"\s+"); // Add to ECU libs foreach (string str in tmp) { if (!ecus.ContainsKey(str)) { //ECU_Lib.Add(str, ECU_Lib.Count); ecus.Add(str, new DBCECU(tmp[i])); } } } #endregion #region --- Messages & Signals --- foreach (Match m in Regex.Matches(s, BO)) { // Deal with Message line: BO_ Tag | Message ID | Message Name | Message Length (bytes) | ECU string messageLine = Regex.Match(m.Value, BOline).Value; //split by whitespace tmp = Regex.Split(messageLine.Replace(":", ""), @"\s+"); // Message Attributes ECU_Name = tmp[4]; Msg_Name = tmp[2]; int midLen = tmp[1].Length > 4 ? 4 : 2; MsgIDHex = "0x" + Convert.ToInt64(tmp[1]).ToString("X3"); DataLength = Convert.ToInt32(tmp[3]); //If ECU doesn't exist, create it if (!ecus.ContainsKey(ECU_Name)) { ecus.Add(ECU_Name, new DBCECU(ECU_Name)); } // Add a new message var newMessage = new DBCMessage(midLen + DataLength, ecus[ECU_Name], MsgIDHex, Msg_Name); messages.Add(MsgIDHex, newMessage); // Add message to Messages dictionary in current ECU if (!ecus[ECU_Name].Messages.ContainsKey(MsgIDHex)) { ecus[ECU_Name].Messages[MsgIDHex] = (IDBCMessage)newMessage; } // Deal with signal line: // SG_ Tag | Signal ID | Optional Multiplexer | Start Bit + Length (bits) + Byte Direction | (Factor, Offset) | Physical Range [min,max] | Physical Units | Response ECU foreach (Match sig in Regex.Matches(m.Value, SGline)) { int multiplexer = 0; // 1 if there is a multiplexer, 0 if not if (Regex.IsMatch(sig.Value, @"\w+\s+\w+\s+\w+\s*:")) { multiplexer = 1; } tmp = Regex.Split(Regex.Replace(sig.Value, @"[\(\)\[\]\|""@,:]", " "), @"\s+"); Snl_name = tmp[1]; // Signal Attributes int startBit = Convert.ToInt32(tmp[2 + multiplexer]); int length = Convert.ToInt32(tmp[3 + multiplexer]); IntDescriptor descriptor = (tmp[4 + multiplexer][1] == '+') ? IntDescriptor.Unsigned : IntDescriptor.Signed; ByteOrder byteOrder; if (tmp[4 + multiplexer][0] == '1') { byteOrder = ByteOrder.Intel; } else { byteOrder = ByteOrder.Motorola; } double factor = Convert.ToDouble(tmp[5 + multiplexer], System.Globalization.CultureInfo.InvariantCulture); double offset = Convert.ToDouble(tmp[6 + multiplexer], System.Globalization.CultureInfo.InvariantCulture); double physMin = Convert.ToDouble(tmp[7 + multiplexer], System.Globalization.CultureInfo.InvariantCulture); double physMax = Convert.ToDouble(tmp[8 + multiplexer], System.Globalization.CultureInfo.InvariantCulture); string physUnits = tmp[9 + multiplexer]; //If physMin and physMax are both 0, then physMax is as high as the largest bitvalue physMax = (physMin == 0 && physMax == 0) ? (1 << length) : physMax; // These values should be 0 and (2 << length - 1) ulong normMin = (ulong)((physMin - offset) / factor); ulong normMax = (ulong)((physMax - offset) / factor); double res = (physMax - physMin) / (normMax - normMin); if (double.IsInfinity(res) || double.IsNaN(res)) { res = 1; } // Responce ECUs for (i = 10 + multiplexer; i < tmp.Length; i++) { if (!ecus.ContainsKey(tmp[i])) { ecus.Add(tmp[i], new DBCECU(tmp[i])); } if (!ecus[tmp[i]].RxMessages.ContainsKey(MsgIDHex)) { ecus[tmp[i]].RxMessages.Add(MsgIDHex, messages[MsgIDHex]); } } int old = startBit; // TODO: verify this is needed. // account for motorola being inverse if (byteOrder == ByteOrder.Motorola) { int newStartBit = startBit; for (i = 1; i < length; i++) { if (newStartBit % 8 == 0) { newStartBit += 15; } else { newStartBit -= 1; } } startBit = newStartBit; } // Add a new signal messages[MsgIDHex].Signals.Add(Snl_name, new DBCSignal(ecus[ECU_Name], messages[MsgIDHex], (uint)startBit, Snl_name, (uint)length, 0, 0, physMax, physMin, normMax, normMin, res, physUnits, descriptor, byteOrder, offset, sig.Value)); } } #endregion #region --- Functionality Description (comments) --- foreach (Match m in Regex.Matches(s, CM)) { /* Note: * Only existing signals can have comments parsed for them, * there is no way to generate a new signal or message from * a comment statement. */ if (Regex.IsMatch(m.Value, @"SG_ ")) { tmp = Regex.Split(m.Value, @"\s+"); MsgIDHex = "0x" + Convert.ToInt64(tmp[2]).ToString("X3"); if (messages.ContainsKey(MsgIDHex)) { Snl_name = tmp[3]; if (messages[MsgIDHex].Signals.ContainsKey(Snl_name)) { string function = ""; for (i = 4; i < tmp.Length; i++) { function += (tmp[i] + " ").Replace("\"", ""); } ((DBCSignal)messages[MsgIDHex].Signals[Snl_name]).Function = function; } } } } #endregion #region --- Base Attribute Definitions --- foreach (Match m in Regex.Matches(s, BA_DEF)) { string attributeName; string attributeType; string tag = "Definition"; List <string> attributeSettings = new List <string>(); tmp = Regex.Split(m.Value, @"\s+"); if (Regex.IsMatch(m.Value, @"BU_")) { attributeName = tmp[2].Replace("\"", ""); attributeType = tmp[3]; for (int j = 4; j < tmp.Length; j++) { attributeSettings.Add(tmp[j].Replace(";", "")); } } else if (Regex.IsMatch(m.Value, @"BO_")) { attributeName = tmp[2].Replace("\"", ""); attributeType = tmp[3]; for (int j = 4; j < tmp.Length; j++) { attributeSettings.Add(tmp[j].Replace(";", "")); } // OG code... fix in future switch (attributeName) { case "GenMsgSendType": //Message send type(cyclic, spontaneous, etc..) string[] values = tmp[tmp.Length - 1].Split(','); for (int k = 0; k < values.Length; k++) { //k is Enum int value, values[k] is string it represents MsgSendTypes.Add(k, values[k].Replace("\"", "").Replace(";", "")); } break; case "GenMsgCycleTime": break; case "GenMsgStartDelayTime": break; case "GenMsgDelayTime": break; default: break; } } else if (Regex.IsMatch(m.Value, @"SG_ ")) { attributeName = tmp[2].Replace("\"", ""); attributeType = tmp[3]; for (int j = 4; j < tmp.Length; j++) { attributeSettings.Add(tmp[j].Replace(";", "")); } } else { // extract info attributeName = tmp[1].Replace("\"", ""); attributeType = tmp[2]; for (int j = 3; j < tmp.Length; j++) { attributeSettings.Add(tmp[j].Replace(";", "")); } // add to dict if (attributes.ContainsKey(attributeName)) { if (attributes[attributeName].ContainsKey(tag)) { attributes[attributeName][tag].Concat(attributeSettings); } else { attributes[attributeName].Add(tag, attributeSettings); } } else { attributes.Add(attributeName, new Dictionary <string, List <string> >()); attributes[attributeName].Add(tag, attributeSettings); } } } #endregion #region --- Base Attribute Definitions Defaults --- foreach (Match m in Regex.Matches(s, BA_DEF_DEF)) { string tag = "Default"; tmp = Regex.Split(Regex.Replace(m.Value, @"[;""]", ""), @"\s+"); if (tmp.Length < 3) { continue; } string attr = tmp[1]; string val = tmp[2]; if (attributes.ContainsKey(attr)) { if (attributes[attr].ContainsKey(tag)) { attributes[attr][tag].Add(val); } else { attributes[attr].Add(tag, new List <string>() { val }); } } else { attributes.Add(attr, new Dictionary <string, List <string> >() { { tag, new List <string>() { val } } }); } } #endregion #region --- Base Attributes --- foreach (Match m in Regex.Matches(s, BA)) { string tag = "Setting"; string attributeName; string attributeValue; List <string> attributeSettings = new List <string>(); //modified regex check to ignore spaces inside of quotes tmp = Regex.Split(m.Value, "(?<=^[^\"]*(?:\"[^\"]*\"[^\"]*)*) (?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"); if (Regex.IsMatch(tmp[2], @"BO_")) { MsgIDHex = "0x" + Convert.ToInt64(tmp[3]).ToString("X3"); //Handle attributes if MsgID exists if (messages.ContainsKey(MsgIDHex)) { attributeName = tmp[1].Replace("\"", ""); attributeValue = tmp[4].Replace(";", ""); switch (attributeName) { case "GenMsgCycleTime": //Cycle time messages[MsgIDHex].CycleTime = uint.Parse(attributeValue); break; case "GenMsgSendType": //Launch type(cyclic, spontaneous, etc.) messages[MsgIDHex].LaunchType = MsgSendTypes[int.Parse(attributeValue)]; break; case "GenMsgDelayTime": messages[MsgIDHex].DelayTime = int.Parse(attributeValue); break; } } } else if (Regex.IsMatch(m.Value, @"SG_ ")) { MsgIDHex = "0x" + Convert.ToInt64(tmp[3]).ToString("X3"); Snl_name = tmp[4]; AttributeName = tmp[1].Replace("\"", ""); AttributeValue = ""; for (i = 5; i < tmp.Length; i++) { AttributeValue += (tmp[i] + " ").Replace("\"", "").Replace(";", ""); } // Check and add if (messages.ContainsKey(MsgIDHex) && messages[MsgIDHex].Signals.ContainsKey(Snl_name)) { ((DBCSignal)messages[MsgIDHex].Signals[Snl_name]).Attributes.Add(AttributeName, AttributeValue); } } else { if (attributes.ContainsKey(tmp[1])) { if (attributes[tmp[1]].ContainsKey(tag)) { attributes[tmp[1]][tag].Add(tmp[2]); } else { attributes[tmp[1]].Add(tag, new List <string>() { tmp[2] }); } } else { attributes.Add(tmp[1], new Dictionary <string, List <string> >() { { tag, new List <string>() { tmp[2] } } }); } //break; } } #endregion #region --- Specified Signal Values --- foreach (Match m in Regex.Matches(s, VAL)) { tmp = Regex.Split(m.Value, @"\s+"); MsgIDHex = "0x" + Convert.ToInt64(tmp[1]).ToString("X3"); Snl_name = tmp[2]; foreach (Match val in Regex.Matches(m.Value, "\\d+\\s+\".*?\"")) { tmp = Regex.Split(val.Value.Replace("\"", " "), @"\s+"); long key = long.Parse(tmp[0]); tmp[0] = ""; string specifiedValue = string.Join <string>(" ", tmp).Trim(); // Check and add if (messages.ContainsKey(MsgIDHex) && messages[MsgIDHex].Signals.ContainsKey(Snl_name)) { if (messages[MsgIDHex].Signals[Snl_name].SpecifiedValues.ContainsKey(key)) { ((DBCSignal)messages[MsgIDHex].Signals[Snl_name]).SpecifiedValues[key] = specifiedValue; } else { ((DBCSignal)messages[MsgIDHex].Signals[Snl_name]).SpecifiedValues.Add(key, specifiedValue); } } } } #endregion } catch (DatabaseLoadingException) { throw; } /*catch (Exception e) * { * throw new DatabaseLoadingException("Parsing of the given DBC file failed.", e, this, ""); * }*/ #region old code section for Signal Groups /* * OG SIG_GROUP_ parsing below * #region SIG_GROUP_ (Signal Groupings) * case "SIG_GROUP_": * * // Remove the tag and use space as a delimiter * tmp = AcquireValues(str); * * MsgIDHex = "0x" + Convert.ToInt64(tmp[1]).ToString("X3"); * ECU_name = MsgID_to_ECUname[MsgIDHex]; * string Group_name = tmp[2]; * * for (int itm = 5; itm < tmp.Length; itm++) * { * Snl_name = tmp[itm]; * if (SignalGroups.ContainsKey(Group_name)) * SignalGroups[Group_name].Add(Messages[MsgIDHex].Signals[Snl_name]); * else * SignalGroups.Add(Group_name, new List<IDBCSignal>() { Messages[MsgIDHex].Signals[Snl_name] }); * } * * break; #endregion * } */ #endregion }
/// <summary> /// 加载DBC Signal /// </summary> /// <param name="content">当前行内容</param> /// <param name="message">当前消息</param> private void LoadSignal(String content, ref DBCMessage message) { var match = Regex.Match(content.Trim(), ConstDefine.SignalRegexPattern); if (!match.Success) { //TODO 应该添加Log return; } UInt16 tempUInt16; Double tempDouble; DBCSignal signal = new DBCSignal(); ByteOrder byteOrder; if (!Enum.TryParse <ByteOrder>(match.Groups[9].Value, out byteOrder)) { byteOrder = ByteOrder.None; } signal.ByteOrder = byteOrder; if (!Double.TryParse(match.Groups[11].Value, out tempDouble)) { tempDouble = 0D; } signal.Factor = tempDouble; if (!Double.TryParse(match.Groups[17].Value, out tempDouble)) { tempDouble = 0D; } signal.Maximum = tempDouble; signal.Message = message; signal.MessageID = message.MessageID; signal.MessageName = message.MessageName; if (!Double.TryParse(match.Groups[15].Value, out tempDouble)) { tempDouble = 0D; } signal.Minimum = tempDouble; if (String.IsNullOrEmpty(match.Groups[2].Value)) { signal.MultiplexerIndicator = MultiplexerIndicator.NormalSignal; } else if (match.Groups[6].Value == "M ") { signal.MultiplexerIndicator = MultiplexerIndicator.MultiplexedSignal; } else if (match.Groups[4].Value == "m") { signal.MultiplexerIndicator = MultiplexerIndicator.MultiplexedSignals; if (!UInt16.TryParse(match.Groups[5].Value, out tempUInt16)) { tempUInt16 = 0; } signal.MultiplexerSwitchValue = tempUInt16; } else { signal.MultiplexerIndicator = MultiplexerIndicator.NormalSignal; } if (!Double.TryParse(match.Groups[13].Value, out tempDouble)) { tempDouble = 0D; } signal.Offset = tempDouble; signal.SignalName = match.Groups[1].Value; if (!UInt16.TryParse(match.Groups[8].Value, out tempUInt16)) { tempUInt16 = 0; } signal.SignalSize = tempUInt16; if (!UInt16.TryParse(match.Groups[7].Value, out tempUInt16)) { tempUInt16 = 0; } signal.StartPosition = tempUInt16; signal.Unit = match.Groups[19].Value; if (match.Groups[10].Value == "+") { signal.ValueType = Infrastructure.ValueType.Unsigned; } else if (match.Groups[10].Value == "-") { signal.ValueType = Infrastructure.ValueType.Signed; } else { signal.ValueType = Infrastructure.ValueType.Unsigned; } message.Signals.Add(signal); }
/// <summary> /// 加载DBC Message /// </summary> /// <param name="content">当前行内容</param> /// <param name="reader">当前文件流</param> private void LoadMessage(String content, StreamReader reader) { DBCMessage message = new DBCMessage(); //起始索引 Int32 preIndex = 0; //终止索引 //获取分隔符位置,开始解析 preIndex = content.IndexOf(" ", preIndex) + 1; var index = content.IndexOf(" ", preIndex); #region 获取Message ID String id = content.Substring(preIndex, index - preIndex); UInt32 messageId; if (!UInt32.TryParse(id, out messageId)) { messageId = 0; } messageId &= 0x9FFFFFFF; message.MessageID = messageId; #endregion #region 判断消息帧类型 UInt32 frameType = messageId >> 31; if (frameType == 0) { message.FrameType = FrameType.StandardFrame; } else { message.FrameType = FrameType.ExtendFrame; } #endregion #region 获取消息Name preIndex = index + 1; index = content.IndexOf(":", preIndex); message.MessageName = content.Substring(preIndex, index - preIndex); #endregion #region 获取消息 Size (dlc) preIndex = index + 2; index = content.IndexOf(" ", preIndex); UInt32 size; if (!UInt32.TryParse(content.Substring(preIndex, index - preIndex), out size)) { size = 0; } message.MessageSize = size; #endregion #region 获取发送节点Name preIndex = index + 1; index = content.IndexOf("", preIndex); message.Transmitter = content.Substring(index, content.Length - index); #endregion #region 将消息添加至节点 foreach (var node in this.DBCChannel.Nodes) { if (message.Transmitter == node.NodeName) { var nextContent = reader.ReadLine(); while (nextContent != null) { if (String.IsNullOrEmpty(nextContent)) { break; } LoadSignal(nextContent, ref message); nextContent = reader.ReadLine(); } node.Messages.Add(message); break; } } #endregion }