1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car.obd2;
18 
19 import android.os.SystemClock;
20 import android.util.JsonWriter;
21 import android.util.Log;
22 import com.android.car.obd2.Obd2Command.LiveFrameCommand;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Optional;
27 import java.util.Set;
28 
29 public class Obd2LiveFrameGenerator {
30     public static final String FRAME_TYPE_LIVE = "live";
31     public static final String TAG = Obd2LiveFrameGenerator.class.getSimpleName();
32 
33     private final Obd2Connection mConnection;
34     private final List<LiveFrameCommand<Integer>> mIntegerCommands = new ArrayList<>();
35     private final List<LiveFrameCommand<Float>> mFloatCommands = new ArrayList<>();
36 
Obd2LiveFrameGenerator(Obd2Connection connection)37     public Obd2LiveFrameGenerator(Obd2Connection connection)
38             throws IOException, InterruptedException {
39         mConnection = connection;
40         Set<Integer> connectionPids = connection.getSupportedPIDs();
41         Set<Integer> apiIntegerPids = Obd2Command.getSupportedIntegerCommands();
42         Set<Integer> apiFloatPids = Obd2Command.getSupportedFloatCommands();
43         apiIntegerPids
44                 .stream()
45                 .filter(connectionPids::contains)
46                 .forEach(
47                         (Integer pid) ->
48                                 mIntegerCommands.add(
49                                         Obd2Command.getLiveFrameCommand(
50                                                 Obd2Command.getIntegerCommand(pid))));
51         apiFloatPids
52                 .stream()
53                 .filter(connectionPids::contains)
54                 .forEach(
55                         (Integer pid) ->
56                                 mFloatCommands.add(
57                                         Obd2Command.getLiveFrameCommand(
58                                                 Obd2Command.getFloatCommand(pid))));
59         Log.i(
60                 TAG,
61                 String.format(
62                         "connectionPids = %s\napiIntegerPids=%s\napiFloatPids = %s\n"
63                                 + "mIntegerCommands = %s\nmFloatCommands = %s\n",
64                         connectionPids,
65                         apiIntegerPids,
66                         apiFloatPids,
67                         mIntegerCommands,
68                         mFloatCommands));
69     }
70 
generate(JsonWriter jsonWriter)71     public JsonWriter generate(JsonWriter jsonWriter) throws IOException {
72         return generate(jsonWriter, SystemClock.elapsedRealtimeNanos());
73     }
74 
generate(JsonWriter jsonWriter, long timestamp)75     public JsonWriter generate(JsonWriter jsonWriter, long timestamp) throws IOException {
76         jsonWriter.beginObject();
77         jsonWriter.name("type").value(FRAME_TYPE_LIVE);
78         jsonWriter.name("timestamp").value(timestamp);
79         jsonWriter.name("intValues").beginArray();
80         for (LiveFrameCommand<Integer> command : mIntegerCommands) {
81             try {
82                 Optional<Integer> result = command.run(mConnection);
83                 if (result.isPresent()) {
84                     jsonWriter.beginObject();
85                     jsonWriter.name("id").value(command.getPid());
86                     jsonWriter.name("value").value(result.get());
87                     jsonWriter.endObject();
88                 }
89             } catch (IOException | InterruptedException e) {
90                 Log.w(
91                         TAG,
92                         String.format(
93                                 "unable to retrieve OBD2 pid %d due to exception: %s",
94                                 command.getPid(), e));
95                 // skip this entry
96             }
97         }
98         jsonWriter.endArray();
99 
100         jsonWriter.name("floatValues").beginArray();
101         for (LiveFrameCommand<Float> command : mFloatCommands) {
102             try {
103                 Optional<Float> result = command.run(mConnection);
104                 if (result.isPresent()) {
105                     jsonWriter.beginObject();
106                     jsonWriter.name("id").value(command.getPid());
107                     jsonWriter.name("value").value(result.get());
108                     jsonWriter.endObject();
109                 }
110             } catch (IOException | InterruptedException e) {
111                 Log.w(
112                         TAG,
113                         String.format(
114                                 "unable to retrieve OBD2 pid %d due to exception: %s",
115                                 command.getPid(), e));
116                 // skip this entry
117             }
118         }
119         jsonWriter.endArray();
120 
121         return jsonWriter.endObject();
122     }
123 }
124