Add OBD mode 1 Logging support for CAN ECUs using J2534.

This commit is contained in:
Dale Schultz 2014-05-14 23:33:34 -04:00
parent c8beae85a1
commit 6389e44cc6
18 changed files with 921 additions and 31 deletions

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2013 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -155,6 +155,8 @@ public class Settings implements Serializable {
private static final String USER_LANGUAGE = "user.language";
private static final String USER_COUNTRY = "user.country";
private static final String EN_US = "en_US";
private static final String SSM = "SSM";
private static final String OBD = "OBD";
private final Dimension windowSize = new Dimension(800, 600);
private final Point windowLocation = new Point();
@ -194,7 +196,7 @@ public class Settings implements Serializable {
private String loggerPort;
private String loggerPortDefault;
private static String loggerProtocol = "SSM";
private static String loggerProtocol = SSM;
private static String loggerDefinitionFilePath;
private static String loggerProfileFilePath;
private static String loggerOutputDirPath = System.getProperty("user.home");
@ -782,6 +784,13 @@ public class Settings implements Serializable {
return false;
}
public boolean isObdProtocol() {
if (loggerProtocol.equals(OBD)) {
return true;
}
return false;
}
public final boolean isUsNumberFormat() {
if (userLocale.equalsIgnoreCase(EN_US)) {
return true;

View File

@ -0,0 +1,198 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.io.protocol.obd.iso15765;
import static com.romraider.io.protocol.obd.iso15765.OBDProtocol.RESPONSE_NON_DATA_BYTES;
import static com.romraider.io.protocol.obd.iso15765.OBDResponseProcessor.extractResponseData;
import static com.romraider.io.protocol.obd.iso15765.OBDResponseProcessor.filterRequestFromResponse;
import static com.romraider.util.HexUtil.asHex;
import static com.romraider.util.ParamChecker.checkNotNull;
import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
import static java.lang.System.arraycopy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.romraider.io.protocol.Protocol;
import com.romraider.logger.ecu.comms.io.protocol.LoggerProtocolOBD;
import com.romraider.logger.ecu.comms.manager.PollingState;
import com.romraider.logger.ecu.comms.query.EcuInit;
import com.romraider.logger.ecu.comms.query.EcuInitCallback;
import com.romraider.logger.ecu.comms.query.EcuQuery;
public final class OBDLoggerProtocol implements LoggerProtocolOBD {
private final Protocol protocol = new OBDProtocol();
@Override
public byte[] constructEcuInitRequest(byte id) {
return protocol.constructEcuInitRequest(id);
}
@Override
public byte[] constructEcuResetRequest(byte id) {
return protocol.constructEcuResetRequest(id);
}
@Override
public byte[] constructReadAddressRequest(
byte id, Collection<EcuQuery> queries) {
Collection<EcuQuery> filteredQueries = filterDuplicates(queries);
return protocol.constructReadAddressRequest(
id, convertToByteAddresses(filteredQueries));
}
@Override
public byte[] constructReadPidRequest(byte id, byte[] pid) {
final byte[][] request = new byte[1][pid.length];
arraycopy(pid, 0, request[0], 0, pid.length);
return protocol.constructReadAddressRequest(id, request);
}
@Override
public byte[] constructReadAddressResponse(
Collection<EcuQuery> queries, PollingState pollState) {
checkNotNullOrEmpty(queries, "queries");
// four byte - CAN ID
// one byte - Response mode
// one byte - Response pid
// variable bytes of data defined for pid
Collection<EcuQuery> filteredQueries = filterDuplicates(queries);
int numAddresses = 0;
for (EcuQuery ecuQuery : filteredQueries) {
numAddresses += ecuQuery.getBytes().length;
numAddresses += getDataLength(ecuQuery);
}
return new byte[(numAddresses + RESPONSE_NON_DATA_BYTES)];
}
@Override
public byte[] preprocessResponse(
byte[] request, byte[] response, PollingState pollState) {
return filterRequestFromResponse(request, response, pollState);
}
@Override
public void processEcuInitResponse(EcuInitCallback callback, byte[] response) {
checkNotNull(callback, "callback");
checkNotNullOrEmpty(response, "response");
protocol.checkValidEcuInitResponse(response);
EcuInit ecuInit = protocol.parseEcuInitResponse(response);
callback.callback(ecuInit);
}
@Override
public void processEcuResetResponse(byte[] response) {
checkNotNullOrEmpty(response, "response");
protocol.checkValidEcuResetResponse(response);
}
// processes the response bytes and sets individual responses on corresponding query objects
@Override
public void processReadAddressResponses(
Collection<EcuQuery> queries, byte[] response, PollingState pollState) {
checkNotNullOrEmpty(queries, "queries");
checkNotNullOrEmpty(response, "response");
final byte[] responseData = extractResponseData(response);
final Collection<EcuQuery> filteredQueries = filterDuplicates(queries);
final Map<String, byte[]> addressResults = new HashMap<String, byte[]>();
int i = 0;
for (EcuQuery filteredQuery : filteredQueries) {
final int addrLength = filteredQuery.getBytes().length;
final int dataLength = getDataLength(filteredQuery);
final byte[] addr = new byte[addrLength];
final byte[] data = new byte[dataLength];
arraycopy(responseData, i, addr, 0, addrLength);
arraycopy(responseData, i + addrLength, data, 0, dataLength);
addressResults.put(asHex(addr), data);
i += addrLength + dataLength;
}
for (EcuQuery query : queries) {
query.setResponse(addressResults.get(query.getHex()));
}
}
@Override
public Protocol getProtocol() {
return protocol;
}
@Override
public byte[] constructWriteAddressRequest(
byte id, byte[] writeAddress, byte value) {
return protocol.constructWriteAddressRequest(id, writeAddress, value);
}
@Override
public void processWriteResponse(byte[] data, byte[] response) {
checkNotNullOrEmpty(data, "data");
checkNotNullOrEmpty(response, "response");
protocol.checkValidWriteResponse(data, response);
}
private Collection<EcuQuery> filterDuplicates(Collection<EcuQuery> queries) {
Collection<EcuQuery> filteredQueries = new ArrayList<EcuQuery>();
for (EcuQuery query : queries) {
if (!filteredQueries.contains(query)) {
filteredQueries.add(query);
}
}
return filteredQueries;
}
private byte[][] convertToByteAddresses(Collection<EcuQuery> queries) {
int byteCount = 0;
for (EcuQuery query : queries) {
byteCount += query.getAddresses().length;
}
final int ADDRESS_SIZE = 1;
// TODO how do we handle variable address lengths ?
final byte[][] addresses = new byte[byteCount][ADDRESS_SIZE];
int i = 0;
for (EcuQuery query : queries) {
final int addrLength = query.getBytes().length;
final byte[] bytes = query.getBytes();
for (int j = 0; j < bytes.length / addrLength; j++) {
arraycopy(bytes, j * addrLength, addresses[i++], 0, addrLength);
}
}
return addresses;
}
private int getDataLength(EcuQuery ecuQuery) {
int dataLength = 1;
final String dataType =
ecuQuery.getLoggerData().getSelectedConvertor().getDataType().toLowerCase();
if (dataType.contains("int16")) {
dataLength = 2;
}
else if (dataType.contains("int32") ||
dataType.contains("float")) {
dataLength = 4;
}
return dataLength;
}
}

View File

@ -0,0 +1,247 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.io.protocol.obd.iso15765;
import static com.romraider.util.HexUtil.asBytes;
import static com.romraider.util.HexUtil.asHex;
import static com.romraider.util.ParamChecker.checkGreaterThanZero;
import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
import static java.lang.System.arraycopy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import com.romraider.Settings;
import com.romraider.io.connection.ConnectionProperties;
import com.romraider.io.protocol.Protocol;
import com.romraider.logger.ecu.comms.manager.PollingState;
import com.romraider.logger.ecu.comms.query.EcuInit;
import com.romraider.logger.ecu.comms.query.SSMEcuInit;
import com.romraider.logger.ecu.definition.EcuDefinition;
import com.romraider.logger.ecu.exception.InvalidResponseException;
import com.romraider.logger.ecu.exception.UnsupportedProtocolException;
import com.romraider.util.SettingsManager;
public final class OBDProtocol implements Protocol {
private static final byte[] ECU_TESTER =
new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0xe0};
private static final byte[] TCU_TESTER =
new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0xe1};
private static byte[] ECU_CALID =
new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0xe8};
private static final byte[] TCU_CALID =
new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0xe9};
private final ByteArrayOutputStream bb = new ByteArrayOutputStream(255);
private static byte[] TESTER = ECU_TESTER;
public static byte[] ECU_ID = ECU_CALID;
public static final byte OBD_INIT_COMMAND = (byte) 0x01;
public static final byte OBD_INIT_RESPONSE = (byte) 0x41;
public static final byte OBD_INFO_COMMAND = (byte) 0x09;
public static final byte OBD_INFO_RESPONSE = (byte) 0x49;
public static final byte OBD_RESET_COMMAND = (byte) 0x04;
public static final byte OBD_RESET_RESPONSE = (byte) 0x44;
public static final byte OBD_NRC = (byte) 0x7F;
public static final int RESPONSE_NON_DATA_BYTES = 5;
@Override
public byte[] constructEcuInitRequest(byte id) {
checkGreaterThanZero(id, "ECU_ID");
setIDs(id);
final byte[] request = buildRequest(
OBD_INFO_COMMAND, true, new byte[]{4});
return request;
}
@Override
public byte[] constructWriteMemoryRequest(
byte id, byte[] address, byte[] values) {
throw new UnsupportedProtocolException(
"Write memory command is not supported on OBD for address: " +
asHex(address));
}
@Override
public byte[] constructWriteAddressRequest(
byte id, byte[] address, byte value) {
throw new UnsupportedProtocolException(
"Write Address command is not supported on OBD for address: " +
asHex(address));
}
@Override
public byte[] constructReadMemoryRequest(
byte id, byte[] address, int numBytes) {
throw new UnsupportedProtocolException(
"Read memory command is not supported on OBD for address: " +
asHex(address));
}
@Override
public byte[] constructReadAddressRequest(byte id, byte[][] addresses) {
checkGreaterThanZero(id, "ECU_ID");
checkNotNullOrEmpty(addresses, "addresses");
setIDs(id);
return buildRequest(OBD_INIT_COMMAND, true, addresses);
}
@Override
public byte[] preprocessResponse(
byte[] request, byte[] response, PollingState pollState) {
return OBDResponseProcessor.filterRequestFromResponse(
request, response, pollState);
}
@Override
public byte[] parseResponseData(byte[] processedResponse) {
checkNotNullOrEmpty(processedResponse, "processedResponse");
return OBDResponseProcessor.extractResponseData(processedResponse);
}
@Override
public void checkValidEcuInitResponse(byte[] processedResponse) {
checkNotNullOrEmpty(processedResponse, "processedResponse");
OBDResponseProcessor.validateResponse(processedResponse);
// four byte - CAN ID
// one byte - Response mode
// one byte - Response pid
// null terminated CAL ID string
// 000007E8 49 .....
byte responseType = processedResponse[4];
if (responseType != OBD_INFO_RESPONSE) {
throw new InvalidResponseException(
"Unexpected ECU Info response type: " +
asHex(new byte[]{responseType}));
}
}
@Override
public EcuInit parseEcuInitResponse(byte[] processedResponse) {
checkNotNullOrEmpty(processedResponse, "processedResponse");
final byte[] ecuInitBytes = parseResponseData(processedResponse);
final byte[] calIdBytes = Arrays.copyOf(ecuInitBytes, 8);
final String calIdStr = new String(calIdBytes);
final Settings settings = SettingsManager.getSettings();
final Map<String, EcuDefinition> defMap =
settings.getLoggerEcuDefinitionMap();
byte[] ecuIdBytes = new byte[] {0,0,0,0,0};
// convert CALID to ECUID based on defined ECU defs
for (EcuDefinition ecuDef : defMap.values()) {
if (ecuDef.getCalId().equals(calIdStr)) {
ecuIdBytes = asBytes(ecuDef.getEcuId());
break;
}
}
arraycopy(ecuIdBytes, 0, ecuInitBytes, 3, 5);
return new SSMEcuInit(ecuInitBytes);
}
@Override
public byte[] constructEcuResetRequest(byte id) {
checkGreaterThanZero(id, "ECU_ID");
// 000007E0 04
return buildRequest((byte) 0, false, new byte[]{OBD_RESET_COMMAND});
}
@Override
public void checkValidEcuResetResponse(byte[] processedResponse) {
checkNotNullOrEmpty(processedResponse, "processedResponse");
// 000007E8 44
byte responseType = processedResponse[4];
if (responseType != OBD_RESET_RESPONSE) {
throw new InvalidResponseException(
"Unexpected OBD Reset response: " +
asHex(processedResponse));
}
}
@Override
public void checkValidWriteResponse(byte[] data, byte[] processedResponse) {
}
@Override
public ConnectionProperties getDefaultConnectionProperties() {
return new ConnectionProperties() {
public int getBaudRate() {
return 500000;
}
public void setBaudRate(int b) {
}
public int getDataBits() {
return 8;
}
public int getStopBits() {
return 1;
}
public int getParity() {
return 0;
}
public int getConnectTimeout() {
return 2000;
}
public int getSendTimeout() {
return 55;
}
};
}
private byte[] buildRequest(
byte command,
boolean addCommand,
byte[]... content) {
bb.reset();
try {
bb.write(TESTER);
if (addCommand) {
bb.write(command);
}
for (byte[] tmp : content) {
bb.write(tmp);
}
} catch (IOException e) {
e.printStackTrace();
}
return bb.toByteArray();
}
private void setIDs(byte id) {
ECU_ID = ECU_CALID;
TESTER = ECU_TESTER;
if (id == 0x18) {
ECU_ID = TCU_CALID;
TESTER = TCU_TESTER;
}
}
}

