blob: 02acbc9fbf7bc5467da693f8d5e3477add209512 [file] [log] [blame]
Enrico Granata6988f002017-02-13 12:07:52 -08001#!/usr/bin/env python3.4
2#
Enrico Granata4c43add2017-03-15 18:01:34 -07003# Copyright (C) 2017 The Android Open Source Project
Enrico Granata6988f002017-02-13 12:07:52 -08004#
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
Enrico Granata4c43add2017-03-15 18:01:34 -070018# This script generates useful Java representations for the OBD2 sensors
19# defined in Vehicle HAL. It is meant to be as an easy way to update the
20# list of diagnostic sensors and get all downstream users of that information
21# updated in a consistent fashion.
Enrico Granata6988f002017-02-13 12:07:52 -080022
Enrico Granata4c43add2017-03-15 18:01:34 -070023import sys
24sys.dont_write_bytecode = True
25
26import hidl_parser.parser
27
Enrico Granata6988f002017-02-13 12:07:52 -080028class SensorList(object):
29 """A list of sensors ordered by a unique identifier."""
30 def __init__(self, descriptor):
31 self.sensors = []
32 self.id = -1
33 self.descriptor = descriptor
34
35 def addSensor(self, sensor):
36 """Add a new sensor to the list."""
37 if not hasattr(sensor, 'id'):
38 self.id += 1
39 sensor.id = self.id
40 self.sensors.append(sensor)
41
42 def finalizeList(self):
43 """Complete the list, adding well-known sensor information."""
44 self.id -= 1
Enrico Granata6988f002017-02-13 12:07:52 -080045 vendorStartSensor = self.sensorClass("VENDOR_START_INDEX",
46 id="LAST_SYSTEM_INDEX + 1")
47 # make calling finalizeList idempotent
48 self.finalizeList = lambda: self
49 return self
50
51 def __getitem__(self, key):
52 return self.sensors.__getitem__(key)
53
54class SensorPolicy(object):
55 """A formatter object that does processing on sensor data."""
56 @classmethod
57 def indentLines(cls, string, numSpaces):
58 indent = ' ' * numSpaces
59 parts = string.split('\n')
60 parts = [indent + part for part in parts]
61 return '\n'.join(parts) + "\n"
62
63 def sensor(self, theSensor, theSensors):
64 """Produce output for a sensor."""
65 pass
66
67 def prefix(self, theSensors):
68 """Prefix string before any sensor data is generated."""
69 return ""
70
Enrico Granatad20ed362017-03-30 11:12:26 -070071 def suffix(self, theSensors):
Enrico Granata6988f002017-02-13 12:07:52 -080072 """Suffix string after all sensor data is generated."""
73 return ""
74
75 def indent(self):
76 """Indentation level for individual sensor data."""
77 return 0
78
79 def separator(self):
80 """Separator between individual sensor data entries."""
81 return ""
82
83 def description(self):
84 """A description of this policy."""
85 return "A sensor policy."
86
87 def sensors(self, theSensors):
88 """Produce output for all sensors."""
89 theSensors = theSensors.finalizeList()
90 s = self.prefix(theSensors) + "\n"
91 first = True
92 for theSensor in theSensors:
93 if first:
94 first = False
95 else:
96 s += self.separator()
97 sensorLine = SensorPolicy.indentLines(self.sensor(theSensor,
98 theSensors), self.indent())
99 s += sensorLine
100 s += self.suffix(theSensors) + "\n"
101 return s
102
Enrico Granata6988f002017-02-13 12:07:52 -0800103class JavaSensorPolicy(SensorPolicy):
104 """The sensor policy that emits Java sensor descriptions."""
105 def sensor(self, theSensor, theSensors):
106 sensorName = theSensor.name.replace("_INDEX", "")
107 sensorId = str(theSensor.id).replace("_INDEX", "")
108 return "public static final int " + sensorName + " = " + \
109 str(sensorId) + ";"
110
111 def prefix(self, theSensors):
Enrico Granata976cee42017-07-25 17:23:45 -0700112 s = " public static final class %sSensorIndex {\n" % \
Enrico Granata4c43add2017-03-15 18:01:34 -0700113 theSensors.descriptor
Enrico Granata976cee42017-07-25 17:23:45 -0700114 s += " private %sSensorIndex() {}\n" % \
Enrico Granata4c43add2017-03-15 18:01:34 -0700115 theSensors.descriptor
Enrico Granata6988f002017-02-13 12:07:52 -0800116 return s
117
118 def suffix(self, theSensors):
Enrico Granata4c43add2017-03-15 18:01:34 -0700119 return " }"
Enrico Granata6988f002017-02-13 12:07:52 -0800120
121 def indent(self):
Enrico Granata4c43add2017-03-15 18:01:34 -0700122 return 8
Enrico Granata6988f002017-02-13 12:07:52 -0800123
Enrico Granatad20ed362017-03-30 11:12:26 -0700124class PythonSensorPolicy(SensorPolicy):
125 """The sensor policy that emits Python sensor descriptions."""
126 def sensor(self, theSensor, theSensors):
Enrico Granata976cee42017-07-25 17:23:45 -0700127 return "DIAGNOSTIC_SENSOR_%s_%s = %s" % (
Enrico Granatad20ed362017-03-30 11:12:26 -0700128 theSensors.descriptor.upper(),
129 theSensor.name.upper(),
130 self.adjustSensorId(theSensors.descriptor.upper(), str(theSensor.id))
131 )
132
133 def adjustSensorId(self, descriptor, sensorId):
134 if sensorId.isdigit(): return sensorId
Enrico Granata976cee42017-07-25 17:23:45 -0700135 return "DIAGNOSTIC_SENSOR_%s_%s" % (descriptor, sensorId.upper())
Enrico Granatad20ed362017-03-30 11:12:26 -0700136
Enrico Granata6988f002017-02-13 12:07:52 -0800137class IntDefSensorPolicy(SensorPolicy):
138 """The sensor policy that emits @IntDef sensor descriptions."""
139 def sensor(self, theSensor, theSensors):
140 sensorName = theSensor.name.replace("_INDEX", "")
Enrico Granata976cee42017-07-25 17:23:45 -0700141 return "%sSensorIndex.%s," % (theSensors.descriptor,sensorName)
Enrico Granata6988f002017-02-13 12:07:52 -0800142
143 def prefix(self, theSensors):
Enrico Granata4c43add2017-03-15 18:01:34 -0700144 return " @Retention(RetentionPolicy.SOURCE)\n @IntDef({"
145
146 def indent(self):
147 return 8
Enrico Granata6988f002017-02-13 12:07:52 -0800148
149 def suffix(self, theSensors):
Enrico Granata976cee42017-07-25 17:23:45 -0700150 return " })\n public @interface Diagnostic%sSensorIndex {}" % \
Enrico Granata4c43add2017-03-15 18:01:34 -0700151 theSensors.descriptor
Enrico Granata6988f002017-02-13 12:07:52 -0800152
153class SensorMeta(type):
154 """Metaclass for sensor classes."""
155 def __new__(cls, name, parents, dct):
156 sensorList = dct['sensorList']
157 class SensorBase(object):
158 def __init__(self, name, comment=None, id=None):
159 self.name = name
160 self.comment = comment if comment else ""
161 if id: self.id = id
162 sensorList.addSensor(self)
163 def __repr__(self):
164 s = ""
165 if self.comment:
166 s = s + self.comment + "\n"
167 s = s + self.name + " = " + str(self.id)
168 return s
169
170 newClass = super().__new__(cls, name, (SensorBase,), dct)
171 sensorList.sensorClass = newClass
172 return newClass
173
174intSensors = SensorList(descriptor="Integer")
175floatSensors = SensorList(descriptor="Float")
176
177class intSensor(metaclass=SensorMeta):
178 sensorList = intSensors
179
180class floatSensor(metaclass=SensorMeta):
181 sensorList = floatSensors
182
Enrico Granata4c43add2017-03-15 18:01:34 -0700183def applyPolicy(policy, destfile):
Enrico Granata6988f002017-02-13 12:07:52 -0800184 """Given a sensor policy, apply it to all known sensor types"""
Enrico Granata4c43add2017-03-15 18:01:34 -0700185 print(policy.sensors(intSensors), file=destfile)
186 print(policy.sensors(floatSensors), file=destfile)
Enrico Granata6988f002017-02-13 12:07:52 -0800187
Enrico Granata4c43add2017-03-15 18:01:34 -0700188def java(destfile):
189 applyPolicy(JavaSensorPolicy(), destfile)
Enrico Granata6988f002017-02-13 12:07:52 -0800190
Enrico Granata4c43add2017-03-15 18:01:34 -0700191def intdef(destfile):
192 applyPolicy(IntDefSensorPolicy(), destfile)
Enrico Granata6988f002017-02-13 12:07:52 -0800193
Enrico Granatad20ed362017-03-30 11:12:26 -0700194def python(destfile):
195 applyPolicy(PythonSensorPolicy(), destfile)
196
197def generateJava(filepath):
198 """Generate Java code for all sensors."""
Enrico Granata4c43add2017-03-15 18:01:34 -0700199 destfile = open(filepath, "w")
200 print("/*", file=destfile)
201 print(" * Copyright (C) 2017 The Android Open Source Project", file=destfile)
202 print(" *", file=destfile)
203 print(" * Licensed under the Apache License, Version 2.0 (the \"License\");", file=destfile)
204 print(" * you may not use this file except in compliance with the License.", file=destfile)
205 print(" * You may obtain a copy of the License at", file=destfile)
206 print(" *", file=destfile)
207 print(" * http://www.apache.org/licenses/LICENSE-2.0", file=destfile)
208 print(" *", file=destfile)
209 print(" * Unless required by applicable law or agreed to in writing, software", file=destfile)
210 print(" * distributed under the License is distributed on an \"AS IS\" BASIS,", file=destfile)
211 print(" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", file=destfile)
212 print(" * See the License for the specific language governing permissions and", file=destfile)
213 print(" * limitations under the License.", file=destfile)
214 print("*/", file=destfile)
215 print("", file=destfile)
216 print("package android.car.hardware;", file=destfile)
217 print("", file=destfile)
218 print("import android.annotation.IntDef;", file=destfile)
Enrico Granata976cee42017-07-25 17:23:45 -0700219 print("import android.annotation.SystemApi;", file=destfile)
Enrico Granata4c43add2017-03-15 18:01:34 -0700220 print("import java.lang.annotation.Retention;", file=destfile)
221 print("import java.lang.annotation.RetentionPolicy;", file=destfile)
222 print("", file=destfile)
223 print("/**", file=destfile)
224 print(" * This class is a container for the indices of integer and float diagnostic sensors.", file=destfile)
225 print(" * These values are extracted from types.hal by packages/services/Car/tools/update-obd2-sensors.py", file=destfile)
226 print(" *", file=destfile)
227 print(" * DO NOT EDIT MANUALLY", file=destfile)
228 print(" *", file=destfile)
229 print(" * @hide", file=destfile)
230 print(" */", file=destfile)
Enrico Granata976cee42017-07-25 17:23:45 -0700231 print("@SystemApi", file=destfile)
Enrico Granata4c43add2017-03-15 18:01:34 -0700232 print("public final class CarDiagnosticSensorIndices {", file=destfile)
233 java(destfile)
234 intdef(destfile)
235 print("}", file=destfile)
Enrico Granata6988f002017-02-13 12:07:52 -0800236
Enrico Granatad20ed362017-03-30 11:12:26 -0700237def generatePython(filepath):
238 """Generate Python code for all sensors."""
239 destfile = open(filepath, "w")
240 print("#!/usr/bin/env python3", file=destfile)
241 print("#", file=destfile)
242 print("# Copyright (C) 2017 The Android Open Source Project", file=destfile)
243 print("#", file=destfile)
244 print("# Licensed under the Apache License, Version 2.0 (the \"License\");", file=destfile)
245 print("# you may not use this file except in compliance with the License.", file=destfile)
246 print("# You may obtain a copy of the License at", file=destfile)
247 print("#", file=destfile)
248 print("# http://www.apache.org/licenses/LICENSE-2.0", file=destfile)
249 print("#", file=destfile)
250 print("# Unless required by applicable law or agreed to in writing, software", file=destfile)
251 print("# distributed under the License is distributed on an \"AS IS\" BASIS,", file=destfile)
252 print("# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", file=destfile)
253 print("# See the License for the specific language governing permissions and", file=destfile)
254 print("# limitations under the License.", file=destfile)
255 print("#", file=destfile)
256 print("# This file is generated by types.hal by packages/services/Car/tools/update-obd2-sensors.py", file=destfile)
257 print("# DO NOT EDIT MANUALLY", file=destfile)
258 python(destfile)
259
Enrico Granata4c43add2017-03-15 18:01:34 -0700260def load(filepath):
261 """Load sensor data from Vehicle HAL."""
262 ast = hidl_parser.parser.parse(filepath)
Enrico Granata976cee42017-07-25 17:23:45 -0700263 integerSensors = ast['enums']['DiagnosticIntegerSensorIndex']
264 floatSensors = ast['enums']['DiagnosticFloatSensorIndex']
Enrico Granata4c43add2017-03-15 18:01:34 -0700265 for case in integerSensors.cases:
266 intSensor(name=case.name, id=case.value)
267 for case in floatSensors.cases:
268 floatSensor(name=case.name, id=case.value)
Enrico Granata6988f002017-02-13 12:07:52 -0800269
Enrico Granata4c43add2017-03-15 18:01:34 -0700270import os
Enrico Granata6988f002017-02-13 12:07:52 -0800271
Enrico Granatad20ed362017-03-30 11:12:26 -0700272if len(sys.argv) != 4:
273 print('syntax: update-obd2-sensors.py <path/to/types.hal> <path/to/CarDiagnosticSensorIndices.java> <path/to/diagnostic_sensors.py>')
274 print('This script will parse types.hal, and use the resulting', end='')
Enrico Granata4c43add2017-03-15 18:01:34 -0700275 print('parse tree to generate CarDiagnosticSensorIndices.java.')
276 sys.exit(1)
277load(sys.argv[1])
Enrico Granatad20ed362017-03-30 11:12:26 -0700278generateJava(sys.argv[2])
279generatePython(sys.argv[3])