Enrico Granata | 6988f00 | 2017-02-13 12:07:52 -0800 | [diff] [blame^] | 1 | #!/usr/bin/env python3.4 |
| 2 | # |
| 3 | # Copyright (C) 2016 The Android Open Source Project |
| 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | # you may not use this file except in compliance with the License. |
| 7 | # You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. |
| 16 | # |
| 17 | |
| 18 | # This script generates useful representations of the current list of OBD2 |
| 19 | # diagnostic sensors we support. It is meant as an easy way to update the |
| 20 | # list of diagnostic sensors and get all the required lists pretty-printed |
| 21 | # and ready for use. |
| 22 | # The script contains three parts: |
| 23 | # 1) the part marked DO NOT MODIFY THIS. This defines a domain-specific language |
| 24 | # that allows one to give a list of sensors; |
| 25 | # 2) the part marked ACTUAL SENSOR DEFINITIONS HERE. This part gives the list |
| 26 | # of diagnostic sensors, provided in the DSL defined above; |
| 27 | # 3) the generate() call at the very end. This triggers the script to perform |
| 28 | # its generation task. |
| 29 | # To keep it simple, this script will produce its output |
| 30 | # to stdout, also in three parts: |
| 31 | # 1) Vehicle HAL enumerations; |
| 32 | # 2) Java classes with a list of sensor identifiers; |
| 33 | # 3) Java @interfaces with a list of sensor identifiers. |
| 34 | # The several parts contain comments that indicate which files the content has |
| 35 | # to be pasted into. Should there be a need, the script could be extended to |
| 36 | # automatically insert the content in the files. |
| 37 | # To run: |
| 38 | # $ ./update-obd2-sensors.py |
| 39 | |
| 40 | ## DO NOT MODIFY THIS |
| 41 | ## This code is the machinery required to make the sensor generator DSL work |
| 42 | class SensorList(object): |
| 43 | """A list of sensors ordered by a unique identifier.""" |
| 44 | def __init__(self, descriptor): |
| 45 | self.sensors = [] |
| 46 | self.id = -1 |
| 47 | self.descriptor = descriptor |
| 48 | |
| 49 | def addSensor(self, sensor): |
| 50 | """Add a new sensor to the list.""" |
| 51 | if not hasattr(sensor, 'id'): |
| 52 | self.id += 1 |
| 53 | sensor.id = self.id |
| 54 | self.sensors.append(sensor) |
| 55 | |
| 56 | def finalizeList(self): |
| 57 | """Complete the list, adding well-known sensor information.""" |
| 58 | self.id -= 1 |
| 59 | lastSystemSensor = self.sensorClass("LAST_SYSTEM_INDEX", |
| 60 | id=self.sensors[-1].name) |
| 61 | vendorStartSensor = self.sensorClass("VENDOR_START_INDEX", |
| 62 | id="LAST_SYSTEM_INDEX + 1") |
| 63 | # make calling finalizeList idempotent |
| 64 | self.finalizeList = lambda: self |
| 65 | return self |
| 66 | |
| 67 | def __getitem__(self, key): |
| 68 | return self.sensors.__getitem__(key) |
| 69 | |
| 70 | class SensorPolicy(object): |
| 71 | """A formatter object that does processing on sensor data.""" |
| 72 | @classmethod |
| 73 | def indentLines(cls, string, numSpaces): |
| 74 | indent = ' ' * numSpaces |
| 75 | parts = string.split('\n') |
| 76 | parts = [indent + part for part in parts] |
| 77 | return '\n'.join(parts) + "\n" |
| 78 | |
| 79 | def sensor(self, theSensor, theSensors): |
| 80 | """Produce output for a sensor.""" |
| 81 | pass |
| 82 | |
| 83 | def prefix(self, theSensors): |
| 84 | """Prefix string before any sensor data is generated.""" |
| 85 | return "" |
| 86 | |
| 87 | def suffix(self): |
| 88 | """Suffix string after all sensor data is generated.""" |
| 89 | return "" |
| 90 | |
| 91 | def indent(self): |
| 92 | """Indentation level for individual sensor data.""" |
| 93 | return 0 |
| 94 | |
| 95 | def separator(self): |
| 96 | """Separator between individual sensor data entries.""" |
| 97 | return "" |
| 98 | |
| 99 | def description(self): |
| 100 | """A description of this policy.""" |
| 101 | return "A sensor policy." |
| 102 | |
| 103 | def sensors(self, theSensors): |
| 104 | """Produce output for all sensors.""" |
| 105 | theSensors = theSensors.finalizeList() |
| 106 | s = self.prefix(theSensors) + "\n" |
| 107 | first = True |
| 108 | for theSensor in theSensors: |
| 109 | if first: |
| 110 | first = False |
| 111 | else: |
| 112 | s += self.separator() |
| 113 | sensorLine = SensorPolicy.indentLines(self.sensor(theSensor, |
| 114 | theSensors), self.indent()) |
| 115 | s += sensorLine |
| 116 | s += self.suffix(theSensors) + "\n" |
| 117 | return s |
| 118 | |
| 119 | class HalSensorPolicy(SensorPolicy): |
| 120 | """The sensor policy that emits Vehicle HAL sensor descriptions.""" |
| 121 | def sensor(self, theSensor, theSensors): |
| 122 | s = "" |
| 123 | if theSensor.comment: |
| 124 | s = theSensor.comment + "\n" |
| 125 | s = s + theSensor.name + " = " + str(theSensor.id) + "," |
| 126 | return s |
| 127 | |
| 128 | def prefix(self, theSensors): |
| 129 | return "enum Obd2%sSensorIndex : int32_t {" % (theSensors.descriptor) |
| 130 | |
| 131 | def suffix(self, theSensors): |
| 132 | return "}" |
| 133 | |
| 134 | def indent(self): |
| 135 | return 2 |
| 136 | |
| 137 | def separator(self): |
| 138 | return "\n" |
| 139 | |
| 140 | def description(self): |
| 141 | return "/** this goes in types.hal **/" |
| 142 | |
| 143 | class JavaSensorPolicy(SensorPolicy): |
| 144 | """The sensor policy that emits Java sensor descriptions.""" |
| 145 | def sensor(self, theSensor, theSensors): |
| 146 | sensorName = theSensor.name.replace("_INDEX", "") |
| 147 | sensorId = str(theSensor.id).replace("_INDEX", "") |
| 148 | return "public static final int " + sensorName + " = " + \ |
| 149 | str(sensorId) + ";" |
| 150 | |
| 151 | def prefix(self, theSensors): |
| 152 | s = "public static final class Obd2%sSensorIndex {\n" % theSensors.descriptor |
| 153 | s += " private Obd2%sSensorIndex() {}\n" % theSensors.descriptor |
| 154 | return s |
| 155 | |
| 156 | def suffix(self, theSensors): |
| 157 | return "}" |
| 158 | |
| 159 | def indent(self): |
| 160 | return 4 |
| 161 | |
| 162 | def description(self): |
| 163 | return "/** this goes in CarDiagnosticEvent.java **/" |
| 164 | |
| 165 | class IntDefSensorPolicy(SensorPolicy): |
| 166 | """The sensor policy that emits @IntDef sensor descriptions.""" |
| 167 | def sensor(self, theSensor, theSensors): |
| 168 | sensorName = theSensor.name.replace("_INDEX", "") |
| 169 | return "Obd2%sSensorIndex.%s," % (theSensors.descriptor,sensorName) |
| 170 | |
| 171 | def prefix(self, theSensors): |
| 172 | return "@Retention(RetentionPolicy.SOURCE)\n@IntDef({" |
| 173 | |
| 174 | def suffix(self, theSensors): |
| 175 | return "})\npublic @interface %sSensorIndex {}" % theSensors.descriptor |
| 176 | |
| 177 | def description(self): |
| 178 | return "/** this goes in CarDiagnosticEvent.java **/" |
| 179 | |
| 180 | class SensorMeta(type): |
| 181 | """Metaclass for sensor classes.""" |
| 182 | def __new__(cls, name, parents, dct): |
| 183 | sensorList = dct['sensorList'] |
| 184 | class SensorBase(object): |
| 185 | def __init__(self, name, comment=None, id=None): |
| 186 | self.name = name |
| 187 | self.comment = comment if comment else "" |
| 188 | if id: self.id = id |
| 189 | sensorList.addSensor(self) |
| 190 | def __repr__(self): |
| 191 | s = "" |
| 192 | if self.comment: |
| 193 | s = s + self.comment + "\n" |
| 194 | s = s + self.name + " = " + str(self.id) |
| 195 | return s |
| 196 | |
| 197 | newClass = super().__new__(cls, name, (SensorBase,), dct) |
| 198 | sensorList.sensorClass = newClass |
| 199 | return newClass |
| 200 | |
| 201 | intSensors = SensorList(descriptor="Integer") |
| 202 | floatSensors = SensorList(descriptor="Float") |
| 203 | |
| 204 | class intSensor(metaclass=SensorMeta): |
| 205 | sensorList = intSensors |
| 206 | |
| 207 | class floatSensor(metaclass=SensorMeta): |
| 208 | sensorList = floatSensors |
| 209 | |
| 210 | def applyPolicy(policy): |
| 211 | """Given a sensor policy, apply it to all known sensor types""" |
| 212 | print(policy.description()) |
| 213 | print(policy.sensors(intSensors)) |
| 214 | print(policy.sensors(floatSensors)) |
| 215 | |
| 216 | def java(): |
| 217 | applyPolicy(JavaSensorPolicy()) |
| 218 | |
| 219 | def hal(): |
| 220 | applyPolicy(HalSensorPolicy()) |
| 221 | |
| 222 | def intdef(): |
| 223 | applyPolicy(IntDefSensorPolicy()) |
| 224 | |
| 225 | def generate(): |
| 226 | """Generate data for all sensors.""" |
| 227 | hal() |
| 228 | java() |
| 229 | intdef() |
| 230 | |
| 231 | ## ACTUAL SENSOR DEFINITIONS HERE |
| 232 | ## Write sensor definitions here; terminate list with generate(). |
| 233 | |
| 234 | intSensor(name="FUEL_SYSTEM_STATUS", comment="/* refer to FuelSystemStatus for a description of this value. */") |
| 235 | intSensor(name="MALFUNCTION_INDICATOR_LIGHT_ON") |
| 236 | intSensor(name="IGNITION_MONITORS_SUPPORTED", comment="/* refer to IgnitionMonitorKind for a description of this value. */") |
| 237 | intSensor(name="IGNITION_SPECIFIC_MONITORS", comment=r"""/* |
| 238 | * The value of this sensor is a bitmask that specifies whether ignition-specific |
| 239 | * tests are available and whether they are complete. The semantics of the individual |
| 240 | * bits in this value are given by, respectively, SparkIgnitionMonitors and |
| 241 | * CompressionIgnitionMonitors depending on the value of IGNITION_MONITORS_SUPPORTED. |
| 242 | */""") |
| 243 | intSensor(name="INTAKE_AIR_TEMPERATURE") |
| 244 | intSensor(name="COMMANDED_SECONDARY_AIR_STATUS", comment="/* refer to SecondaryAirStatus for a description of this value. */") |
| 245 | intSensor(name="NUM_OXYGEN_SENSORS_PRESENT") |
| 246 | intSensor(name="RUNTIME_SINCE_ENGINE_START") |
| 247 | intSensor(name="DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON") |
| 248 | intSensor(name="WARMUPS_SINCE_CODES_CLEARED") |
| 249 | intSensor(name="DISTANCE_TRAVELED_SINCE_CODES_CLEARED") |
| 250 | intSensor(name="ABSOLUTE_BAROMETRIC_PRESSURE") |
| 251 | intSensor(name="CONTROL_MODULE_VOLTAGE") |
| 252 | intSensor(name="AMBIENT_AIR_TEMPERATURE") |
| 253 | intSensor(name="TIME_WITH_MALFUNCTION_LIGHT_ON") |
| 254 | intSensor(name="TIME_SINCE_TROUBLE_CODES_CLEARED") |
| 255 | intSensor(name="MAX_FUEL_AIR_EQUIVALENCE_RATIO") |
| 256 | intSensor(name="MAX_OXYGEN_SENSOR_VOLTAGE") |
| 257 | intSensor(name="MAX_OXYGEN_SENSOR_CURRENT") |
| 258 | intSensor(name="MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE") |
| 259 | intSensor(name="MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR") |
| 260 | intSensor(name="FUEL_TYPE", comment="/* refer to FuelType for a description of this value. */") |
| 261 | intSensor(name="FUEL_RAIL_ABSOLUTE_PRESSURE") |
| 262 | intSensor(name="ENGINE_OIL_TEMPERATURE") |
| 263 | intSensor(name="DRIVER_DEMAND_PERCENT_TORQUE") |
| 264 | intSensor(name="ENGINE_ACTUAL_PERCENT_TORQUE") |
| 265 | intSensor(name="ENGINE_REFERENCE_PERCENT_TORQUE") |
| 266 | intSensor(name="ENGINE_PERCENT_TORQUE_DATA_IDLE") |
| 267 | intSensor(name="ENGINE_PERCENT_TORQUE_DATA_POINT1") |
| 268 | intSensor(name="ENGINE_PERCENT_TORQUE_DATA_POINT2") |
| 269 | intSensor(name="ENGINE_PERCENT_TORQUE_DATA_POINT3") |
| 270 | intSensor(name="ENGINE_PERCENT_TORQUE_DATA_POINT4") |
| 271 | |
| 272 | floatSensor(name="CALCULATED_ENGINE_LOAD") |
| 273 | floatSensor(name="ENGINE_COOLANT_TEMPERATURE") |
| 274 | floatSensor(name="SHORT_TERM_FUEL_TRIM_BANK1") |
| 275 | floatSensor(name="LONG_TERM_FUEL_TRIM_BANK1") |
| 276 | floatSensor(name="SHORT_TERM_FUEL_TRIM_BANK2") |
| 277 | floatSensor(name="LONG_TERM_FUEL_TRIM_BANK2") |
| 278 | floatSensor(name="FUEL_PRESSURE") |
| 279 | floatSensor(name="INTAKE_MANIFOLD_ABSOLUTE_PRESSURE") |
| 280 | floatSensor(name="ENGINE_RPM") |
| 281 | floatSensor(name="VEHICLE_SPEED") |
| 282 | floatSensor(name="TIMING_ADVANCE") |
| 283 | floatSensor(name="MAF_AIR_FLOW_RATE") |
| 284 | floatSensor(name="THROTTLE_POSITION") |
| 285 | floatSensor(name="OXYGEN_SENSOR1_VOLTAGE") |
| 286 | floatSensor(name="OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM") |
| 287 | floatSensor(name="OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO") |
| 288 | floatSensor(name="OXYGEN_SENSOR2_VOLTAGE") |
| 289 | floatSensor(name="OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM") |
| 290 | floatSensor(name="OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO") |
| 291 | floatSensor(name="OXYGEN_SENSOR3_VOLTAGE") |
| 292 | floatSensor(name="OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM") |
| 293 | floatSensor(name="OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO") |
| 294 | floatSensor(name="OXYGEN_SENSOR4_VOLTAGE") |
| 295 | floatSensor(name="OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM") |
| 296 | floatSensor(name="OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO") |
| 297 | floatSensor(name="OXYGEN_SENSOR5_VOLTAGE") |
| 298 | floatSensor(name="OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM") |
| 299 | floatSensor(name="OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO") |
| 300 | floatSensor(name="OXYGEN_SENSOR6_VOLTAGE") |
| 301 | floatSensor(name="OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM") |
| 302 | floatSensor(name="OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO") |
| 303 | floatSensor(name="OXYGEN_SENSOR7_VOLTAGE") |
| 304 | floatSensor(name="OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM") |
| 305 | floatSensor(name="OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO") |
| 306 | floatSensor(name="OXYGEN_SENSOR8_VOLTAGE") |
| 307 | floatSensor(name="OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM") |
| 308 | floatSensor(name="OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO") |
| 309 | floatSensor(name="FUEL_RAIL_PRESSURE") |
| 310 | floatSensor(name="FUEL_RAIL_GAUGE_PRESSURE") |
| 311 | floatSensor(name="COMMANDED_EXHAUST_GAS_RECIRCULATION") |
| 312 | floatSensor(name="EXHAUST_GAS_RECIRCULATION_ERROR") |
| 313 | floatSensor(name="COMMANDED_EVAPORATIVE_PURGE") |
| 314 | floatSensor(name="FUEL_TANK_LEVEL_INPUT") |
| 315 | floatSensor(name="EVAPORATION_SYSTEM_VAPOR_PRESSURE") |
| 316 | floatSensor(name="CATALYST_TEMPERATURE_BANK1_SENSOR1") |
| 317 | floatSensor(name="CATALYST_TEMPERATURE_BANK2_SENSOR1") |
| 318 | floatSensor(name="CATALYST_TEMPERATURE_BANK1_SENSOR2") |
| 319 | floatSensor(name="CATALYST_TEMPERATURE_BANK2_SENSOR2") |
| 320 | floatSensor(name="ABSOLUTE_LOAD_VALUE") |
| 321 | floatSensor(name="FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO") |
| 322 | floatSensor(name="RELATIVE_THROTTLE_POSITION") |
| 323 | floatSensor(name="ABSOLUTE_THROTTLE_POSITION_B") |
| 324 | floatSensor(name="ABSOLUTE_THROTTLE_POSITION_C") |
| 325 | floatSensor(name="ACCELERATOR_PEDAL_POSITION_D") |
| 326 | floatSensor(name="ACCELERATOR_PEDAL_POSITION_E") |
| 327 | floatSensor(name="ACCELERATOR_PEDAL_POSITION_F") |
| 328 | floatSensor(name="COMMANDED_THROTTLE_ACTUATOR") |
| 329 | floatSensor(name="ETHANOL_FUEL_PERCENTAGE") |
| 330 | floatSensor(name="ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE") |
| 331 | floatSensor(name="SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1") |
| 332 | floatSensor(name="SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2") |
| 333 | floatSensor(name="SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3") |
| 334 | floatSensor(name="SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4") |
| 335 | floatSensor(name="LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1") |
| 336 | floatSensor(name="LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2") |
| 337 | floatSensor(name="LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3") |
| 338 | floatSensor(name="LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4") |
| 339 | floatSensor(name="RELATIVE_ACCELERATOR_PEDAL_POSITION") |
| 340 | floatSensor(name="HYBRID_BATTERY_PACK_REMAINING_LIFE") |
| 341 | floatSensor(name="FUEL_INJECTION_TIMING") |
| 342 | floatSensor(name="ENGINE_FUEL_RATE") |
| 343 | |
| 344 | generate() |