예제 #1
0
        public Parser(MainWindow mainWindow, string dbcPath = null)
        {
            this.mainWindow = mainWindow;
            items           = new Dictionary <string, ListElement>();
            packets         = new SortedList <uint, Packet>();
            // time = SystemClock.ElapsedRealtime() + 1000;

            Packet p;

            if (dbcPath != null)
            {
                Reader reader = new DBCLib.Reader();

                reader.AllowErrors = true;

                List <object> entries = reader.Read(dbcPath);
                foreach (object entry in entries)
                {
                    if (entry is Message)
                    {
                        Message message = (Message)entry;

                        packets.Add(message.Id, p = new Packet(message.Id, this));
                        foreach (Message.Signal signal in message.Signals)
                        {
                            var valueLookup = (DBCLib.Value)
                                              entries.Where(x => x is DBCLib.Value && ((DBCLib.Value)x).ContextSignalName == signal.Name).FirstOrDefault();
                            p.AddValue(
                                signal.Name,//.Replace("_", " "),
                                signal.Unit,
                                signal.Name,
                                (bytes) => {
                                double result;
                                if (signal.StartBit + signal.BitSize > bytes.Length * 8) // check data length
                                {
                                    return(null);
                                }
                                if (signal.Multiplexer) // if this is our multiplex / page selector
                                {
                                    return
                                    (p.currentMultiplexer =                                         // store it
                                                            ExtractSignalFromBytes(bytes, signal)); // and return it
                                }
                                else if (signal.MultiplexerIdentifier != null)                      // else if this is a sub-item
                                {
                                    if (signal.MultiplexerIdentifier == p.currentMultiplexer)       // check if we're on the same page
                                    {
                                        result = ExtractSignalFromBytes(bytes, signal);             // then return it
                                    }
                                    else
                                    {
                                        return(null);
                                    }
                                }
                                else
                                {
                                    result = ExtractSignalFromBytes(bytes, signal);
                                }
                                if (valueLookup != null)
                                {
                                    string s =
                                        valueLookup.Mapping.Where(x => x.Key == result).FirstOrDefault().Value; //TryGetValue((long)result, out s);
                                    if (s != null)
                                    {
                                        return(s);
                                    }
                                }
                                return(result);
                            },
                                null
                                );
                        }
                    }
                }
            }

            packets.Add(0xFFF1, p = new Packet(0x1, this));
            p.AddValue("Byte 0", "b", "br",
                       (bytes) => (bytes[0]));
            p.AddValue("Byte 1", "b", "br",
                       (bytes) => (bytes[1]));
            p.AddValue("Byte 2", "b", "br",
                       (bytes) => (bytes[2]));
            p.AddValue("Byte 3", "b", "br",
                       (bytes) => (bytes[3]));
            p.AddValue("Byte 4", "b", "br",
                       (bytes) => (bytes[4]));
            p.AddValue("Byte 5", "b", "br",
                       (bytes) => (bytes[5]));
            p.AddValue("Byte 6", "b", "br",
                       (bytes) => (bytes[6]));
            p.AddValue("Byte 7", "b", "br",
                       (bytes) => (bytes[7]));

            packets.Add(0xFFF2, p = new Packet(0x2, this));
            p.AddValue("Word 0", "b", "br",
                       (bytes) => (bytes[0] + (bytes[1] << 8)));
            p.AddValue("Word 1", "b", "br",
                       (bytes) => (bytes[2] + (bytes[3] << 8)));
            p.AddValue("Word 2", "b", "br",
                       (bytes) => (bytes[4] + (bytes[5] << 8)));
            p.AddValue("Word 3", "b", "br",
                       (bytes) => (bytes[6] + (bytes[7] << 8)));

            packets.Add(0xFFF3, p = new Packet(0x3, this));
            p.AddValue("Int 0", "b", "br",
                       (bytes) => (bytes[0] + (bytes[1] << 8)) - (512 * (bytes[1] & 0x80)));
            p.AddValue("Int 1", "b", "br",
                       (bytes) => (bytes[2] + (bytes[3] << 8)) - (512 * (bytes[3] & 0x80)));
            p.AddValue("Int 2", "b", "br",
                       (bytes) => (bytes[4] + (bytes[5] << 8)) - (512 * (bytes[5] & 0x80)));
            p.AddValue("Int 3", "b", "br",
                       (bytes) => (bytes[6] + (bytes[7] << 8)) - (512 * (bytes[7] & 0x80)));

            packets.Add(0xFFF5, p = new Packet(0x5, this));
            p.AddValue("12 bit 0", "b", "br",
                       (bytes) => (bytes[0] + ((bytes[1] & 0x0F) << 4)));
            p.AddValue("12 bit 1", "b", "br",
                       (bytes) => (((bytes[1] & 0xF0) >> 4) + ((bytes[2]) << 8)));
            p.AddValue("12 bit 3", "b", "br",
                       (bytes) => (bytes[3] + ((bytes[4] & 0x0F) << 4)));
            p.AddValue("12 bit 4", "b", "br",
                       (bytes) => (((bytes[4] & 0xF0) >> 4) + ((bytes[5]) << 8)));
            p.AddValue("12 bit 5", "b", "br",
                       (bytes) => (bytes[6] + ((bytes[7] & 0x0F) << 4)));

            packets.Add(0xFFF6, p = new Packet(0x6, this));
            p.AddValue("Temp 1", " C", "h",
                       (bytes) => (bytes[1] - 40));
            p.AddValue("Temp 2", " C", "h",
                       (bytes) => (bytes[0] - 40));
            p.AddValue("Temp 3", " C", "h",
                       (bytes) => (bytes[2] - 40));
            p.AddValue("Temp 4", " C", "h",
                       (bytes) => (bytes[3] - 40));
            p.AddValue("Temp 5", " C", "h",
                       (bytes) => (bytes[4] - 40));
            p.AddValue("Temp 6", " C", "h",
                       (bytes) => (bytes[5] - 40));
            p.AddValue("Temp 7", " C", "h",
                       (bytes) => (bytes[6] - 40));
            p.AddValue("Temp 8", " C", "h",
                       (bytes) => (bytes[7] - 40));
        }
