Automatically generate the Java list of OBD2 sensor indices from the HIDL definition.
This commit introduces the hidl_parser library, which is capable of generating a parse tree from a set of HIDL enum definitions.
It then uses the output of hidl_parser to generate CarDiagnosticSensorIndices.java.
Test: update-obd2-sensors.py + rebuild
Change-Id: Ie368b616468b0a2b46da5aa92deb4617c78302e1
diff --git a/tools/hidl_parser/__init__.py b/tools/hidl_parser/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/hidl_parser/__init__.py
diff --git a/tools/hidl_parser/parser.py b/tools/hidl_parser/parser.py
new file mode 100644
index 0000000..b0349c0
--- /dev/null
+++ b/tools/hidl_parser/parser.py
@@ -0,0 +1,246 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# A parser for enum types defined in HIDL.
+# This script can parse HIDL files and generate a parse tree.
+# To use, import and call parse("path/to/file.hal")
+# It will return a Python dictionary with two keys:
+# - header: an instance of Header
+# - enums: a dictionary of EnumDecl objects by name
+# This script cannot parse structs for now, but that would be easy to add.
+
+# It requires 'ply' (Python Lex/Yacc).
+
+import ply
+
+tokens = ('package', 'import', 'enum',
+ 'COLON', 'IDENTIFIER', 'COMMENT', 'NUMBER', 'HEX', 'OR', 'EQUALS',
+ 'LPAREN', 'RPAREN', 'LBRACE', 'RBRACE', 'DOT', 'SEMICOLON', 'VERSION',
+ 'COMMA', 'SHIFT')
+
+t_COLON = r':'
+t_NUMBER = r'[0-9]+'
+t_HEX = r'0x[0-9A-Fa-f]+'
+t_OR = r'\|'
+t_EQUALS = r'='
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+t_SHIFT = r'<<'
+
+def t_COMMENT(t):
+ r'(/\*(.|\n)*?\*/)|(//.*)'
+ pass
+
+t_LBRACE = r'{'
+t_RBRACE = r'}'
+t_DOT = r'\.'
+t_SEMICOLON = r';'
+t_VERSION = r'@[0-9].[0-9]'
+t_COMMA = r','
+t_ignore = ' \n\t'
+
+def t_IDENTIFIER(t):
+ r'[a-zA-Z_][a-zA-Z_0-9]*'
+ if t.value == 'package':
+ t.type = 'package'
+ elif t.value == 'import':
+ t.type = 'import'
+ elif t.value == 'enum':
+ t.type = 'enum'
+ return t
+
+def t_error(t):
+ t.type = t.value[0]
+ t.value = t.value[0]
+ t.lexer.skip(1)
+ return t
+
+import ply.lex as lex
+lexer = lex.lex()
+
+class EnumHeader(object):
+ def __init__(self, name, base):
+ self.name = name
+ self.base = base
+
+ def __str__(self):
+ return '%s%s' % (self.name, ' %s' % self.base if self.base else '')
+
+class EnumDecl(object):
+ def __init__(self, header, cases):
+ self.header = header
+ self.cases = cases
+
+ def __str__(self):
+ return '%s {\n%s\n}' % (self.header,
+ '\n'.join(str(x) for x in self.cases))
+
+ def __repr__(self):
+ return self.__str__()
+
+class EnumCase(object):
+ def __init__(self, name, value):
+ self.name = name
+ self.value = value
+
+ def __str__(self):
+ return '%s = %s' % (self.name, self.value)
+
+class PackageID(object):
+ def __init__(self, name, version):
+ self.name = name
+ self.version = version
+
+ def __str__(self):
+ return '%s%s' % (self.name, self.version)
+
+class Package(object):
+ def __init__(self, package):
+ self.package = package
+
+ def __str__(self):
+ return 'package %s' % self.package
+
+class Import(object):
+ def __init__(self, package):
+ self.package = package
+
+ def __str__(self):
+ return 'import %s' % self.package
+
+class Header(object):
+ def __init__(self, package, imports):
+ self.package = package
+ self.imports = imports
+
+ def __str__(self):
+ return str(self.package) + "\n" + \
+ '\n'.join(str(x) for x in self.imports)
+
+# Error rule for syntax errors
+def p_error(p):
+ print("Syntax error in input: %s" % p)
+
+def p_document(t):
+ 'document : header enum_decls'
+ enums = {}
+ for enum in t[2]:
+ enums[enum.header.name] = enum
+ t[0] = {'header' : t[1], 'enums' : enums}
+
+def p_enum_decls_1(t):
+ 'enum_decls : enum_decl'
+ t[0] = [t[1]]
+def p_enum_decls_2(t):
+ 'enum_decls : enum_decls enum_decl'
+ t[0] = t[1] + [t[2]]
+
+def p_enum_cases_1(t):
+ 'enum_cases : enum_case'
+ t[0] = [t[1]]
+def p_enum_cases_2(t):
+ 'enum_cases : enum_cases COMMA enum_case'
+ t[0] = t[1] + [t[3]]
+
+def p_enum_base_1(t):
+ 'enum_base : VERSION COLON COLON IDENTIFIER'
+ t[0] = '%s::%s' % (t[1], t[4])
+def p_enum_base_2(t):
+ 'enum_base : IDENTIFIER'
+ t[0] = t[1]
+
+def p_enum_header_1(t):
+ 'enum_header : enum IDENTIFIER'
+ t[0] = EnumHeader(t[2], None)
+def p_enum_header_2(t):
+ 'enum_header : enum IDENTIFIER COLON enum_base'
+ t[0] = EnumHeader(t[2], t[4])
+
+def p_enum_decl_1(t):
+ 'enum_decl : enum_header LBRACE enum_cases RBRACE SEMICOLON'
+ t[0] = EnumDecl(t[1], t[3])
+def p_enum_decl_2(t):
+ 'enum_decl : enum_header LBRACE enum_cases COMMA RBRACE SEMICOLON'
+ t[0] = EnumDecl(t[1], t[3])
+
+def p_enum_value_1(t):
+ '''enum_value : NUMBER
+ | HEX
+ | IDENTIFIER'''
+ t[0] = t[1]
+def p_enum_value_2(t):
+ 'enum_value : enum_value SHIFT NUMBER'
+ t[0] = '%s << %s' % (t[1], t[3])
+def p_enum_value_3(t):
+ 'enum_value : enum_value OR enum_value'
+ t[0] = "%s | %s" % (t[1], t[3])
+def p_enum_value_4(t):
+ 'enum_value : LPAREN enum_value RPAREN'
+ t[0] = t[2]
+def p_enum_value_5(t):
+ 'enum_value : IDENTIFIER COLON IDENTIFIER'
+ t[0] = '%s:%s' % (t[1],t[3])
+
+def p_enum_case(t):
+ 'enum_case : IDENTIFIER EQUALS enum_value'
+ t[0] = EnumCase(t[1], t[3])
+
+def p_header_1(t):
+ 'header : package_decl'
+ t[0] = Header(t[1], [])
+
+def p_header_2(t):
+ 'header : package_decl import_decls'
+ t[0] = Header(t[1], t[2])
+
+def p_import_decls_1(t):
+ 'import_decls : import_decl'
+ t[0] = [t[1]]
+
+def p_import_decls_2(t):
+ 'import_decls : import_decls import_decl'
+ t[0] = t[1] + [t[2]]
+
+def p_package_decl(t):
+ 'package_decl : package package_ID SEMICOLON'
+ t[0] = Package(t[2])
+
+def p_import_decl(t):
+ 'import_decl : import package_ID SEMICOLON'
+ t[0] = Import(t[2])
+
+def p_package_ID(t):
+ 'package_ID : dotted_identifier VERSION'
+ t[0] = PackageID(t[1], t[2])
+
+def p_dotted_identifier_1(t):
+ 'dotted_identifier : IDENTIFIER'
+ t[0] = t[1]
+def p_dotted_identifier_2(t):
+ 'dotted_identifier : dotted_identifier DOT IDENTIFIER'
+ t[0] = t[1] + '.' + t[3]
+
+class SilentLogger(object):
+ def warning(*args):
+ pass
+
+import ply.yacc as yacc
+parser = yacc.yacc(debug=False, write_tables=False, errorlog=SilentLogger())
+import sys
+
+def parse(filename):
+ return parser.parse(open(filename, 'r').read())
diff --git a/tools/update-obd2-sensors.py b/tools/update-obd2-sensors.py
index 1691c42..d0a89d4 100755
--- a/tools/update-obd2-sensors.py
+++ b/tools/update-obd2-sensors.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3.4
#
-# Copyright (C) 2016 The Android Open Source Project
+# Copyright (C) 2017 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,30 +15,16 @@
# limitations under the License.
#
-# This script generates useful representations of the current list of OBD2
-# diagnostic sensors we support. It is meant as an easy way to update the
-# list of diagnostic sensors and get all the required lists pretty-printed
-# and ready for use.
-# The script contains three parts:
-# 1) the part marked DO NOT MODIFY THIS. This defines a domain-specific language
-# that allows one to give a list of sensors;
-# 2) the part marked ACTUAL SENSOR DEFINITIONS HERE. This part gives the list
-# of diagnostic sensors, provided in the DSL defined above;
-# 3) the generate() call at the very end. This triggers the script to perform
-# its generation task.
-# To keep it simple, this script will produce its output
-# to stdout, also in three parts:
-# 1) Vehicle HAL enumerations;
-# 2) Java classes with a list of sensor identifiers;
-# 3) Java @interfaces with a list of sensor identifiers.
-# The several parts contain comments that indicate which files the content has
-# to be pasted into. Should there be a need, the script could be extended to
-# automatically insert the content in the files.
-# To run:
-# $ ./update-obd2-sensors.py
+# This script generates useful Java representations for the OBD2 sensors
+# defined in Vehicle HAL. It is meant to be as an easy way to update the
+# list of diagnostic sensors and get all downstream users of that information
+# updated in a consistent fashion.
-## DO NOT MODIFY THIS
-## This code is the machinery required to make the sensor generator DSL work
+import sys
+sys.dont_write_bytecode = True
+
+import hidl_parser.parser
+
class SensorList(object):
"""A list of sensors ordered by a unique identifier."""
def __init__(self, descriptor):
@@ -56,8 +42,6 @@
def finalizeList(self):
"""Complete the list, adding well-known sensor information."""
self.id -= 1
- lastSystemSensor = self.sensorClass("LAST_SYSTEM_INDEX",
- id=self.sensors[-1].name)
vendorStartSensor = self.sensorClass("VENDOR_START_INDEX",
id="LAST_SYSTEM_INDEX + 1")
# make calling finalizeList idempotent
@@ -116,30 +100,6 @@
s += self.suffix(theSensors) + "\n"
return s
-class HalSensorPolicy(SensorPolicy):
- """The sensor policy that emits Vehicle HAL sensor descriptions."""
- def sensor(self, theSensor, theSensors):
- s = ""
- if theSensor.comment:
- s = theSensor.comment + "\n"
- s = s + theSensor.name + " = " + str(theSensor.id) + ","
- return s
-
- def prefix(self, theSensors):
- return "enum Obd2%sSensorIndex : int32_t {" % (theSensors.descriptor)
-
- def suffix(self, theSensors):
- return "}"
-
- def indent(self):
- return 2
-
- def separator(self):
- return "\n"
-
- def description(self):
- return "/** this goes in types.hal **/"
-
class JavaSensorPolicy(SensorPolicy):
"""The sensor policy that emits Java sensor descriptions."""
def sensor(self, theSensor, theSensors):
@@ -149,18 +109,17 @@
str(sensorId) + ";"
def prefix(self, theSensors):
- s = "public static final class Obd2%sSensorIndex {\n" % theSensors.descriptor
- s += " private Obd2%sSensorIndex() {}\n" % theSensors.descriptor
+ s = " public static final class Obd2%sSensorIndex {\n" % \
+ theSensors.descriptor
+ s += " private Obd2%sSensorIndex() {}\n" % \
+ theSensors.descriptor
return s
def suffix(self, theSensors):
- return "}"
+ return " }"
def indent(self):
- return 4
-
- def description(self):
- return "/** this goes in CarDiagnosticEvent.java **/"
+ return 8
class IntDefSensorPolicy(SensorPolicy):
"""The sensor policy that emits @IntDef sensor descriptions."""
@@ -169,13 +128,14 @@
return "Obd2%sSensorIndex.%s," % (theSensors.descriptor,sensorName)
def prefix(self, theSensors):
- return "@Retention(RetentionPolicy.SOURCE)\n@IntDef({"
+ return " @Retention(RetentionPolicy.SOURCE)\n @IntDef({"
+
+ def indent(self):
+ return 8
def suffix(self, theSensors):
- return "})\npublic @interface %sSensorIndex {}" % theSensors.descriptor
-
- def description(self):
- return "/** this goes in CarDiagnosticEvent.java **/"
+ return " })\n public @interface %sSensorIndex {}" % \
+ theSensors.descriptor
class SensorMeta(type):
"""Metaclass for sensor classes."""
@@ -207,138 +167,71 @@
class floatSensor(metaclass=SensorMeta):
sensorList = floatSensors
-def applyPolicy(policy):
+def applyPolicy(policy, destfile):
"""Given a sensor policy, apply it to all known sensor types"""
- print(policy.description())
- print(policy.sensors(intSensors))
- print(policy.sensors(floatSensors))
+ print(policy.sensors(intSensors), file=destfile)
+ print(policy.sensors(floatSensors), file=destfile)
-def java():
- applyPolicy(JavaSensorPolicy())
+def java(destfile):
+ applyPolicy(JavaSensorPolicy(), destfile)
-def hal():
- applyPolicy(HalSensorPolicy())
+def intdef(destfile):
+ applyPolicy(IntDefSensorPolicy(), destfile)
-def intdef():
- applyPolicy(IntDefSensorPolicy())
-
-def generate():
+def generate(filepath):
"""Generate data for all sensors."""
- hal()
- java()
- intdef()
+ destfile = open(filepath, "w")
+ print("/*", file=destfile)
+ print(" * Copyright (C) 2017 The Android Open Source Project", file=destfile)
+ print(" *", file=destfile)
+ print(" * Licensed under the Apache License, Version 2.0 (the \"License\");", file=destfile)
+ print(" * you may not use this file except in compliance with the License.", file=destfile)
+ print(" * You may obtain a copy of the License at", file=destfile)
+ print(" *", file=destfile)
+ print(" * http://www.apache.org/licenses/LICENSE-2.0", file=destfile)
+ print(" *", file=destfile)
+ print(" * Unless required by applicable law or agreed to in writing, software", file=destfile)
+ print(" * distributed under the License is distributed on an \"AS IS\" BASIS,", file=destfile)
+ print(" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", file=destfile)
+ print(" * See the License for the specific language governing permissions and", file=destfile)
+ print(" * limitations under the License.", file=destfile)
+ print("*/", file=destfile)
+ print("", file=destfile)
+ print("package android.car.hardware;", file=destfile)
+ print("", file=destfile)
+ print("import android.annotation.IntDef;", file=destfile)
+ print("import java.lang.annotation.Retention;", file=destfile)
+ print("import java.lang.annotation.RetentionPolicy;", file=destfile)
+ print("", file=destfile)
+ print("/**", file=destfile)
+ print(" * This class is a container for the indices of integer and float diagnostic sensors.", file=destfile)
+ print(" * These values are extracted from types.hal by packages/services/Car/tools/update-obd2-sensors.py", file=destfile)
+ print(" *", file=destfile)
+ print(" * DO NOT EDIT MANUALLY", file=destfile)
+ print(" *", file=destfile)
+ print(" * @hide", file=destfile)
+ print(" */", file=destfile)
+ print("public final class CarDiagnosticSensorIndices {", file=destfile)
+ java(destfile)
+ intdef(destfile)
+ print("}", file=destfile)
-## ACTUAL SENSOR DEFINITIONS HERE
-## Write sensor definitions here; terminate list with generate().
+def load(filepath):
+ """Load sensor data from Vehicle HAL."""
+ ast = hidl_parser.parser.parse(filepath)
+ integerSensors = ast['enums']['Obd2IntegerSensorIndex']
+ floatSensors = ast['enums']['Obd2FloatSensorIndex']
+ for case in integerSensors.cases:
+ intSensor(name=case.name, id=case.value)
+ for case in floatSensors.cases:
+ floatSensor(name=case.name, id=case.value)
-intSensor(name="FUEL_SYSTEM_STATUS", comment="/* refer to FuelSystemStatus for a description of this value. */")
-intSensor(name="MALFUNCTION_INDICATOR_LIGHT_ON")
-intSensor(name="IGNITION_MONITORS_SUPPORTED", comment="/* refer to IgnitionMonitorKind for a description of this value. */")
-intSensor(name="IGNITION_SPECIFIC_MONITORS", comment=r"""/*
- * The value of this sensor is a bitmask that specifies whether ignition-specific
- * tests are available and whether they are complete. The semantics of the individual
- * bits in this value are given by, respectively, SparkIgnitionMonitors and
- * CompressionIgnitionMonitors depending on the value of IGNITION_MONITORS_SUPPORTED.
- */""")
-intSensor(name="INTAKE_AIR_TEMPERATURE")
-intSensor(name="COMMANDED_SECONDARY_AIR_STATUS", comment="/* refer to SecondaryAirStatus for a description of this value. */")
-intSensor(name="NUM_OXYGEN_SENSORS_PRESENT")
-intSensor(name="RUNTIME_SINCE_ENGINE_START")
-intSensor(name="DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON")
-intSensor(name="WARMUPS_SINCE_CODES_CLEARED")
-intSensor(name="DISTANCE_TRAVELED_SINCE_CODES_CLEARED")
-intSensor(name="ABSOLUTE_BAROMETRIC_PRESSURE")
-intSensor(name="CONTROL_MODULE_VOLTAGE")
-intSensor(name="AMBIENT_AIR_TEMPERATURE")
-intSensor(name="TIME_WITH_MALFUNCTION_LIGHT_ON")
-intSensor(name="TIME_SINCE_TROUBLE_CODES_CLEARED")
-intSensor(name="MAX_FUEL_AIR_EQUIVALENCE_RATIO")
-intSensor(name="MAX_OXYGEN_SENSOR_VOLTAGE")
-intSensor(name="MAX_OXYGEN_SENSOR_CURRENT")
-intSensor(name="MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE")
-intSensor(name="MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR")
-intSensor(name="FUEL_TYPE", comment="/* refer to FuelType for a description of this value. */")
-intSensor(name="FUEL_RAIL_ABSOLUTE_PRESSURE")
-intSensor(name="ENGINE_OIL_TEMPERATURE")
-intSensor(name="DRIVER_DEMAND_PERCENT_TORQUE")
-intSensor(name="ENGINE_ACTUAL_PERCENT_TORQUE")
-intSensor(name="ENGINE_REFERENCE_PERCENT_TORQUE")
-intSensor(name="ENGINE_PERCENT_TORQUE_DATA_IDLE")
-intSensor(name="ENGINE_PERCENT_TORQUE_DATA_POINT1")
-intSensor(name="ENGINE_PERCENT_TORQUE_DATA_POINT2")
-intSensor(name="ENGINE_PERCENT_TORQUE_DATA_POINT3")
-intSensor(name="ENGINE_PERCENT_TORQUE_DATA_POINT4")
+import os
-floatSensor(name="CALCULATED_ENGINE_LOAD")
-floatSensor(name="ENGINE_COOLANT_TEMPERATURE")
-floatSensor(name="SHORT_TERM_FUEL_TRIM_BANK1")
-floatSensor(name="LONG_TERM_FUEL_TRIM_BANK1")
-floatSensor(name="SHORT_TERM_FUEL_TRIM_BANK2")
-floatSensor(name="LONG_TERM_FUEL_TRIM_BANK2")
-floatSensor(name="FUEL_PRESSURE")
-floatSensor(name="INTAKE_MANIFOLD_ABSOLUTE_PRESSURE")
-floatSensor(name="ENGINE_RPM")
-floatSensor(name="VEHICLE_SPEED")
-floatSensor(name="TIMING_ADVANCE")
-floatSensor(name="MAF_AIR_FLOW_RATE")
-floatSensor(name="THROTTLE_POSITION")
-floatSensor(name="OXYGEN_SENSOR1_VOLTAGE")
-floatSensor(name="OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM")
-floatSensor(name="OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO")
-floatSensor(name="OXYGEN_SENSOR2_VOLTAGE")
-floatSensor(name="OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM")
-floatSensor(name="OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO")
-floatSensor(name="OXYGEN_SENSOR3_VOLTAGE")
-floatSensor(name="OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM")
-floatSensor(name="OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO")
-floatSensor(name="OXYGEN_SENSOR4_VOLTAGE")
-floatSensor(name="OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM")
-floatSensor(name="OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO")
-floatSensor(name="OXYGEN_SENSOR5_VOLTAGE")
-floatSensor(name="OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM")
-floatSensor(name="OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO")
-floatSensor(name="OXYGEN_SENSOR6_VOLTAGE")
-floatSensor(name="OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM")
-floatSensor(name="OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO")
-floatSensor(name="OXYGEN_SENSOR7_VOLTAGE")
-floatSensor(name="OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM")
-floatSensor(name="OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO")
-floatSensor(name="OXYGEN_SENSOR8_VOLTAGE")
-floatSensor(name="OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM")
-floatSensor(name="OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO")
-floatSensor(name="FUEL_RAIL_PRESSURE")
-floatSensor(name="FUEL_RAIL_GAUGE_PRESSURE")
-floatSensor(name="COMMANDED_EXHAUST_GAS_RECIRCULATION")
-floatSensor(name="EXHAUST_GAS_RECIRCULATION_ERROR")
-floatSensor(name="COMMANDED_EVAPORATIVE_PURGE")
-floatSensor(name="FUEL_TANK_LEVEL_INPUT")
-floatSensor(name="EVAPORATION_SYSTEM_VAPOR_PRESSURE")
-floatSensor(name="CATALYST_TEMPERATURE_BANK1_SENSOR1")
-floatSensor(name="CATALYST_TEMPERATURE_BANK2_SENSOR1")
-floatSensor(name="CATALYST_TEMPERATURE_BANK1_SENSOR2")
-floatSensor(name="CATALYST_TEMPERATURE_BANK2_SENSOR2")
-floatSensor(name="ABSOLUTE_LOAD_VALUE")
-floatSensor(name="FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO")
-floatSensor(name="RELATIVE_THROTTLE_POSITION")
-floatSensor(name="ABSOLUTE_THROTTLE_POSITION_B")
-floatSensor(name="ABSOLUTE_THROTTLE_POSITION_C")
-floatSensor(name="ACCELERATOR_PEDAL_POSITION_D")
-floatSensor(name="ACCELERATOR_PEDAL_POSITION_E")
-floatSensor(name="ACCELERATOR_PEDAL_POSITION_F")
-floatSensor(name="COMMANDED_THROTTLE_ACTUATOR")
-floatSensor(name="ETHANOL_FUEL_PERCENTAGE")
-floatSensor(name="ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE")
-floatSensor(name="SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1")
-floatSensor(name="SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2")
-floatSensor(name="SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3")
-floatSensor(name="SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4")
-floatSensor(name="LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1")
-floatSensor(name="LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2")
-floatSensor(name="LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3")
-floatSensor(name="LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4")
-floatSensor(name="RELATIVE_ACCELERATOR_PEDAL_POSITION")
-floatSensor(name="HYBRID_BATTERY_PACK_REMAINING_LIFE")
-floatSensor(name="FUEL_INJECTION_TIMING")
-floatSensor(name="ENGINE_FUEL_RATE")
-
-generate()
+if len(sys.argv) != 3:
+ print('syntax: update-obd2-sensors.py <path/to/types.hal> <path/to/CarDiagnosticSensorIndices.java>')
+ print('This scrippt will parse types.hal, and use the resulting', end='')
+ print('parse tree to generate CarDiagnosticSensorIndices.java.')
+ sys.exit(1)
+load(sys.argv[1])
+generate(sys.argv[2])