View File

@ -0,0 +1,132 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.io.protocol.obd.iso15765;
import static com.romraider.io.protocol.obd.iso15765.OBDProtocol.ECU_ID;
import static com.romraider.io.protocol.obd.iso15765.OBDProtocol.OBD_INFO_RESPONSE;
import static com.romraider.io.protocol.obd.iso15765.OBDProtocol.OBD_INIT_RESPONSE;
import static com.romraider.io.protocol.obd.iso15765.OBDProtocol.OBD_NRC;
import static com.romraider.io.protocol.obd.iso15765.OBDProtocol.OBD_RESET_RESPONSE;
import static com.romraider.io.protocol.obd.iso15765.OBDProtocol.RESPONSE_NON_DATA_BYTES;
import static com.romraider.util.ByteUtil.asUnsignedInt;
import static com.romraider.util.HexUtil.asHex;
import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
import java.util.Arrays;
import com.romraider.logger.ecu.comms.manager.PollingState;
import com.romraider.logger.ecu.exception.InvalidResponseException;
public final class OBDResponseProcessor {
private OBDResponseProcessor() {
throw new UnsupportedOperationException();
}
public final static byte[] filterRequestFromResponse(
byte[] request, byte[] response, PollingState pollState) {
checkNotNullOrEmpty(response, "response");
return response;
}
public final static void validateResponse(byte[] response) {
checkNotNullOrEmpty(response, "response");
assertTrue(response.length > RESPONSE_NON_DATA_BYTES,
"Invalid response length");
assertEquals(ECU_ID, response, "Invalid ECU id");
if (response[4] == OBD_NRC) {
assertNrc(OBD_NRC, response[4], response[5], response[6],
"Request type not supported");
}
assertOneOf(new byte[]{
OBD_INIT_RESPONSE, OBD_INFO_RESPONSE, OBD_RESET_RESPONSE},
response[4], "Invalid response code");
}
public final static byte[] extractResponseData(byte[] response) {
checkNotNullOrEmpty(response, "response");
// ECU_addr response_mode pid1 response_data1 ... [pid6 response_data6]
validateResponse(response);
final byte[] data = new byte[response.length - RESPONSE_NON_DATA_BYTES];
System.arraycopy(response, RESPONSE_NON_DATA_BYTES, data, 0, data.length);
return data;
}
private final static void assertTrue(boolean condition, String msg) {
if (!condition) {
throw new InvalidResponseException(msg);
}
}
private final static void assertNrc(
byte expected, byte actual, byte command, byte code, String msg) {
if (actual == expected) {
String ec = "unsupported.";
if (code == 0x12) {
ec = "request sub-function is not supported.";
}
if (code == 0x13) {
ec = "invalid format or length.";
}
if (code == 0x22) {
ec = "is supported but data is currently not available.";
}
throw new InvalidResponseException(String.format(
"%s. Command: %s, %s",
msg, asHex(command), ec));
}
}
private final static void assertEquals(
byte[] expected, byte[] actual, String msg) {
final byte[] idBytes = Arrays.copyOf(actual, 4);
final int idExpected = asUnsignedInt(expected);
final int idActual = asUnsignedInt(idBytes);
if (idActual != idExpected) {
throw new InvalidResponseException(String.format(
"%s. Expected: %s. Actual: %s.",
msg, asHex(expected), asHex(idBytes)));
}
}
private final static void assertOneOf(
byte[] validOptions, byte actual, String msg) {
for (byte option : validOptions) {
if (option == actual) {
return;
}
}
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < validOptions.length; i++) {
if (i > 0) {
builder.append(", ");
}
builder.append(asHex(validOptions[i]));
}
throw new InvalidResponseException(String.format(
"%s. Expected one of [%s]. Actual: %s.",
msg, builder.toString(), asHex(actual)));
}
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2012 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -48,7 +48,8 @@ public final class LoggerConnectionFactory {
ConnectionManager.class).newInstance(manager);
} catch (Exception e) {
manager.close();
throw new UnsupportedProtocolException(e.getCause().getMessage(), e);
throw new UnsupportedProtocolException(
protocolName, e);
}
}
}

