├── .gitignore ├── LICENSE ├── README.md ├── adapter ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── devesion │ │ └── commons │ │ └── obd │ │ └── adapter │ │ ├── command │ │ ├── AbstractCommand.java │ │ ├── CommandResult.java │ │ ├── ObdCommand.java │ │ ├── ObdCommandVisitor.java │ │ ├── at │ │ │ ├── AbstractAtCommand.java │ │ │ ├── AbstractSetStateCommand.java │ │ │ ├── AdaptiveTimeoutProtocolCommand.java │ │ │ ├── AtCommand.java │ │ │ ├── EnableBaudRateCommand.java │ │ │ ├── ResetCommand.java │ │ │ ├── SelectProtocolCommand.java │ │ │ ├── SetBaudRateCommand.java │ │ │ ├── SetDefaultsCommand.java │ │ │ ├── SetEchoCommand.java │ │ │ ├── SetHeadersCommand.java │ │ │ ├── SetLineFeedCommand.java │ │ │ ├── SetMemoryCommand.java │ │ │ └── SetSpacesCommand.java │ │ ├── diagnostic │ │ │ ├── AbstractDiagnosticCommand.java │ │ │ ├── DiagnosticCommand.java │ │ │ ├── DiagnosticCommandMode.java │ │ │ ├── DiagnosticCommandPid.java │ │ │ ├── info │ │ │ │ └── InfoCommandPid.java │ │ │ ├── monitors │ │ │ │ └── MonitorCommandPid.java │ │ │ └── sensors │ │ │ │ ├── AbstractSensorCommand.java │ │ │ │ ├── AmbientAirTemperatureCommand.java │ │ │ │ ├── EngineCoolantTemperatureCommand.java │ │ │ │ ├── EngineLoadCommand.java │ │ │ │ ├── EngineRpmCommand.java │ │ │ │ ├── EngineRuntimeCommand.java │ │ │ │ ├── FuelConsumptionRateCommand.java │ │ │ │ ├── FuelLevelCommand.java │ │ │ │ ├── FuelPressureCommand.java │ │ │ │ ├── FuelTypeCommand.java │ │ │ │ ├── IntakeAirTemperatureCommand.java │ │ │ │ ├── MassAirFlowCommand.java │ │ │ │ ├── SensorCommand.java │ │ │ │ ├── SensorCommandPid.java │ │ │ │ ├── SpeedCommand.java │ │ │ │ ├── ThrottlePositionCommand.java │ │ │ │ └── units │ │ │ │ ├── AbstractSensorCommandValue.java │ │ │ │ ├── AirFlowValue.java │ │ │ │ ├── FuelConsumptionValue.java │ │ │ │ ├── FuelPressureValue.java │ │ │ │ ├── FuelTypeValue.java │ │ │ │ ├── PercentageValue.java │ │ │ │ ├── PressureValue.java │ │ │ │ ├── RpmValue.java │ │ │ │ ├── SensorCommandValue.java │ │ │ │ ├── SimpleValue.java │ │ │ │ ├── SpeedValue.java │ │ │ │ ├── TemperatureValue.java │ │ │ │ ├── TimeValue.java │ │ │ │ ├── UnitFactory.java │ │ │ │ └── VoltageValue.java │ │ └── invoker │ │ │ ├── CommandExceptionFactory.java │ │ │ └── CommandInvoker.java │ │ ├── link │ │ ├── CommandMarshaller.java │ │ ├── CommandUnmarshaller.java │ │ ├── ObdLink.java │ │ └── elm │ │ │ ├── AbstractCommandMarshaller.java │ │ │ ├── AbstractCommandUnmarshaller.java │ │ │ ├── AtCommandMarshaller.java │ │ │ ├── AtCommandUnmarshaller.java │ │ │ ├── CommandMarshallerBridge.java │ │ │ ├── CommandUnmarshallerBridge.java │ │ │ ├── DiagnosticCommandMarshaller.java │ │ │ ├── DiagnosticCommandUnmarshaller.java │ │ │ ├── ElmLink.java │ │ │ └── ElmTransport.java │ │ └── shared │ │ ├── HexTools.java │ │ ├── ObdAbstractRuntimeException.java │ │ ├── ObdCommandResponseException.java │ │ ├── ObdCommunicationException.java │ │ ├── ObdInvalidCommandResponseException.java │ │ ├── ObdNoDataForCommandResponseException.java │ │ ├── ObdNotProperlyInitializedException.java │ │ └── ObdNumberedEnum.java │ └── test │ └── java │ └── com │ └── devesion │ └── commons │ └── obd │ ├── ObdAdapterClient.java │ ├── TestSupport.java │ └── adapter │ ├── command │ ├── AbstractCommandTest.java │ ├── CommandResultTest.java │ ├── at │ │ ├── AbstractAtCommandTest.java │ │ ├── AbstractSetStateCommandTest.java │ │ ├── SelectProtocolCommandTest.java │ │ ├── SetEchoCommandTest.java │ │ ├── SetHeadersCommandTest.java │ │ ├── SetLineFeedCommandTest.java │ │ ├── SetMemoryCommandTest.java │ │ └── SetSpacesCommandTest.java │ ├── diagnostic │ │ ├── AbstractDiagnosticCommandTest.java │ │ └── sensors │ │ │ ├── AbstractSensorCommandTest.java │ │ │ ├── AmbientAirTemperatureCommandTest.java │ │ │ ├── BaseSensorCommandTest.java │ │ │ ├── EngineCoolantTemperatureCommandTest.java │ │ │ ├── EngineLoadCommandTest.java │ │ │ ├── EngineRpmCommandTest.java │ │ │ ├── EngineRuntimeCommandTest.java │ │ │ ├── FuelConsumptionRateCommandTest.java │ │ │ ├── FuelLevelCommandTest.java │ │ │ ├── FuelTypeCommandTest.java │ │ │ ├── IntakeAirTemperatureCommandTest.java │ │ │ ├── MassAirFlowCommandTest.java │ │ │ ├── ThrottlePositionCommandTest.java │ │ │ └── units │ │ │ ├── AirFlowValueTest.java │ │ │ ├── BaseValueTest.java │ │ │ ├── FuelConsumptionValueTest.java │ │ │ ├── FuelTypeValueTest.java │ │ │ ├── RpmValueTest.java │ │ │ ├── SimpleValueTest.java │ │ │ ├── TemperatureValueTest.java │ │ │ ├── TimeValueTest.java │ │ │ └── UnitFactoryTest.java │ └── invoker │ │ └── CommandInvokerTest.java │ ├── link │ └── elm │ │ ├── AbstractCommandUnmarshallerTest.java │ │ ├── DiagnosticCommandUnmarshallerTest.java │ │ ├── ElmLinkTest.java │ │ └── ElmTransportTest.java │ └── shared │ ├── BaseObdCommandResponseExceptionTest.java │ ├── ObdCommandResponseExceptionTest.java │ ├── ObdInvalidCommandResponseExceptionTest.java │ └── ObdnoDataForCommandResponseExceptionTest.java ├── client ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── autonalyzer │ │ └── adapter │ │ └── android │ │ ├── Launcher.java │ │ ├── domain │ │ ├── DiagnosticStatus.java │ │ ├── DiagnosticStatusFactory.java │ │ ├── DiagnosticStatusSpecification.java │ │ └── DiagnosticTransportSpecification.java │ │ └── infrastructure │ │ ├── DefaultDiagnosticStatusFactory.java │ │ ├── DiagnosticStatusReadException.java │ │ ├── gateway │ │ ├── DiagnosticStatusGateway.java │ │ ├── ProbingDiagnosticStatusGateway.java │ │ ├── ProbingDiagnosticStatusGatewayFactory.java │ │ └── elm │ │ │ ├── ElmDiagnosticStatusGateway.java │ │ │ └── ProbingElmDiagnosticStatusGateway.java │ │ └── transport │ │ ├── DiagnosticTransport.java │ │ ├── DiagnosticTransportFactory.java │ │ ├── DiagnosticTransportProbe.java │ │ ├── ProbingDiagnosticTransportFactory.java │ │ └── serial │ │ ├── SerialDiagnosticTransport.java │ │ └── SerialDiagnosticTransportFactory.java │ └── resources │ └── log4j.properties └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | target 3 | bin 4 | 5 | # Package Files # 6 | *.jar 7 | *.war 8 | *.ear 9 | 10 | # IDE files # 11 | .settings 12 | .project 13 | .classpath 14 | .idea 15 | *.iml -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and 10 | distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright 13 | owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all other entities 16 | that control, are controlled by, or are under common control with that entity. 17 | For the purposes of this definition, "control" means (i) the power, direct or 18 | indirect, to cause the direction or management of such entity, whether by 19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 20 | outstanding shares, or (iii) beneficial ownership of such entity. 21 | 22 | "You" (or "Your") shall mean an individual or Legal Entity exercising 23 | permissions granted by this License. 24 | 25 | "Source" form shall mean the preferred form for making modifications, including 26 | but not limited to software source code, documentation source, and configuration 27 | files. 28 | 29 | "Object" form shall mean any form resulting from mechanical transformation or 30 | translation of a Source form, including but not limited to compiled object code, 31 | generated documentation, and conversions to other media types. 32 | 33 | "Work" shall mean the work of authorship, whether in Source or Object form, made 34 | available under the License, as indicated by a copyright notice that is included 35 | in or attached to the work (an example is provided in the Appendix below). 36 | 37 | "Derivative Works" shall mean any work, whether in Source or Object form, that 38 | is based on (or derived from) the Work and for which the editorial revisions, 39 | annotations, elaborations, or other modifications represent, as a whole, an 40 | original work of authorship. For the purposes of this License, Derivative Works 41 | shall not include works that remain separable from, or merely link (or bind by 42 | name) to the interfaces of, the Work and Derivative Works thereof. 43 | 44 | "Contribution" shall mean any work of authorship, including the original version 45 | of the Work and any modifications or additions to that Work or Derivative Works 46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work 47 | by the copyright owner or by an individual or Legal Entity authorized to submit 48 | on behalf of the copyright owner. For the purposes of this definition, 49 | "submitted" means any form of electronic, verbal, or written communication sent 50 | to the Licensor or its representatives, including but not limited to 51 | communication on electronic mailing lists, source code control systems, and 52 | issue tracking systems that are managed by, or on behalf of, the Licensor for 53 | the purpose of discussing and improving the Work, but excluding communication 54 | that is conspicuously marked or otherwise designated in writing by the copyright 55 | owner as "Not a Contribution." 56 | 57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 58 | of whom a Contribution has been received by Licensor and subsequently 59 | incorporated within the Work. 60 | 61 | 2. Grant of Copyright License. 62 | 63 | Subject to the terms and conditions of this License, each Contributor hereby 64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 65 | irrevocable copyright license to reproduce, prepare Derivative Works of, 66 | publicly display, publicly perform, sublicense, and distribute the Work and such 67 | Derivative Works in Source or Object form. 68 | 69 | 3. Grant of Patent License. 70 | 71 | Subject to the terms and conditions of this License, each Contributor hereby 72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, 73 | irrevocable (except as stated in this section) patent license to make, have 74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where 75 | such license applies only to those patent claims licensable by such Contributor 76 | that are necessarily infringed by their Contribution(s) alone or by combination 77 | of their Contribution(s) with the Work to which such Contribution(s) was 78 | submitted. If You institute patent litigation against any entity (including a 79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a 80 | Contribution incorporated within the Work constitutes direct or contributory 81 | patent infringement, then any patent licenses granted to You under this License 82 | for that Work shall terminate as of the date such litigation is filed. 83 | 84 | 4. Redistribution. 85 | 86 | You may reproduce and distribute copies of the Work or Derivative Works thereof 87 | in any medium, with or without modifications, and in Source or Object form, 88 | provided that You meet the following conditions: 89 | 90 | You must give any other recipients of the Work or Derivative Works a copy of 91 | this License; and 92 | You must cause any modified files to carry prominent notices stating that You 93 | changed the files; and 94 | You must retain, in the Source form of any Derivative Works that You distribute, 95 | all copyright, patent, trademark, and attribution notices from the Source form 96 | of the Work, excluding those notices that do not pertain to any part of the 97 | Derivative Works; and 98 | If the Work includes a "NOTICE" text file as part of its distribution, then any 99 | Derivative Works that You distribute must include a readable copy of the 100 | attribution notices contained within such NOTICE file, excluding those notices 101 | that do not pertain to any part of the Derivative Works, in at least one of the 102 | following places: within a NOTICE text file distributed as part of the 103 | Derivative Works; within the Source form or documentation, if provided along 104 | with the Derivative Works; or, within a display generated by the Derivative 105 | Works, if and wherever such third-party notices normally appear. The contents of 106 | the NOTICE file are for informational purposes only and do not modify the 107 | License. You may add Your own attribution notices within Derivative Works that 108 | You distribute, alongside or as an addendum to the NOTICE text from the Work, 109 | provided that such additional attribution notices cannot be construed as 110 | modifying the License. 111 | You may add Your own copyright statement to Your modifications and may provide 112 | additional or different license terms and conditions for use, reproduction, or 113 | distribution of Your modifications, or for any such Derivative Works as a whole, 114 | provided Your use, reproduction, and distribution of the Work otherwise complies 115 | with the conditions stated in this License. 116 | 117 | 5. Submission of Contributions. 118 | 119 | Unless You explicitly state otherwise, any Contribution intentionally submitted 120 | for inclusion in the Work by You to the Licensor shall be under the terms and 121 | conditions of this License, without any additional terms or conditions. 122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of 123 | any separate license agreement you may have executed with Licensor regarding 124 | such Contributions. 125 | 126 | 6. Trademarks. 127 | 128 | This License does not grant permission to use the trade names, trademarks, 129 | service marks, or product names of the Licensor, except as required for 130 | reasonable and customary use in describing the origin of the Work and 131 | reproducing the content of the NOTICE file. 132 | 133 | 7. Disclaimer of Warranty. 134 | 135 | Unless required by applicable law or agreed to in writing, Licensor provides the 136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, 137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, 138 | including, without limitation, any warranties or conditions of TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are 140 | solely responsible for determining the appropriateness of using or 141 | redistributing the Work and assume any risks associated with Your exercise of 142 | permissions under this License. 143 | 144 | 8. Limitation of Liability. 145 | 146 | In no event and under no legal theory, whether in tort (including negligence), 147 | contract, or otherwise, unless required by applicable law (such as deliberate 148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be 149 | liable to You for damages, including any direct, indirect, special, incidental, 150 | or consequential damages of any character arising as a result of this License or 151 | out of the use or inability to use the Work (including but not limited to 152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or 153 | any and all other commercial damages or losses), even if such Contributor has 154 | been advised of the possibility of such damages. 155 | 156 | 9. Accepting Warranty or Additional Liability. 157 | 158 | While redistributing the Work or Derivative Works thereof, You may choose to 159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or 160 | other liability obligations and/or rights consistent with this License. However, 161 | in accepting such obligations, You may act only on Your own behalf and on Your 162 | sole responsibility, not on behalf of any other Contributor, and only if You 163 | agree to indemnify, defend, and hold each Contributor harmless for any liability 164 | incurred by, or claims asserted against, such Contributor by reason of your 165 | accepting any such warranty or additional liability. 166 | 167 | END OF TERMS AND CONDITIONS 168 | 169 | APPENDIX: How to apply the Apache License to your work 170 | 171 | To apply the Apache License to your work, attach the following boilerplate 172 | notice, with the fields enclosed by brackets "[]" replaced with your own 173 | identifying information. (Don't include the brackets!) The text should be 174 | enclosed in the appropriate comment syntax for the file format. We also 175 | recommend that a file or class name and description of purpose be included on 176 | the same "printed page" as the copyright notice for easier identification within 177 | third-party archives. 178 | 179 | Copyright [yyyy] [name of copyright owner] 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. 192 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # java-obd-adapter 2 | java-obd-adapter - OBD-II Java Adapter API 3 | 4 | ### Requisites 5 | * Java 7 6 | * Maven 3 7 | 8 | ### Supported Commands 9 | 10 | AT Commands 11 | * AT Z - AT Reset 12 | * AT SP - AT Select Protocol 13 | * AT D - AT Defaults 14 | * AT E - AT Set Echo On/Off 15 | * AT H - AT Set Headers On/Off 16 | * AT L - AT Set Linefeed On/Off 17 | * AT M - AT Set Memory On/Off 18 | * AT S - AT Set Spaces On/Off 19 | 20 | Diagnostic Commands 21 | * 01 04 - ENGINE_LOAD 22 | * 01 05 - ENGINE_COOLANT_TEMPERATURE 23 | * 01 0C - ENGINE_RPM 24 | * 01 0D - VEHICLE_SPEED 25 | * 01 0F - INTAKE_AIR_TEMPERATURE 26 | * 01 10 - MASS_AIR_FLOW 27 | * 01 11 - THROTTLE_POSITION_PERCENTAGE 28 | * 01 1F - ENGINE_RUN_TIME 29 | * 01 2F - FUEL_LEVEL 30 | * 01 46 - AMBIENT_AIR_TEMPERATURE 31 | * 01 51 - FUEL_TYPE 32 | * 01 5E - FUEL_CONSUMPTION_1 33 | * 01 5F - FUEL_CONSUMPTION_2 34 | 35 | ### Usage 36 | ``` 37 | 38 | com.devesion.commons.obd 39 | obd-adapter 40 | 1.0-SNAPSHOT 41 | 42 | ``` 43 | 44 | ``` 45 | private void invokeInitialCommands() { 46 | invokeCommandQuietly(new ResetCommand()); 47 | invokeCommand(new SetEchoCommand(false)); 48 | invokeCommand(new SetLineFeedCommand(false)); 49 | invokeCommand(new SetHeadersCommand(false)); 50 | invokeCommand(new SetSpacesCommand(false)); 51 | invokeCommand(new AdaptiveTimeoutProtocolCommand()); 52 | invokeCommand(new SelectProtocolCommand()); 53 | } 54 | 55 | private int readEngineRpm() { 56 | EngineRpmCommand engineRpmCommand = new EngineRpmCommand(); 57 | invokeCommand(engineRpmCommand); 58 | return engineRpmCommand.getValue().getIntValue(); 59 | } 60 | 61 | private int readVehicleSpeed() { 62 | SpeedCommand speedCommand = new SpeedCommand(); 63 | invokeCommand(speedCommand); 64 | return speedCommand.getValue().getIntValue(); 65 | } 66 | 67 | private float readThrottlePositionPercentage() { 68 | ThrottlePositionCommand throttlePositionCommand = new ThrottlePositionCommand(); 69 | invokeCommand(throttlePositionCommand); 70 | return throttlePositionCommand.getValue().getIntValue(); 71 | } 72 | 73 | private double readMassAirFlow() { 74 | MassAirFlowCommand massAirFlowObdCommand = new MassAirFlowCommand(); 75 | invokeCommand(massAirFlowObdCommand); 76 | return massAirFlowObdCommand.getValue().getFloatValue(); 77 | } 78 | 79 | private void invokeCommand(ObdCommand command) { 80 | try { 81 | CommandInvoker commandInvoker = createCommandInvoker(); 82 | log.info("invoking command {}", command); 83 | commandInvoker.invoke(command); 84 | } catch (Exception e) { 85 | throw new DiagnosticStatusReadException(e); 86 | } 87 | } 88 | 89 | private void invokeCommandQuietly(ObdCommand command) { 90 | CommandInvoker commandInvoker = createCommandInvoker(); 91 | log.info("invoking command {}", command); 92 | commandInvoker.invokeQuietly(command); 93 | } 94 | 95 | private CommandInvoker createCommandInvoker(InputStream inputStream, OutputStream outputStream) { 96 | ObdLink obdLink = new ElmLink(inputStream, outputStream); 97 | return new CommandInvoker(obdLink); 98 | } 99 | ``` 100 | 101 | 102 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/devesion/java-obd-adapter/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 103 | 104 | -------------------------------------------------------------------------------- /adapter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | obd-adapter 7 | com.devesion.commons.obd 8 | 1.0-SNAPSHOT 9 | 10 | 11 | 4.0.0 12 | adapter 13 | ${project.groupId}.${project.artifactId} 14 | 15 | 16 | 17 | org.rxtx 18 | rxtx 19 | 2.1.7 20 | test 21 | 22 | 23 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/AbstractCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command; 2 | 3 | /** 4 | * Skeletal implementation of {@link com.devesion.commons.obd.adapter.command.ObdCommand} interface. 5 | */ 6 | public abstract class AbstractCommand implements ObdCommand { 7 | 8 | private CommandResult result = CommandResult.empty(); 9 | 10 | public CommandResult getResult() { 11 | return result; 12 | } 13 | 14 | @Override 15 | public void setResult(CommandResult result) { 16 | this.result = result; 17 | } 18 | 19 | @Override 20 | public boolean checkResponseEnabled() { 21 | return true; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/CommandResult.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command; 2 | 3 | import lombok.AccessLevel; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | import java.nio.IntBuffer; 8 | 9 | /** 10 | * Represents OBD command result. 11 | */ 12 | @ToString 13 | public class CommandResult { 14 | 15 | @Getter(AccessLevel.PACKAGE) 16 | private IntBuffer responseBuffer; 17 | 18 | private CommandResult(IntBuffer responseBuffer) { 19 | this.responseBuffer = responseBuffer; 20 | } 21 | 22 | public static CommandResult empty() { 23 | return withBuffer(IntBuffer.allocate(10)); 24 | } 25 | 26 | public static CommandResult withBuffer(IntBuffer responseBuffer) { 27 | return new CommandResult(responseBuffer); 28 | } 29 | 30 | public int getByteNumber(int byteNumber) { 31 | return responseBuffer.get(byteNumber); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/ObdCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command; 2 | 3 | /** 4 | * Represents OBD command interface. 5 | */ 6 | public interface ObdCommand { 7 | 8 | CommandResult getResult(); 9 | 10 | void setResult(CommandResult result); 11 | 12 | boolean checkResponseEnabled(); 13 | 14 | void accept(ObdCommandVisitor visitor); 15 | } 16 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/ObdCommandVisitor.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command; 2 | 3 | import com.devesion.commons.obd.adapter.command.at.AtCommand; 4 | import com.devesion.commons.obd.adapter.command.diagnostic.DiagnosticCommand; 5 | 6 | /** 7 | * OBD Command Visitor Interface. 8 | */ 9 | public interface ObdCommandVisitor { 10 | 11 | void visit(AtCommand command); 12 | 13 | void visit(DiagnosticCommand command); 14 | } 15 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/AbstractAtCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | import com.devesion.commons.obd.adapter.command.AbstractCommand; 4 | import com.devesion.commons.obd.adapter.command.ObdCommandVisitor; 5 | import lombok.EqualsAndHashCode; 6 | 7 | /** 8 | * Supertype for every AT Command. 9 | */ 10 | @EqualsAndHashCode(callSuper = true) 11 | abstract class AbstractAtCommand extends AbstractCommand implements AtCommand { 12 | 13 | @Override 14 | public void accept(ObdCommandVisitor visitor) { 15 | visitor.visit(this); 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | final StringBuilder sb = new StringBuilder("AbstractAtCommand{"); 21 | sb.append("operands='").append(getOperands()).append("'}"); 22 | return sb.toString(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/AbstractSetStateCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT set boolean state Command. 5 | */ 6 | public class AbstractSetStateCommand extends AbstractAtCommand { 7 | 8 | private final String operandPrefix; 9 | private final boolean enabled; 10 | 11 | public AbstractSetStateCommand(String operandPrefix, boolean enabled) { 12 | this.operandPrefix = operandPrefix; 13 | this.enabled = enabled; 14 | } 15 | 16 | @Override 17 | public String getOperands() { 18 | int enabledInt = enabled ? 1 : 0; 19 | return operandPrefix + enabledInt; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/AdaptiveTimeoutProtocolCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT Adaptive Timing Protocol Command. 5 | */ 6 | public class AdaptiveTimeoutProtocolCommand extends AbstractAtCommand { 7 | 8 | @Override 9 | public String getOperands() { 10 | return "AT 2"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/AtCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | 5 | public interface AtCommand extends ObdCommand { 6 | 7 | String getOperands(); 8 | } 9 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/EnableBaudRateCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT Reset Command. 5 | */ 6 | public class EnableBaudRateCommand extends AbstractAtCommand { 7 | 8 | @Override 9 | public String getOperands() { 10 | return "PP 0C ON"; 11 | } 12 | 13 | @Override 14 | public boolean checkResponseEnabled() { 15 | return false; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/ResetCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT Reset Command. 5 | */ 6 | public class ResetCommand extends AbstractAtCommand { 7 | 8 | @Override 9 | public String getOperands() { 10 | return "Z"; 11 | } 12 | 13 | @Override 14 | public boolean checkResponseEnabled() { 15 | return false; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/SelectProtocolCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT Select Protocol Command. 5 | */ 6 | public class SelectProtocolCommand extends AbstractAtCommand { 7 | 8 | @Override 9 | public String getOperands() { 10 | return "SP 0"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/SetBaudRateCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT Reset Command. 5 | */ 6 | public class SetBaudRateCommand extends AbstractAtCommand { 7 | 8 | @Override 9 | public String getOperands() { 10 | return "PP 0C SV 23"; 11 | } 12 | 13 | @Override 14 | public boolean checkResponseEnabled() { 15 | return false; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/SetDefaultsCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT Defaults Command. 5 | */ 6 | public class SetDefaultsCommand extends AbstractAtCommand { 7 | 8 | @Override 9 | public String getOperands() { 10 | return "D"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/SetEchoCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT Set Echo On/Off Command. 5 | */ 6 | public class SetEchoCommand extends AbstractSetStateCommand { 7 | 8 | private static final String SET_ECHO_PREFIX = "E"; 9 | 10 | public SetEchoCommand(boolean enabled) { 11 | super(SET_ECHO_PREFIX, enabled); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/SetHeadersCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT Set Headers On/Off Command. 5 | */ 6 | public class SetHeadersCommand extends AbstractSetStateCommand { 7 | 8 | private static final String SET_HEADERS_PREFIX = "H"; 9 | 10 | public SetHeadersCommand(boolean enabled) { 11 | super(SET_HEADERS_PREFIX, enabled); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/SetLineFeedCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT Set Linefeed On/Off Command. 5 | */ 6 | public class SetLineFeedCommand extends AbstractSetStateCommand { 7 | 8 | private static final String SET_LINE_FEED_PREFIX = "L"; 9 | 10 | public SetLineFeedCommand(boolean enabled) { 11 | super(SET_LINE_FEED_PREFIX, enabled); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/SetMemoryCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT Set Memory On/Off Command. 5 | */ 6 | public class SetMemoryCommand extends AbstractSetStateCommand { 7 | 8 | private static final String SET_MEMORY_PREFIX = "M"; 9 | 10 | public SetMemoryCommand(boolean enabled) { 11 | super(SET_MEMORY_PREFIX, enabled); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/at/SetSpacesCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | /** 4 | * Represents AT Set Spaces On/Off Command. 5 | */ 6 | public class SetSpacesCommand extends AbstractSetStateCommand { 7 | 8 | private static final String SET_SPACES_PREFIX = "S"; 9 | 10 | public SetSpacesCommand(boolean enabled) { 11 | super(SET_SPACES_PREFIX, enabled); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/AbstractDiagnosticCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic; 2 | 3 | import com.devesion.commons.obd.adapter.command.AbstractCommand; 4 | import com.devesion.commons.obd.adapter.command.ObdCommandVisitor; 5 | import lombok.EqualsAndHashCode; 6 | 7 | @EqualsAndHashCode(callSuper = true) 8 | public abstract class AbstractDiagnosticCommand extends AbstractCommand implements DiagnosticCommand { 9 | 10 | @Override 11 | public void accept(ObdCommandVisitor visitor) { 12 | visitor.visit(this); 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | final StringBuilder sb = new StringBuilder("AbstractDiagnosticCommand{"); 18 | sb.append("mode='").append(getMode()).append("', pid='").append(getPid()).append("'}"); 19 | return sb.toString(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/DiagnosticCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | public interface DiagnosticCommand extends ObdCommand { 7 | 8 | ObdNumberedEnum getMode(); 9 | 10 | ObdNumberedEnum getPid(); 11 | } 12 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/DiagnosticCommandMode.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic; 2 | 3 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 4 | import lombok.Getter; 5 | 6 | public enum DiagnosticCommandMode implements ObdNumberedEnum { 7 | SENSORS(1), 8 | TROUBLES(3), 9 | CLEAR(4), 10 | MONITORS(6), 11 | INFO(9); 12 | 13 | @Getter 14 | private int number; 15 | 16 | DiagnosticCommandMode(int number) { 17 | this.number = number; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/DiagnosticCommandPid.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic; 2 | 3 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 4 | 5 | public interface DiagnosticCommandPid extends ObdNumberedEnum { 6 | } 7 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/info/InfoCommandPid.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.info; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.DiagnosticCommandPid; 4 | import lombok.Getter; 5 | 6 | // TODO: 7 | public enum InfoCommandPid implements DiagnosticCommandPid { 8 | ONE(1); 9 | 10 | @Getter 11 | private int number; 12 | 13 | InfoCommandPid(int number) { 14 | this.number = number; 15 | } 16 | } -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/monitors/MonitorCommandPid.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.monitors; 2 | 3 | // TODO: 4 | public enum MonitorCommandPid { 5 | ONE(1); 6 | 7 | private int number; 8 | 9 | MonitorCommandPid(int number) { 10 | this.number = number; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/AbstractSensorCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.AbstractDiagnosticCommand; 4 | import com.devesion.commons.obd.adapter.command.diagnostic.DiagnosticCommandMode; 5 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 6 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 7 | import lombok.AccessLevel; 8 | import lombok.Getter; 9 | import lombok.Setter; 10 | 11 | abstract class AbstractSensorCommand extends AbstractDiagnosticCommand implements SensorCommand { 12 | 13 | @Getter(AccessLevel.PACKAGE) 14 | @Setter(AccessLevel.PACKAGE) 15 | private UnitFactory unitFactory = new UnitFactory(); 16 | 17 | @Override 18 | public ObdNumberedEnum getMode() { 19 | return DiagnosticCommandMode.SENSORS; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/AmbientAirTemperatureCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current ambient air temperature. 8 | */ 9 | public class AmbientAirTemperatureCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.AMBIENT_AIR_TEMPERATURE; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createTemperatureValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/EngineCoolantTemperatureCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current engine coolant temperature. 8 | */ 9 | public class EngineCoolantTemperatureCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.ENGINE_COOLANT_TEMPERATURE; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createTemperatureValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/EngineLoadCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current engine load. 8 | */ 9 | public class EngineLoadCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.ENGINE_LOAD; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createPercentageValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/EngineRpmCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current engine RPM. 8 | */ 9 | public class EngineRpmCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.ENGINE_RPM; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createRpmValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/EngineRuntimeCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current engine run time. 8 | */ 9 | public class EngineRuntimeCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.ENGINE_RUN_TIME; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createTimeValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/FuelConsumptionRateCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current fuel consumption rate. 8 | */ 9 | public class FuelConsumptionRateCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.FUEL_CONSUMPTION_1; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createFuelConsumptionValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/FuelLevelCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current fuel level percentage. 8 | */ 9 | public class FuelLevelCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.FUEL_LEVEL; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createFuelLevelValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/FuelPressureCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current fuel pressure in kPa. 8 | */ 9 | public class FuelPressureCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.FUEL_PRESSURE; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createFuelPressureValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/FuelTypeCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current fuel type. 8 | */ 9 | public class FuelTypeCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.FUEL_TYPE; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createFuelTypeValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/IntakeAirTemperatureCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current intake air temperature. 8 | */ 9 | public class IntakeAirTemperatureCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.INTAKE_AIR_TEMPERATURE; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createTemperatureValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/MassAirFlowCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current MAF value. 8 | */ 9 | public class MassAirFlowCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.MASS_AIR_FLOW; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createAirFlowValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/SensorCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.DiagnosticCommand; 4 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 5 | 6 | public interface SensorCommand extends DiagnosticCommand { 7 | 8 | SensorCommandValue getValue(); 9 | } 10 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/SensorCommandPid.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.DiagnosticCommandPid; 4 | import lombok.Getter; 5 | 6 | /** 7 | * Popular com.autonalyzer.adapter.android.infrastture.diagnostic command sensor's PIDs - OBD Mode 1. 8 | */ 9 | public enum SensorCommandPid implements DiagnosticCommandPid { 10 | PIDS_SUPPORTED_SET_1(0x00), 11 | OVERALL_STATUS(0x01), 12 | FUEL_SYSTEM_STATUS(0x03), 13 | ENGINE_LOAD(0x04), 14 | ENGINE_COOLANT_TEMPERATURE(0x05), 15 | SHORT_TERM_FUEL_BANK1(0x06), 16 | LONG_TERM_FUEL_BANK1(0x07), 17 | SHORT_TERM_FUEL_BANK2(0x08), 18 | LONG_TERM_FUEL_BANK2(0x09), 19 | FUEL_PRESSURE(0x0A), 20 | INTAKE_MANIFOLD_PRESSURE(0x0B), 21 | ENGINE_RPM(0x0C), 22 | VEHICLE_SPEED(0x0D), 23 | INTAKE_AIR_TEMPERATURE(0x0F), 24 | MASS_AIR_FLOW(0x10), 25 | THROTTLE_POSITION_PERCENTAGE(0x11), 26 | ENGINE_RUN_TIME(0x1F), 27 | PIDS_SUPPORTED_SET_2(0x20), 28 | FUEL_LEVEL(0x2F), 29 | BAROMETRIC_PRESSURE(0x33), 30 | AMBIENT_AIR_TEMPERATURE(0x46), 31 | FUEL_TYPE(0x51), 32 | FUEL_CONSUMPTION_1(0x5E), 33 | FUEL_CONSUMPTION_2(0x5F), 34 | ENGINE_TORQUE_NM(0x63), 35 | ENGINE_TORQUE_PERCENTAGE(0x64), 36 | TURBOCHARGER_PRESSURE(0x6F), 37 | EXHAUST_PRESSURE(0x73); 38 | 39 | @Getter 40 | private int number; 41 | 42 | SensorCommandPid(int number) { 43 | this.number = number; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/SpeedCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current Vehicle Speed value. 8 | */ 9 | public class SpeedCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.VEHICLE_SPEED; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createSpeedValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/ThrottlePositionCommand.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | 6 | /** 7 | * Reads current Throttle Position Percentage. 8 | */ 9 | public class ThrottlePositionCommand extends AbstractSensorCommand { 10 | 11 | @Override 12 | public ObdNumberedEnum getPid() { 13 | return SensorCommandPid.THROTTLE_POSITION_PERCENTAGE; 14 | } 15 | 16 | @Override 17 | public SensorCommandValue getValue() { 18 | return getUnitFactory().createPercentageValue(getResult()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/AbstractSensorCommandValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import lombok.AccessLevel; 5 | import lombok.Getter; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | @Slf4j 9 | abstract class AbstractSensorCommandValue implements SensorCommandValue { 10 | 11 | @Getter(AccessLevel.PACKAGE) 12 | private CommandResult commandResult = CommandResult.empty(); 13 | 14 | public AbstractSensorCommandValue(CommandResult commandResult) { 15 | this.commandResult = commandResult; 16 | } 17 | 18 | @Override 19 | public int getIntValue() { 20 | return (int) getFloatValue(); 21 | } 22 | 23 | @Override 24 | public float getFloatValue() { 25 | return calculateValue(); 26 | } 27 | 28 | protected int getResultByteNumber(int byteNumber) { 29 | return commandResult.getByteNumber(byteNumber); 30 | } 31 | 32 | protected abstract float calculateValue(); 33 | 34 | @Override 35 | public String toString() { 36 | final StringBuilder sb = new StringBuilder("AbstractSensorCommandValue{"); 37 | sb.append("intValue=").append(getIntValue()).append(", ").append("floatValue=").append(getFloatValue()).append('}'); 38 | return sb.toString(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/AirFlowValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | 5 | /** 6 | * Represents Air Flow Value Object. 7 | */ 8 | class AirFlowValue extends SimpleValue { 9 | 10 | private static final float AIR_FLOW_DIVISOR = 100.0f; 11 | 12 | AirFlowValue(CommandResult commandResult) { 13 | super(commandResult, AIR_FLOW_DIVISOR); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/FuelConsumptionValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | 5 | /** 6 | * Represents Fuel Consumption Value Object. 7 | */ 8 | class FuelConsumptionValue extends SimpleValue { 9 | 10 | private static final float FUEL_CONSUMPTION_DIVISOR = 20f; 11 | 12 | FuelConsumptionValue(CommandResult commandResult) { 13 | super(commandResult, FUEL_CONSUMPTION_DIVISOR); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/FuelPressureValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | 5 | /** 6 | * Represents Fuel pressure Value Object. 7 | */ 8 | class FuelPressureValue extends PressureValue { 9 | 10 | FuelPressureValue(CommandResult commandResult) { 11 | super(commandResult); 12 | } 13 | 14 | @Override 15 | protected float calculateValue() { 16 | int majorByte = getResultByteNumber(0); 17 | return majorByte * 3; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/FuelTypeValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import com.google.common.base.Optional; 5 | import lombok.AccessLevel; 6 | import lombok.Getter; 7 | 8 | /** 9 | * Represents Fuel Type Value Object. 10 | */ 11 | class FuelTypeValue extends AbstractSensorCommandValue { 12 | 13 | public FuelTypeValue(CommandResult commandResult) { 14 | super(commandResult); 15 | } 16 | 17 | @Override 18 | protected float calculateValue() { 19 | return getResultByteNumber(0); 20 | } 21 | 22 | public Optional getType() { 23 | return FuelType.valueOf(getIntValue()); 24 | } 25 | 26 | public enum FuelType { 27 | GASOLINE(0x01), 28 | METHANOL(0x02), 29 | ETHANOL(0x03), 30 | DIESEL(0x04), 31 | LPG(0x05), 32 | CNG(0x06), 33 | PROPANE(0x07), 34 | ELECTRIC(0x08), 35 | BIFUEL_RUNNING_GASOLINE(0x09), 36 | BIFUEL_RUNNING_METHANOL(0x0A), 37 | BIFUEL_RUNNING_ETHANOL(0x0B), 38 | BIFUEL_RUNNING_LPG(0x0C), 39 | BIFUEL_RUNNING_CNG(0x0D), 40 | BIFUEL_RUNNING_PROPANE(0x0E), 41 | BIFUEL_RUNNING_ELECTRIC(0x0F), 42 | BIFUEL_RUNNING_GASOLINE_ELECTRIC(0x10), 43 | HYBRID_GASOLINE(0x11), 44 | HYBRID_ETHANOL(0x12), 45 | HYBRID_DIESEL(0x13), 46 | HYBRID_ELECTRIC(0x14), 47 | HYBRID_MIXED(0x15), 48 | HYBRID_REGENERATIVE(0x16); 49 | 50 | @Getter(AccessLevel.PACKAGE) 51 | private int typeNumber; 52 | 53 | FuelType(int typeNumber) { 54 | this.typeNumber = typeNumber; 55 | } 56 | 57 | public static Optional valueOf(int typeNumber) { 58 | for (FuelType type : values()) { 59 | if (type.typeNumber == typeNumber) { 60 | return Optional.of(type); 61 | } 62 | } 63 | 64 | return Optional.absent(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/PercentageValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | 5 | /** 6 | * Represents Percentage Value Object. 7 | */ 8 | class PercentageValue extends AbstractSensorCommandValue { 9 | 10 | PercentageValue(CommandResult commandResult) { 11 | super(commandResult); 12 | } 13 | 14 | @Override 15 | protected float calculateValue() { 16 | int majorByte = getResultByteNumber(0); 17 | return (majorByte * 100.0f) / 255.0f; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/PressureValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | 5 | /** 6 | * Represents Pressure Value Object. 7 | */ 8 | class PressureValue extends AbstractSensorCommandValue { 9 | 10 | PressureValue(CommandResult commandResult) { 11 | super(commandResult); 12 | } 13 | 14 | @Override 15 | protected float calculateValue() { 16 | return 0; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/RpmValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | 5 | /** 6 | * Represents RPM Value Object. 7 | */ 8 | class RpmValue extends SimpleValue { 9 | 10 | private static final float RPM_DIVISOR = 4.0f; 11 | 12 | RpmValue(CommandResult commandResult) { 13 | super(commandResult, RPM_DIVISOR); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/SensorCommandValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | public interface SensorCommandValue { 4 | 5 | int getIntValue(); 6 | 7 | float getFloatValue(); 8 | } 9 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/SimpleValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | @Slf4j 7 | class SimpleValue extends AbstractSensorCommandValue { 8 | 9 | private static final int DEFAULT_MULTIPLIER = 256; 10 | private final float multiplier; 11 | private final float divisor; 12 | 13 | SimpleValue(CommandResult commandResult, float divisor) { 14 | super(commandResult); 15 | this.multiplier = DEFAULT_MULTIPLIER; 16 | this.divisor = divisor; 17 | } 18 | 19 | SimpleValue(CommandResult commandResult, float multiplier, float divisor) { 20 | super(commandResult); 21 | this.multiplier = multiplier; 22 | this.divisor = divisor; 23 | } 24 | 25 | @Override 26 | protected float calculateValue() { 27 | int majorByte = getResultByteNumber(0); 28 | int minorByte = getResultByteNumber(1); 29 | return (majorByte * multiplier + minorByte) / divisor; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/SpeedValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | 5 | /** 6 | * Represents Speeds Value Object. 7 | */ 8 | class SpeedValue extends AbstractSensorCommandValue { 9 | 10 | SpeedValue(CommandResult commandResult) { 11 | super(commandResult); 12 | } 13 | 14 | @Override 15 | protected float calculateValue() { 16 | return getResultByteNumber(0); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/TemperatureValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | 5 | /** 6 | * Represents Temperature Value Object. 7 | */ 8 | class TemperatureValue extends AbstractSensorCommandValue { 9 | 10 | TemperatureValue(CommandResult commandResult) { 11 | super(commandResult); 12 | } 13 | 14 | @Override 15 | protected float calculateValue() { 16 | int majorByte = getResultByteNumber(0); 17 | return majorByte - 40; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/TimeValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | 5 | /** 6 | * Represents Time Value Object. 7 | */ 8 | class TimeValue extends SimpleValue { 9 | 10 | private static final float RPM_DIVISOR = 1.0f; 11 | 12 | TimeValue(CommandResult commandResult) { 13 | super(commandResult, RPM_DIVISOR); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/UnitFactory.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | 5 | public class UnitFactory { 6 | 7 | public SensorCommandValue createAirFlowValue(CommandResult commandResult) { 8 | return new AirFlowValue(commandResult); 9 | } 10 | 11 | public SensorCommandValue createFuelConsumptionValue(CommandResult commandResult) { 12 | return new FuelConsumptionValue(commandResult); 13 | } 14 | 15 | public SensorCommandValue createFuelLevelValue(CommandResult commandResult) { 16 | return new PercentageValue(commandResult); 17 | } 18 | 19 | public SensorCommandValue createFuelTypeValue(CommandResult commandResult) { 20 | return new FuelTypeValue(commandResult); 21 | } 22 | 23 | public SensorCommandValue createPercentageValue(CommandResult commandResult) { 24 | return new PercentageValue(commandResult); 25 | } 26 | 27 | public SensorCommandValue createPressureValue(CommandResult commandResult) { 28 | return new PressureValue(commandResult); 29 | } 30 | 31 | public SensorCommandValue createFuelPressureValue(CommandResult commandResult) { 32 | return new FuelPressureValue(commandResult); 33 | } 34 | 35 | public SensorCommandValue createRpmValue(CommandResult commandResult) { 36 | return new RpmValue(commandResult); 37 | } 38 | 39 | public SensorCommandValue createSpeedValue(CommandResult commandResult) { 40 | return new SpeedValue(commandResult); 41 | } 42 | 43 | public SensorCommandValue createTemperatureValue(CommandResult commandResult) { 44 | return new TemperatureValue(commandResult); 45 | } 46 | 47 | public SensorCommandValue createTimeValue(CommandResult commandResult) { 48 | return new TimeValue(commandResult); 49 | } 50 | 51 | public SensorCommandValue createVoltageValue(CommandResult commandResult) { 52 | return new VoltageValue(commandResult); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/VoltageValue.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | 5 | /** 6 | * Represents Voltage Value Object. 7 | */ 8 | class VoltageValue extends AbstractSensorCommandValue { 9 | 10 | VoltageValue(CommandResult commandResult) { 11 | super(commandResult); 12 | } 13 | 14 | @Override 15 | protected float calculateValue() { 16 | return 0; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/invoker/CommandExceptionFactory.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.invoker; 2 | 3 | class CommandExceptionFactory { 4 | } 5 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/command/invoker/CommandInvoker.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.invoker; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import com.devesion.commons.obd.adapter.command.ObdCommand; 5 | import com.devesion.commons.obd.adapter.link.ObdLink; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | /** 9 | * Responsible for invoking OBD Commands. 10 | */ 11 | @Slf4j 12 | public class CommandInvoker { 13 | 14 | private final ObdLink obdLink; 15 | 16 | public CommandInvoker(ObdLink obdLink) { 17 | this.obdLink = obdLink; 18 | } 19 | 20 | public void invokeQuietly(ObdCommand command) { 21 | try { 22 | invoke(command); 23 | } catch (Exception e) { 24 | log.error("cannot invoke command {} - {}", command, e.getMessage()); 25 | } 26 | } 27 | 28 | public void invoke(ObdCommand command) { 29 | log.debug("invoking OBD Command '{}'", command); 30 | CommandResult result = obdLink.sendCommand(command); 31 | log.debug("OBD Command result '{}'", result); 32 | command.setResult(result); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/CommandMarshaller.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | 5 | /** 6 | * Represents OBD command marshaller interface. 7 | */ 8 | public interface CommandMarshaller { 9 | 10 | String marshal(ObdCommand command); 11 | } 12 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/CommandUnmarshaller.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import com.devesion.commons.obd.adapter.command.CommandResult; 5 | 6 | /** 7 | * Represents OBD command unmarshaller interface. 8 | */ 9 | public interface CommandUnmarshaller { 10 | 11 | CommandResult unmarshal(ObdCommand command, String data); 12 | } 13 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/ObdLink.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import com.devesion.commons.obd.adapter.command.ObdCommand; 5 | 6 | /** 7 | * Represents OBD link between two nodes (ie. bluetooth device and PC). 8 | */ 9 | public interface ObdLink { 10 | 11 | CommandResult sendCommand(ObdCommand command); 12 | } 13 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/elm/AbstractCommandMarshaller.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.adapter.link.CommandMarshaller; 4 | import com.devesion.commons.obd.adapter.shared.HexTools; 5 | 6 | abstract class AbstractCommandMarshaller implements CommandMarshaller { 7 | private static final String SPACE = " "; 8 | private static final String CR = "\r"; 9 | 10 | protected String buildRequest(String mnemonic, String operands) { 11 | return mnemonic + SPACE + operands + CR; 12 | } 13 | 14 | protected String buildRequestWithCount(String mnemonic, String operands, int count) { 15 | return mnemonic + SPACE + operands + HexTools.toHexString(count) + CR; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/elm/AbstractCommandUnmarshaller.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import com.devesion.commons.obd.adapter.link.CommandUnmarshaller; 5 | import com.devesion.commons.obd.adapter.shared.ObdNoDataForCommandResponseException; 6 | import com.devesion.commons.obd.adapter.shared.ObdNotProperlyInitializedException; 7 | 8 | abstract class AbstractCommandUnmarshaller implements CommandUnmarshaller { 9 | 10 | private static final String ELM_WHITE = "[\\s]"; 11 | private static final String ELM_CAN_BUS_SEPARATOR = "[0-9]:"; 12 | private static final String ELM_NODATA_ERROR = "NODATA"; 13 | private static final String ELM_SEARCHING_ERROR = "SEARCHING"; 14 | private static final String ELM_BUS_ERROR = "BUS"; 15 | 16 | protected String normalizeResponse(String responseData) { 17 | return responseData 18 | .replaceAll(ELM_WHITE, "") 19 | .replaceAll(ELM_CAN_BUS_SEPARATOR, "") 20 | .toUpperCase(); 21 | } 22 | 23 | protected void checkResponse(ObdCommand command, String responseData) { 24 | if (responseData.contains(ELM_NODATA_ERROR)) { 25 | throw new ObdNoDataForCommandResponseException(command, responseData); 26 | } 27 | 28 | if (responseData.contains(ELM_SEARCHING_ERROR)) { 29 | throw new ObdNotProperlyInitializedException(command, responseData); 30 | } 31 | 32 | if (responseData.contains(ELM_BUS_ERROR)) { 33 | throw new ObdNotProperlyInitializedException(command, responseData); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/elm/AtCommandMarshaller.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import com.devesion.commons.obd.adapter.command.at.AtCommand; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | @Slf4j 8 | class AtCommandMarshaller extends AbstractCommandMarshaller { 9 | 10 | private static final String PROTOCOL_COMMAND_MNEMONIC = "AT"; 11 | 12 | @Override 13 | public String marshal(ObdCommand command) { 14 | AtCommand protocolCommand = (AtCommand) command; 15 | String commandMnemonic = PROTOCOL_COMMAND_MNEMONIC; 16 | String commandOperands = protocolCommand.getOperands(); 17 | return buildRequest(commandMnemonic, commandOperands); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/elm/AtCommandUnmarshaller.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import com.devesion.commons.obd.adapter.command.CommandResult; 5 | import com.devesion.commons.obd.adapter.shared.ObdInvalidCommandResponseException; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | @Slf4j 9 | class AtCommandUnmarshaller extends AbstractCommandUnmarshaller { 10 | 11 | private static final String ELM_PROTOCOL_ACK_OK = "OK"; 12 | 13 | @Override 14 | public CommandResult unmarshal(ObdCommand command, String responseData) { 15 | log.debug("unmarshaling response '{}", responseData); 16 | 17 | responseData = normalizeResponse(responseData); 18 | log.debug("after normalization '{}", responseData); 19 | 20 | if (command.checkResponseEnabled()) { 21 | checkResponse(command, responseData); 22 | if (responseData.contains(ELM_PROTOCOL_ACK_OK)) { 23 | return CommandResult.empty(); 24 | } 25 | 26 | throw new ObdInvalidCommandResponseException(command, responseData); 27 | } 28 | 29 | return CommandResult.empty(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/elm/CommandMarshallerBridge.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import com.devesion.commons.obd.adapter.command.ObdCommandVisitor; 5 | import com.devesion.commons.obd.adapter.command.at.AtCommand; 6 | import com.devesion.commons.obd.adapter.command.diagnostic.DiagnosticCommand; 7 | import com.devesion.commons.obd.adapter.link.CommandMarshaller; 8 | import lombok.AccessLevel; 9 | import lombok.Getter; 10 | 11 | /** 12 | * Represents OBD command marshaller bridge implementation. 13 | */ 14 | class CommandMarshallerBridge implements CommandMarshaller { 15 | 16 | @Override 17 | public String marshal(ObdCommand command) { 18 | MarshallerFactoryVisitor marshallerFactoryVisitor = new MarshallerFactoryVisitor(); 19 | command.accept(marshallerFactoryVisitor); 20 | CommandMarshaller concreteMarshaller = marshallerFactoryVisitor.getConcreteMarshaller(); 21 | return concreteMarshaller.marshal(command); 22 | } 23 | 24 | private class MarshallerFactoryVisitor implements ObdCommandVisitor { 25 | 26 | @Getter(AccessLevel.PRIVATE) 27 | private CommandMarshaller concreteMarshaller; 28 | 29 | @Override 30 | public void visit(AtCommand command) { 31 | concreteMarshaller = new AtCommandMarshaller(); 32 | } 33 | 34 | @Override 35 | public void visit(DiagnosticCommand command) { 36 | concreteMarshaller = new DiagnosticCommandMarshaller(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/elm/CommandUnmarshallerBridge.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import com.devesion.commons.obd.adapter.command.ObdCommandVisitor; 5 | import com.devesion.commons.obd.adapter.command.at.AtCommand; 6 | import com.devesion.commons.obd.adapter.command.diagnostic.DiagnosticCommand; 7 | import com.devesion.commons.obd.adapter.command.CommandResult; 8 | import com.devesion.commons.obd.adapter.link.CommandUnmarshaller; 9 | import lombok.AccessLevel; 10 | import lombok.Getter; 11 | 12 | /** 13 | * Represents OBD command unmarshaller bridge implementation. 14 | */ 15 | class CommandUnmarshallerBridge implements CommandUnmarshaller { 16 | 17 | @Override 18 | public CommandResult unmarshal(ObdCommand command, String responseData) { 19 | UnmarshallerFactoryVisitor unmarshallerFactoryVisitor = new UnmarshallerFactoryVisitor(); 20 | command.accept(unmarshallerFactoryVisitor); 21 | CommandUnmarshaller concreteUnmarshaller = unmarshallerFactoryVisitor.getConcreteUnmarshaller(); 22 | return concreteUnmarshaller.unmarshal(command, responseData); 23 | } 24 | 25 | private class UnmarshallerFactoryVisitor implements ObdCommandVisitor { 26 | 27 | @Getter(AccessLevel.PRIVATE) 28 | private CommandUnmarshaller concreteUnmarshaller; 29 | 30 | @Override 31 | public void visit(AtCommand command) { 32 | concreteUnmarshaller = new AtCommandUnmarshaller(); 33 | } 34 | 35 | @Override 36 | public void visit(DiagnosticCommand command) { 37 | concreteUnmarshaller = new DiagnosticCommandUnmarshaller(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/elm/DiagnosticCommandMarshaller.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import com.devesion.commons.obd.adapter.command.diagnostic.DiagnosticCommand; 5 | import com.devesion.commons.obd.adapter.shared.HexTools; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | @Slf4j 9 | class DiagnosticCommandMarshaller extends AbstractCommandMarshaller { 10 | 11 | @Override 12 | public String marshal(ObdCommand command) { 13 | DiagnosticCommand diagnosticCommand = (DiagnosticCommand) command; 14 | String commandMnemonic = HexTools.toHexString(diagnosticCommand.getMode()); 15 | String commandOperands = HexTools.toHexString(diagnosticCommand.getPid()); 16 | return buildRequestWithCount(commandMnemonic, commandOperands, 1); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/elm/DiagnosticCommandUnmarshaller.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import com.devesion.commons.obd.adapter.command.diagnostic.DiagnosticCommand; 5 | import com.devesion.commons.obd.adapter.command.CommandResult; 6 | import com.devesion.commons.obd.adapter.shared.HexTools; 7 | import com.devesion.commons.obd.adapter.shared.ObdInvalidCommandResponseException; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.nio.IntBuffer; 11 | 12 | @Slf4j 13 | class DiagnosticCommandUnmarshaller extends AbstractCommandUnmarshaller { 14 | 15 | private static final String ELM_DIAGNOSTIC_ACK_OK = "41"; 16 | private static final String ELM_DIAGNOSTIC_RESPONSE_REGEXP = "([0-9A-F]{2})+"; 17 | private static final int ELM_MAX_COMMAND_RESPONSE_LENGTH = 256; 18 | 19 | @Override 20 | public CommandResult unmarshal(ObdCommand command, String responseData) { 21 | DiagnosticCommand diagnosticCommand = (DiagnosticCommand) command; 22 | log.debug("unmarshaling response"); 23 | log.debug(responseData); 24 | 25 | responseData = normalizeResponse(responseData); 26 | log.debug("after normalization '{}'", responseData); 27 | 28 | responseData = omitMagicSequence(diagnosticCommand, responseData); 29 | log.debug("after omitting magic sequence '{}'", responseData); 30 | 31 | checkResponse(command, responseData); 32 | checkDiagnosticResponse(command, responseData); 33 | 34 | IntBuffer responseBuffer = readByteBuffer(responseData); 35 | return CommandResult.withBuffer(responseBuffer); 36 | } 37 | 38 | private void checkDiagnosticResponse(ObdCommand command, String responseData) { 39 | if (!responseData.matches(ELM_DIAGNOSTIC_RESPONSE_REGEXP)) { 40 | throw new ObdInvalidCommandResponseException(command, responseData); 41 | } 42 | } 43 | 44 | private String omitMagicSequence(DiagnosticCommand command, String responseData) { 45 | String magicSequence = ELM_DIAGNOSTIC_ACK_OK + HexTools.toHexString(command.getPid()); 46 | log.debug("magic sequence {}", magicSequence); 47 | 48 | int magicSequenceIndex = responseData.indexOf(magicSequence); 49 | if (magicSequenceIndex < 0) { 50 | return responseData; 51 | } 52 | 53 | int magicSequenceLength = magicSequence.length(); 54 | return responseData.substring(magicSequenceIndex + magicSequenceLength); 55 | } 56 | 57 | private IntBuffer readByteBuffer(String data) { 58 | IntBuffer buffer = IntBuffer.allocate(ELM_MAX_COMMAND_RESPONSE_LENGTH); 59 | int readByteIndex = 0; 60 | int readCharIndex = 0; 61 | while (readByteIndex < data.length()) { 62 | int readByte = HexTools.fromHexString(data, readByteIndex, readByteIndex + 2); 63 | buffer.put(readByte); 64 | readByteIndex += 2; 65 | readCharIndex += 1; 66 | 67 | if (readCharIndex >= ELM_MAX_COMMAND_RESPONSE_LENGTH) { 68 | break; 69 | } 70 | } 71 | 72 | buffer.flip(); 73 | return buffer; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/elm/ElmLink.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import com.devesion.commons.obd.adapter.command.ObdCommand; 5 | import com.devesion.commons.obd.adapter.link.CommandMarshaller; 6 | import com.devesion.commons.obd.adapter.link.CommandUnmarshaller; 7 | import com.devesion.commons.obd.adapter.link.ObdLink; 8 | import lombok.AccessLevel; 9 | import lombok.Getter; 10 | import lombok.extern.slf4j.Slf4j; 11 | 12 | import java.io.InputStream; 13 | import java.io.OutputStream; 14 | 15 | /** 16 | * Represents ELM link between two nodes (ie. bluetooth device and PC). 17 | */ 18 | @Slf4j 19 | public class ElmLink implements ObdLink { 20 | 21 | private final ElmTransport transport; 22 | 23 | @Getter(AccessLevel.PACKAGE) 24 | private CommandMarshaller commandMarshaller; 25 | 26 | @Getter(AccessLevel.PACKAGE) 27 | private CommandUnmarshaller commandUnmarshaller; 28 | 29 | public ElmLink(InputStream inputStream, OutputStream outputStream) { 30 | this(new ElmTransport(inputStream, outputStream)); 31 | } 32 | 33 | public ElmLink(ElmTransport transport) { 34 | this(transport, new CommandMarshallerBridge(), new CommandUnmarshallerBridge()); 35 | } 36 | 37 | public ElmLink(ElmTransport transport, CommandMarshaller commandMarshaller, CommandUnmarshaller commandUnmarshaller) { 38 | this.transport = transport; 39 | this.commandMarshaller = commandMarshaller; 40 | this.commandUnmarshaller = commandUnmarshaller; 41 | } 42 | 43 | @Override 44 | public CommandResult sendCommand(ObdCommand command) { 45 | String commandData = commandMarshaller.marshal(command); 46 | String commandResultData = transport.sendDataAndReadResponse(commandData); 47 | return commandUnmarshaller.unmarshal(command, commandResultData); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/link/elm/ElmTransport.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.adapter.shared.ObdCommunicationException; 4 | import lombok.extern.slf4j.Slf4j; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.OutputStream; 9 | 10 | /** 11 | * Represents ELM IO transport between two nodes (ie. bluetooth device and PC). 12 | */ 13 | @Slf4j 14 | public class ElmTransport { 15 | private static final char ELM_PROMPT = '>'; 16 | 17 | private final InputStream inputStream; 18 | private final OutputStream outputStream; 19 | 20 | public ElmTransport(InputStream inputStream, OutputStream outputStream) { 21 | this.inputStream = inputStream; 22 | this.outputStream = outputStream; 23 | } 24 | 25 | public String sendDataAndReadResponse(String data) { 26 | sendData(data); 27 | return readData(); 28 | } 29 | 30 | public void sendData(String data) { 31 | log.debug("Sending bytes '{}'", data); 32 | writeBytes(data); 33 | } 34 | 35 | private void writeBytes(String data) { 36 | try { 37 | outputStream.write(data.getBytes()); 38 | outputStream.flush(); 39 | } catch (IOException e) { 40 | throw new ObdCommunicationException("cannot send data to output stream", e); 41 | } 42 | } 43 | 44 | public String readData() { 45 | log.debug("waiting for response"); 46 | StringBuilder res = new StringBuilder(); 47 | char c; 48 | while ((c = readChar()) != ELM_PROMPT) { 49 | log.debug("read char '{}'", c); 50 | res.append(c); 51 | } 52 | 53 | log.debug("reading end"); 54 | String data = res.toString().trim(); 55 | log.debug("Read raw data '{}'", data); 56 | return data; 57 | } 58 | 59 | private char readChar() { 60 | try { 61 | return (char) inputStream.read(); 62 | } catch (IOException e) { 63 | throw new ObdCommunicationException("cannot read data from input stream", e); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/shared/HexTools.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | public final class HexTools { 4 | 5 | private HexTools() { 6 | throw new AssertionError(); 7 | } 8 | 9 | public static int fromHexString(String data, int begin, int end) { 10 | return Integer.decode("0x" + data.substring(begin, end)); 11 | } 12 | 13 | public static String toHexString(ObdNumberedEnum numberedEnum) { 14 | return toHexString(numberedEnum.getNumber()); 15 | } 16 | 17 | public static String toHexString(int value) { 18 | return Integer.toHexString(0x100 | (0xFF & value)).substring(1).toUpperCase(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/shared/ObdAbstractRuntimeException.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | /** 4 | * Runtime exception superclass for OBD Adapter. 5 | */ 6 | public abstract class ObdAbstractRuntimeException extends RuntimeException { 7 | 8 | public ObdAbstractRuntimeException() { 9 | } 10 | 11 | public ObdAbstractRuntimeException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/shared/ObdCommandResponseException.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import lombok.Getter; 5 | 6 | /** 7 | * Represents invalid OBD command. 8 | */ 9 | public class ObdCommandResponseException extends ObdCommunicationException { 10 | 11 | @Getter 12 | private ObdCommand command; 13 | 14 | private String responseData; 15 | 16 | public ObdCommandResponseException(ObdCommand command) { 17 | this.command = command; 18 | } 19 | 20 | public ObdCommandResponseException(ObdCommand command, String responseData) { 21 | this.command = command; 22 | this.responseData = responseData; 23 | } 24 | 25 | @Override 26 | public String getMessage() { 27 | String message = "command '" + command + ""; 28 | 29 | if (responseData != null) { 30 | message += "', response '" + responseData + "'"; 31 | } 32 | 33 | return message; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/shared/ObdCommunicationException.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | /** 4 | * Represents general OBD communication exception. 5 | */ 6 | public class ObdCommunicationException extends ObdAbstractRuntimeException { 7 | 8 | public ObdCommunicationException() { 9 | } 10 | 11 | public ObdCommunicationException(String message, Throwable cause) { 12 | super(message, cause); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/shared/ObdInvalidCommandResponseException.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | 5 | /** 6 | * Represents invalid OBD command. 7 | */ 8 | public class ObdInvalidCommandResponseException extends ObdCommandResponseException { 9 | 10 | private String responseData; 11 | 12 | public ObdInvalidCommandResponseException(ObdCommand command, String responseData) { 13 | super(command, responseData); 14 | this.responseData = responseData; 15 | } 16 | 17 | @Override 18 | public String getMessage() { 19 | StringBuilder sb = new StringBuilder(); 20 | String superMessage = super.getMessage(); 21 | sb.append(superMessage).append(", responseData - '").append(responseData).append("'"); 22 | return sb.toString(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/shared/ObdNoDataForCommandResponseException.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | 5 | /** 6 | * Represents OBD "NO DATA" response. 7 | */ 8 | public class ObdNoDataForCommandResponseException extends ObdCommandResponseException { 9 | 10 | public ObdNoDataForCommandResponseException(ObdCommand command) { 11 | super(command); 12 | } 13 | 14 | public ObdNoDataForCommandResponseException(ObdCommand command, String responseData) { 15 | super(command, responseData); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/shared/ObdNotProperlyInitializedException.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | 5 | /** 6 | * Represents OBD "SEARCHING..." or "BUS INIT" response. 7 | */ 8 | public class ObdNotProperlyInitializedException extends ObdCommandResponseException { 9 | 10 | public ObdNotProperlyInitializedException(ObdCommand command, String responseData) { 11 | super(command, responseData); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/devesion/commons/obd/adapter/shared/ObdNumberedEnum.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | public interface ObdNumberedEnum { 4 | 5 | int getNumber(); 6 | } 7 | -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/ObdAdapterClient.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd; 2 | 3 | import com.devesion.commons.obd.adapter.command.at.AdaptiveTimeoutProtocolCommand; 4 | import com.devesion.commons.obd.adapter.command.at.ResetCommand; 5 | import com.devesion.commons.obd.adapter.command.at.SelectProtocolCommand; 6 | import com.devesion.commons.obd.adapter.command.at.SetDefaultsCommand; 7 | import com.devesion.commons.obd.adapter.command.at.SetEchoCommand; 8 | import com.devesion.commons.obd.adapter.command.at.SetLineFeedCommand; 9 | import com.devesion.commons.obd.adapter.command.at.SetMemoryCommand; 10 | import com.devesion.commons.obd.adapter.command.at.SetSpacesCommand; 11 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.EngineCoolantTemperatureCommand; 12 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.EngineLoadCommand; 13 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.EngineRpmCommand; 14 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.IntakeAirTemperatureCommand; 15 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.MassAirFlowCommand; 16 | import com.devesion.commons.obd.adapter.command.invoker.CommandInvoker; 17 | import com.devesion.commons.obd.adapter.link.ObdLink; 18 | import com.devesion.commons.obd.adapter.link.elm.ElmLink; 19 | import gnu.io.CommPortIdentifier; 20 | import gnu.io.SerialPort; 21 | import gnu.io.SerialPortEvent; 22 | import gnu.io.SerialPortEventListener; 23 | import lombok.extern.slf4j.Slf4j; 24 | 25 | import java.io.InputStream; 26 | import java.io.OutputStream; 27 | import java.util.Enumeration; 28 | 29 | @Slf4j 30 | public class ObdAdapterClient implements SerialPortEventListener { 31 | 32 | private static final int TIME_OUT = 2000; 33 | private static final int DATA_RATE = 38400; 34 | private InputStream is; 35 | private OutputStream os; 36 | 37 | public static void main(String... args) { 38 | ObdAdapterClient client = new ObdAdapterClient(); 39 | client.run(); 40 | } 41 | 42 | private void run() { 43 | prepareSerialPort(); 44 | sendTestCommands(); 45 | } 46 | 47 | private void prepareSerialPort() { 48 | // String wantedPortName = "/dev/pts/34"; 49 | String wantedPortName = "/dev/ttyUSB0"; 50 | System.setProperty("gnu.io.rxtx.SerialPorts", wantedPortName); 51 | Enumeration portIdentifiers = CommPortIdentifier.getPortIdentifiers(); 52 | 53 | CommPortIdentifier portId = null; 54 | 55 | while (portIdentifiers.hasMoreElements()) { 56 | CommPortIdentifier pid = (CommPortIdentifier) portIdentifiers.nextElement(); 57 | if (pid.getPortType() == CommPortIdentifier.PORT_SERIAL && 58 | pid.getName().equals(wantedPortName)) { 59 | portId = pid; 60 | break; 61 | } 62 | } 63 | 64 | try { 65 | // open serial port, and use class name for the appName. 66 | SerialPort serialPort = (SerialPort) portId.open(ObdAdapterClient.class.getName(), TIME_OUT); 67 | 68 | // set port parameters 69 | serialPort.setSerialPortParams(DATA_RATE, 70 | SerialPort.DATABITS_8, 71 | SerialPort.STOPBITS_1, 72 | SerialPort.PARITY_NONE); 73 | 74 | // open the streams 75 | is = serialPort.getInputStream(); 76 | os = serialPort.getOutputStream(); 77 | 78 | // add event listeners 79 | serialPort.addEventListener(this); 80 | serialPort.notifyOnDataAvailable(false); 81 | } catch (Exception e) { 82 | log.error("cannot connect to serial port", e); 83 | } 84 | } 85 | 86 | private void sendTestCommands() { 87 | ObdLink obdLink = new ElmLink(is, os); 88 | CommandInvoker commandInvoker = new CommandInvoker(obdLink); 89 | 90 | ResetCommand resetCommand = new ResetCommand(); 91 | commandInvoker.invoke(resetCommand); 92 | 93 | SetDefaultsCommand setDefaultsCommand = new SetDefaultsCommand(); 94 | commandInvoker.invoke(setDefaultsCommand); 95 | 96 | SetEchoCommand setEchoCommand = new SetEchoCommand(false); 97 | commandInvoker.invoke(setEchoCommand); 98 | 99 | SetMemoryCommand setMemoryCommand = new SetMemoryCommand(false); 100 | commandInvoker.invoke(setMemoryCommand); 101 | 102 | SetLineFeedCommand setLinefeedCommand = new SetLineFeedCommand(false); 103 | commandInvoker.invoke(setLinefeedCommand); 104 | 105 | SetSpacesCommand setSpacesCommand = new SetSpacesCommand(false); 106 | commandInvoker.invoke(setSpacesCommand); 107 | 108 | AdaptiveTimeoutProtocolCommand adaptiveTimeoutProtocol = new AdaptiveTimeoutProtocolCommand(); 109 | commandInvoker.invoke(adaptiveTimeoutProtocol); 110 | 111 | SelectProtocolCommand selectProtocolCommand = new SelectProtocolCommand(); 112 | commandInvoker.invoke(selectProtocolCommand); 113 | 114 | EngineRpmCommand engineRpmCommand = new EngineRpmCommand(); 115 | log.info("command - '{}'", engineRpmCommand); 116 | commandInvoker.invoke(engineRpmCommand); 117 | log.info("command response - '{}'\n", engineRpmCommand.getValue()); 118 | 119 | EngineLoadCommand engineLoadCommand = new EngineLoadCommand(); 120 | commandInvoker.invoke(engineLoadCommand); 121 | 122 | EngineCoolantTemperatureCommand engineCoolantTemperatureCommand = new EngineCoolantTemperatureCommand(); 123 | log.info("command - '{}'", engineCoolantTemperatureCommand); 124 | commandInvoker.invoke(engineCoolantTemperatureCommand); 125 | log.info("command response - '{}'\n", engineCoolantTemperatureCommand.getValue()); 126 | 127 | IntakeAirTemperatureCommand intakeAirTemperatureCommand = new IntakeAirTemperatureCommand(); 128 | commandInvoker.invoke(intakeAirTemperatureCommand); 129 | 130 | MassAirFlowCommand massAirFlowCommand = new MassAirFlowCommand(); 131 | log.info("command - '{}'", massAirFlowCommand); 132 | commandInvoker.invoke(massAirFlowCommand); 133 | log.info("command response - '{}'\n", massAirFlowCommand.getValue()); 134 | // 135 | // ThrottlePositionCommand throttlePositionCommand = new ThrottlePositionCommand(); 136 | // log.info("command - '{}'", throttlePositionCommand); 137 | // commandInvoker.invoke(throttlePositionCommand); 138 | // log.info("command response - '{}'\n", throttlePositionCommand.getValue().getFloatValue()); 139 | // 140 | // EngineRuntimeCommand engineRuntimeCommand = new EngineRuntimeCommand(); 141 | // commandInvoker.invoke(engineRuntimeCommand); 142 | } 143 | 144 | @Override 145 | public void serialEvent(SerialPortEvent oEvent) { 146 | // Ignore all the other eventTypes, but you should consider the other 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/TestSupport.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd; 2 | 3 | import org.mockito.invocation.InvocationOnMock; 4 | import org.mockito.stubbing.Answer; 5 | 6 | import java.util.UUID; 7 | import java.util.concurrent.ThreadLocalRandom; 8 | 9 | public final class TestSupport { 10 | 11 | private static ThreadLocalRandom random = ThreadLocalRandom.current(); 12 | 13 | private TestSupport() { 14 | throw new AssertionError(); 15 | } 16 | 17 | public static String getRandomString() { 18 | UUID randomUUID = UUID.randomUUID(); 19 | return randomUUID.toString(); 20 | } 21 | 22 | public static boolean getRandomBoolean() { 23 | return random.nextBoolean(); 24 | } 25 | 26 | public static int getRandomInt() { 27 | return Math.abs(random.nextInt()); 28 | } 29 | 30 | public static int getRandomInt(int max) { 31 | return Math.abs(random.nextInt(0, max)); 32 | } 33 | 34 | public static long getRandomLong() { 35 | return Math.abs(random.nextLong()); 36 | } 37 | 38 | public static int getRandomIntByte() { 39 | return getRandomInt(255); 40 | } 41 | 42 | public static class InputStreamAnswer implements Answer { 43 | 44 | private final byte[] rawData; 45 | private int curIndex = 0; 46 | 47 | public InputStreamAnswer(String streamData) { 48 | this.rawData = streamData.getBytes(); 49 | } 50 | 51 | @Override 52 | public Object answer(InvocationOnMock invocation) throws Throwable { 53 | return rawData[curIndex++]; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/AbstractCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command; 2 | 3 | import org.mockito.Mock; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.fest.assertions.api.Assertions.assertThat; 8 | import static org.mockito.MockitoAnnotations.initMocks; 9 | import static org.powermock.api.mockito.PowerMockito.verifyZeroInteractions; 10 | 11 | public class AbstractCommandTest { 12 | 13 | @Mock 14 | private CommandResult commandResultMock; 15 | 16 | @Mock 17 | private ObdCommandVisitor obdCommandVisitorMock; 18 | 19 | private AbstractCommand sut; 20 | 21 | @BeforeMethod 22 | private void beforeMethod() { 23 | initMocks(this); 24 | sut = new FakeAbstractCommand(); 25 | } 26 | 27 | @Test 28 | public void getResultShouldReturnSetValue() throws Exception { 29 | // given 30 | 31 | // when 32 | sut.setResult(commandResultMock); 33 | CommandResult commandResult = sut.getResult(); 34 | 35 | // then 36 | assertThat(commandResult).isEqualTo(commandResultMock); 37 | } 38 | 39 | @Test 40 | public void acceptShouldDoNothing() throws Exception { 41 | // given 42 | 43 | // when 44 | sut.accept(obdCommandVisitorMock); 45 | 46 | // then 47 | verifyZeroInteractions(obdCommandVisitorMock); 48 | } 49 | 50 | private static class FakeAbstractCommand extends AbstractCommand { 51 | @Override 52 | public void accept(ObdCommandVisitor visitor) { 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/CommandResultTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command; 2 | 3 | import com.devesion.commons.obd.TestSupport; 4 | import org.testng.annotations.Test; 5 | 6 | import java.nio.IntBuffer; 7 | 8 | import static org.fest.assertions.api.Assertions.assertThat; 9 | 10 | public class CommandResultTest { 11 | 12 | private CommandResult sut; 13 | 14 | @Test 15 | public void withBufferShouldCreateResultWithPassedBuffer() throws Exception { 16 | // given 17 | IntBuffer expectedResponseBuffer = IntBuffer.allocate(0); 18 | 19 | // when 20 | sut = CommandResult.withBuffer(expectedResponseBuffer); 21 | IntBuffer responseBuffer = sut.getResponseBuffer(); 22 | 23 | // then 24 | assertThat(responseBuffer).isEqualTo(expectedResponseBuffer); 25 | } 26 | 27 | @Test 28 | public void emptyShouldCreateResultWithEmptyBuffer() throws Exception { 29 | // given 30 | 31 | // when 32 | sut = CommandResult.empty(); 33 | IntBuffer responseBuffer = sut.getResponseBuffer(); 34 | 35 | // then 36 | assertThat(responseBuffer.limit()).isEqualTo(10); 37 | } 38 | 39 | @Test 40 | public void getByteNumberShouldReturnProperByteFromBuffer() throws Exception { 41 | // given 42 | int responseBufferLength = 100; 43 | IntBuffer expectedResponseBuffer = IntBuffer.allocate(responseBufferLength); 44 | for (int i = 0; i < responseBufferLength; i++) { 45 | int randomValue = TestSupport.getRandomInt(); 46 | expectedResponseBuffer.put(randomValue); 47 | } 48 | 49 | // when 50 | sut = CommandResult.withBuffer(expectedResponseBuffer); 51 | 52 | boolean valuesAreNotEqual = false; 53 | for (int i = 0; i < responseBufferLength; i++) { 54 | int readValue = sut.getByteNumber(i); 55 | int expectedValue = expectedResponseBuffer.get(i); 56 | valuesAreNotEqual |= (readValue != expectedValue); 57 | } 58 | 59 | // then 60 | assertThat(valuesAreNotEqual).isFalse(); 61 | } 62 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/at/AbstractAtCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommandVisitor; 4 | import org.mockito.Mock; 5 | import org.testng.annotations.BeforeMethod; 6 | import org.testng.annotations.Test; 7 | 8 | import static org.mockito.Mockito.verify; 9 | import static org.mockito.MockitoAnnotations.initMocks; 10 | 11 | public class AbstractAtCommandTest { 12 | 13 | @Mock 14 | private ObdCommandVisitor protocolCommandVisitorMock; 15 | 16 | private AbstractAtCommand sut; 17 | 18 | @BeforeMethod 19 | private void beforeMethod() { 20 | initMocks(this); 21 | sut = new FakeAbstractProtocolCommand(); 22 | } 23 | 24 | @Test 25 | public void testAccept() throws Exception { 26 | // given 27 | 28 | // when 29 | sut.accept(protocolCommandVisitorMock); 30 | 31 | // then 32 | verify(protocolCommandVisitorMock).visit(sut); 33 | } 34 | 35 | private static class FakeAbstractProtocolCommand extends AbstractAtCommand { 36 | @Override 37 | public String getOperands() { 38 | return null; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/at/AbstractSetStateCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | import static org.fest.assertions.api.Assertions.assertThat; 6 | 7 | abstract class AbstractSetStateCommandTest { 8 | 9 | private AtCommand sut; 10 | 11 | @Test 12 | protected void constructorShouldSetStateOff() throws Exception { 13 | // given 14 | String expectedOperands = getOperandPrefix() + "0"; 15 | 16 | // when 17 | sut = createCommand(false); 18 | 19 | // then 20 | String operands = sut.getOperands(); 21 | assertThat(operands).isEqualTo(expectedOperands); 22 | } 23 | 24 | @Test 25 | protected void constructorShouldSetStateOn() throws Exception { 26 | // given 27 | String expectedOperands = getOperandPrefix() + "1"; 28 | 29 | // when 30 | sut = createCommand(true); 31 | 32 | // then 33 | String operands = sut.getOperands(); 34 | assertThat(operands).isEqualTo(expectedOperands); 35 | } 36 | 37 | protected abstract String getOperandPrefix(); 38 | 39 | protected abstract AtCommand createCommand(boolean state); 40 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/at/SelectProtocolCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | import org.testng.annotations.BeforeMethod; 4 | import org.testng.annotations.Test; 5 | 6 | import static org.fest.assertions.api.Assertions.assertThat; 7 | 8 | public class SelectProtocolCommandTest { 9 | 10 | private SelectProtocolCommand sut; 11 | 12 | @BeforeMethod 13 | private void beforeMethod() { 14 | sut = new SelectProtocolCommand(); 15 | } 16 | 17 | @Test 18 | public void getOperandsShouldReturnProperElmCommand() throws Exception { 19 | // given 20 | String expectedOperands = "SP 0"; 21 | 22 | // when 23 | String operands = sut.getOperands(); 24 | 25 | // then 26 | assertThat(operands).isEqualTo(expectedOperands); 27 | } 28 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/at/SetEchoCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | public class SetEchoCommandTest extends AbstractSetStateCommandTest { 6 | 7 | @Test 8 | public void constructorShouldSetEchoOff() throws Exception { 9 | constructorShouldSetStateOff(); 10 | } 11 | 12 | @Test 13 | public void constructorShouldSetEchoOn() throws Exception { 14 | constructorShouldSetStateOn(); 15 | } 16 | 17 | @Override 18 | protected String getOperandPrefix() { 19 | return "E"; 20 | } 21 | 22 | @Override 23 | protected AtCommand createCommand(boolean state) { 24 | return new SetEchoCommand(state); 25 | } 26 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/at/SetHeadersCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | public class SetHeadersCommandTest extends AbstractSetStateCommandTest { 6 | 7 | @Test 8 | public void constructorShouldSetHeadersOff() throws Exception { 9 | constructorShouldSetStateOff(); 10 | } 11 | 12 | @Test 13 | public void constructorShouldSetHeadersOn() throws Exception { 14 | constructorShouldSetStateOn(); 15 | } 16 | 17 | @Override 18 | protected String getOperandPrefix() { 19 | return "H"; 20 | } 21 | 22 | @Override 23 | protected AtCommand createCommand(boolean state) { 24 | return new SetHeadersCommand(state); 25 | } 26 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/at/SetLineFeedCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | public class SetLineFeedCommandTest extends AbstractSetStateCommandTest { 6 | 7 | @Test 8 | public void constructorShouldSetLineFeedOff() throws Exception { 9 | constructorShouldSetStateOff(); 10 | } 11 | 12 | @Test 13 | public void constructorShouldSetLineFeedOn() throws Exception { 14 | constructorShouldSetStateOn(); 15 | } 16 | 17 | @Override 18 | protected String getOperandPrefix() { 19 | return "L"; 20 | } 21 | 22 | @Override 23 | protected AtCommand createCommand(boolean state) { 24 | return new SetLineFeedCommand(state); 25 | } 26 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/at/SetMemoryCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | public class SetMemoryCommandTest extends AbstractSetStateCommandTest { 6 | 7 | @Test 8 | public void constructorShouldSetMemoryOff() throws Exception { 9 | constructorShouldSetStateOff(); 10 | } 11 | 12 | @Test 13 | public void constructorShouldSetMemoryOn() throws Exception { 14 | constructorShouldSetStateOn(); 15 | } 16 | 17 | @Override 18 | protected String getOperandPrefix() { 19 | return "M"; 20 | } 21 | 22 | @Override 23 | protected AtCommand createCommand(boolean state) { 24 | return new SetMemoryCommand(state); 25 | } 26 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/at/SetSpacesCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.at; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | public class SetSpacesCommandTest extends AbstractSetStateCommandTest { 6 | 7 | @Test 8 | public void constructorShouldSetSpacesOff() throws Exception { 9 | constructorShouldSetStateOff(); 10 | } 11 | 12 | @Test 13 | public void constructorShouldSetSpacesOn() throws Exception { 14 | constructorShouldSetStateOn(); 15 | } 16 | 17 | @Override 18 | protected String getOperandPrefix() { 19 | return "S"; 20 | } 21 | 22 | @Override 23 | protected AtCommand createCommand(boolean state) { 24 | return new SetSpacesCommand(state); 25 | } 26 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/AbstractDiagnosticCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommandVisitor; 4 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 5 | import org.mockito.Mock; 6 | import org.testng.annotations.BeforeMethod; 7 | import org.testng.annotations.Test; 8 | 9 | import static org.mockito.Mockito.verify; 10 | import static org.mockito.MockitoAnnotations.initMocks; 11 | 12 | public class AbstractDiagnosticCommandTest { 13 | 14 | @Mock 15 | private ObdCommandVisitor diagnosticCommandVisitorMock; 16 | 17 | private AbstractDiagnosticCommand sut; 18 | 19 | @BeforeMethod 20 | private void beforeMethod() { 21 | initMocks(this); 22 | sut = new FakeAbstractDiagnosticCommand(); 23 | } 24 | 25 | @Test 26 | public void testAccept() throws Exception { 27 | // given 28 | 29 | // when 30 | sut.accept(diagnosticCommandVisitorMock); 31 | 32 | // then 33 | verify(diagnosticCommandVisitorMock).visit(sut); 34 | } 35 | 36 | private static class FakeAbstractDiagnosticCommand extends AbstractDiagnosticCommand { 37 | 38 | @Override 39 | public ObdNumberedEnum getMode() { 40 | return null; 41 | } 42 | 43 | @Override 44 | public ObdNumberedEnum getPid() { 45 | return null; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/AbstractSensorCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.DiagnosticCommandMode; 4 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 5 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 6 | import org.testng.annotations.BeforeMethod; 7 | import org.testng.annotations.Test; 8 | 9 | import static org.fest.assertions.api.Assertions.assertThat; 10 | import static org.mockito.MockitoAnnotations.initMocks; 11 | 12 | public class AbstractSensorCommandTest { 13 | 14 | private AbstractSensorCommand sut; 15 | 16 | @BeforeMethod 17 | private void beforeMethod() { 18 | initMocks(this); 19 | sut = new FakeAbstractSensorCommand(); 20 | } 21 | 22 | @Test 23 | public void getModeShouldReturnSensors() throws Exception { 24 | // given 25 | 26 | // when 27 | ObdNumberedEnum mode = sut.getMode(); 28 | 29 | // then 30 | assertThat(mode).isEqualTo(DiagnosticCommandMode.SENSORS); 31 | } 32 | 33 | private static class FakeAbstractSensorCommand extends AbstractSensorCommand { 34 | 35 | @Override 36 | public SensorCommandValue getValue() { 37 | return null; 38 | } 39 | 40 | @Override 41 | public ObdNumberedEnum getPid() { 42 | return null; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/AmbientAirTemperatureCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class AmbientAirTemperatureCommandTest extends BaseSensorCommandTest { 10 | 11 | private AmbientAirTemperatureCommand sut; 12 | 13 | @BeforeMethod 14 | private void beforeMethod() { 15 | initMocks(this); 16 | 17 | sut = new AmbientAirTemperatureCommand(); 18 | UnitFactory unitFactoryMock = recordUnitFactoryCreatesTemperature(); 19 | sut.setUnitFactory(unitFactoryMock); 20 | } 21 | 22 | @Test 23 | public void getPidShouldReturnObdPidForSensor() throws Exception { 24 | testCommandReturnsProperPid(sut, SensorCommandPid.AMBIENT_AIR_TEMPERATURE); 25 | } 26 | 27 | @Test 28 | public void getValueShouldCreateTemperatureValueObjectFromResultBuffer() throws Exception { 29 | testCommandGetValueCreateProperValueObject(sut); 30 | } 31 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/BaseSensorCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.SensorCommandValue; 5 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 6 | import com.devesion.commons.obd.adapter.shared.ObdNumberedEnum; 7 | import org.mockito.Mock; 8 | 9 | import static org.fest.assertions.api.Assertions.assertThat; 10 | import static org.mockito.Mockito.when; 11 | 12 | abstract class BaseSensorCommandTest { 13 | 14 | @Mock 15 | private UnitFactory unitFactoryMock; 16 | 17 | @Mock 18 | private CommandResult commandResultMock; 19 | 20 | @Mock 21 | private SensorCommandValue sensorCommandValueMock; 22 | 23 | protected void testCommandReturnsProperPid(SensorCommand sut, SensorCommandPid pid) { 24 | // given 25 | 26 | // when 27 | ObdNumberedEnum mode = sut.getPid(); 28 | 29 | // then 30 | assertThat(mode).isEqualTo(pid); 31 | } 32 | 33 | protected void testCommandGetValueCreateProperValueObject(SensorCommand sut) { 34 | // given 35 | sut.setResult(commandResultMock); 36 | 37 | // when 38 | SensorCommandValue value = sut.getValue(); 39 | 40 | // then 41 | assertThat(value).isEqualTo(sensorCommandValueMock); 42 | } 43 | 44 | protected UnitFactory recordUnitFactoryCreatesTemperature() { 45 | when(unitFactoryMock.createTemperatureValue(commandResultMock)).thenReturn(sensorCommandValueMock); 46 | return unitFactoryMock; 47 | } 48 | 49 | protected UnitFactory recordUnitFactoryCreatesPercentage() { 50 | when(unitFactoryMock.createPercentageValue(commandResultMock)).thenReturn(sensorCommandValueMock); 51 | return unitFactoryMock; 52 | } 53 | 54 | protected UnitFactory recordUnitFactoryCreatesRpm() { 55 | when(unitFactoryMock.createRpmValue(commandResultMock)).thenReturn(sensorCommandValueMock); 56 | return unitFactoryMock; 57 | } 58 | 59 | protected UnitFactory recordUnitFactoryCreatesTime() { 60 | when(unitFactoryMock.createTimeValue(commandResultMock)).thenReturn(sensorCommandValueMock); 61 | return unitFactoryMock; 62 | } 63 | 64 | protected UnitFactory recordUnitFactoryCreatesFuelConsuption() { 65 | when(unitFactoryMock.createFuelConsumptionValue(commandResultMock)).thenReturn(sensorCommandValueMock); 66 | return unitFactoryMock; 67 | } 68 | 69 | protected UnitFactory recordUnitFactoryCreatesFuelLevel() { 70 | when(unitFactoryMock.createFuelLevelValue(commandResultMock)).thenReturn(sensorCommandValueMock); 71 | return unitFactoryMock; 72 | } 73 | 74 | protected UnitFactory recordUnitFactoryCreatesFuelType() { 75 | when(unitFactoryMock.createFuelTypeValue(commandResultMock)).thenReturn(sensorCommandValueMock); 76 | return unitFactoryMock; 77 | } 78 | 79 | protected UnitFactory recordUnitFactoryCreatesAirFlow() { 80 | when(unitFactoryMock.createAirFlowValue(commandResultMock)).thenReturn(sensorCommandValueMock); 81 | return unitFactoryMock; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/EngineCoolantTemperatureCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class EngineCoolantTemperatureCommandTest extends BaseSensorCommandTest { 10 | 11 | private EngineCoolantTemperatureCommand sut; 12 | 13 | @BeforeMethod 14 | private void beforeMethod() { 15 | initMocks(this); 16 | 17 | sut = new EngineCoolantTemperatureCommand(); 18 | UnitFactory unitFactoryMock = recordUnitFactoryCreatesTemperature(); 19 | sut.setUnitFactory(unitFactoryMock); 20 | } 21 | 22 | @Test 23 | public void getPidShouldReturnObdPidForSensor() throws Exception { 24 | testCommandReturnsProperPid(sut, SensorCommandPid.ENGINE_COOLANT_TEMPERATURE); 25 | } 26 | 27 | @Test 28 | public void getValueShouldCreateTemperatureValueObjectFromResultBuffer() throws Exception { 29 | testCommandGetValueCreateProperValueObject(sut); 30 | } 31 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/EngineLoadCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class EngineLoadCommandTest extends BaseSensorCommandTest { 10 | 11 | private EngineLoadCommand sut; 12 | 13 | @BeforeMethod 14 | private void beforeMethod() { 15 | initMocks(this); 16 | 17 | sut = new EngineLoadCommand(); 18 | UnitFactory unitFactoryMock = recordUnitFactoryCreatesPercentage(); 19 | sut.setUnitFactory(unitFactoryMock); 20 | } 21 | 22 | @Test 23 | public void getPidShouldReturnObdPidForSensor() throws Exception { 24 | testCommandReturnsProperPid(sut, SensorCommandPid.ENGINE_LOAD); 25 | } 26 | 27 | @Test 28 | public void getValueShouldCreatePercentageValueObjectFromResultBuffer() throws Exception { 29 | testCommandGetValueCreateProperValueObject(sut); 30 | } 31 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/EngineRpmCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class EngineRpmCommandTest extends BaseSensorCommandTest { 10 | 11 | private EngineRpmCommand sut; 12 | 13 | @BeforeMethod 14 | private void beforeMethod() { 15 | initMocks(this); 16 | 17 | sut = new EngineRpmCommand(); 18 | UnitFactory unitFactoryMock = recordUnitFactoryCreatesRpm(); 19 | sut.setUnitFactory(unitFactoryMock); 20 | } 21 | 22 | @Test 23 | public void getPidShouldReturnObdPidForSensor() throws Exception { 24 | testCommandReturnsProperPid(sut, SensorCommandPid.ENGINE_RPM); 25 | } 26 | 27 | @Test 28 | public void getValueShouldCreateRpmValueObjectFromResultBuffer() throws Exception { 29 | testCommandGetValueCreateProperValueObject(sut); 30 | } 31 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/EngineRuntimeCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class EngineRuntimeCommandTest extends BaseSensorCommandTest { 10 | 11 | private EngineRuntimeCommand sut; 12 | 13 | @BeforeMethod 14 | private void beforeMethod() { 15 | initMocks(this); 16 | 17 | sut = new EngineRuntimeCommand(); 18 | UnitFactory unitFactoryMock = recordUnitFactoryCreatesTime(); 19 | sut.setUnitFactory(unitFactoryMock); 20 | } 21 | 22 | @Test 23 | public void getPidShouldReturnObdPidForSensor() throws Exception { 24 | testCommandReturnsProperPid(sut, SensorCommandPid.ENGINE_RUN_TIME); 25 | } 26 | 27 | @Test 28 | public void getValueShouldCreateTimeValueObjectFromResultBuffer() throws Exception { 29 | testCommandGetValueCreateProperValueObject(sut); 30 | } 31 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/FuelConsumptionRateCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class FuelConsumptionRateCommandTest extends BaseSensorCommandTest { 10 | 11 | private FuelConsumptionRateCommand sut; 12 | 13 | @BeforeMethod 14 | private void beforeMethod() { 15 | initMocks(this); 16 | 17 | sut = new FuelConsumptionRateCommand(); 18 | UnitFactory unitFactoryMock = recordUnitFactoryCreatesFuelConsuption(); 19 | sut.setUnitFactory(unitFactoryMock); 20 | } 21 | 22 | @Test 23 | public void getPidShouldReturnObdPidForSensor() throws Exception { 24 | testCommandReturnsProperPid(sut, SensorCommandPid.FUEL_CONSUMPTION_1); 25 | } 26 | 27 | @Test 28 | public void getValueShouldCreateFuelConsumptionValueObjectFromResultBuffer() throws Exception { 29 | testCommandGetValueCreateProperValueObject(sut); 30 | } 31 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/FuelLevelCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class FuelLevelCommandTest extends BaseSensorCommandTest { 10 | 11 | private FuelLevelCommand sut; 12 | 13 | @BeforeMethod 14 | private void beforeMethod() { 15 | initMocks(this); 16 | 17 | sut = new FuelLevelCommand(); 18 | UnitFactory unitFactoryMock = recordUnitFactoryCreatesFuelLevel(); 19 | sut.setUnitFactory(unitFactoryMock); 20 | } 21 | 22 | @Test 23 | public void getPidShouldReturnObdPidForSensor() throws Exception { 24 | testCommandReturnsProperPid(sut, SensorCommandPid.FUEL_LEVEL); 25 | } 26 | 27 | @Test 28 | public void getValueShouldCreateFuelLevelValueObjectFromResultBuffer() throws Exception { 29 | testCommandGetValueCreateProperValueObject(sut); 30 | } 31 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/FuelTypeCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class FuelTypeCommandTest extends BaseSensorCommandTest { 10 | 11 | private FuelTypeCommand sut; 12 | 13 | @BeforeMethod 14 | private void beforeMethod() { 15 | initMocks(this); 16 | 17 | sut = new FuelTypeCommand(); 18 | UnitFactory unitFactoryMock = recordUnitFactoryCreatesFuelType(); 19 | sut.setUnitFactory(unitFactoryMock); 20 | } 21 | 22 | @Test 23 | public void getPidShouldReturnObdPidForSensor() throws Exception { 24 | testCommandReturnsProperPid(sut, SensorCommandPid.FUEL_TYPE); 25 | } 26 | 27 | @Test 28 | public void getValueShouldCreateFuelTypeValueObjectFromResultBuffer() throws Exception { 29 | testCommandGetValueCreateProperValueObject(sut); 30 | } 31 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/IntakeAirTemperatureCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class IntakeAirTemperatureCommandTest extends BaseSensorCommandTest { 10 | 11 | private IntakeAirTemperatureCommand sut; 12 | 13 | @BeforeMethod 14 | private void beforeMethod() { 15 | initMocks(this); 16 | 17 | sut = new IntakeAirTemperatureCommand(); 18 | UnitFactory unitFactoryMock = recordUnitFactoryCreatesTemperature(); 19 | sut.setUnitFactory(unitFactoryMock); 20 | } 21 | 22 | @Test 23 | public void getPidShouldReturnObdPidForSensor() throws Exception { 24 | testCommandReturnsProperPid(sut, SensorCommandPid.INTAKE_AIR_TEMPERATURE); 25 | } 26 | 27 | @Test 28 | public void getValueShouldCreateTemperatureValueObjectFromResultBuffer() throws Exception { 29 | testCommandGetValueCreateProperValueObject(sut); 30 | } 31 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/MassAirFlowCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class MassAirFlowCommandTest extends BaseSensorCommandTest { 10 | 11 | private MassAirFlowCommand sut; 12 | 13 | @BeforeMethod 14 | private void beforeMethod() { 15 | initMocks(this); 16 | 17 | sut = new MassAirFlowCommand(); 18 | UnitFactory unitFactoryMock = recordUnitFactoryCreatesAirFlow(); 19 | sut.setUnitFactory(unitFactoryMock); 20 | } 21 | 22 | @Test 23 | public void getPidShouldReturnObdPidForSensor() throws Exception { 24 | testCommandReturnsProperPid(sut, SensorCommandPid.MASS_AIR_FLOW); 25 | } 26 | 27 | @Test 28 | public void getValueShouldCreateAirFlowValueObjectFromResultBuffer() throws Exception { 29 | testCommandGetValueCreateProperValueObject(sut); 30 | } 31 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/ThrottlePositionCommandTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors; 2 | 3 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.UnitFactory; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class ThrottlePositionCommandTest extends BaseSensorCommandTest { 10 | 11 | private ThrottlePositionCommand sut; 12 | 13 | @BeforeMethod 14 | private void beforeMethod() { 15 | initMocks(this); 16 | 17 | sut = new ThrottlePositionCommand(); 18 | UnitFactory unitFactoryMock = recordUnitFactoryCreatesPercentage(); 19 | sut.setUnitFactory(unitFactoryMock); 20 | } 21 | 22 | @Test 23 | public void getPidShouldReturnObdPidForSensor() throws Exception { 24 | testCommandReturnsProperPid(sut, SensorCommandPid.THROTTLE_POSITION_PERCENTAGE); 25 | } 26 | 27 | @Test 28 | public void getValueShouldCreatePercentageValueObjectFromResultBuffer() throws Exception { 29 | testCommandGetValueCreateProperValueObject(sut); 30 | } 31 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/AirFlowValueTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class AirFlowValueTest extends BaseValueTest { 10 | 11 | @BeforeMethod 12 | private void beforeMethod() { 13 | initMocks(this); 14 | } 15 | 16 | @Test 17 | public void constructorShouldSetDefaultDivisorAndMultiplier() throws Exception { 18 | constructorShouldSetDefaultDivisorAndMultiplier(256, 100); 19 | } 20 | 21 | @Override 22 | protected AbstractSensorCommandValue createSut(CommandResult commandResultMock) { 23 | return new AirFlowValue(commandResultMock); 24 | } 25 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/BaseValueTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import org.mockito.Mock; 5 | 6 | import static org.fest.assertions.api.Assertions.assertThat; 7 | import static org.mockito.Mockito.when; 8 | 9 | abstract class BaseValueTest { 10 | 11 | @Mock 12 | private CommandResult commandResultMock; 13 | 14 | protected void constructorShouldSetDefaultDivisorAndMultiplier(float multiplier, float divisor) throws Exception { 15 | // given 16 | when(commandResultMock.getByteNumber(0)).thenReturn(1); 17 | when(commandResultMock.getByteNumber(1)).thenReturn(0); 18 | float expectedValue = multiplier / divisor; 19 | 20 | // when 21 | AbstractSensorCommandValue sut = createSut(commandResultMock); 22 | float value = sut.calculateValue(); 23 | 24 | // then 25 | assertThat(value).isEqualTo(expectedValue); 26 | } 27 | 28 | protected abstract AbstractSensorCommandValue createSut(CommandResult commandResultMock); 29 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/FuelConsumptionValueTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class FuelConsumptionValueTest extends BaseValueTest { 10 | 11 | @BeforeMethod 12 | private void beforeMethod() { 13 | initMocks(this); 14 | } 15 | 16 | @Test 17 | public void constructorShouldSetDefaultDivisorAndMultiplier() throws Exception { 18 | constructorShouldSetDefaultDivisorAndMultiplier(256, 20); 19 | } 20 | 21 | @Override 22 | protected AbstractSensorCommandValue createSut(CommandResult commandResultMock) { 23 | return new FuelConsumptionValue(commandResultMock); 24 | } 25 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/FuelTypeValueTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import com.google.common.base.Optional; 5 | import org.mockito.Mock; 6 | import org.testng.annotations.BeforeMethod; 7 | import org.testng.annotations.Test; 8 | 9 | import static com.devesion.commons.obd.adapter.command.diagnostic.sensors.units.FuelTypeValue.FuelType; 10 | import static org.fest.assertions.api.Assertions.assertThat; 11 | import static org.mockito.Mockito.when; 12 | import static org.mockito.MockitoAnnotations.initMocks; 13 | 14 | public class FuelTypeValueTest { 15 | 16 | @Mock 17 | private CommandResult commandResultMock; 18 | 19 | private FuelTypeValue sut; 20 | 21 | @BeforeMethod 22 | private void beforeMethod() { 23 | initMocks(this); 24 | sut = new FuelTypeValue(commandResultMock); 25 | } 26 | 27 | @Test 28 | public void getTypeShouldSelectProperEnumType() throws Exception { 29 | // given 30 | 31 | // when 32 | boolean fuelTypesAreEqual = true; 33 | for (FuelType expectedFuelType : FuelType.values()) { 34 | when(commandResultMock.getByteNumber(0)).thenReturn(expectedFuelType.getTypeNumber()); 35 | Optional fuelTypeOptional = sut.getType(); 36 | FuelType fuelType = fuelTypeOptional.get(); 37 | fuelTypesAreEqual &= fuelType.equals(expectedFuelType); 38 | } 39 | 40 | // then 41 | assertThat(fuelTypesAreEqual).isTrue(); 42 | } 43 | 44 | @Test 45 | public void getTypeShouldReturnAbsentForUnknownFuelTypeByte() throws Exception { 46 | // given 47 | int maxFuelTypeNumber = getMaxFuelTypeNumber(); 48 | int unknownFuelTypeNumber = maxFuelTypeNumber + 1; 49 | when(commandResultMock.getByteNumber(0)).thenReturn(unknownFuelTypeNumber); 50 | 51 | // when 52 | Optional fuelTypeOptional = sut.getType(); 53 | 54 | // then 55 | assertThat(fuelTypeOptional.isPresent()).isFalse(); 56 | } 57 | 58 | private int getMaxFuelTypeNumber() { 59 | int maxFuelTypeNumber = 0; 60 | for (FuelType fuelType : FuelType.values()) { 61 | int fuelTypeNumber = fuelType.getTypeNumber(); 62 | maxFuelTypeNumber = (maxFuelTypeNumber > fuelTypeNumber) ? maxFuelTypeNumber : fuelTypeNumber; 63 | } 64 | 65 | return maxFuelTypeNumber; 66 | } 67 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/RpmValueTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.testng.annotations.BeforeMethod; 6 | import org.testng.annotations.DataProvider; 7 | import org.testng.annotations.Test; 8 | 9 | import java.nio.IntBuffer; 10 | 11 | import static org.fest.assertions.api.Assertions.assertThat; 12 | import static org.mockito.MockitoAnnotations.initMocks; 13 | 14 | @Slf4j 15 | public class RpmValueTest extends BaseValueTest { 16 | 17 | @BeforeMethod 18 | private void beforeMethod() { 19 | initMocks(this); 20 | } 21 | 22 | @Test 23 | public void constructorShouldSetDefaultDivisorAndMultiplier() throws Exception { 24 | constructorShouldSetDefaultDivisorAndMultiplier(256, 4); 25 | } 26 | 27 | @Override 28 | protected AbstractSensorCommandValue createSut(CommandResult commandResultMock) { 29 | return new RpmValue(commandResultMock); 30 | } 31 | 32 | @DataProvider(name = "rpmValues") 33 | public Object[][] createData1() { 34 | return new Object[][] { 35 | { IntBuffer.wrap(new int[]{0x0C, 0x99}), 806}, 36 | { IntBuffer.wrap(new int[]{0x0A, 0x96}), 677}, 37 | { IntBuffer.wrap(new int[]{0x0A, 0x7A}), 670}, 38 | { IntBuffer.wrap(new int[]{0x0A, 0x5A}), 662}, 39 | }; 40 | } 41 | 42 | @Test(dataProvider = "rpmValues") 43 | public void getIntValueShouldReturnProperValue(IntBuffer resultBuffer, float expectedValue) { 44 | // given 45 | CommandResult commandResult = CommandResult.withBuffer(resultBuffer); 46 | 47 | // when 48 | AbstractSensorCommandValue sut = new RpmValue(commandResult); 49 | sut.calculateValue(); 50 | float value = sut.getIntValue(); 51 | 52 | // then 53 | assertThat(value).isEqualTo(expectedValue); 54 | } 55 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/SimpleValueTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import org.mockito.Mock; 5 | import org.testng.annotations.BeforeMethod; 6 | import org.testng.annotations.Test; 7 | 8 | import static com.devesion.commons.obd.TestSupport.getRandomIntByte; 9 | import static org.fest.assertions.api.Assertions.assertThat; 10 | import static org.mockito.Mockito.when; 11 | import static org.mockito.MockitoAnnotations.initMocks; 12 | 13 | public class SimpleValueTest { 14 | 15 | @Mock 16 | private CommandResult commandResultMock; 17 | 18 | private SimpleValue sut; 19 | 20 | @BeforeMethod 21 | private void beforeMethod() { 22 | initMocks(this); 23 | recordCommandResultMockBehavior(); 24 | } 25 | 26 | @Test 27 | public void testCalculateValue() throws Exception { 28 | // given 29 | int randomMultiplier = getRandomIntByte(); 30 | int randomDivisor = getRandomIntByte(); 31 | float expectedCalculatedValue = getExpectedCalculatedValue(randomMultiplier, randomDivisor); 32 | 33 | sut = new SimpleValue(commandResultMock, randomMultiplier, randomDivisor); 34 | 35 | // when 36 | float calculatedValue = sut.calculateValue(); 37 | 38 | // then 39 | assertThat(calculatedValue).isEqualTo(expectedCalculatedValue); 40 | } 41 | 42 | @Test 43 | public void calculateValueShouldUseDefaultMultiplier() throws Exception { 44 | // given 45 | int defaultMultiplier = 255; 46 | int randomDivisor = getRandomIntByte(); 47 | float expectedCalculatedValue = getExpectedCalculatedValue(defaultMultiplier, randomDivisor); 48 | 49 | sut = new SimpleValue(commandResultMock, defaultMultiplier, randomDivisor); 50 | 51 | // when 52 | float calculatedValue = sut.calculateValue(); 53 | 54 | // then 55 | assertThat(calculatedValue).isEqualTo(expectedCalculatedValue); 56 | } 57 | 58 | private float getExpectedCalculatedValue(int randomMultiplier, float randomDivisor) { 59 | return (commandResultMock.getByteNumber(0) * randomMultiplier + commandResultMock.getByteNumber(1)) / randomDivisor; 60 | } 61 | 62 | private void recordCommandResultMockBehavior() { 63 | int randomMajorByte = getRandomIntByte(); 64 | int randomMinorByte = getRandomIntByte(); 65 | when(commandResultMock.getByteNumber(0)).thenReturn(randomMajorByte); 66 | when(commandResultMock.getByteNumber(1)).thenReturn(randomMinorByte); 67 | } 68 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/TemperatureValueTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | public class TemperatureValueTest { 6 | @Test 7 | public void Should() throws Exception { 8 | } 9 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/TimeValueTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class TimeValueTest extends BaseValueTest { 10 | 11 | @BeforeMethod 12 | private void beforeMethod() { 13 | initMocks(this); 14 | } 15 | 16 | @Test 17 | public void constructorShouldSetDefaultDivisorAndMultiplier() throws Exception { 18 | constructorShouldSetDefaultDivisorAndMultiplier(256, 1); 19 | } 20 | 21 | @Override 22 | protected AbstractSensorCommandValue createSut(CommandResult commandResultMock) { 23 | return new TimeValue(commandResultMock); 24 | } 25 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/diagnostic/sensors/units/UnitFactoryTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.diagnostic.sensors.units; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import org.mockito.Mock; 5 | import org.testng.annotations.BeforeMethod; 6 | import org.testng.annotations.Test; 7 | 8 | import static org.fest.assertions.api.Assertions.assertThat; 9 | import static org.mockito.MockitoAnnotations.initMocks; 10 | 11 | public class UnitFactoryTest { 12 | 13 | @Mock 14 | private CommandResult commandResultMock; 15 | 16 | private UnitFactory sut; 17 | 18 | @BeforeMethod 19 | private void beforeMethod() { 20 | initMocks(this); 21 | sut = new UnitFactory(); 22 | } 23 | 24 | @Test 25 | public void testCreateAirFlowValue() throws Exception { 26 | // given 27 | 28 | // when 29 | SensorCommandValue valueObject = sut.createAirFlowValue(commandResultMock); 30 | 31 | // then 32 | assertValueObjectHasProperTypeAndResult(valueObject, AirFlowValue.class); 33 | } 34 | 35 | @Test 36 | public void testCreateFuelConsumptionValue() throws Exception { 37 | // given 38 | 39 | // when 40 | SensorCommandValue valueObject = sut.createFuelConsumptionValue(commandResultMock); 41 | 42 | // then 43 | assertValueObjectHasProperTypeAndResult(valueObject, FuelConsumptionValue.class); 44 | } 45 | 46 | @Test 47 | public void testCreateFuelLevelValue() throws Exception { 48 | // given 49 | 50 | // when 51 | SensorCommandValue valueObject = sut.createFuelLevelValue(commandResultMock); 52 | 53 | // then 54 | assertValueObjectHasProperTypeAndResult(valueObject, PercentageValue.class); 55 | } 56 | 57 | @Test 58 | public void testCreateFuelTypeValue() throws Exception { 59 | // given 60 | 61 | // when 62 | SensorCommandValue valueObject = sut.createFuelTypeValue(commandResultMock); 63 | 64 | // then 65 | assertValueObjectHasProperTypeAndResult(valueObject, FuelTypeValue.class); 66 | } 67 | 68 | @Test 69 | public void testCreatePercentageValue() throws Exception { 70 | // given 71 | 72 | // when 73 | SensorCommandValue valueObject = sut.createPercentageValue(commandResultMock); 74 | 75 | // then 76 | assertValueObjectHasProperTypeAndResult(valueObject, PercentageValue.class); 77 | } 78 | 79 | @Test 80 | public void testCreatePressureValue() throws Exception { 81 | // given 82 | 83 | // when 84 | SensorCommandValue valueObject = sut.createPressureValue(commandResultMock); 85 | 86 | // then 87 | assertValueObjectHasProperTypeAndResult(valueObject, PressureValue.class); 88 | } 89 | 90 | @Test 91 | public void testCreateRpmValue() throws Exception { 92 | // given 93 | 94 | // when 95 | SensorCommandValue valueObject = sut.createRpmValue(commandResultMock); 96 | 97 | // then 98 | assertValueObjectHasProperTypeAndResult(valueObject, RpmValue.class); 99 | } 100 | 101 | @Test 102 | public void testCreateTemperatureValue() throws Exception { 103 | // given 104 | 105 | // when 106 | SensorCommandValue valueObject = sut.createTemperatureValue(commandResultMock); 107 | 108 | // then 109 | assertValueObjectHasProperTypeAndResult(valueObject, TemperatureValue.class); 110 | } 111 | 112 | @Test 113 | public void testCreateTimeValue() throws Exception { 114 | // given 115 | 116 | // when 117 | SensorCommandValue valueObject = sut.createTimeValue(commandResultMock); 118 | 119 | // then 120 | assertValueObjectHasProperTypeAndResult(valueObject, TimeValue.class); 121 | } 122 | 123 | @Test 124 | public void testCreateVoltageValue() throws Exception { 125 | // given 126 | 127 | // when 128 | SensorCommandValue valueObject = sut.createVoltageValue(commandResultMock); 129 | 130 | // then 131 | assertValueObjectHasProperTypeAndResult(valueObject, VoltageValue.class); 132 | } 133 | 134 | @SuppressWarnings("unchecked") 135 | private void assertValueObjectHasProperTypeAndResult(SensorCommandValue valueObject, Class instanceClass) { 136 | assertThat(valueObject).isInstanceOf(instanceClass); 137 | assertThat(((T) valueObject).getCommandResult()).isEqualTo(commandResultMock); 138 | } 139 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/command/invoker/CommandInvokerTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.command.invoker; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import com.devesion.commons.obd.adapter.command.ObdCommand; 5 | import com.devesion.commons.obd.adapter.link.CommandMarshaller; 6 | import com.devesion.commons.obd.adapter.link.CommandUnmarshaller; 7 | import com.devesion.commons.obd.adapter.link.ObdLink; 8 | import org.mockito.Mock; 9 | import org.testng.annotations.BeforeMethod; 10 | 11 | import static org.mockito.MockitoAnnotations.initMocks; 12 | 13 | // TODO 14 | public class CommandInvokerTest { 15 | 16 | @Mock 17 | private ObdLink obdLinkMock; 18 | 19 | @Mock 20 | private CommandMarshaller commandMarshallerMock; 21 | 22 | @Mock 23 | private CommandUnmarshaller commandUnmarshallerMock; 24 | 25 | @Mock 26 | private ObdCommand obdCommandMock; 27 | 28 | @Mock 29 | private CommandResult commandResultMock; 30 | 31 | private CommandInvoker sut; 32 | 33 | @BeforeMethod 34 | private void beforeMethod() { 35 | initMocks(this); 36 | } 37 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/link/elm/AbstractCommandUnmarshallerTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.adapter.command.CommandResult; 4 | import com.devesion.commons.obd.adapter.command.ObdCommand; 5 | import junit.framework.TestCase; 6 | import org.testng.annotations.BeforeMethod; 7 | import org.testng.annotations.DataProvider; 8 | import org.testng.annotations.Test; 9 | 10 | import static org.fest.assertions.api.Assertions.assertThat; 11 | 12 | public class AbstractCommandUnmarshallerTest extends TestCase { 13 | 14 | private AbstractCommandUnmarshaller sut; 15 | 16 | @BeforeMethod 17 | public void beforeMethod() { 18 | sut = new FakeAbstractCommandUnmarshaller(); 19 | } 20 | 21 | @DataProvider(name = "responselues") 22 | public Object[][] createData1() { 23 | return new Object[][] { 24 | { "1234 1234", "12341234"}, 25 | { "123\n41\n2 3\n41 2", "1234123412"}, 26 | { "0:410C0A820100\n" + "1:076D0000000000", "410C0A820100076D0000000000"} 27 | }; 28 | } 29 | 30 | @Test(dataProvider = "responselues") 31 | public void normalizeResponseShouldNormalizeResponse(String responseToNormalize, String expectedResponse) { 32 | // given 33 | 34 | // when 35 | String normalizedResponse = sut.normalizeResponse(responseToNormalize); 36 | 37 | // then 38 | assertThat(normalizedResponse).isEqualTo(expectedResponse); 39 | } 40 | 41 | private class FakeAbstractCommandUnmarshaller extends AbstractCommandUnmarshaller { 42 | 43 | @Override 44 | public CommandResult unmarshal(ObdCommand command, String data) { 45 | return null; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/link/elm/DiagnosticCommandUnmarshallerTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class DiagnosticCommandUnmarshallerTest extends TestCase { 6 | 7 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/link/elm/ElmLinkTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.TestSupport; 4 | import com.devesion.commons.obd.adapter.command.CommandResult; 5 | import com.devesion.commons.obd.adapter.command.ObdCommand; 6 | import com.devesion.commons.obd.adapter.link.CommandMarshaller; 7 | import com.devesion.commons.obd.adapter.link.CommandUnmarshaller; 8 | import org.mockito.Mock; 9 | import org.testng.annotations.BeforeMethod; 10 | import org.testng.annotations.Test; 11 | 12 | import static org.fest.assertions.api.Assertions.assertThat; 13 | import static org.mockito.Mockito.when; 14 | import static org.mockito.MockitoAnnotations.initMocks; 15 | 16 | public class ElmLinkTest { 17 | 18 | @Mock 19 | private ElmTransport elmTransportMock; 20 | 21 | @Mock 22 | private CommandMarshaller commandMarshallerMock; 23 | 24 | @Mock 25 | private CommandUnmarshaller commandUnmarshallerMock; 26 | 27 | @Mock 28 | private ObdCommand obdCommandMock; 29 | 30 | @Mock 31 | private CommandResult commandResultMock; 32 | 33 | private ElmLink sut; 34 | 35 | @BeforeMethod 36 | private void beforeMethod() { 37 | initMocks(this); 38 | sut = new ElmLink(elmTransportMock, commandMarshallerMock, commandUnmarshallerMock); 39 | 40 | String commandData = TestSupport.getRandomString(); 41 | String commandResponseData = TestSupport.getRandomString(); 42 | 43 | when(elmTransportMock.sendDataAndReadResponse(commandData)).thenReturn(commandResponseData); 44 | when(commandMarshallerMock.marshal(obdCommandMock)).thenReturn(commandData); 45 | when(commandUnmarshallerMock.unmarshal(obdCommandMock, commandResponseData)).thenReturn(commandResultMock); 46 | } 47 | 48 | @Test 49 | public void constructorShouldSetDefaultMarshallers() throws Exception { 50 | // given 51 | 52 | // when 53 | sut = new ElmLink(elmTransportMock); 54 | 55 | // then 56 | CommandMarshaller commandMarshaller = sut.getCommandMarshaller(); 57 | CommandUnmarshaller commandUnmarshaller = sut.getCommandUnmarshaller(); 58 | assertThat(commandMarshaller).isNotNull(); 59 | assertThat(commandUnmarshaller).isNotNull(); 60 | } 61 | 62 | @Test 63 | public void invokeShouldMarshalCommandAndUnmarshalResponse() throws Exception { 64 | // given 65 | 66 | // when 67 | CommandResult commandResult = sut.sendCommand(obdCommandMock); 68 | 69 | // then 70 | assertThat(commandResult).isEqualTo(commandResultMock); 71 | } 72 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/link/elm/ElmTransportTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.link.elm; 2 | 3 | import com.devesion.commons.obd.TestSupport; 4 | import com.devesion.commons.obd.adapter.shared.ObdCommunicationException; 5 | import org.mockito.InOrder; 6 | import org.mockito.Mock; 7 | import org.testng.annotations.BeforeMethod; 8 | import org.testng.annotations.Test; 9 | 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.io.OutputStream; 13 | 14 | import static com.devesion.commons.obd.TestSupport.InputStreamAnswer; 15 | import static com.googlecode.catchexception.CatchException.catchException; 16 | import static com.googlecode.catchexception.CatchException.caughtException; 17 | import static org.fest.assertions.api.Assertions.assertThat; 18 | import static org.mockito.Mockito.atLeastOnce; 19 | import static org.mockito.Mockito.doThrow; 20 | import static org.mockito.Mockito.inOrder; 21 | import static org.mockito.Mockito.when; 22 | import static org.mockito.MockitoAnnotations.initMocks; 23 | 24 | public class ElmTransportTest { 25 | 26 | @Mock 27 | private InputStream isMock; 28 | 29 | @Mock 30 | private OutputStream osMock; 31 | 32 | private ElmTransport sut; 33 | 34 | @BeforeMethod 35 | private void beforeMethod() { 36 | initMocks(this); 37 | sut = new ElmTransport(isMock, osMock); 38 | } 39 | 40 | @Test 41 | public void readDataShouldReadInputStreamToTheElmPrompt() throws Exception { 42 | // given 43 | String expectedData = getRandomStreamData(); 44 | String streamData = " " + expectedData + ">"; 45 | 46 | when(isMock.read()).thenAnswer(new InputStreamAnswer(streamData)); 47 | 48 | // when 49 | String readData = sut.readData(); 50 | 51 | // then 52 | assertThat(readData).isEqualTo(expectedData); 53 | } 54 | 55 | @Test 56 | @SuppressWarnings("unchecked") 57 | public void readDataShouldWrapExceptionsWithRuntimeException() throws Exception { 58 | // given 59 | when(isMock.read()).thenThrow(IOException.class); 60 | 61 | // when 62 | catchException(sut).readData(); 63 | 64 | // then 65 | Exception exception = caughtException(); 66 | assertThat(exception).isExactlyInstanceOf(ObdCommunicationException.class); 67 | } 68 | 69 | @Test 70 | public void sendDataShouldWriteDataToTheOutputStream() throws Exception { 71 | // given 72 | String expectedData = getRandomStreamData(); 73 | 74 | // when 75 | sut.sendData(expectedData); 76 | 77 | // then 78 | InOrder inOrder = inOrder(osMock); 79 | inOrder.verify(osMock).write(expectedData.getBytes()); 80 | inOrder.verify(osMock).flush(); 81 | } 82 | 83 | @Test 84 | @SuppressWarnings("unchecked") 85 | public void sendDataShouldWrapExceptionsDuringWriteWithRuntimeException() throws Exception { 86 | // given 87 | String expectedData = getRandomStreamData(); 88 | doThrow(IOException.class).when(osMock).write(expectedData.getBytes()); 89 | 90 | // when 91 | catchException(sut).sendData(expectedData); 92 | 93 | // then 94 | Exception exception = caughtException(); 95 | assertThat(exception).isExactlyInstanceOf(ObdCommunicationException.class); 96 | } 97 | 98 | @Test 99 | @SuppressWarnings("unchecked") 100 | public void sendDataShouldWrapExceptionsDuringFlushWithRuntimeException() throws Exception { 101 | // given 102 | String expectedData = getRandomStreamData(); 103 | doThrow(IOException.class).when(osMock).flush(); 104 | 105 | // when 106 | catchException(sut).sendData(expectedData); 107 | 108 | // then 109 | Exception exception = caughtException(); 110 | assertThat(exception).isExactlyInstanceOf(ObdCommunicationException.class); 111 | } 112 | 113 | @Test 114 | public void testSendDataAndReadResponse() throws Exception { 115 | // given 116 | String expectedData = getRandomStreamData(); 117 | String expectedResponseData = getRandomStreamData(); 118 | String expectedResponseStreamData = " " + expectedResponseData + ">"; 119 | when(isMock.read()).thenAnswer(new InputStreamAnswer(expectedResponseStreamData)); 120 | 121 | // when 122 | String readData = sut.sendDataAndReadResponse(expectedData); 123 | 124 | // then 125 | InOrder inOrder = inOrder(isMock, osMock); 126 | inOrder.verify(osMock).write(expectedData.getBytes()); 127 | inOrder.verify(osMock).flush(); 128 | inOrder.verify(isMock, atLeastOnce()).read(); 129 | assertThat(readData).isEqualTo(expectedResponseData); 130 | } 131 | 132 | private String getRandomStreamData() { 133 | return TestSupport.getRandomString() + " " + TestSupport.getRandomString() + " " + TestSupport.getRandomString(); 134 | } 135 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/shared/BaseObdCommandResponseExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import org.mockito.Mock; 5 | 6 | import static org.fest.assertions.api.Assertions.assertThat; 7 | 8 | abstract class BaseObdCommandResponseExceptionTest { 9 | 10 | @Mock 11 | private ObdCommand obdCommandMock; 12 | 13 | protected void testConstructorShouldSetCommand() { 14 | // given 15 | 16 | // when 17 | ObdCommandResponseException sut = createException(obdCommandMock); 18 | 19 | // then 20 | assertThat(sut.getCommand()).isEqualTo(obdCommandMock); 21 | } 22 | 23 | protected abstract ObdCommandResponseException createException(ObdCommand obdCommandMock); 24 | } 25 | -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/shared/ObdCommandResponseExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class ObdCommandResponseExceptionTest extends BaseObdCommandResponseExceptionTest { 10 | 11 | @BeforeMethod 12 | private void beforeMethod() { 13 | initMocks(this); 14 | } 15 | 16 | @Test 17 | public void constructorShouldSetCommand() throws Exception { 18 | testConstructorShouldSetCommand(); 19 | } 20 | 21 | @Override 22 | protected ObdCommandResponseException createException(ObdCommand obdCommandMock) { 23 | return new ObdCommandResponseException(obdCommandMock); 24 | } 25 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/shared/ObdInvalidCommandResponseExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class ObdInvalidCommandResponseExceptionTest extends BaseObdCommandResponseExceptionTest { 10 | 11 | @BeforeMethod 12 | private void beforeMethod() { 13 | initMocks(this); 14 | } 15 | 16 | @Test 17 | public void constructorShouldSetCommand() throws Exception { 18 | testConstructorShouldSetCommand(); 19 | } 20 | 21 | @Override 22 | protected ObdCommandResponseException createException(ObdCommand obdCommandMock) { 23 | return new ObdInvalidCommandResponseException(obdCommandMock, "NODATA"); 24 | } 25 | } -------------------------------------------------------------------------------- /adapter/src/test/java/com/devesion/commons/obd/adapter/shared/ObdnoDataForCommandResponseExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.devesion.commons.obd.adapter.shared; 2 | 3 | import com.devesion.commons.obd.adapter.command.ObdCommand; 4 | import org.testng.annotations.BeforeMethod; 5 | import org.testng.annotations.Test; 6 | 7 | import static org.mockito.MockitoAnnotations.initMocks; 8 | 9 | public class ObdnoDataForCommandResponseExceptionTest extends BaseObdCommandResponseExceptionTest { 10 | 11 | @BeforeMethod 12 | private void beforeMethod() { 13 | initMocks(this); 14 | } 15 | 16 | @Test 17 | public void constructorShouldSetCommand() throws Exception { 18 | testConstructorShouldSetCommand(); 19 | } 20 | 21 | @Override 22 | protected ObdCommandResponseException createException(ObdCommand obdCommandMock) { 23 | return new ObdNoDataForCommandResponseException(obdCommandMock); 24 | } 25 | } -------------------------------------------------------------------------------- /client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | obd-adapter 7 | com.devesion.commons.obd 8 | 1.0-SNAPSHOT 9 | 10 | 11 | 4.0.0 12 | client 13 | ${project.groupId}.${project.artifactId} 14 | 15 | 16 | 1.2.2.RELEASE 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-maven-plugin 24 | 25 | 26 | 27 | repackage 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter 39 | ${project.dependency.spring-boot-dependencies.version} 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-logging 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-log4j 51 | ${project.dependency.spring-boot-dependencies.version} 52 | 53 | 54 | 55 | com.devesion.commons.obd 56 | adapter 57 | 1.0-SNAPSHOT 58 | 59 | 60 | 61 | org.rxtx 62 | rxtx 63 | 2.1.7 64 | 65 | 66 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/Launcher.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android; 2 | 3 | import com.autonalyzer.adapter.android.domain.DiagnosticStatus; 4 | import com.autonalyzer.adapter.android.domain.DiagnosticStatusFactory; 5 | import com.autonalyzer.adapter.android.infrastructure.DefaultDiagnosticStatusFactory; 6 | import com.google.common.base.Optional; 7 | import lombok.extern.slf4j.Slf4j; 8 | 9 | @Slf4j 10 | public class Launcher { 11 | 12 | public static void main(String[] args) { 13 | while (true) { 14 | DiagnosticStatusFactory statusFactory = new DefaultDiagnosticStatusFactory(); 15 | Optional status = statusFactory.getCurrentStatus(); 16 | log.info("status {}", status); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/domain/DiagnosticStatus.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.domain; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | @EqualsAndHashCode 9 | @ToString 10 | public class DiagnosticStatus { 11 | 12 | @Setter 13 | @Getter 14 | private int runtime; 15 | 16 | @Setter 17 | @Getter 18 | private int speed; 19 | 20 | @Setter 21 | @Getter 22 | private int rpm; 23 | 24 | @Setter 25 | @Getter 26 | private float throttlePosition; 27 | 28 | @Setter 29 | @Getter 30 | private double massAirFlow; 31 | 32 | @Setter 33 | @Getter 34 | private int load; 35 | 36 | @Setter 37 | @Getter 38 | private int fuelLevel; 39 | 40 | @Setter 41 | @Getter 42 | private int fuelPressure; 43 | 44 | @Setter 45 | @Getter 46 | private int fuelType; 47 | 48 | @Setter 49 | @Getter 50 | private double ambientTemperature; 51 | 52 | @Setter 53 | @Getter 54 | private double coolantTemperature; 55 | 56 | @Setter 57 | @Getter 58 | private double intakeAirTemperature; 59 | } 60 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/domain/DiagnosticStatusFactory.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.domain; 2 | 3 | import com.google.common.base.Optional; 4 | 5 | public interface DiagnosticStatusFactory { 6 | 7 | Optional getCurrentStatus(); 8 | } 9 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/domain/DiagnosticStatusSpecification.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.domain; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.ToString; 5 | 6 | @EqualsAndHashCode 7 | @ToString 8 | public class DiagnosticStatusSpecification { 9 | 10 | private String trackId; 11 | 12 | private DiagnosticTransportSpecification diagnosticTransportSpecification; 13 | 14 | public DiagnosticStatusSpecification(DiagnosticTransportSpecification diagnosticTransportSpecification) { 15 | this.diagnosticTransportSpecification = diagnosticTransportSpecification; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/domain/DiagnosticTransportSpecification.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.domain; 2 | 3 | public class DiagnosticTransportSpecification { 4 | 5 | private VehicleLinkType type; 6 | private String name; 7 | 8 | public DiagnosticTransportSpecification(String fqn) { 9 | 10 | } 11 | 12 | public DiagnosticTransportSpecification(String typeName, String deviceName) { 13 | 14 | } 15 | 16 | public DiagnosticTransportSpecification(VehicleLinkType type, String deviceName) { 17 | this.type = type; 18 | this.name = deviceName; 19 | } 20 | 21 | public enum VehicleLinkType { 22 | BLUETOOTH 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/DefaultDiagnosticStatusFactory.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure; 2 | 3 | import com.autonalyzer.adapter.android.domain.DiagnosticStatus; 4 | import com.autonalyzer.adapter.android.domain.DiagnosticStatusFactory; 5 | import com.autonalyzer.adapter.android.infrastructure.gateway.DiagnosticStatusGateway; 6 | import com.autonalyzer.adapter.android.infrastructure.gateway.ProbingDiagnosticStatusGatewayFactory; 7 | import com.google.common.base.Optional; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | @Slf4j 11 | public class DefaultDiagnosticStatusFactory implements DiagnosticStatusFactory { 12 | 13 | private ProbingDiagnosticStatusGatewayFactory diagnosticStatusGatewayFactory; 14 | 15 | private static Optional diagnosticStatusGatewayOptional = Optional.absent(); 16 | 17 | public DefaultDiagnosticStatusFactory() { 18 | this.diagnosticStatusGatewayFactory = new ProbingDiagnosticStatusGatewayFactory(); 19 | } 20 | 21 | @Override 22 | public Optional getCurrentStatus() { 23 | try { 24 | openVehicleStatusGateway(); 25 | return readCurrentStatus(); 26 | } catch (DiagnosticStatusReadException e) { 27 | log.error("cannot read vehicle status - {}", e.getMessage()); 28 | closeVehicleStatusGateway(); 29 | return Optional.absent(); 30 | } 31 | } 32 | 33 | private void openVehicleStatusGateway() { 34 | if (!diagnosticStatusGatewayOptional.isPresent()) { 35 | diagnosticStatusGatewayOptional = diagnosticStatusGatewayFactory.createDiagnosticStatusGateway(); 36 | } 37 | } 38 | 39 | private Optional readCurrentStatus() { 40 | DiagnosticStatus vehicleStatus = null; 41 | if (diagnosticStatusGatewayOptional.isPresent()) { 42 | DiagnosticStatusGateway diagnosticStatusGateway = diagnosticStatusGatewayOptional.get(); 43 | vehicleStatus = diagnosticStatusGateway.readCurrentStatus(); 44 | } 45 | 46 | return Optional.fromNullable(vehicleStatus); 47 | } 48 | 49 | private void closeVehicleStatusGateway() { 50 | if (diagnosticStatusGatewayOptional.isPresent()) { 51 | DiagnosticStatusGateway diagnosticStatusGateway = diagnosticStatusGatewayOptional.get(); 52 | diagnosticStatusGateway.close(); 53 | diagnosticStatusGatewayOptional = Optional.absent(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/DiagnosticStatusReadException.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure; 2 | 3 | public class DiagnosticStatusReadException extends RuntimeException { 4 | 5 | public DiagnosticStatusReadException(String message) { 6 | super(message); 7 | } 8 | 9 | public DiagnosticStatusReadException(String message, Throwable cause) { 10 | super(message, cause); 11 | } 12 | 13 | public DiagnosticStatusReadException(Throwable cause) { 14 | super(cause); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/gateway/DiagnosticStatusGateway.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure.gateway; 2 | 3 | import com.autonalyzer.adapter.android.domain.DiagnosticStatus; 4 | 5 | import java.io.Closeable; 6 | 7 | public interface DiagnosticStatusGateway extends Closeable { 8 | 9 | void open(); 10 | 11 | DiagnosticStatus readCurrentStatus(); 12 | 13 | void close(); 14 | } 15 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/gateway/ProbingDiagnosticStatusGateway.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure.gateway; 2 | 3 | public interface ProbingDiagnosticStatusGateway extends DiagnosticStatusGateway { 4 | 5 | boolean probe(); 6 | } 7 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/gateway/ProbingDiagnosticStatusGatewayFactory.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure.gateway; 2 | 3 | import com.autonalyzer.adapter.android.infrastructure.gateway.elm.ProbingElmDiagnosticStatusGateway; 4 | import com.autonalyzer.adapter.android.infrastructure.transport.DiagnosticTransport; 5 | import com.autonalyzer.adapter.android.infrastructure.transport.DiagnosticTransportFactory; 6 | import com.autonalyzer.adapter.android.infrastructure.transport.ProbingDiagnosticTransportFactory; 7 | import com.google.common.base.Optional; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.util.List; 11 | 12 | @Slf4j 13 | public class ProbingDiagnosticStatusGatewayFactory { 14 | 15 | private DiagnosticTransportFactory vehicleDiagnosticTransportFactory = new ProbingDiagnosticTransportFactory(); 16 | 17 | public Optional createDiagnosticStatusGateway() { 18 | log.info("creating new diagnosticStatusGateway"); 19 | 20 | List transports = vehicleDiagnosticTransportFactory.createAvailableTransports(); 21 | for (DiagnosticTransport transport : transports) { 22 | Optional diagnosticStatusGatewayOptional = probeSingleTransport(transport); 23 | if (diagnosticStatusGatewayOptional.isPresent()) { 24 | return diagnosticStatusGatewayOptional; 25 | } 26 | } 27 | 28 | return Optional.absent(); 29 | } 30 | 31 | private Optional probeSingleTransport(DiagnosticTransport transport) { 32 | log.info("probing transport {}", transport); 33 | 34 | ProbingDiagnosticStatusGateway diagnosticStatusGateway = new ProbingElmDiagnosticStatusGateway(transport); 35 | if (diagnosticStatusGateway.probe()) { 36 | log.info("probe OK"); 37 | return Optional.of(diagnosticStatusGateway); 38 | } else { 39 | log.info("probe FAIL"); 40 | diagnosticStatusGateway.close(); 41 | return Optional.absent(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/gateway/elm/ElmDiagnosticStatusGateway.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure.gateway.elm; 2 | 3 | import com.autonalyzer.adapter.android.domain.DiagnosticStatus; 4 | import com.autonalyzer.adapter.android.infrastructure.gateway.DiagnosticStatusGateway; 5 | import com.autonalyzer.adapter.android.infrastructure.transport.DiagnosticTransport; 6 | import com.devesion.commons.obd.adapter.command.ObdCommand; 7 | import com.devesion.commons.obd.adapter.command.at.AdaptiveTimeoutProtocolCommand; 8 | import com.devesion.commons.obd.adapter.command.at.ResetCommand; 9 | import com.devesion.commons.obd.adapter.command.at.SelectProtocolCommand; 10 | import com.devesion.commons.obd.adapter.command.at.SetEchoCommand; 11 | import com.devesion.commons.obd.adapter.command.at.SetHeadersCommand; 12 | import com.devesion.commons.obd.adapter.command.at.SetLineFeedCommand; 13 | import com.devesion.commons.obd.adapter.command.at.SetSpacesCommand; 14 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.AmbientAirTemperatureCommand; 15 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.EngineCoolantTemperatureCommand; 16 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.EngineLoadCommand; 17 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.EngineRpmCommand; 18 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.EngineRuntimeCommand; 19 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.FuelLevelCommand; 20 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.FuelPressureCommand; 21 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.FuelTypeCommand; 22 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.IntakeAirTemperatureCommand; 23 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.MassAirFlowCommand; 24 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.SensorCommand; 25 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.SpeedCommand; 26 | import com.devesion.commons.obd.adapter.command.diagnostic.sensors.ThrottlePositionCommand; 27 | import com.devesion.commons.obd.adapter.command.invoker.CommandInvoker; 28 | import com.devesion.commons.obd.adapter.link.ObdLink; 29 | import com.devesion.commons.obd.adapter.link.elm.ElmLink; 30 | import com.devesion.commons.obd.adapter.shared.ObdNoDataForCommandResponseException; 31 | import com.devesion.commons.obd.adapter.shared.ObdNotProperlyInitializedException; 32 | import com.google.common.util.concurrent.Uninterruptibles; 33 | import lombok.extern.slf4j.Slf4j; 34 | 35 | import java.io.InputStream; 36 | import java.io.OutputStream; 37 | import java.time.Duration; 38 | import java.time.Instant; 39 | import java.util.concurrent.TimeUnit; 40 | 41 | /** 42 | * Echo disabled 43 | * Linefeed disabled 44 | * Spaces disabled 45 | * Headers disabled 46 | * Adaptive Timing: 2 47 | * New Protocol: Automatic 48 | * Headers enabled 49 | * Headers disabled 50 | */ 51 | @Slf4j 52 | public class ElmDiagnosticStatusGateway implements DiagnosticStatusGateway { 53 | 54 | private static final int SLOW_STATUS_DURATION = 10; 55 | private static final int VERY_SLOW_STATUS_DURATION = 60; 56 | 57 | private boolean opened = false; 58 | private boolean initialized = false; 59 | 60 | private Instant lastSlowStatusTime = Instant.now(); 61 | private Instant lastVerySlowStatusTime = Instant.now(); 62 | 63 | private final DiagnosticStatus diagnosticStatus = new DiagnosticStatus(); 64 | private final DiagnosticTransport diagnosticTransport; 65 | 66 | public ElmDiagnosticStatusGateway(DiagnosticTransport diagnosticTransport) { 67 | this.diagnosticTransport = diagnosticTransport; 68 | } 69 | 70 | @Override 71 | public void open() { 72 | if (!opened) { 73 | openTransport(); 74 | opened = true; 75 | } 76 | } 77 | 78 | private void initialize() { 79 | if (!initialized) { 80 | initializeCommands(); 81 | initialized = true; 82 | } 83 | } 84 | 85 | private void initializeCommands() { 86 | log.info("Initializing ELM protocol"); 87 | invokeCommandQuietly(new ResetCommand()); 88 | // invokeCommandQuietly(new SetBaudRateCommand()); 89 | // invokeCommandQuietly(new EnableBaudRateCommand()); 90 | invokeCommandQuietly(new ResetCommand()); 91 | invokeCommand(new SetEchoCommand(false)); 92 | invokeCommand(new SetLineFeedCommand(false)); 93 | invokeCommand(new SetHeadersCommand(false)); 94 | invokeCommand(new SetSpacesCommand(false)); 95 | invokeCommand(new AdaptiveTimeoutProtocolCommand()); 96 | invokeCommand(new SelectProtocolCommand()); 97 | } 98 | 99 | @Override 100 | public DiagnosticStatus readCurrentStatus() { 101 | try { 102 | open(); 103 | initialize(); 104 | readFastStatus(diagnosticStatus); 105 | readSlowStatus(diagnosticStatus); 106 | readVerySlowStatus(diagnosticStatus); 107 | } catch (ObdNotProperlyInitializedException e) { 108 | log.error("Reinitializing ELM due to {}", e.getMessage()); 109 | deinitialize(); 110 | close(); 111 | sleepGap(); 112 | } catch (Exception e) { 113 | log.error("Invoking fail - {}", e); 114 | } 115 | 116 | return diagnosticStatus; 117 | } 118 | 119 | private void readFastStatus(DiagnosticStatus diagnosticStatus) { 120 | diagnosticStatus.setRpm(readEngineRpm()); 121 | diagnosticStatus.setSpeed(readVehicleSpeed()); 122 | diagnosticStatus.setThrottlePosition(readThrottlePositionPercentage()); 123 | diagnosticStatus.setMassAirFlow(readMassAirFlow()); 124 | diagnosticStatus.setLoad(readEngineLoad()); 125 | } 126 | 127 | private void readSlowStatus(DiagnosticStatus diagnosticStatus) { 128 | Instant now = Instant.now(); 129 | Duration duration = Duration.between(lastSlowStatusTime, now); 130 | if (duration.getSeconds() > SLOW_STATUS_DURATION) { 131 | diagnosticStatus.setFuelPressure(readFuelPressure()); 132 | diagnosticStatus.setCoolantTemperature(readCoolantTemperature()); 133 | diagnosticStatus.setIntakeAirTemperature(readIntakeAirTemperature()); 134 | lastSlowStatusTime = Instant.now(); 135 | } 136 | } 137 | 138 | private void readVerySlowStatus(DiagnosticStatus diagnosticStatus) { 139 | Instant now = Instant.now(); 140 | Duration duration = Duration.between(lastVerySlowStatusTime, now); 141 | if (duration.getSeconds() > VERY_SLOW_STATUS_DURATION) { 142 | diagnosticStatus.setFuelLevel(readFuelLevel()); 143 | diagnosticStatus.setFuelType(readFuelType()); 144 | diagnosticStatus.setRuntime(readEngineRuntime()); 145 | diagnosticStatus.setAmbientTemperature(readAmbientAirTemperature()); 146 | lastVerySlowStatusTime = Instant.now(); 147 | } 148 | } 149 | private int readEngineRpm() { 150 | SensorCommand command = new EngineRpmCommand(); 151 | invokeCommand(command); 152 | return command.getValue().getIntValue(); 153 | } 154 | 155 | private int readVehicleSpeed() { 156 | SensorCommand command = new SpeedCommand(); 157 | invokeCommand(command); 158 | return command.getValue().getIntValue(); 159 | } 160 | 161 | private float readThrottlePositionPercentage() { 162 | SensorCommand command = new ThrottlePositionCommand(); 163 | invokeCommand(command); 164 | return command.getValue().getIntValue(); 165 | } 166 | 167 | private double readMassAirFlow() { 168 | SensorCommand command = new MassAirFlowCommand(); 169 | invokeCommand(command); 170 | return command.getValue().getFloatValue(); 171 | } 172 | 173 | private int readEngineLoad() { 174 | SensorCommand command = new EngineLoadCommand(); 175 | invokeCommand(command); 176 | return command.getValue().getIntValue(); 177 | } 178 | 179 | private int readFuelLevel() { 180 | SensorCommand command = new FuelLevelCommand(); 181 | invokeCommand(command); 182 | return command.getValue().getIntValue(); 183 | } 184 | 185 | private int readFuelType() { 186 | SensorCommand command = new FuelTypeCommand(); 187 | invokeCommand(command); 188 | return command.getValue().getIntValue(); 189 | } 190 | 191 | private int readFuelPressure() { 192 | SensorCommand command = new FuelPressureCommand(); 193 | invokeCommand(command); 194 | return command.getValue().getIntValue(); 195 | } 196 | 197 | private int readEngineRuntime() { 198 | SensorCommand command = new EngineRuntimeCommand(); 199 | invokeCommand(command); 200 | return command.getValue().getIntValue(); 201 | } 202 | 203 | private int readAmbientAirTemperature() { 204 | SensorCommand command = new AmbientAirTemperatureCommand(); 205 | invokeCommand(command); 206 | return command.getValue().getIntValue(); 207 | } 208 | 209 | private int readCoolantTemperature() { 210 | SensorCommand command = new EngineCoolantTemperatureCommand(); 211 | invokeCommand(command); 212 | return command.getValue().getIntValue(); 213 | } 214 | 215 | private int readIntakeAirTemperature() { 216 | SensorCommand command = new IntakeAirTemperatureCommand(); 217 | invokeCommand(command); 218 | return command.getValue().getIntValue(); 219 | } 220 | 221 | private void invokeCommand(ObdCommand command) { 222 | try { 223 | CommandInvoker commandInvoker = createCommandInvoker(); 224 | log.debug("Invoking command {}", command); 225 | commandInvoker.invoke(command); 226 | } catch (ObdNoDataForCommandResponseException e) { 227 | log.debug("Invoking fail - {}", e.getMessage()); 228 | } 229 | } 230 | 231 | private void invokeCommandQuietly(ObdCommand command) { 232 | CommandInvoker commandInvoker = createCommandInvoker(); 233 | log.debug("Invoking command {}", command); 234 | commandInvoker.invokeQuietly(command); 235 | } 236 | 237 | private CommandInvoker createCommandInvoker() { 238 | InputStream inputStream = diagnosticTransport.getInputStream(); 239 | OutputStream outputStream = diagnosticTransport.getOutputStream(); 240 | ObdLink obdLink = new ElmLink(inputStream, outputStream); 241 | return new CommandInvoker(obdLink); 242 | } 243 | 244 | private void sleepGap() { 245 | Uninterruptibles.sleepUninterruptibly(5, TimeUnit.SECONDS); 246 | } 247 | 248 | @Override 249 | public void close() { 250 | closeTransport(); 251 | opened = false; 252 | } 253 | 254 | private void deinitialize() { 255 | initialized = false; 256 | } 257 | 258 | private void openTransport() { 259 | diagnosticTransport.open(); 260 | } 261 | 262 | private void closeTransport() { 263 | diagnosticTransport.close(); 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/gateway/elm/ProbingElmDiagnosticStatusGateway.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure.gateway.elm; 2 | 3 | import com.autonalyzer.adapter.android.infrastructure.gateway.ProbingDiagnosticStatusGateway; 4 | import com.autonalyzer.adapter.android.infrastructure.transport.DiagnosticTransport; 5 | 6 | public class ProbingElmDiagnosticStatusGateway extends ElmDiagnosticStatusGateway implements ProbingDiagnosticStatusGateway { 7 | 8 | public ProbingElmDiagnosticStatusGateway(DiagnosticTransport diagnosticTransport) { 9 | super(diagnosticTransport); 10 | } 11 | 12 | @Override 13 | public boolean probe() { 14 | try { 15 | open(); 16 | return true; 17 | } catch (Exception e) { 18 | close(); 19 | return false; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/transport/DiagnosticTransport.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure.transport; 2 | 3 | import java.io.Closeable; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | 7 | public interface DiagnosticTransport extends Closeable { 8 | 9 | void open(); 10 | 11 | InputStream getInputStream(); 12 | 13 | OutputStream getOutputStream(); 14 | 15 | void close(); 16 | } 17 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/transport/DiagnosticTransportFactory.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure.transport; 2 | 3 | import java.util.List; 4 | 5 | public interface DiagnosticTransportFactory { 6 | 7 | List createAvailableTransports(); 8 | } 9 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/transport/DiagnosticTransportProbe.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure.transport; 2 | 3 | import java.util.List; 4 | 5 | public interface DiagnosticTransportProbe { 6 | 7 | List createAvailableTransports(); 8 | } 9 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/transport/ProbingDiagnosticTransportFactory.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure.transport; 2 | 3 | import com.autonalyzer.adapter.android.infrastructure.transport.serial.SerialDiagnosticTransportFactory; 4 | import com.google.common.collect.Lists; 5 | 6 | import java.util.List; 7 | 8 | public class ProbingDiagnosticTransportFactory implements DiagnosticTransportFactory { 9 | 10 | private List probes = Lists.newArrayList(); 11 | 12 | public ProbingDiagnosticTransportFactory() { 13 | DiagnosticTransportProbe bluetoothTransportProbe = new SerialDiagnosticTransportFactory(); 14 | registerDiagnosticTransportFactory(bluetoothTransportProbe); 15 | } 16 | 17 | private void registerDiagnosticTransportFactory(DiagnosticTransportProbe diagnosticTransportProbe) { 18 | probes.add(diagnosticTransportProbe); 19 | } 20 | 21 | @Override 22 | public List createAvailableTransports() { 23 | List allAvailableTransports = Lists.newArrayList(); 24 | for (DiagnosticTransportProbe probe : probes) { 25 | List probedTransports = probe.createAvailableTransports(); 26 | allAvailableTransports.addAll(probedTransports); 27 | } 28 | 29 | return allAvailableTransports; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/transport/serial/SerialDiagnosticTransport.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure.transport.serial; 2 | 3 | import com.autonalyzer.adapter.android.infrastructure.transport.DiagnosticTransport; 4 | import gnu.io.CommPortIdentifier; 5 | import gnu.io.SerialPort; 6 | import gnu.io.SerialPortEvent; 7 | import gnu.io.SerialPortEventListener; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.io.OutputStream; 13 | import java.util.Enumeration; 14 | 15 | @Slf4j 16 | public class SerialDiagnosticTransport implements DiagnosticTransport, SerialPortEventListener { 17 | 18 | private static final int TIME_OUT = 2000; 19 | // private static final int DATA_RATE = 38400; 20 | 21 | // private static final int DATA_RATE = 57600; 22 | private static final int DATA_RATE = 115200; 23 | // private static final int DATA_RATE = 38400; 24 | // private static final int DATA_RATE = 14400; 25 | private InputStream is; 26 | private OutputStream os; 27 | 28 | @Override 29 | public void close() { 30 | try { 31 | if (is != null) { 32 | is.close(); 33 | } 34 | 35 | if (os != null) { 36 | os.close(); 37 | } 38 | } catch (IOException e) { 39 | log.error("cannot close streams"); 40 | } 41 | } 42 | 43 | @Override 44 | public void open() { 45 | log.info("opening serial transport"); 46 | String wantedPortName = "/dev/ttyUSB0"; 47 | // String wantedPortName = "/dev/rfcomm1"; 48 | System.setProperty("gnu.io.rxtx.SerialPorts", wantedPortName); 49 | Enumeration portIdentifiers = CommPortIdentifier.getPortIdentifiers(); 50 | 51 | CommPortIdentifier portId = null; 52 | 53 | while (portIdentifiers.hasMoreElements()) { 54 | CommPortIdentifier pid = (CommPortIdentifier) portIdentifiers.nextElement(); 55 | log.info("pid {}", pid); 56 | if (pid.getPortType() == CommPortIdentifier.PORT_SERIAL && 57 | pid.getName().equals(wantedPortName)) { 58 | portId = pid; 59 | break; 60 | } 61 | } 62 | 63 | if (portId == null) { 64 | return; 65 | } 66 | 67 | try { 68 | // open serial port, and use class name for the appName. 69 | SerialPort serialPort = (SerialPort) portId.open(SerialDiagnosticTransport.class.getName(), TIME_OUT); 70 | 71 | // set port parameters 72 | serialPort.setSerialPortParams(DATA_RATE, 73 | SerialPort.DATABITS_8, 74 | SerialPort.STOPBITS_1, 75 | SerialPort.PARITY_NONE); 76 | 77 | serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_XONXOFF_IN); 78 | serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_XONXOFF_OUT); 79 | 80 | // open the streams 81 | is = serialPort.getInputStream(); 82 | os = serialPort.getOutputStream(); 83 | 84 | // add event listeners 85 | serialPort.addEventListener(this); 86 | serialPort.notifyOnDataAvailable(false); 87 | log.info("serial transport opened"); 88 | } catch (Exception e) { 89 | log.error("cannot connect to serial port", e); 90 | } 91 | } 92 | 93 | @Override 94 | public InputStream getInputStream() { 95 | return is; 96 | } 97 | 98 | @Override 99 | public OutputStream getOutputStream() { 100 | return os; 101 | } 102 | 103 | @Override 104 | public void serialEvent(SerialPortEvent oEvent) { 105 | // Ignore all the other eventTypes, but you should consider the other 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /client/src/main/java/com/autonalyzer/adapter/android/infrastructure/transport/serial/SerialDiagnosticTransportFactory.java: -------------------------------------------------------------------------------- 1 | package com.autonalyzer.adapter.android.infrastructure.transport.serial; 2 | 3 | import com.autonalyzer.adapter.android.infrastructure.transport.DiagnosticTransport; 4 | import com.autonalyzer.adapter.android.infrastructure.transport.DiagnosticTransportProbe; 5 | import com.google.common.collect.Lists; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | import java.util.List; 9 | 10 | @Slf4j 11 | public class SerialDiagnosticTransportFactory implements DiagnosticTransportProbe { 12 | 13 | @Override 14 | public List createAvailableTransports() { 15 | DiagnosticTransport diagnosticTransport = new SerialDiagnosticTransport(); 16 | return Lists.newArrayList(diagnosticTransport); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Set root logger level to DEBUG and its only appender to A1. 2 | log4j.rootLogger=INFO, A1, file 3 | 4 | log4j.appender.file=org.apache.log4j.RollingFileAppender 5 | log4j.appender.file.File=autonalyzer.log 6 | log4j.appender.file.MaxFileSize=100MB 7 | log4j.appender.file.MaxBackupIndex=10 8 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n 10 | log4j.appender.file.Threshold=DEBUG 11 | 12 | # A1 is set to be a ConsoleAppender. 13 | log4j.appender.A1=org.apache.log4j.ConsoleAppender 14 | 15 | # A1 uses PatternLayout. 16 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout 17 | log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c\t - %m%n 18 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | org.sonatype.oss 8 | oss-parent 9 | 7 10 | 11 | 12 | 4.0.0 13 | com.devesion.commons.obd 14 | obd-adapter 15 | pom 16 | 1.0-SNAPSHOT 17 | ${project.groupId}.${project.artifactId} 18 | 19 | 20 | 21 | The Apache Software License, Version 2.0 22 | http://www.apache.org/licenses/LICENSE-2.0.txt 23 | repo 24 | 25 | 26 | 27 | 28 | scm:git:git@github.com:dembol/java-obd-adapter.git 29 | scm:git:git@github.com:dembol/java-obd-adapter.git 30 | git@github.com:dembol/java-obd-adapter.git 31 | HEAD 32 | 33 | 34 | 35 | 36 | dembol 37 | Lukasz Dembinski 38 | dembol@devesion.com 39 | 40 | developer 41 | 42 | 43 | 44 | 45 | 46 | 47 | ossrh 48 | https://oss.sonatype.org/content/repositories/snapshots 49 | 50 | 51 | ossrh 52 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 53 | 54 | 55 | 56 | 57 | 1.8 58 | 1.16.2 59 | 1.7.6 60 | 18.0 61 | 62 | 1.5.1 63 | 1.9.5 64 | 1.0.4 65 | 2.0M5 66 | 6.8.5 67 | 4.6 68 | 69 | 70 | 71 | 72 | 73 | org.apache.maven.plugins 74 | maven-compiler-plugin 75 | 3.2 76 | 77 | ${java.version} 78 | ${java.version} 79 | true 80 | 81 | 82 | 83 | org.codehaus.mojo 84 | cobertura-maven-plugin 85 | 2.6 86 | 87 | 88 | org.apache.maven.plugins 89 | maven-release-plugin 90 | 2.2.2 91 | 92 | -Dgpg.passphrase=${gpg.passphrase} 93 | 94 | 95 | 96 | org.sonatype.plugins 97 | nexus-staging-maven-plugin 98 | 1.6.3 99 | true 100 | 101 | ossrh 102 | https://oss.sonatype.org/ 103 | true 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | org.codehaus.mojo 113 | cobertura-maven-plugin 114 | 115 | 116 | 117 | 118 | 119 | 120 | release-sign-artifacts 121 | 122 | 123 | performRelease 124 | true 125 | 126 | 127 | 128 | 129 | 130 | org.apache.maven.plugins 131 | maven-gpg-plugin 132 | 1.4 133 | 134 | 135 | sign-artifacts 136 | verify 137 | 138 | sign 139 | 140 | 141 | 2AC54014 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | org.projectlombok 154 | lombok 155 | ${project.dependency.lombok.version} 156 | 157 | 158 | 159 | com.google.guava 160 | guava 161 | ${project.dependency.google.guava.version} 162 | 163 | 164 | 165 | 166 | org.slf4j 167 | slf4j-log4j12 168 | ${project.dependency.slf4j.log4j12.version} 169 | 170 | 171 | 172 | 173 | org.testng 174 | testng 175 | ${project.dependency.testng.version} 176 | test 177 | 178 | 179 | org.mockito 180 | mockito-all 181 | ${project.dependency.mockito.version} 182 | test 183 | 184 | 185 | org.powermock 186 | powermock-module-testng 187 | ${project.dependency.powermock.version} 188 | test 189 | 190 | 191 | org.powermock 192 | powermock-api-mockito 193 | ${project.dependency.powermock.version} 194 | test 195 | 196 | 197 | org.easytesting 198 | fest-assert-core 199 | ${project.dependency.fest-assert-core.version} 200 | test 201 | 202 | 203 | com.googlecode.catch-exception 204 | catch-exception 205 | ${project.dependency.google.catch-exception.version} 206 | test 207 | 208 | 209 | 210 | 211 | adapter 212 | client 213 | 214 | --------------------------------------------------------------------------------