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
17package com.android.car.obd2.test;
18
19import static com.android.car.obd2.test.Utils.concatIntArrays;
20import static com.android.car.obd2.test.Utils.stringsToIntArray;
21import static org.junit.Assert.*;
22
23import com.android.car.obd2.Obd2Command;
24import com.android.car.obd2.Obd2Connection;
25import java.util.Optional;
26import org.junit.Test;
27
28public class Obd2CommandTest {
29    private static final String[] EXPECTED_INIT_COMMANDS =
30            new String[] {
31                "ATD\r", "ATZ\r", "AT E0\r", "AT L0\r", "AT S0\r", "AT H0\r", "AT SP 0\r"
32            };
33
34    private static final String OBD2_PROMPT = ">";
35
36    private static final String[] EXPECTED_INIT_RESPONSES =
37            new String[] {
38                OBD2_PROMPT,
39                OBD2_PROMPT,
40                OBD2_PROMPT,
41                OBD2_PROMPT,
42                OBD2_PROMPT,
43                OBD2_PROMPT,
44                OBD2_PROMPT
45            };
46
47    private static final float FLOAT_EQUALITY_DELTA = 0.0001f;
48
49    void checkLiveFrameIntCommand(int pid, String responseBytes, int expectedResponse) {
50        String[] commandToSend = new String[] {String.format("01%02X\r", pid)};
51
52        String[] responseToGet =
53                new String[] {String.format("41 %02X %s", pid, responseBytes), OBD2_PROMPT};
54
55        MockObd2UnderlyingTransport transport =
56                new MockObd2UnderlyingTransport(
57                        concatIntArrays(
58                                stringsToIntArray(EXPECTED_INIT_COMMANDS),
59                                stringsToIntArray(commandToSend)),
60                        concatIntArrays(
61                                stringsToIntArray(EXPECTED_INIT_RESPONSES),
62                                stringsToIntArray(responseToGet)));
63        Obd2Connection obd2Connection = new Obd2Connection(transport);
64        Obd2Command<Integer> commandObject =
65                Obd2Command.getLiveFrameCommand(Obd2Command.getIntegerCommand(pid));
66        assertNotNull(commandObject);
67        Optional<Integer> receivedResponse = Optional.empty();
68        try {
69            receivedResponse = commandObject.run(obd2Connection);
70        } catch (Exception e) {
71            assertTrue("live frame command " + pid + " caused an exception: " + e, false);
72        }
73        assertTrue("live frame contains a response", receivedResponse.isPresent());
74        assertEquals(expectedResponse, (int) receivedResponse.get());
75    }
76
77    void checkLiveFrameFloatCommand(int pid, String responseBytes, float expectedResponse) {
78        String[] commandToSend = new String[] {String.format("01%02X\r", pid)};
79
80        String[] responseToGet =
81                new String[] {String.format("41 %02X %s", pid, responseBytes), OBD2_PROMPT};
82
83        MockObd2UnderlyingTransport transport =
84                new MockObd2UnderlyingTransport(
85                        concatIntArrays(
86                                stringsToIntArray(EXPECTED_INIT_COMMANDS),
87                                stringsToIntArray(commandToSend)),
88                        concatIntArrays(
89                                stringsToIntArray(EXPECTED_INIT_RESPONSES),
90                                stringsToIntArray(responseToGet)));
91        Obd2Connection obd2Connection = new Obd2Connection(transport);
92        Obd2Command<Float> commandObject =
93                Obd2Command.getLiveFrameCommand(Obd2Command.getFloatCommand(pid));
94        assertNotNull(commandObject);
95        Optional<Float> receivedResponse = Optional.empty();
96        try {
97            receivedResponse = commandObject.run(obd2Connection);
98        } catch (Exception e) {
99            assertTrue("live frame command " + pid + " caused an exception: " + e, false);
100        }
101        assertTrue("live frame contains a response", receivedResponse.isPresent());
102        assertEquals(expectedResponse, (float) receivedResponse.get(), FLOAT_EQUALITY_DELTA);
103    }
104
105    void checkFreezeFrameIntCommand(int pid, String responseBytes, int expectedResponse) {
106        String[] commandToSend = new String[] {String.format("02%02X 01\r", pid)};
107
108        String[] responseToGet =
109                new String[] {String.format("42 %02X 01 %s", pid, responseBytes), OBD2_PROMPT};
110
111        MockObd2UnderlyingTransport transport =
112                new MockObd2UnderlyingTransport(
113                        concatIntArrays(
114                                stringsToIntArray(EXPECTED_INIT_COMMANDS),
115                                stringsToIntArray(commandToSend)),
116                        concatIntArrays(
117                                stringsToIntArray(EXPECTED_INIT_RESPONSES),
118                                stringsToIntArray(responseToGet)));
119        Obd2Connection obd2Connection = new Obd2Connection(transport);
120        Obd2Command<Integer> commandObject =
121                Obd2Command.getFreezeFrameCommand(Obd2Command.getIntegerCommand(pid), 0x1);
122        assertNotNull(commandObject);
123        Optional<Integer> receivedResponse = Optional.empty();
124        try {
125            receivedResponse = commandObject.run(obd2Connection);
126        } catch (Exception e) {
127            assertTrue("freeze frame command " + pid + " caused an exception: " + e, false);
128        }
129        assertTrue("freeze frame contains a response", receivedResponse.isPresent());
130        assertEquals(expectedResponse, (int) receivedResponse.get());
131    }
132
133    void checkFreezeFrameFloatCommand(int pid, String responseBytes, float expectedResponse) {
134        String[] commandToSend = new String[] {String.format("02%02X 01\r", pid)};
135
136        String[] responseToGet =
137                new String[] {String.format("42 %02X 01 %s", pid, responseBytes), OBD2_PROMPT};
138
139        MockObd2UnderlyingTransport transport =
140                new MockObd2UnderlyingTransport(
141                        concatIntArrays(
142                                stringsToIntArray(EXPECTED_INIT_COMMANDS),
143                                stringsToIntArray(commandToSend)),
144                        concatIntArrays(
145                                stringsToIntArray(EXPECTED_INIT_RESPONSES),
146                                stringsToIntArray(responseToGet)));
147        Obd2Connection obd2Connection = new Obd2Connection(transport);
148        Obd2Command<Float> commandObject =
149                Obd2Command.getFreezeFrameCommand(Obd2Command.getFloatCommand(pid), 0x1);
150        assertNotNull(commandObject);
151        Optional<Float> receivedResponse = Optional.empty();
152        try {
153            receivedResponse = commandObject.run(obd2Connection);
154        } catch (Exception e) {
155            assertTrue("freeze frame command " + pid + " caused an exception: " + e, false);
156        }
157        assertTrue("freeze frame contains a response", receivedResponse.isPresent());
158        assertEquals(expectedResponse, (float) receivedResponse.get(), FLOAT_EQUALITY_DELTA);
159    }
160
161    void checkCommand(int pid, String responseBytes, int expectedResponse) {
162        checkLiveFrameIntCommand(pid, responseBytes, expectedResponse);
163        checkFreezeFrameIntCommand(pid, responseBytes, expectedResponse);
164    }
165
166    void checkCommand(int pid, String responseBytes, float expectedResponse) {
167        checkLiveFrameFloatCommand(pid, responseBytes, expectedResponse);
168        checkFreezeFrameFloatCommand(pid, responseBytes, expectedResponse);
169    }
170
171    @Test
172    public void testEngineOilTemperature() {
173        checkCommand(0x5C, "87", 95);
174    }
175
176    @Test
177    public void testAmbientAirTemperature() {
178        checkCommand(0x46, "A1", 63.137257f);
179    }
180
181    @Test
182    public void testCalculatedEngineLoad() {
183        checkCommand(0x04, "34", 23.1111f);
184    }
185
186    @Test
187    public void testEngineCoolantTemperature() {
188        checkCommand(0x05, "63", 59);
189    }
190
191    @Test
192    public void testFuelGaugePressure() {
193        checkCommand(0x0A, "12", 54);
194    }
195
196    @Test
197    public void testFuelSystemStatus() {
198        checkCommand(0x03, "08", 8);
199    }
200
201    @Test
202    public void testFuelTankLevel() {
203        checkCommand(0x2F, "5F", 37.2549f);
204    }
205
206    @Test
207    public void testFuelTrim() {
208        checkCommand(0x06, "42", 54.6875f);
209        checkCommand(0x07, "42", 54.6875f);
210        checkCommand(0x08, "42", 54.6875f);
211        checkCommand(0x09, "42", 54.6875f);
212    }
213
214    @Test
215    public void testRpm() {
216        checkCommand(0x0C, "12 0F", 1155);
217    }
218
219    @Test
220    public void testEngineRuntime() {
221        checkCommand(0x1F, "04 10", 1040);
222    }
223
224    @Test
225    public void testSpeed() {
226        checkCommand(0x0D, "82", 130);
227    }
228
229    @Test
230    public void testThrottlePosition() {
231        checkCommand(0x11, "3D", 23.921576f);
232    }
233}
234