예제 #1
0
        /// <summary>
        /// Constuct a new DBC Signal.
        /// </summary>
        /// <param name="ecu">The parent ecu object.</param>
        /// <param name="message">The parent message object.</param>
        /// <param name="startbit">The bit index in the start byte at which this signal begins.</param>
        /// <param name="name">The name of this signal.</param>
        /// <param name="length">The number of bits in this signal.</param>
        /// <param name="def"></param>
        /// <param name="sna"></param>
        /// <param name="physMax">The physical maximum value of this signal.</param>
        /// <param name="physMin">The physical minimum value of this signal.</param>
        /// <param name="normMax"></param>
        /// <param name="normMin"></param>
        /// <param name="res"></param>
        /// <param name="units">The particular units of this signal's value.</param>
        /// <param name="descriptor"></param>
        /// <param name="order">The byteOrder of this signal (for multi-byte signals).</param>
        /// <param name="offset">The offset of the physical value.</param>
        /// <param name="line">The line in the dbc file, for debugging reasons.</param>
        public DBCSignal(DBCECU ecu, DBCMessage message, uint startbit, string name, uint length,
                         ulong def, ulong sna, double physMax, double physMin, ulong normMax, ulong normMin, double res, string units,
                         IntDescriptor descriptor, ByteOrder order, double offset, string line)
        {
            Order     = order;
            ECU       = ecu;
            Message   = message;
            this.line = line;
            StartBit  = startbit;

            Name      = name;
            BitLength = length;

            DefaultValue = def;
            SNA          = sna;

            // Range is specified
            PhysMax    = physMax;
            PhysMin    = physMin;
            NormMax    = normMax;
            NormMin    = normMin;
            Factor     = res;
            Value      = DefaultValue;
            Descriptor = descriptor;
            Offset     = offset;
            Units      = units;
        }
예제 #2
0
        /// <summary>
        /// Performs a deep copy of another DBCSignal.
        /// </summary>
        /// <param name="other">DBCSignal to copy.</param>
        public DBCSignal(DBCSignal other)
        {
            Order    = other.Order;
            ECU      = other.ECU;
            Message  = other.Message;
            StartBit = other.StartBit;

            Name      = other.Name;
            BitLength = other.BitLength;

            DefaultValue = other.DefaultValue;
            SNA          = other.SNA;

            // Range is specified
            PhysMax    = other.PhysicalMax;
            PhysMin    = other.PhysicalMin;
            NormMax    = other.NormMax;
            NormMin    = other.NormMin;
            Factor     = other.Factor;
            Descriptor = other.Descriptor;
            Offset     = other.Offset;
            Units      = other.Units;

            // Attributes
            foreach (var attr in other.Attributes)
            {
                Attributes.Add(attr.Key, attr.Value);
            }

            // Specific Values
            foreach (var spv in other.SpecifiedValues)
            {
                SpecifiedValues.Add(spv.Key, spv.Value);
            }

            Value = other.Value;
        }
예제 #3
0
        /// <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
        }