예제 #2
0
        public Parser(MainWindow mainWindow, ObservableCollection <DBCwAssociatedBus> dbcList = null)
        {
            this.mainWindow = mainWindow;
            items           = new Dictionary <string, ListElement>();
            packets         = new SortedList <Tuple <uint, int>, Packet>();

            Packet p;

            if (dbcList != null)
            {
                foreach (DBCwAssociatedBus dbcFile in dbcList) //parse each file
                {
                    //if (dbcFile != null)
                    //{

                    Reader reader = new DBCLib.Reader();

                    reader.AllowErrors = true;

                    List <object> entries = reader.Read(dbcFile.Path);
                    foreach (object entry in entries)
                    {
                        if (entry is Message)
                        {
                            Message message = (Message)entry;

                            try
                            {
                                packets.Add(Tuple.Create(message.Id, int.Parse(dbcFile.Bus)), p = new Packet(message.Id, dbcFile, this));

                                foreach (Message.Signal signal in message.Signals)
                                {
                                    string nameWoPrefix = Regex.Replace(signal.Name, @"^_(_|\d)*_", "");
                                    var    valueLookup  = (DBCLib.Value)
                                                          entries.Where(x => x is DBCLib.Value && ((DBCLib.Value)x).ContextSignalName == signal.Name).FirstOrDefault();

                                    List <KeyValuePair <long, string> > VT_List = new List <KeyValuePair <long, string> >();
                                    if (valueLookup != null)
                                    {
                                        VT_List = valueLookup.Mapping.ToList();
                                    }


                                    p.AddValue(
                                        dbcFile.Bus + "_" + (message.Id).ToString("X") + "_" + nameWoPrefix,
                                        message.Name,
                                        dbcFile.Bus,
                                        signal.Unit,
                                        nameWoPrefix,
                                        (bytes) =>
                                    {
                                        double result;
                                        if (signal.StartBit + signal.BitSize > bytes.Length * 8)     // check data length
                                        {
                                            return(null);
                                        }
                                        if (signal.Multiplexer)     // if this is our multiplex / page selector
                                        {
                                            return
                                            (p.currentMultiplexer =                                         // store it
                                                                    ExtractSignalFromBytes(bytes, signal)); // and return it
                                        }
                                        else if (signal.MultiplexerIdentifier != null)
                                        {                                                             // else if this is a sub-item
                                            if (signal.MultiplexerIdentifier == p.currentMultiplexer) // check if we're on the same page
                                            {
                                                result = ExtractSignalFromBytes(bytes, signal);       // then return it
                                            }
                                            else
                                            {
                                                return(null);
                                            }
                                        }
                                        else
                                        {
                                            result = ExtractSignalFromBytes(bytes, signal);
                                        }
                                        //if (valueLookup != null)
                                        //{
                                        //    string s =
                                        //    valueLookup.Mapping.Where(x => x.Key == result).FirstOrDefault().Value; //TryGetValue((long)result, out s);
                                        //    if (s != null)
                                        //        return s;
                                        //}
                                        return(result);
                                    },
                                        VT_List
                                        ,
                                        null
                                        );
                                }
                            }
                            catch { }
                        }
                    }

                    //}
                }
            }
        }
