/* CanZE Take a closer look at your ZE car Copyright (C) 2015 - The CanZE Team http://canze.fisch.lu This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * This class manages all know fields. * Actually only the simple fields from the free CAN stream are handled. */ package lu.fisch.canze.actors; import android.os.Environment; import lu.fisch.canze.activities.MainActivity; import lu.fisch.canze.interfaces.VirtualFieldAction; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; /** * * @author robertfisch test */ public class Fields { private static final int FIELD_ID = 0; // to be stated in HEX, no leading 0x private static final int FIELD_FROM = 1; // decimal private static final int FIELD_TO = 2; // decimal private static final int FIELD_RESOLUTION = 3; // double private static final int FIELD_OFFSET = 4; // double private static final int FIELD_DECIMALS = 5; // decimal private static final int FIELD_UNIT = 6; private static final int FIELD_REQUEST_ID = 7; // to be stated in HEX, no leading 0x private static final int FIELD_RESPONSE_ID = 8; // to be stated in HEX, no leading 0x private static final int FIELD_OPTIONS = 9; // to be stated in HEX, no leading 0x private static final int FIELD_NAME = 10; // can be displayed/saved. Now only used for Diag ISO-TP private static final int FIELD_LIST = 11; // same public static final int TOAST_NONE = 0; public static final int TOAST_DEVICE = 1; public static final int TOAST_ALL = 2; private final ArrayList<Field> fields = new ArrayList<>(); private final HashMap<String, Field> fieldsBySid = new HashMap<>(); private static Fields instance = null; private double runningUsage = 0; //private int car = CAR_ANY; private Fields() { // the will be called by load(), and only after we know (or have changed) the car //fillStatic(); //addVirtualFields(); } public static boolean initialised() { return (instance==null); } public static Fields getInstance() { if(instance==null) instance=new Fields(); return instance; } private void addVirtualFields() { addVirtualFieldUsage(); addVirtualFieldUsageLpf(); addVirtualFieldFrictionTorque(); addVirtualFieldFrictionPower(); addVirtualFieldDcPower(); addVirtualFieldHeaterSetpoint(); } private void addVirtualFieldUsage() { final String SID_EVC_TractionBatteryVoltage = "7ec.623203.24"; // unit = V final String SID_EVC_TractionBatteryCurrent = "7ec.623204.24"; // unit = A final String SID_RealSpeed = "5d7.0"; // unit = km/h // It would be easier use SID_Consumption = "1fd.48" (dash kWh) instead of V*A, but dash is not precise and includes other consumers addVirtualFieldCommon ("6100", "kWh/100km", SID_EVC_TractionBatteryVoltage+";"+SID_EVC_TractionBatteryCurrent+";"+SID_RealSpeed, new VirtualFieldAction() { @Override public double updateValue(HashMap<String, Field> dependantFields) { // get voltage double dcVolt = dependantFields.get(SID_EVC_TractionBatteryVoltage).getValue(); // get current double dcPwr = dcVolt * dependantFields.get(SID_EVC_TractionBatteryCurrent).getValue() / 1000.0; // get real speed double realSpeed = dependantFields.get(SID_RealSpeed).getValue(); if (realSpeed >= 5) return -(Math.round(1000.0 * dcPwr / realSpeed) / 10.0); else return 0; } }); } private void addVirtualFieldFrictionTorque() { final String SID_DriverBrakeWheel_Torque_Request = "130.44"; //UBP braking wheel torque the driver wants final String SID_ElecBrakeWheelsTorqueApplied = "1f8.28"; //10ms addVirtualFieldCommon ("6101", "Nm", SID_DriverBrakeWheel_Torque_Request+";"+SID_ElecBrakeWheelsTorqueApplied, new VirtualFieldAction() { @Override public double updateValue(HashMap<String,Field> dependantFields) { return dependantFields.get(SID_DriverBrakeWheel_Torque_Request).getValue() - dependantFields.get(SID_ElecBrakeWheelsTorqueApplied).getValue(); } }); } private void addVirtualFieldFrictionPower() { final String SID_DriverBrakeWheel_Torque_Request = "130.44"; //UBP braking wheel torque the driver wants final String SID_ElecBrakeWheelsTorqueApplied = "1f8.28"; //10ms final String SID_ElecEngineRPM = "1f8.40"; //10ms addVirtualFieldCommon ("6102", "kW", SID_DriverBrakeWheel_Torque_Request+";"+SID_ElecBrakeWheelsTorqueApplied+";"+SID_ElecEngineRPM, new VirtualFieldAction() { @Override public double updateValue(HashMap<String,Field> dependantFields) { return (dependantFields.get(SID_DriverBrakeWheel_Torque_Request).getValue() - dependantFields.get(SID_ElecBrakeWheelsTorqueApplied).getValue()) * dependantFields.get(SID_ElecEngineRPM).getValue() / MainActivity.reduction; } }); } private void addVirtualFieldDcPower() { final String SID_TractionBatteryVoltage = "7ec.623203.24"; final String SID_TractionBatteryCurrent = "7ec.623204.24"; addVirtualFieldCommon ("6103", "kW", SID_TractionBatteryVoltage+";"+SID_TractionBatteryCurrent, new VirtualFieldAction() { @Override public double updateValue(HashMap<String,Field> dependantFields) { return dependantFields.get(SID_TractionBatteryVoltage).getValue() * dependantFields.get(SID_TractionBatteryCurrent).getValue() / 1000; } }); } private void addVirtualFieldUsageLpf() { final String SID_VirtualUsage = "800.6100.24"; addVirtualFieldCommon ("6104", "kWh/100km", SID_VirtualUsage, new VirtualFieldAction() { @Override public double updateValue(HashMap<String, Field> dependantFields) { double value = dependantFields.get(SID_VirtualUsage).getValue(); if (value != 0) { runningUsage = runningUsage * 0.95 + value * 0.05; } return runningUsage; } }); } private void addVirtualFieldHeaterSetpoint() { final String SID_VirtualUsage = "699.8"; addVirtualFieldCommon ("6105", "°C", SID_VirtualUsage, new VirtualFieldAction() { @Override public double updateValue(HashMap<String, Field> dependantFields) { double value = dependantFields.get(SID_VirtualUsage).getValue(); if (value == 0) { return Double.NaN; } else if (value == 4) { return -10.0; } else if (value == 5) { return 40.0; } return value; } }); } private void addVirtualFieldCommon (String virtualId, String unit, String dependantIds, VirtualFieldAction virtualFieldAction) { // create a list of field this new virtual field will depend on HashMap<String, Field> dependantFields = new HashMap<>(); boolean allOk = true; for (String idStr: dependantIds.split(";")){ Field field = getBySID(idStr); if (field != null) { dependantFields.put(idStr, field); } else { allOk = false; } } if (allOk) { VirtualField virtualField = new VirtualField(virtualId, dependantFields, unit, virtualFieldAction); // add it to the list of fields add(virtualField); } } private void fillStatic() { String fieldDef = // ID (hex), startBit, endBit, resolution, offset (aplied BEFORE resolution multiplication), decimals, unit, requestID (hex string), responseID (hex string), // options (hex, see MainActivity for definitions), optional name, optional list "" // 2016-01-27 + "130,44,55,-3,4094,0,Nm,,,ff\n" // DriverBrakeWheelTq_Req + "186,16,27,0.5,800,1,Nm,,,ff\n" // MeanEffectiveTorque + "186,40,49,0.125,0,1,%,,,ff\n" // Throttle + "18a,27,38,0.5,800,1,Nm,,,ff\n" // Coasting Torque + "1f8,16,27,1,4096,0,Nm,,,ff\n" // TotalPotentialResistiveWheelsTorque + "1f8,28,39,-1,4096,0,Nm,,,ff\n" // ElecBrakeWheelsTorqueApplied + "1f8,40,50,10,0,0,Rpm,,,ff\n" // ElecEngineRPM + "1fd,0,7,0.390625,0,1,%,,,ff\n" // 12V Battery Current? + "1fd,48,55,1,80,0,kW,,,ff\n" // Consumption + "427,40,47,0.3,0,0,kW,,,e2\n" // Available Charging Power + "427,49,57,0.1,0,1,kWh,,,e2\n" // Available Energy + "42a,30,39,0.1,400,1,°C,,,ff\n" // Evaporator Temp Measure + "42a,48,50,1,0,0,,,,e2\n" // ClimLoopMode + "42e,0,12,0.02,0,2,%,,,e3\n" // State of Charge + "42e,20,24,5,0,0,%,,,e2\n" // Engine Fan Speed + "42e,38,43,1,0,1,A,,,e3\n" // Charging Pilot Current + "42e,44,50,1,40,0,°C,,,e3\n" // HV Battery Temp + "42e,56,63,0.3,0,1,kW,,,ff\n" // Charging Power + "430,24,33,0.5,30,1,°C,,,e2\n" // Comp Temperature Discharge + "430,38,39,1,0,0,,,,e2\n" // HV Battery Cooling State + "430,40,49,0.1,400,1,°C,,,e2\n" // HV Battery Evaporator Temp + "432,36,37,1,0,0,,,,e2\n" // HV Bat Conditionning Mode + "4f8,4,5,1,0,0,,,,ff\n" // Parking brake + "534,32,40,1,40,0,°C,,,e5\n" // Temp out + "5d7,0,15,0.01,0,2,km/h,,,ff\n" // Speed + "5da,0,7,1,40,0,ºC,,,e7\n" // Water temperature + "654,2,2,1,0,0,,,,ff\n" // Charging Plug Connected + "654,25,31,1,0,0,,,,ff\n" // State of Charge + "654,32,41,1,0,0,min,,,ff\n" // Time to Full + "654,42,51,1,0,0,km,,,ff\n" // Available Distance + "656,48,55,1,40,0,°C,,,e2\n" // External Temp + "658,33,39,1,0,0,%,,,ff\n" // Battery Health + "65b,41,43,1,0,0,,,,ff\n" // Charging Status Display + "673,0,0,1,0,0,,,,ff\n" // Speed pressure misadaptation + "673,2,4,1,0,0,,,,ff\n" // Rear right wheel state + "673,5,7,1,0,0,,,,ff\n" // Rear left wheel state + "673,8,10,1,0,0,,,,ff\n" // Front right wheel state + "673,11,13,1,0,0,,,,ff\n" // Front left wheel state + "673,16,23,13.725,0,0,mbar,,,ff\n" // Rear right wheel pressure + "673,24,31,13.725,0,0,mbar,,,ff\n" // Rear left wheel pressure + "673,32,39,13.725,0,0,mbar,,,ff\n" // Front right wheel pressure + "673,40,47,13.725,0,0,mbar,,,ff\n" // Front left wheel pressure + "699,8,15,0.5,0,0,°C,,,e2\n" // Temperature + "760,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "760,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "760,128,143,1,0,0,,2180,6180,ff\n" // Soft + "760,144,159,1,0,0,,2180,6180,ff\n" // Version + "762,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "762,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "762,128,143,1,0,0,,2180,6180,ff\n" // Soft + "762,144,159,1,0,0,,2180,6180,ff\n" // Version + "763,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "763,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "763,128,143,1,0,0,,2180,6180,ff\n" // Soft + "763,144,159,1,0,0,,2180,6180,ff\n" // Version + "764,26,35,0.1,400,0,°C,2121,6121,e2\n" // IH_InCarTemp + "764,8,15,0.4,100,0,°C,2121,6121,5\n" // IH_InCarTemp + "764,36,43,1,0,0,%,2121,6121,e2\n" // IH_RHumidity + "764,16,23,1,0,0,%,2121,6121,5\n" // IH_RHumidity + "764,86,87,1,0,0,,2143,6143,ff\n" // Eco mode requested + "764,110,117,1,40,0,%,2143,6143,ff\n" // IH_ExternalTemp //+ "764,88,92,100,0,0,W,2143,6143,ff\n" // Compressor power + "764,134,142,.1,0,0,bar,2143,6143,ff\n" // IH_ACHighPressureSensor + "764,107,116,10,0,0,rpm,2144,6144,ff\n" // Compressor RPM + "764,40,41,1,0,0,,2167,6167,ff\n" // IH_ExternalTemp + "764,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "764,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "764,128,143,1,0,0,,2180,6180,ff\n" // Soft + "764,144,159,1,0,0,,2180,6180,ff\n" // Version + "765,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "765,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "765,128,143,1,0,0,,2180,6180,ff\n" // Soft + "765,144,159,1,0,0,,2180,6180,ff\n" // Version + "76d,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "76d,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "76d,128,143,1,0,0,,2180,6180,ff\n" // Soft + "76d,144,159,1,0,0,,2180,6180,ff\n" // Version + "76e,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "76e,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "76e,128,143,1,0,0,,2180,6180,ff\n" // Soft + "76e,144,159,1,0,0,,2180,6180,ff\n" // Version + "772,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "772,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "772,128,143,1,0,0,,2180,6180,ff\n" // Soft + "772,144,159,1,0,0,,2180,6180,ff\n" // Version + "77e,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "77e,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "77e,128,143,1,0,0,,2180,6180,ff\n" // Soft + "77e,144,159,1,0,0,,2180,6180,ff\n" // Version + "77e,24,39,0.015625,0,2,ºC,223018,623018,ff\n" // DCDC converter temperature + "77e,24,31,0.015625,0,2,°C,22302b,62302b,ff\n" // inverter temperature + "793,0,0,1,0,0,,1081,5081,ff\n" // start diag + "793,0,0,1,0,0,,10c0,50c0,ff\n" // start diag + "793,0,0,1,0,0,,3e01,7e01,ff\n" // Tester present + "793,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "793,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "793,128,143,1,0,0,,2180,6180,ff\n" // Soft + "793,144,159,1,0,0,,2180,6180,ff\n" // Version + "7b6,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "7b6,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "7b6,128,143,1,0,0,,2180,6180,ff\n" // Soft + "7b6,144,159,1,0,0,,2180,6180,ff\n" // Version + "7bb,336,351,0.01,0,2,kW,2101,6101,e2\n" // Maximum battery input power + "7bb,56,71,10,0,0,°C,2103,6103,5\n" // Mean battery compartment temp + "7bb,192,207,0.01,0,2,%,2103,6103,e2\n" // Real State of Charge + "7bb,32,39,1,40,0,°C,2104,6104,e2\n" // Cell 1 Temperature + "7bb,56,63,1,40,0,°C,2104,6104,e2\n" // Cell 2 Temperature + "7bb,80,87,1,40,0,°C,2104,6104,e2\n" // Cell 3 Temperature + "7bb,104,111,1,40,0,°C,2104,6104,e2\n" // Cell 4 Temperature + "7bb,128,135,1,40,0,°C,2104,6104,e2\n" // Cell 5 Temperature + "7bb,152,159,1,40,0,°C,2104,6104,e2\n" // Cell 6 Temperature + "7bb,176,183,1,40,0,°C,2104,6104,e2\n" // Cell 7 Temperature + "7bb,200,207,1,40,0,°C,2104,6104,e2\n" // Cell 8 Temperature + "7bb,224,231,1,40,0,°C,2104,6104,e2\n" // Cell 9 Temperature + "7bb,248,255,1,40,0,°C,2104,6104,e2\n" // Cell 10 Temperature + "7bb,272,279,1,40,0,°C,2104,6104,e2\n" // Cell 11 Temperature + "7bb,296,303,1,40,0,°C,2104,6104,e2\n" // Cell 12 Temperature + "7bb,600,607,1,40,0,degC,2104,6104,ff\n" // 21_04_#76_Average_Battery_Temperature + "7bb,16,23,1,0,0,,2107,6107,e2\n" // Cell 1 Balancing switch + "7bb,24,31,1,0,0,,2107,6107,e2\n" // Cell 2 Balancing switch + "7bb,32,39,1,0,0,,2107,6107,e2\n" // Cell 3 Balancing switch + "7bb,40,47,1,0,0,,2107,6107,e2\n" // Cell 4 Balancing switch + "7bb,48,55,1,0,0,,2107,6107,e2\n" // Cell 5 Balancing switch + "7bb,56,63,1,0,0,,2107,6107,e2\n" // Cell 6 Balancing switch + "7bb,64,71,1,0,0,,2107,6107,e2\n" // Cell 7 Balancing switch + "7bb,72,79,1,0,0,,2107,6107,e2\n" // Cell 8 Balancing switch + "7bb,80,87,1,0,0,,2107,6107,e2\n" // Cell 9 Balancing switch + "7bb,88,95,1,0,0,,2107,6107,e2\n" // Cell 10 Balancing switch + "7bb,96,102,1,0,0,,2107,6107,e2\n" // Cell 11 Balancing switch + "7bb,104,111,1,0,0,,2107,6107,e2\n" // Cell 12 Balancing switch + "7bb,32,39,1,0,0,°C,2104,6104,105\n" // Cell 1 Balancing switch + "7bb,56,63,1,0,0,°C,2104,6104,105\n" // Cell 2 Balancing switch + "7bb,80,87,1,0,0,°C,2104,6104,105\n" // Cell 3 Balancing switch + "7bb,104,111,1,0,0,°C,2104,6104,105\n" // Cell 4 Balancing switch + "7bb,16,31,0.001,0,3,V,2141,6141,ff\n" // Cell 01 V + "7bb,32,47,0.001,0,3,V,2141,6141,ff\n" // Cell 02 V + "7bb,48,63,0.001,0,3,V,2141,6141,ff\n" // Cell 03 V + "7bb,64,79,0.001,0,3,V,2141,6141,ff\n" // Cell 04 V + "7bb,80,95,0.001,0,3,V,2141,6141,ff\n" // Cell 05 V + "7bb,96,111,0.001,0,3,V,2141,6141,ff\n" // Cell 06 V + "7bb,112,127,0.001,0,3,V,2141,6141,ff\n" // Cell 07 V + "7bb,128,143,0.001,0,3,V,2141,6141,ff\n" // Cell 08 V + "7bb,144,159,0.001,0,3,V,2141,6141,ff\n" // Cell 09 V + "7bb,160,175,0.001,0,3,V,2141,6141,ff\n" // Cell 10 V + "7bb,176,191,0.001,0,3,V,2141,6141,ff\n" // Cell 11 V + "7bb,192,207,0.001,0,3,V,2141,6141,ff\n" // Cell 12 V + "7bb,208,223,0.001,0,3,V,2141,6141,ff\n" // Cell 13 V + "7bb,224,239,0.001,0,3,V,2141,6141,ff\n" // Cell 14 V + "7bb,240,255,0.001,0,3,V,2141,6141,ff\n" // Cell 15 V + "7bb,256,271,0.001,0,3,V,2141,6141,ff\n" // Cell 16 V + "7bb,272,287,0.001,0,3,V,2141,6141,ff\n" // Cell 17 V + "7bb,288,303,0.001,0,3,V,2141,6141,ff\n" // Cell 18 V + "7bb,304,319,0.001,0,3,V,2141,6141,ff\n" // Cell 19 V + "7bb,320,335,0.001,0,3,V,2141,6141,ff\n" // Cell 20 V + "7bb,336,351,0.001,0,3,V,2141,6141,ff\n" // Cell 21 V + "7bb,352,367,0.001,0,3,V,2141,6141,ff\n" // Cell 22 V + "7bb,368,383,0.001,0,3,V,2141,6141,ff\n" // Cell 23 V + "7bb,384,399,0.001,0,3,V,2141,6141,ff\n" // Cell 24 V + "7bb,400,415,0.001,0,3,V,2141,6141,ff\n" // Cell 25 V + "7bb,416,431,0.001,0,3,V,2141,6141,ff\n" // Cell 26 V + "7bb,432,447,0.001,0,3,V,2141,6141,ff\n" // Cell 27 V + "7bb,448,463,0.001,0,3,V,2141,6141,ff\n" // Cell 28 V + "7bb,464,479,0.001,0,3,V,2141,6141,ff\n" // Cell 29 V + "7bb,480,495,0.001,0,3,V,2141,6141,ff\n" // Cell 30 V + "7bb,496,511,0.001,0,3,V,2141,6141,ff\n" // Cell 31 V + "7bb,512,527,0.001,0,3,V,2141,6141,ff\n" // Cell 32 V + "7bb,528,543,0.001,0,3,V,2141,6141,ff\n" // Cell 33 V + "7bb,544,559,0.001,0,3,V,2141,6141,ff\n" // Cell 34 V + "7bb,560,575,0.001,0,3,V,2141,6141,ff\n" // Cell 35 V + "7bb,576,591,0.001,0,3,V,2141,6141,ff\n" // Cell 36 V + "7bb,592,607,0.001,0,3,V,2141,6141,ff\n" // Cell 37 V + "7bb,608,623,0.001,0,3,V,2141,6141,ff\n" // Cell 38 V + "7bb,624,639,0.001,0,3,V,2141,6141,ff\n" // Cell 39 V + "7bb,640,655,0.001,0,3,V,2141,6141,ff\n" // Cell 40 V + "7bb,656,671,0.001,0,3,V,2141,6141,ff\n" // Cell 41 V + "7bb,672,687,0.001,0,3,V,2141,6141,ff\n" // Cell 42 V + "7bb,688,703,0.001,0,3,V,2141,6141,ff\n" // Cell 43 V + "7bb,704,719,0.001,0,3,V,2141,6141,ff\n" // Cell 44 V + "7bb,720,735,0.001,0,3,V,2141,6141,ff\n" // Cell 45 V + "7bb,736,751,0.001,0,3,V,2141,6141,ff\n" // Cell 46 V + "7bb,752,767,0.001,0,3,V,2141,6141,ff\n" // Cell 47 V + "7bb,768,783,0.001,0,3,V,2141,6141,ff\n" // Cell 48 V + "7bb,784,799,0.001,0,3,V,2141,6141,ff\n" // Cell 49 V + "7bb,800,815,0.001,0,3,V,2141,6141,ff\n" // Cell 50 V + "7bb,816,831,0.001,0,3,V,2141,6141,ff\n" // Cell 51 V + "7bb,832,847,0.001,0,3,V,2141,6141,ff\n" // Cell 52 V + "7bb,848,863,0.001,0,3,V,2141,6141,ff\n" // Cell 53 V + "7bb,864,879,0.001,0,3,V,2141,6141,ff\n" // Cell 54 V + "7bb,880,895,0.001,0,3,V,2141,6141,ff\n" // Cell 55 V + "7bb,896,911,0.001,0,3,V,2141,6141,ff\n" // Cell 56 V + "7bb,912,927,0.001,0,3,V,2141,6141,ff\n" // Cell 57 V + "7bb,928,943,0.001,0,3,V,2141,6141,ff\n" // Cell 58 V + "7bb,944,959,0.001,0,3,V,2141,6141,ff\n" // Cell 59 V + "7bb,960,975,0.001,0,3,V,2141,6141,ff\n" // Cell 60 V + "7bb,976,991,0.001,0,3,V,2141,6141,ff\n" // Cell 61 V + "7bb,992,1007,0.001,0,3,V,2141,6141,ff\n" // Cell 62 V + "7bb,16,31,0.001,0,3,V,2142,6142,ff\n" // Cell 63 V + "7bb,32,47,0.001,0,3,V,2142,6142,ff\n" // Cell 64 Vl + "7bb,48,63,0.001,0,3,V,2142,6142,ff\n" // Cell 65 V + "7bb,64,79,0.001,0,3,V,2142,6142,ff\n" // Cell 66 V + "7bb,80,95,0.001,0,3,V,2142,6142,ff\n" // Cell 67 V + "7bb,96,111,0.001,0,3,V,2142,6142,ff\n" // Cell 68 V + "7bb,112,127,0.001,0,3,V,2142,6142,ff\n" // Cell 69 V + "7bb,128,143,0.001,0,3,V,2142,6142,ff\n" // Cell 70 V + "7bb,144,159,0.001,0,3,V,2142,6142,ff\n" // Cell 71 V + "7bb,160,175,0.001,0,3,V,2142,6142,ff\n" // Cell 72 V + "7bb,176,191,0.001,0,3,V,2142,6142,ff\n" // Cell 73 V + "7bb,192,207,0.001,0,3,V,2142,6142,ff\n" // Cell 74 V + "7bb,208,223,0.001,0,3,V,2142,6142,ff\n" // Cell 75 V + "7bb,224,239,0.001,0,3,V,2142,6142,ff\n" // Cell 76 V + "7bb,240,255,0.001,0,3,V,2142,6142,ff\n" // Cell 77 V + "7bb,256,271,0.001,0,3,V,2142,6142,ff\n" // Cell 78 V + "7bb,272,287,0.001,0,3,V,2142,6142,ff\n" // Cell 79 V + "7bb,288,303,0.001,0,3,V,2142,6142,ff\n" // Cell 80 V + "7bb,304,319,0.001,0,3,V,2142,6142,ff\n" // Cell 81 V + "7bb,320,335,0.001,0,3,V,2142,6142,ff\n" // Cell 82 V + "7bb,336,351,0.001,0,3,V,2142,6142,ff\n" // Cell 83 V + "7bb,352,367,0.001,0,3,V,2142,6142,ff\n" // Cell 84 V + "7bb,368,383,0.001,0,3,V,2142,6142,ff\n" // Cell 85 V + "7bb,384,399,0.001,0,3,V,2142,6142,ff\n" // Cell 86 V + "7bb,400,415,0.001,0,3,V,2142,6142,ff\n" // Cell 87 V + "7bb,416,431,0.001,0,3,V,2142,6142,ff\n" // Cell 88 V + "7bb,432,447,0.001,0,3,V,2142,6142,ff\n" // Cell 89 V + "7bb,448,463,0.001,0,3,V,2142,6142,ff\n" // Cell 90 V + "7bb,464,479,0.001,0,3,V,2142,6142,ff\n" // Cell 91 V + "7bb,480,495,0.001,0,3,V,2142,6142,ff\n" // Cell 92 V + "7bb,496,511,0.001,0,3,V,2142,6142,ff\n" // Cell 93 V + "7bb,512,527,0.001,0,3,V,2142,6142,ff\n" // Cell 94 V + "7bb,528,543,0.001,0,3,V,2142,6142,ff\n" // Cell 95 V + "7bb,544,559,0.001,0,3,V,2142,6142,ff\n" // Cell 96 V + "7bb,96,119,1,0,0,km,2161,6161,ff\n" // Battery mileage in km + "7bb,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "7bb,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "7bb,128,143,1,0,0,,2180,6180,ff\n" // Soft + "7bb,144,159,1,0,0,,2180,6180,ff\n" // Version + "7bc,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "7bc,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "7bc,128,143,1,0,0,,2180,6180,ff\n" // Soft + "7bc,144,159,1,0,0,,2180,6180,ff\n" // Version + "7da,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "7da,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "7da,128,143,1,0,0,,2180,6180,ff\n" // Soft + "7da,144,159,1,0,0,,2180,6180,ff\n" // Version + "7ec,56,63,1,0,0,,2180,6180,ff\n" // diagVersion + "7ec,64,87,1,0,0,,2180,6180,2ff\n" // Supplier (string!) + "7ec,128,143,1,0,0,,2180,6180,ff\n" // Soft + "7ec,144,159,1,0,0,,2180,6180,ff\n" // Version + "7ec,24,39,2,0,2,%,222002,622002,e2\n" // SOC + "7ec,24,39,2.083333333,0,2,%,222002,622002,e5\n" // SOC + "7ec,24,39,0.01,0,2,V,222005,622005,ff\n" // 12V battery voltage + "7ec,24,47,1,0,0,km,222006,622006,ff\n" // Odometer + "7ec,24,31,0.5,0,1,A,223028,623028,ff\n" // 14V current? + "7ec,24,39,0.5,0,2,V,223203,623203,ff\n" // HV Battery voltage + "7ec,24,39,0.25,32768,2,A,223204,623204,ff\n" // HV Battery current + "7ec,24,31,1,0,0,%,223206,623206,ff\n" // Battery health in % + "7ec,24,31,1,1,0,,223318,623318,ff\n" // Motor Water pump speed + "7ec,24,31,1,1,0,,223319,623319,ff\n" // Charger pump speed + "7ec,24,31,1,1,0,,22331a,62331a,ff\n" // Heater water pump speed + "7ec,24,47,0.001,1,0,kWh,2233dc,6233dc,ff\n" // Consumed domestic energy +"7ec,240,263,1,0,0,km,2233d4,6233d4,ff\n" // +"7ec,216,239,1,0,0,km,2233d4,6233d4,ff\n" // +"7ec,192,215,1,0,0,km,2233d4,6233d4,ff\n" // +"7ec,168,191,1,0,0,km,2233d4,6233d4,ff\n" // +"7ec,144,167,1,0,0,km,2233d4,6233d4,ff\n" // +"7ec,120,143,1,0,0,km,2233d4,6233d4,ff\n" // +"7ec,96,119,1,0,0,km,2233d4,6233d4,ff\n" // +"7ec,72,95,1,0,0,km,2233d4,6233d4,ff\n" // +"7ec,48,71,1,0,0,km,2233d4,6233d4,ff\n" // +"7ec,24,47,1,0,0,km,2233d4,6233d4,ff\n" // +"7ec,96,103,1,0,0,,2233d5,6233d5,ff,\n" // +"7ec,88,95,1,0,0,,2233d5,6233d5,ff\n" // +"7ec,80,87,1,0,0,,2233d5,6233d5,ff\n" // +"7ec,72,79,1,0,0,,2233d5,6233d5,ff\n" // +"7ec,64,71,1,0,0,,2233d5,6233d5,ff\n" // +"7ec,56,63,1,0,0,,2233d5,6233d5,ff\n" // +"7ec,48,55,1,0,0,,2233d5,6233d5,ff\n" // +"7ec,40,47,1,0,0,,2233d5,6233d5,ff\n" // +"7ec,32,39,1,0,0,,2233d5,6233d5,ff\n" // +"7ec,24,31,1,0,0,,2233d5,6233d5,ff\n" // +"7ec,96,103,1,0,0,,2233d6,6233d6,ff\n" // +"7ec,88,95,1,0,0,,2233d6,6233d6,ff\n" // +"7ec,80,87,1,0,0,,2233d6,6233d6,ff\n" // +"7ec,72,79,1,0,0,,2233d6,6233d6,ff\n" // +"7ec,64,71,1,0,0,,2233d6,6233d6,ff\n" // +"7ec,56,63,1,0,0,,2233d6,6233d6,ff\n" // +"7ec,48,55,1,0,0,,2233d6,6233d6,ff\n" // +"7ec,40,47,1,0,0,,2233d6,6233d6,ff\n" // +"7ec,32,39,1,0,0,,2233d6,6233d6,ff\n" // +"7ec,24,31,1,0,0,,2233d6,6233d6,ff\n" // +"7ec,168,183,.2,0,0,%,2233d7,6233d7,ff\n" // +"7ec,152,167,.2,0,0,%,2233d7,6233d7,ff\n" // +"7ec,136,151,.2,0,0,%,2233d7,6233d7,ff\n" // +"7ec,120,135,.2,0,0,%,2233d7,6233d7,ff\n" // +"7ec,104,119,.2,0,0,%,2233d7,6233d7,ff\n" // +"7ec,88,103,.2,0,0,%,2233d7,6233d7,ff\n" // +"7ec,72,87,.2,0,0,%,2233d7,6233d7,ff\n" // +"7ec,56,71,.2,0,0,%,2233d7,6233d7,ff\n" // +"7ec,40,55,.2,0,0,%,2233d7,6233d7,ff\n" // +"7ec,24,39,.2,0,0,%,2233d7,6233d7,ff\n" // +"7ec,96,103,1,40,0,°C,2233d8,6233d8,ff\n" // +"7ec,88,95,1,40,0,°C,2233d8,6233d8,ff\n" // +"7ec,80,87,1,40,0,°C,2233d8,6233d8,ff\n" // +"7ec,72,79,1,40,0,°C,2233d8,6233d8,ff\n" // +"7ec,64,71,1,40,0,°C,2233d8,6233d8,ff\n" // +"7ec,56,63,1,40,0,°C,2233d8,6233d8,ff\n" // +"7ec,48,55,1,40,0,°C,2233d8,6233d8,ff\n" // +"7ec,40,47,1,40,0,°C,2233d8,6233d8,ff\n" // +"7ec,32,39,1,40,0,°C,2233d8,6233d8,ff\n" // +"7ec,24,31,1,40,0,°C,2233d8,6233d8,ff\n" // +"7ec,168,183,1,0,0,min,2233d9,6233d9,ff\n" // +"7ec,152,167,1,0,0,min,2233d9,6233d9,ff\n" // +"7ec,136,151,1,0,0,min,2233d9,6233d9,ff\n" // +"7ec,120,135,1,0,0,min,2233d9,6233d9,ff\n" // +"7ec,104,119,1,0,0,min,2233d9,6233d9,ff\n" // +"7ec,88,103,1,0,0,min,2233d9,6233d9,ff\n" // +"7ec,72,87,1,0,0,min,2233d9,6233d9,ff\n" // +"7ec,56,71,1,0,0,min,2233d9,6233d9,ff\n" // +"7ec,40,55,1,0,0,min,2233d9,6233d9,ff\n" // +"7ec,24,39,1,0,0,min,2233d9,6233d9,ff\n" // ; fillDynamic (fieldDef); } private void fillDynamic(String fieldDef) { // try { // //fieldDef += readFromLocalFile(); // } // catch(Exception e) // { // // ignore // } String[] lines = fieldDef.split("\n"); for (String line : lines) { //MainActivity.debug("Fields: Reading > "+line); //Get all tokens available in line String[] tokens = line.split(","); if (tokens.length >= 10) { int frameId = Integer.parseInt(tokens[FIELD_ID].trim(), 16); Frame frame = Frames.getInstance().getById(frameId); if (frame == null) { MainActivity.debug("frame does not exist:" + tokens[FIELD_ID].trim()); } else { short options = Short.parseShort(tokens[FIELD_OPTIONS].trim(), 16); // ensure this field matches the selected car if ((options & MainActivity.car) != 0) { //Create a new field object and fill his data MainActivity.debug(tokens[FIELD_ID] + "." + tokens[FIELD_RESPONSE_ID] + "." + tokens[FIELD_FROM]); Field field = new Field( frame, Short.parseShort(tokens[FIELD_FROM].trim()), Short.parseShort(tokens[FIELD_TO].trim()), Double.parseDouble(tokens[FIELD_RESOLUTION].trim()), Integer.parseInt(tokens[FIELD_DECIMALS].trim()), Integer.parseInt(tokens[FIELD_OFFSET].trim()), tokens[FIELD_UNIT].trim(), //tokens[FIELD_REQUEST_ID].trim(), tokens[FIELD_RESPONSE_ID].trim(), options, tokens.length >= 11 ? tokens[FIELD_NAME] : null, tokens.length >= 12 ? tokens[FIELD_LIST] : null ); // we are maintaining a list of all fields in a frame so we can very // quickly update all fields when a message (=frame data) comes in // note that for free frames a frame is identified by it's ID and itś definition // is entirely given // for an ISOTP frame (diagnostics) frame, the frame is just a skeleton and // the definition is entirely dependant on the responseID. Therefor, when an // ISOTP field is defined, new frames are created dynamically if (field.isIsoTp()) { Frame subFrame = Frames.getInstance().getById(frameId, field.getResponseId()); if (subFrame == null) { subFrame = new Frame(frame.getId(),frame.getInterval(),frame.getSendingEcu(),field.getResponseId(),frame); Frames.getInstance().add (subFrame); } subFrame.addField(field); field.setFrame(subFrame); } else { frame.addField(field); } // add the field to the list of available fields add(field); } } } } } private String readFromLocalFile() { //*Don't* hardcode "/sdcard" File sdcard = Environment.getExternalStorageDirectory(); MainActivity.debug("SD: "+sdcard.getAbsolutePath()); //Get the text file File file = new File(sdcard,"fields.csv"); //Read text from file StringBuilder text = new StringBuilder(); try { BufferedReader br = new BufferedReader(new FileReader(file)); String line; while ((line = br.readLine()) != null) { text.append(line); text.append('\n'); } br.close(); } catch (IOException e) { e.printStackTrace(); } return text.toString(); } /* private void readFromFile(String filename) throws IOException // FileNotFoundException, { BufferedReader fileReader = new BufferedReader(new FileReader(filename)); String line; //Read the file line by line starting from the second line while ((line = fileReader.readLine()) != null) { //Get all tokens available in line String[] tokens = line.split(","); if (tokens.length == 15) { int divider = Integer.parseInt(tokens[FIELD_DIVIDER].trim()); int multiplier = Integer.parseInt(tokens[FIELD_MULTIPLIER].trim()); int decimals = Integer.parseInt(tokens[FIELD_DECIMALS].trim()); double multi = ((double) multiplier/divider)/(decimals==0?1:decimals); // <<<<<< Probably wrong, as decimals have completely changed, and that should be in file too int frameId = Integer.parseInt(tokens[FIELD_ID].trim().replace("0x", ""), 16); Frame frame = Frames.getInstance().getById(frameId); Field field = new Field( frame, Integer.parseInt(tokens[FIELD_FROM].trim()), Integer.parseInt(tokens[FIELD_TO].trim()), multi, Integer.parseInt(tokens[FIELD_DECIMALS].trim()), ( tokens[FIELD_OFFSET].trim().contains("0x") ? Integer.parseInt(tokens[FIELD_OFFSET].trim().replace("0x", ""), 16) : Integer.parseInt(tokens[FIELD_OFFSET].trim()) ), tokens[FIELD_UNIT].intern(), tokens[FIELD_REQUEST_ID].trim().replace("0x", "").intern(), tokens[FIELD_RESPONSE_ID].trim().replace("0x", "").intern(), Integer.parseInt(tokens[FIELD_CAR].trim()) //Integer.parseInt(tokens[FIELD_SKIPS].trim()) //Integer.parseInt(tokens[FIELD_FREQ].trim()) ); // add the field to the list of available fields add(field); } } } */ public Field getBySID(String sid) { sid=sid.toLowerCase(); /* // first let's try to get the field that is bound to the selected car Field tryField = fieldsBySid.get(MainActivity.car + "."+sid); if(tryField!=null) return tryField; // if none is found, try the other one, starting with 0 = CAR_ANY for(int i=0; i<5; i++) { tryField = fieldsBySid.get(i + "." + sid); if (tryField != null) return tryField; } */ // since we changed logic to initialize the hashmaps with only the current car's fields, we're always fine just looking for the SID Field tryField = fieldsBySid.get(sid); if(tryField!=null) return tryField; return null; } public int size() { return fields.size(); } public Field get(int index) { return fields.get(index); } public Object[] toArray() { return fields.toArray(); } public void add(Field field) { fields.add(field); fieldsBySid.put(field.getSID(),field); //fieldsBySid.put(field.getCar()+"."+field.getSID(),field); } /* // this should never be done :-) public void notifyAllFieldListeners() { for(int i=0; i< fields.size(); i++) { fields.get(i).notifyFieldListeners(); } } */ public void clearAllFields() { for(int i=0; i< fields.size(); i++) { fields.get(i).setValue(0); } } public ArrayList<Field> getAllFields () { return fields; } public void load () { fields.clear(); fieldsBySid.clear(); fillStatic(); addVirtualFields(); MainActivity.getInstance().registerApplicationFields(); // this registers i.e. speed for save driving mode } public void load (String initString) { fields.clear(); fieldsBySid.clear(); fillDynamic(initString); //addVirtualFields(); MainActivity.getInstance().registerApplicationFields(); // this registers i.e. speed for save driving mode } public void loadMore (String initString) { fillDynamic(initString); } /* -------------------------------- * Tests ... \ ------------------------------ */ public static void main(String[] args) { } }