• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2#
3# Copyright (C) 2017 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# A tool that can read diagnostic events from a Diagnostic JSON document
19# and forward them to Vehicle HAL via vhal_emulator
20# Use thusly:
21# $ ./diagnostic_injector.py <path/to/diagnostic.json>
22
23import argparse
24import json
25import sys
26import time
27
28import vhal_consts_2_0 as c
29
30# vhal_emulator depends on a custom Python package that requires installation
31# give user guidance should the import fail
32try:
33    from vhal_emulator import Vhal
34except ImportError as e:
35    isProtobuf = False
36    pipTool = "pip%s" % ("3" if sys.version_info > (3,0) else "")
37    if hasattr(e, 'name'):
38        if e.name == 'google': isProtobuf = True
39    elif hasattr(e, 'message'):
40        if e.message.endswith('symbol_database'):
41            isProtobuf = True
42    if isProtobuf:
43        print('could not find protobuf.')
44        print('protobuf can be installed via "sudo %s install --upgrade protobuf"' % pipTool)
45        sys.exit(1)
46    else:
47        raise e
48
49from diagnostic_builder import DiagnosticEventBuilder
50
51class DiagnosticHalWrapper(object):
52    def __init__(self, device):
53        self.vhal = Vhal(c.vhal_types_2_0, device)
54        self.liveFrameConfig = self.chat(
55            lambda hal: hal.getConfig(c.VEHICLEPROPERTY_OBD2_LIVE_FRAME))
56        self.freezeFrameConfig = self.chat(
57            lambda hal: hal.getConfig(c.VEHICLEPROPERTY_OBD2_FREEZE_FRAME))
58        self.eventTypeData = {
59            'live' : {
60                'builder'  : lambda: DiagnosticEventBuilder(self.liveFrameConfig),
61                'property' :  c.VEHICLEPROPERTY_OBD2_LIVE_FRAME
62            },
63            'freeze' : {
64                'builder'  : lambda: DiagnosticEventBuilder(self.freezeFrameConfig),
65                'property' :  c.VEHICLEPROPERTY_OBD2_FREEZE_FRAME
66            },
67        }
68
69    def chat(self, request):
70        request(self.vhal)
71        return self.vhal.rxMsg()
72
73    def inject(self, file):
74        data = json.load(open(file))
75        lastTimestamp = 0
76        for event in data:
77            currentTimestamp = event['timestamp']
78            # time travel isn't supported (yet)
79            assert currentTimestamp >= lastTimestamp
80            # wait the delta between this event and the previous one
81            # before sending it out; but on the first event, send now
82            # or we'd wait for a long long long time
83            if lastTimestamp != 0:
84                # also, timestamps are in nanoseconds, but sleep() uses seconds
85                time.sleep((currentTimestamp-lastTimestamp)/1000000000)
86            lastTimestamp = currentTimestamp
87            # now build the event
88            eventType = event['type'].encode('utf-8')
89            eventTypeData = self.eventTypeData[eventType]
90            builder = eventTypeData['builder']()
91            builder.setStringValue(event.get('stringValue', ''))
92            for intValue in event['intValues']:
93                builder.addIntSensor(intValue['id'], intValue['value'])
94            for floatValue in event['floatValues']:
95                builder.addFloatSensor(floatValue['id'], floatValue['value'])
96            builtEvent = builder.build()
97            print ("Sending %s %s..." % (eventType, builtEvent)),
98            # and send it
99            status = self.chat(
100                lambda hal:
101                    hal.setProperty(eventTypeData['property'],
102                        0,
103                        builtEvent)).status
104            if status == 0:
105                print("ok!")
106            else:
107                print("fail: %s" % status)
108
109parser = argparse.ArgumentParser(description='Diagnostic Events Injector')
110parser.add_argument('jsondoc', nargs='+')
111parser.add_argument('-s', action='store', dest='deviceid', default=None)
112
113args = parser.parse_args()
114
115halWrapper = DiagnosticHalWrapper(device=args.deviceid)
116
117for arg in args.jsondoc:
118    print("Injecting %s" % arg)
119    halWrapper.inject(arg)
120