예제 #3
0
        public Parser()
        {
            items   = new Dictionary <string, ListElement>();
            packets = new SortedList <uint, Packet>();
            // time = SystemClock.ElapsedRealtime() + 1000;

            Packet p;

            if (use_DBC != KnownDBC.None)
            {
                Reader reader  = new DBCLib.Reader();
                string dbcPath = @"C:\git\CANBUS-Analyzer\DBCTools\Samples";
                switch (use_DBC)
                {
                case KnownDBC.Model3:
                    dbcPath += @"\tesla_model3.dbc";
                    break;

                case KnownDBC.ModelSAWD:
                    dbcPath += @"\tesla_models_awd.dbc";
                    break;

                case KnownDBC.ModelSRWD:
                    dbcPath += @"\tesla_models_rwd.dbc";
                    break;
                }

                List <object> entries = reader.Read(dbcPath);
                foreach (object entry in entries)
                {
                    if (entry is Message)
                    {
                        Message message = (Message)entry;

                        packets.Add(message.Id, p = new Packet(message.Id, this));
                        foreach (Message.Signal signal in message.Signals)
                        {
                            p.AddValue(
                                signal.Name.Replace("_", " "),
                                signal.Unit,
                                signal.Name,
                                (bytes) => ExtractSignalFromBytes(bytes, signal),
                                null
                                );
                        }
                    }
                }
            }

            packets.Add(0x1, p = new Packet(0x1, this));
            p.AddValue("Byte 0", "b", "br",
                       (bytes) => (bytes[0]));
            p.AddValue("Byte 1", "b", "br",
                       (bytes) => (bytes[1]));
            p.AddValue("Byte 2", "b", "br",
                       (bytes) => (bytes[2]));
            p.AddValue("Byte 3", "b", "br",
                       (bytes) => (bytes[3]));
            p.AddValue("Byte 4", "b", "br",
                       (bytes) => (bytes[4]));
            p.AddValue("Byte 5", "b", "br",
                       (bytes) => (bytes[5]));
            p.AddValue("Byte 6", "b", "br",
                       (bytes) => (bytes[6]));
            p.AddValue("Byte 7", "b", "br",
                       (bytes) => (bytes[7]));

            packets.Add(0x2, p = new Packet(0x2, this));
            p.AddValue("Word 0", "b", "br",
                       (bytes) => (bytes[0] + (bytes[1] << 8)));
            p.AddValue("Word 1", "b", "br",
                       (bytes) => (bytes[2] + (bytes[3] << 8)));
            p.AddValue("Word 2", "b", "br",
                       (bytes) => (bytes[4] + (bytes[5] << 8)));
            p.AddValue("Word 3", "b", "br",
                       (bytes) => (bytes[6] + (bytes[7] << 8)));

            packets.Add(0x3, p = new Packet(0x3, this));
            p.AddValue("Int 0", "b", "br",
                       (bytes) => (bytes[0] + (bytes[1] << 8)) - (512 * (bytes[1] & 0x80)));
            p.AddValue("Int 1", "b", "br",
                       (bytes) => (bytes[2] + (bytes[3] << 8)) - (512 * (bytes[3] & 0x80)));
            p.AddValue("Int 2", "b", "br",
                       (bytes) => (bytes[4] + (bytes[5] << 8)) - (512 * (bytes[5] & 0x80)));
            p.AddValue("Int 3", "b", "br",
                       (bytes) => (bytes[6] + (bytes[7] << 8)) - (512 * (bytes[7] & 0x80)));

            packets.Add(0x5, p = new Packet(0x5, this));
            p.AddValue("12 bit 0", "b", "br",
                       (bytes) => (bytes[0] + ((bytes[1] & 0x0F) << 4)));
            p.AddValue("12 bit 1", "b", "br",
                       (bytes) => (((bytes[1] & 0xF0) >> 4) + ((bytes[2]) << 8)));
            p.AddValue("12 bit 3", "b", "br",
                       (bytes) => (bytes[3] + ((bytes[4] & 0x0F) << 4)));
            p.AddValue("12 bit 4", "b", "br",
                       (bytes) => (((bytes[4] & 0xF0) >> 4) + ((bytes[5]) << 8)));
            p.AddValue("12 bit 5", "b", "br",
                       (bytes) => (bytes[6] + ((bytes[7] & 0x0F) << 4)));

            packets.Add(0x6, p = new Packet(0x6, this));
            p.AddValue("Temp 1", " C", "h",
                       (bytes) => (bytes[1] - 40));
            p.AddValue("Temp 2", " C", "h",
                       (bytes) => (bytes[0] - 40));
            p.AddValue("Temp 3", " C", "h",
                       (bytes) => (bytes[2] - 40));
            p.AddValue("Temp 4", " C", "h",
                       (bytes) => (bytes[3] - 40));
            p.AddValue("Temp 5", " C", "h",
                       (bytes) => (bytes[4] - 40));
            p.AddValue("Temp 6", " C", "h",
                       (bytes) => (bytes[5] - 40));
            p.AddValue("Temp 7", " C", "h",
                       (bytes) => (bytes[6] - 40));
            p.AddValue("Temp 8", " C", "h",
                       (bytes) => (bytes[7] - 40));
        }