View File

@ -0,0 +1,176 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.ecu.comms.io.connection;
import static com.romraider.util.HexUtil.asHex;
import static com.romraider.util.ParamChecker.checkNotNull;
import static org.apache.log4j.Logger.getLogger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import org.apache.log4j.Logger;
import com.romraider.Settings;
import com.romraider.util.SettingsManager;
import com.romraider.io.connection.ConnectionManager;
import com.romraider.io.protocol.ProtocolFactory;
import com.romraider.logger.ecu.comms.io.protocol.LoggerProtocolOBD;
import com.romraider.logger.ecu.comms.manager.PollingState;
import com.romraider.logger.ecu.comms.manager.PollingStateImpl;
import com.romraider.logger.ecu.comms.query.EcuInitCallback;
import com.romraider.logger.ecu.comms.query.EcuQuery;
public final class OBDLoggerConnection implements LoggerConnection {
private static final Logger LOGGER = getLogger(OBDLoggerConnection.class);
private final LoggerProtocolOBD protocol;
private final ConnectionManager manager;
private Collection<EcuQuery> obdQueries = new ArrayList<EcuQuery>();
public OBDLoggerConnection(ConnectionManager manager) {
checkNotNull(manager, "manager");
this.manager = manager;
final Settings settings = SettingsManager.getSettings();
this.protocol = (LoggerProtocolOBD) ProtocolFactory.getProtocol(
settings.getLoggerProtocol(),
settings.getTransportProtocol());
}
@Override
public void ecuReset(byte id) {
byte[] request = protocol.constructEcuResetRequest(id);
LOGGER.debug(String.format("OBD Reset Request ---> %s",
asHex(request)));
byte[] response = manager.send(request);
byte[] processedResponse = protocol.preprocessResponse(
request, response, new PollingStateImpl());
LOGGER.debug(String.format("OBD Reset Response <--- %s",
asHex(processedResponse)));
protocol.processEcuResetResponse(processedResponse);
}
@Override
// Build an init string similar to the SSM version so the logger definition
// can reference supported parameters with ecubyte/bit attributes.
public void ecuInit(EcuInitCallback callback, byte id) {
final byte[] processedResponse = new byte[46];
final byte[] request = protocol.constructEcuInitRequest(id);
LOGGER.debug(String.format("OBD Calibration ID Request ---> %s",
asHex(request)));
final byte[] tmp = manager.send(request);
final byte[] response = protocol.preprocessResponse(
request, tmp, new PollingStateImpl());
LOGGER.debug(String.format("OBD Calibration ID Response <--- %s",
asHex(response)));
System.arraycopy(response, 0, processedResponse, 0, response.length);
int j = 7;
while (response[j] != 0 && j < response.length) { j++; }
final byte[] calIdStr = new byte[j - 7];
System.arraycopy(response, 7, calIdStr, 0, j - 7);
System.arraycopy(calIdStr, 0, processedResponse, 5, 8);
LOGGER.info(String.format("OBD Calibration ID: %s", new String(calIdStr)));
final byte[] supportedPidsPid = {
(byte) 0x00, (byte) 0x20, (byte) 0x40, (byte) 0x60,
(byte) 0x80, (byte) 0xA0, (byte) 0xC0, (byte) 0xE0};
int i = 13;
for (byte pid : supportedPidsPid) {
final byte[] pidRequest = protocol.constructReadPidRequest(
id, new byte[]{pid});
LOGGER.debug(String.format("OBD PID Group %02X Request ---> %s",
pid, asHex(pidRequest)));
final byte[] pidtmp = manager.send(pidRequest);
final byte[] pidPpResponse = protocol.preprocessResponse(
pidRequest, pidtmp, new PollingStateImpl());
LOGGER.debug(String.format("OBD PID Group %02X Response <--- %s",
pid, asHex(pidPpResponse)));
System.arraycopy(pidPpResponse, 6, processedResponse, i, 4);
i = i + 4;
if ((pidPpResponse[pidPpResponse.length - 1] & 0x01) == 0) break;
}
// Check if PID 0x65 is supported and if so read it to obtain the Aux
// Input support bits. Map the first byte into the init string. This
// byte can be referenced as byte 40 by the ecubyte/bit attributes in
// the logger definition to indicate supported switches.
if ((processedResponse[25] & 0x08) > 0) {
final byte[] aiRequest = protocol.constructReadPidRequest(
id, new byte[]{0x65});
LOGGER.debug(String.format(
"OBD Auxiliary Inputs Support Request ---> %s",
asHex(aiRequest)));
final byte[] aiResponse = manager.send(aiRequest);
final byte[] aiPpResponse = protocol.preprocessResponse(
aiRequest, aiResponse, new PollingStateImpl());
LOGGER.debug(String.format(
"OBD Auxiliary Inputs Support Response <--- %s",
asHex(aiPpResponse)));
System.arraycopy(aiPpResponse, 6, processedResponse, 45, 1);
}
LOGGER.debug(String.format("OBD Init Response <--- %s",
asHex(processedResponse))); // contains CALID not ECUID
protocol.processEcuInitResponse(callback, processedResponse);
}
@Override
public final void sendAddressReads(
Collection<EcuQuery> queries,
byte id,
PollingState pollState) {
final int obdQueryListLength = queries.size();
for (int i = 0; i < obdQueryListLength; i += 6) {
for (int j = i; (j < i + 6) && (j < obdQueryListLength); j++) {
obdQueries.add(((ArrayList<EcuQuery>) queries).get(j));
}
final byte[] request = protocol.constructReadAddressRequest(
id, obdQueries);
LOGGER.debug(String.format("Mode:%d OBD Request ---> %s",
pollState.getCurrentState(), asHex(request)));
final byte[] response = protocol.constructReadAddressResponse(
obdQueries, pollState);
manager.send(request, response, pollState);
final byte[] processedResponse = protocol.preprocessResponse(
request, response, pollState);
LOGGER.debug(String.format("Mode:%d OBD Response <--- %s",
pollState.getCurrentState(), asHex(processedResponse)));
protocol.processReadAddressResponses(
obdQueries, processedResponse, pollState);
obdQueries.clear();
}
}
@Override
public void clearLine() {
manager.clearLine();
}
@Override
public void close() {
manager.close();
}
@Override
public void sendAddressWrites(Map<EcuQuery, byte[]> writeQueries, byte id) {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,26 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.ecu.comms.io.protocol;
public interface LoggerProtocolOBD extends LoggerProtocol {
byte[] constructReadPidRequest(byte id, byte[] pid);
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2012 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -66,6 +66,7 @@ public final class QueryManagerImpl implements QueryManager {
private final Map<String, Query> addList = new HashMap<String, Query>();
private final List<String> removeList = new ArrayList<String>();
private static final PollingState pollState = new PollingStateImpl();
private static final Settings settings = SettingsManager.getSettings();
private static final String ECU = "ECU";
private static final String TCU = "TCU";
private static final String EXT = "Externals";
@ -141,7 +142,7 @@ public final class QueryManagerImpl implements QueryManager {
started = true;
queryManagerThread = Thread.currentThread();
LOGGER.debug("QueryManager started.");
Settings settings = SettingsManager.getSettings();
try {
stop = false;
while (!stop) {
@ -177,7 +178,6 @@ public final class QueryManagerImpl implements QueryManager {
}
try {
Settings settings = SettingsManager.getSettings();
LoggerConnection connection =
getConnection(settings.getLoggerProtocol(),
settings.getLoggerPort(),
@ -223,7 +223,6 @@ public final class QueryManagerImpl implements QueryManager {
int count = 0;
try {
txManager.start();
Settings settings = SettingsManager.getSettings();
boolean lastPollState = settings.isFastPoll();
while (!stop) {
pollState.setFastPoll(settings.isFastPoll());
@ -311,7 +310,7 @@ public final class QueryManagerImpl implements QueryManager {
private void sendEcuQueries(TransmissionManager txManager) {
final List<EcuQuery> ecuQueries = filterEcuQueries(queryMap.values());
if (fileLoggerQuery != null
&& SettingsManager.getSettings().isFileLoggingControllerSwitchActive())
&& settings.isFileLoggingControllerSwitchActive())
ecuQueries.add(fileLoggerQuery);
txManager.sendQueries(ecuQueries, pollState);
}
@ -332,7 +331,8 @@ public final class QueryManagerImpl implements QueryManager {
}
private void handleQueryResponse() {
monitor.monitorFileLoggerSwitch(fileLoggerQuery.getResponse());
if (settings.isFileLoggingControllerSwitchActive())
monitor.monitorFileLoggerSwitch(fileLoggerQuery.getResponse());
final Response response = buildResponse(queryMap.values());
for (final DataUpdateHandler dataUpdateHandler : dataUpdateHandlers) {
runAsDaemon(new Runnable() {
@ -407,10 +407,10 @@ public final class QueryManagerImpl implements QueryManager {
if (pollState.isFastPoll()) {
state = "Fast-K:";
}
if (SettingsManager.getSettings().getTransportProtocol().equals("ISO15765")) {
if (settings.getTransportProtocol().equals("ISO15765")) {
state = "CAN bus:";
}
if (SettingsManager.getSettings().isLogExternalsOnly()) {
if (settings.isLogExternalsOnly()) {
state = "Externals:";
}
double duration = (System.currentTimeMillis() - start) / 1000.0;

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2013 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -35,4 +35,6 @@ public interface EcuDataConvertor {
String getFormat();
String getExpression();
String getDataType();
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2013 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -162,4 +162,9 @@ public final class EcuDerivedParameterConvertorImpl implements EcuDerivedParamet
}
}
}
@Override
public String getDataType() {
return null;
}
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2013 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -70,4 +70,9 @@ public final class EcuDtcConvertorImpl implements EcuDataConvertor {
public String getExpression() {
return "x";
}
@Override
public String getDataType() {
return null;
}
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2013 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -26,7 +26,6 @@ import static com.romraider.util.ByteUtil.asUnsignedInt;
import static com.romraider.util.JEPUtil.evaluate;
import static com.romraider.util.ParamChecker.checkNotNull;
import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
import static com.romraider.util.ParamChecker.isValidBit;
import java.text.DecimalFormat;
import java.util.HashMap;
@ -59,20 +58,20 @@ public final class EcuParameterConvertorImpl implements EcuDataConvertor {
this.expression = expression;
this.format = new DecimalFormat(format);
this.bit = bit;
this.dataType = dataType;
this.dataType = (dataType == null ? "uint8" : dataType);
this.replaceMap = replaceMap;
this.gaugeMinMax = gaugeMinMax;
}
public double convert(byte[] bytes) {
if (isValidBit(bit)) {
return (bytes[0] & (1 << bit)) > 0 ? 1 : 0;
if (bit >= 0 && bit <= 31) {
return (asUnsignedInt(bytes) & (1 << bit)) != 0 ? 1 : 0;
} else {
double value = 0;
if (dataType != null && dataType.equalsIgnoreCase(FLOAT)) {
if (dataType.equalsIgnoreCase(FLOAT)) {
value = (double) asFloat(bytes, 0 , bytes.length);
}
else if (dataType != null && dataType.startsWith(INT)) {
else if (dataType.toLowerCase().startsWith(INT)) {
value = (double) asSignedInt(bytes);
}
else {
@ -111,4 +110,9 @@ public final class EcuParameterConvertorImpl implements EcuDataConvertor {
public String getExpression() {
return expression;
}
@Override
public String getDataType() {
return dataType;
}
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2013 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -60,4 +60,9 @@ public final class EcuSwitchConvertorImpl implements EcuDataConvertor {
public String getExpression() {
return "x";
}
@Override
public String getDataType() {
return null;
}
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2013 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -73,4 +73,9 @@ public final class ExternalDataConvertorImpl implements EcuDataConvertor {
public String getExpression() {
return expression;
}
@Override
public String getDataType() {
return null;
}
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2013 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -75,6 +75,7 @@ import com.romraider.logger.ecu.ui.swing.menubar.action.LogFileNumberFormatActio
import com.romraider.logger.ecu.ui.swing.menubar.action.LoggerDebugLocationAction;
import com.romraider.logger.ecu.ui.swing.menubar.action.LoggerDebuggingLevelAction;
import com.romraider.logger.ecu.ui.swing.menubar.action.LoggerDefinitionLocationAction;
import com.romraider.logger.ecu.ui.swing.menubar.action.ObdModeAction;
import com.romraider.logger.ecu.ui.swing.menubar.action.ReadEcuCodesAction;
import com.romraider.logger.ecu.ui.swing.menubar.action.ReloadProfileAction;
import com.romraider.logger.ecu.ui.swing.menubar.action.ResetConnectionAction;
@ -92,7 +93,7 @@ import com.romraider.util.SettingsManager;
public class EcuLoggerMenuBar extends JMenuBar {
private static final long serialVersionUID = 7081586516953740186L;
Settings settings = SettingsManager.getSettings();
final Settings settings = SettingsManager.getSettings();
public EcuLoggerMenuBar(EcuLogger logger, List<ExternalDataSource> externalDataSources) {
@ -120,8 +121,11 @@ public class EcuLoggerMenuBar extends JMenuBar {
settingsMenu.add(fastPoll);
RadioButtonMenuItem canBus = new RadioButtonMenuItem("CAN bus Logging (2007+)", VK_N, getKeyStroke(VK_N, CTRL_MASK), new CanBusModeAction(logger), settings.isCanBus());
canBus.setToolTipText("Select to enable logging via CAN bus using a J2534 compatible cable");
RadioButtonMenuItem obdProtocol = new RadioButtonMenuItem("OBD Logging Protocol", VK_B, getKeyStroke(VK_B, ALT_MASK), new ObdModeAction(logger), settings.isObdProtocol());
obdProtocol.setToolTipText("Select to switch logging comminucations protocol to OBD. Only supported for CAN bus using a J2534 compatible cable.");
if (isPlatform(WINDOWS)) {
settingsMenu.add(canBus);
settingsMenu.add(obdProtocol);
}
settingsMenu.add(new JSeparator());
settingsMenu.add(new RadioButtonMenuItem("Use Absolute Timestamp In Log File", VK_T, getKeyStroke(VK_T, CTRL_MASK), new LogFileAbsoluteTimestampAction(logger), logger.getSettings().isFileLoggingAbsoluteTimestamp()));

View File

@ -0,0 +1,70 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.ecu.ui.swing.menubar.action;
import static javax.swing.JOptionPane.OK_OPTION;
import static javax.swing.JOptionPane.QUESTION_MESSAGE;
import static javax.swing.JOptionPane.YES_NO_OPTION;
import static javax.swing.JOptionPane.showConfirmDialog;
import java.awt.event.ActionEvent;
import com.romraider.Settings;
import com.romraider.logger.ecu.EcuLogger;
import com.romraider.swing.menubar.action.AbstractAction;
import com.romraider.util.SettingsManager;
public final class ObdModeAction extends AbstractAction {
public ObdModeAction(EcuLogger logger) {
super(logger);
}
public void actionPerformed(ActionEvent actionEvent) {
final Settings settings = SettingsManager.getSettings();
try {
logger.stopLogging();
if ((Boolean) getValue(SELECTED_KEY) &&
!settings.isObdProtocol() &&
showConfirmation() == OK_OPTION) {
settings.setTransportProtocol("ISO15765");
settings.setLoggerProtocol("OBD");
}
else {
settings.setLoggerProtocol("SSM");
}
logger.loadLoggerParams();
logger.startLogging();
}
catch (Exception e) {
logger.reportError(e);
}
}
private final int showConfirmation() {
return showConfirmDialog(logger,
"Confirm switching to the OBD communications protocol.\n" +
"This mode is only supported for CAN enabled ECUs using " +
"a J2534 compatible cable.",
"OBD Comminucations Mode",
YES_NO_OPTION,
QUESTION_MESSAGE);
}
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2012 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -28,7 +28,7 @@ public final class HexUtil {
return asHex(new byte[]{b});
}
public static String asHex(byte in[]) {
public static String asHex(byte[] in) {
return bytesToHex(in).toUpperCase();
}

View File

@ -1,6 +1,6 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2012 RomRaider.com
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -28,7 +28,8 @@ public final class JEPUtil {
}
public static double evaluate(String expression, double value) {
JEP parser = new JEP();
final JEP parser = new JEP();
parser.addStandardFunctions();
parser.initSymTab(); // clear the contents of the symbol table
parser.addVariable("x", value);
parser.parseExpression(expression);
@ -36,7 +37,7 @@ public final class JEPUtil {
}
public static double evaluate(String expression, Map<String, Double> valueMap) {
JEP parser = new JEP();
final JEP parser = new JEP();
parser.initSymTab(); // clear the contents of the symbol table
for (String id : valueMap.keySet()) {
parser.addVariable(id, valueMap.get(id));