예제 #4
0
        public Parser(MainActivity mainActivity, CustomAdapter adapter)
        {
            this.adapter      = adapter;
            this.mainActivity = mainActivity;
            items             = new ConcurrentDictionary <string, ListElement>();
            packets           = new SortedList <int, Packet>();
            time = SystemClock.ElapsedRealtime() + 1000;

            /* tags:
             *  p: performance
             *  t: trip
             *  b: battery
             *  c: temperature
             *  f: front drive unit
             *  s: startup (app will wait until these packets are found before starting 'normal' mode)
             *  i: imperial
             *  m: metric
             *  i: ignore (in trip tabs, with slow/ELM adapters)
             *  z: BMS
             *  x: Cells
             *  e: efficiency
             */

            Packet p;


#if USEDCB
            //String dbcPath = "Model3CAN.dbc";
            //string path = Directory.GetCurrentDirectory();
            //var pathFile = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads);
            ////IEnumerable<string> files2 = Directory.EnumerateFiles((String)pathFile, "*.dbc");
            //dbcPath = (string)pathFile + "/" + dbcPath;
            //inputStream = mainActivity.Assets.Open("CAN_BUS_LOG_Feb_10.txt");

            //LINES 185 to 239 are taken from CANBUS-Analyzer https://github.com/amund7/CANBUS-Analyzer
            //if (dbcPath != null)
            if (true)
            {
                Reader reader = new DBCLib.Reader();

                reader.AllowErrors = true;

                //List<object> entries = reader.Read(dbcPath);
                //AssetManager assets = this.Assets;
                List <KeyValuePair <uint, string> > errors   = null;
                List <KeyValuePair <uint, string> > warnings = null;
                using (StreamReader streamReader = new StreamReader(mainActivity.Assets.Open("Model3CAN.dbc"), Encoding.Default, false))
                {
                    List <object> entries = reader.Read(streamReader, "Model3CAN.dbc", errors, warnings);

                    //List<object> entries = reader.Read(mainActivity.Assets.Open("Model3CAN.dbc"));

                    foreach (object entry in entries)
                    {
                        if (entry is DBCLib.Message)
                        {
                            DBCLib.Message message = (DBCLib.Message)entry;

                            packets.Add((int)message.Id, p = new Packet((int)message.Id, this));
                            foreach (DBCLib.Message.Signal signal in message.Signals)
                            {
                                var valueLookup = (DBCLib.Value)
                                                  entries.Where(x => x is DBCLib.Value && ((DBCLib.Value)x).ContextSignalName == signal.Name).FirstOrDefault();
                                p.AddValue(
                                    signal.Name.Replace("_", " ").Remove(signal.Name.Length - 3), //.Replace("_", " "),
                                    signal.Unit,
                                    NameToTag(message.Id),                                        //NameToTag(signal.Name),
                                    (bytes) =>
                                {
                                    double result;
                                    if (signal.StartBit + signal.BitSize > bytes.Length * 8)   // check data length
                                    {
                                        return(0);
                                    }
                                    if (signal.Multiplexer)   // if this is our multiplex / page selector
                                    {
                                        return
                                        (p.currentMultiplexer =                                         // store it
                                                                ExtractSignalFromBytes(bytes, signal)); // and return it
                                    }
                                    else if (signal.MultiplexerIdentifier != null)
                                    {                                                             // else if this is a sub-item
                                        if (signal.MultiplexerIdentifier == p.currentMultiplexer) // check if we're on the same page
                                        {
                                            result = ExtractSignalFromBytes(bytes, signal);       // then return it
                                        }
                                        else
                                        {
                                            return(0);
                                        }
                                    }
                                    else
                                    {
                                        result = ExtractSignalFromBytes(bytes, signal);
                                    }
                                    if (valueLookup != null)
                                    {
                                        string s =
                                            valueLookup.Mapping.Where(x => x.Key == result).FirstOrDefault().Value; //TryGetValue((long)result, out s);
                                        if (s != null)
                                        {
                                            return(0);
                                        }
                                        //return s;
                                    }
                                    return(result);
                                },
                                    null
                                    );
                            }
                        }
                    }
                }
            }
#else
            /*packets.Add(0x256, p = new Packet(0x256, this));
             * p.AddValue("Metric", "bool", "s", (bytes) => {
             * metric = Convert.ToBoolean(bytes[3] & 0x80);
             * if (metric) {
             *  foreach (var packet in packets)
             *    foreach (var v in packet.Value.values)
             *      if (v.tag.Contains("i"))
             *        packet.Value.values.Remove(v);
             * } else {
             *  foreach (var packet in packets)
             *    foreach (var v in packet.Value.values)
             *      if (v.tag.Contains("m"))
             *        packet.Value.values.Remove(v);
             * }
             * return metric ? 1 : 0;
             * });*/
            packets.Add(0x528, p = new Packet(0x528, this));
            p.AddValue("UNIX Time", "Sec", "br", (bytes) => (bytes[0] << 8 * 3) + (bytes[1] << 8 * 2) + (bytes[2] << 8) + bytes[3]);

            packets.Add(0x266, p = new Packet(0x266, this));
            p.AddValue("Rr inverter 12V", "V12", "", (bytes) => bytes[0] / 10.0);
            p.AddValue("Rr power", " kW", "e", (bytes) => mechPower =
                           ((bytes[2] + ((bytes[3] & 0x7) << 8)) - (512 * (bytes[3] & 0x4))) / 2.0);
            //p.AddValue("Rr mech power HP", "HP", "pf", (bytes) => mechPower * kw_to_hp);
            p.AddValue("Rr dissipation", " kW", "", (bytes) => {
                rDissipation = bytes[1] * 125.0 / 1000.0;

                /*dissipationUpdated = true;
                 * dissipationTimeStamp = DateTime.Now.Millisecond;*/
                return(rDissipation);
            });
            p.AddValue("Rr stator current", "A", "", (bytes) => bytes[4] + ((bytes[5] & 0x7) << 8));
            p.AddValue("Rr regen power max", "KW", "b", (bytes) => (bytes[7] * 4) - 200);
            p.AddValue("Rr drive power max", "KW", "b", (bytes) => drivePowerMax =
                           (((bytes[6] & 0x3F) << 5) + ((bytes[5] & 0xF0) >> 3)) + 1);


            packets.Add(0x132, p = new Packet(0x132, this));
            p.AddValue("Battery voltage", " V", "bpr", (bytes) => volt =
                           (bytes[0] + (bytes[1] << 8)) / 100.0);
            p.AddValue("Battery current", " A", "b", (bytes) => amp =
                           1000 - ((Int16)((((bytes[3]) << 8) + bytes[2]))) / 10.0);
            p.AddValue("Battery power", " kW", "bpe", (bytes) => power = amp * volt / 1000.0);

            packets.Add(0x3B6, p = new Packet(0x3B6, this));
            p.AddValue("Odometer", "Km", "b",
                       (bytes) => odometer = (bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24)) / 1000.0);

            packets.Add(0x154, p = new Packet(0x154, this));
            p.AddValue("Rr torque measured", "Nm", "p", (bytes) => torque =
                           (bytes[5] + ((bytes[6] & 0x1F) << 8) - (512 * (bytes[6] & 0x10))) * 0.25);

            packets.Add(0x108, p = new Packet(0x108, this));
            p.AddValue("Rr motor RPM", "RPM", "",
                       (bytes) => rrpm = (bytes[5] + (bytes[6] << 8)) - (512 * (bytes[6] & 0x80)));

            packets.Add(0x376, p = new Packet(0x376, this));
            p.AddValue("Inverter temp 1", " C", "e",
                       (bytes) => (bytes[0] - 40));
            p.AddValue("Inverter temp 2", " C", "e",
                       (bytes) => (bytes[1] - 40));
            p.AddValue("Inverter temp 3", " C", "e",
                       (bytes) => (bytes[2] - 40));
            p.AddValue("Inverter temp 4", " C", "e",
                       (bytes) => (bytes[4] - 40));


            packets.Add(0x292, p = new Packet(0x292, this));
            p.AddValue("SOC UI", "%", "br", (bytes) => (bytes[0] + ((bytes[1] & 0x3) << 8)) / 10.0);
            p.AddValue("SOC Min", "%", "br", (bytes) => ((bytes[1] >> 2) + ((bytes[2] & 0xF) << 6)) / 10.0);
            p.AddValue("SOC Max", "%", "br", (bytes) => ((bytes[2] >> 4) + ((bytes[3] & 0x3F) << 4)) / 10.0);
            p.AddValue("SOC Avg", "%", "br", (bytes) => ((bytes[3] >> 6) + ((bytes[4]) << 2)) / 10.0);



            packets.Add(0x252, p = new Packet(0x252, this));
            p.AddValue("Max discharge power", "kW", "b", (bytes) => (bytes[2] + (bytes[3] << 8)) / 100.0);
            p.AddValue("Max regen power", "kW", "b", (bytes) => (bytes[0] + (bytes[1] << 8)) / 100.0);

            packets.Add(0x2A4, p = new Packet(0x2A4, this));
            p.AddValue("7 bit 0", "b", "br",
                       (bytes) => (bytes[0] & 0x7F));
            p.AddValue("5 bit 1", "b", "br",
                       (bytes) => (bytes[1] & 0xF8) >> 3);
            p.AddValue("5 bit 2", "b", "br",
                       (bytes) => ((bytes[1] & 0x7) << 2) + ((bytes[2] & 0xC0) >> 6));
            p.AddValue("7 bit 3", "b", "br",
                       (bytes) => (bytes[3] & 0x7F));
            p.AddValue("7 bit 4", "b", "br",
                       (bytes) => (bytes[4] & 0xFE) >> 1);

            /*p.AddValue("33A 12 bit 3", "b", "br",
             * (bytes) => (bytes[3] + ((bytes[4] & 0x0F) << 8)));
             * p.AddValue("33A 12 bit 4", "b", "br",
             * (bytes) => (((bytes[4] & 0xF0) >> 4) + ((bytes[5]) << 4)));
             * p.AddValue("33A 12 bit 5", "b", "br",
             * (bytes) => (bytes[6] + ((bytes[7] & 0x0F) << 8)));*/


            packets.Add(0x352, p = new Packet(0x352, this));
            p.AddValue("Nominal full pack", "kWh", "br", (bytes) => nominalFullPackEnergy = (bytes[0] + ((bytes[1] & 0x03) << 8)) * 0.1);
            p.AddValue("Nominal remaining", "kWh", "br", (bytes) => nominalRemaining      = ((bytes[1] >> 2) + ((bytes[2] & 0x0F) * 64)) * 0.1);
            p.AddValue("Expected remaining", "kWh", "r", (bytes) => ((bytes[2] >> 4) + ((bytes[3] & 0x3F) * 16)) * 0.1);
            p.AddValue("Ideal remaining", "kWh", "r", (bytes) => ((bytes[3] >> 6) + ((bytes[4] & 0xFF) * 4)) * 0.1);
            p.AddValue("To charge complete", "kWh", "", (bytes) => (bytes[5] + ((bytes[6] & 0x03) << 8)) * 0.1);
            p.AddValue("Energy buffer", "kWh", "br", (bytes) => buffer = ((bytes[6] >> 2) + ((bytes[7] & 0x03) * 64)) * 0.1);

            /*p.AddValue("SOC", "%", "br", (bytes) => soc = (nominalRemaining - buffer) / (nominalFullPackEnergy - buffer) * 100.0);
             * This one seems to be confirmed to be far off the UI displayed SOC
             */

            packets.Add(0x212, p = new Packet(0x212, this));
            p.AddValue("Battery temp", "C", "i",
                       (bytes) => ((bytes[7]) / 2.0) - 40.0);

            packets.Add(0x321, p = new Packet(0x321, this));
            p.AddValue("CoolantTempBatteryInlet", "C", "e",
                       (bytes) => ((bytes[0] + ((bytes[1] & 0x3) << 8)) * 0.125) - 40);
            p.AddValue("CoolantTempPowertrainInlet", "C", "e",
                       (bytes) => (((((bytes[2] & 0xF) << 8) + bytes[1]) >> 2) * 0.125) - 40);
            p.AddValue("Ambient Temp raw", "C", "e",
                       (bytes) => ((bytes[3] * 0.5) - 40));
            p.AddValue("Ambient Temp filtered", "C", "e",
                       (bytes) => ((bytes[5] * 0.5) - 40));



            packets.Add(0x3D2, p = new Packet(0x3D2, this));
            p.AddValue("Charge total", "kWH", "bs",
                       (bytes) => {
                chargeTotal =
                    (bytes[0] +
                     (bytes[1] << 8) +
                     (bytes[2] << 16) +
                     (bytes[3] << 24)) / 1000.0;

                /*if (mainActivity.currentTab.trip.chargeStart == 0)
                 * mainActivity.currentTab.trip.chargeStart = chargeTotal;
                 * charge = chargeTotal - mainActivity.currentTab.trip.chargeStart;*/
                return(chargeTotal);
            });

            p.AddValue("Discharge total", "kWH", "b",
                       (bytes) => {
                dischargeTotal =
                    (bytes[4] +
                     (bytes[5] << 8) +
                     (bytes[6] << 16) +
                     (bytes[7] << 24)) / 1000.0;

                /*if (mainActivity.currentTab.trip.dischargeStart == 0)
                 * mainActivity.currentTab.trip.dischargeStart = dischargeTotal;
                 * discharge = dischargeTotal - mainActivity.currentTab.trip.dischargeStart;*/
                return(dischargeTotal);
            });



            /*packets.Add(0x712, p = new Packet(0x712, this));
             * p.AddValue("Last cell block updated", "xb", "", (bytes) => {
             * int cell = 0;
             * double voltage = 0.0;
             * for (int i = 0; i < 3; i++) {
             *  voltage = (((bytes[i * 2 + 3] << 8) + bytes[i * 2 + 2]) /100.0);
             *  if (voltage > 0)
             *    UpdateItem("Cell " + (cell = ((bytes[0]) * 3 + i + 1)).ToString().PadLeft(2) + " temp"
             *      , "zVC"
             *      , "z"
             *      , bytes[0]
             *      , voltage
             *      , 0x712);
             * }
             * return bytes[0];
             * });
             */

            // these are placeholders for the filters to be generated correctly.
            p.AddValue("Cell temp min", "C", "b", null);
            p.AddValue("Cell temp avg", "C", "bcp", null);
            p.AddValue("Cell temp max", "C", "b", null);
            p.AddValue("Cell temp diff", "Cd", "bc", null);
            p.AddValue("Cell min", "Vc", "b", null);
            p.AddValue("Cell avg", "Vc", "bpzr", null);
            p.AddValue("Cell max", "Vc", "b", null);
            p.AddValue("Cell diff", "Vcd", "bz", null);
            for (int i = 1; i <= 96; i++)
            {
                p.AddValue("Cell " + i.ToString().PadLeft(2) + " voltage"
                           , "zVC"
                           , "z", null);
            }
            for (int i = 1; i <= 32; i++)
            {
                p.AddValue("Cell " + i.ToString().PadLeft(2) + " temp"
                           , "zCC"
                           , "c"
                           , null);
            }
#endif
        }