package com.openxc.messages;
import com.google.common.base.Objects;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import android.os.Parcel;
import com.google.common.base.MoreObjects;
import com.google.gson.annotations.SerializedName;
/**
* A diagnostic response message from the vehicle interface.
*/
public class DiagnosticResponse extends DiagnosticMessage {
private static final String VALUE_KEY = "value";
private static final String NEGATIVE_RESPONSE_CODE_KEY = "negative_response_code";
private static final String SUCCESS_KEY = "success";
private static final String[] sRequiredFieldsValues = new String[] {
BUS_KEY, ID_KEY, MODE_KEY, SUCCESS_KEY };
private static final Set<String> sRequiredFields = new HashSet<>(
Arrays.asList(sRequiredFieldsValues));
@SerializedName(SUCCESS_KEY)
private boolean mSuccess = false;
@SerializedName(VALUE_KEY)
private Double mValue;
@SerializedName(NEGATIVE_RESPONSE_CODE_KEY)
private NegativeResponseCode mNegativeResponseCode = NegativeResponseCode.NONE;
public DiagnosticResponse(int busId, int id, int mode) {
super(busId, id, mode);
}
public DiagnosticResponse(int busId, int id, int mode, int pid,
byte[] payload) {
super(busId, id, mode, pid);
setPayload(payload);
}
public DiagnosticResponse(int busId, int id, int mode, int pid,
byte[] payload,
NegativeResponseCode negativeResponseCode,
double value) {
this(busId, id, mode, pid, payload);
mNegativeResponseCode = negativeResponseCode == null ?
NegativeResponseCode.NONE : negativeResponseCode;
mValue = value;
}
public boolean isSuccessful() {
return mNegativeResponseCode == NegativeResponseCode.NONE;
}
public boolean hasValue() {
return mValue != null;
}
public Double getValue() {
return mValue;
}
public void setValue(Double value) {
mValue = value;
}
public NegativeResponseCode getNegativeResponseCode() {
return mNegativeResponseCode;
}
public void setNegativeResponseCode(NegativeResponseCode code) {
mNegativeResponseCode = code;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("timestamp", getTimestamp())
.add("id", getId())
.add("mode", getMode())
.add("pid", getPid())
.add("payload", Arrays.toString(getPayload()))
.add("value", getValue())
.add("negative_response_code", getNegativeResponseCode())
.add("extras", getExtras())
.toString();
}
public static boolean containsRequiredFields(Set<String> fields) {
return fields.containsAll(sRequiredFields);
}
@Override
public boolean equals(Object obj) {
if (!super.equals(obj) || !(obj instanceof DiagnosticResponse)) {
return false;
}
final DiagnosticResponse other = (DiagnosticResponse) obj;
return Objects.equal(mValue, other.mValue)
&& Objects.equal(mNegativeResponseCode, other.mNegativeResponseCode);
}
public static enum NegativeResponseCode {
NONE(-1),
GENERAL_REJECT(0x10),
SERVICE_NOT_SUPPORTED(0x11),
SUB_FUNCTION_NOT_SUPPORTED(0x12),
INCORRECT_MESSAGE_LENGTH_OR_INVALID_FORMAT(0x13),
RESPONSE_TOO_LONG(0x14),
BUSY_REPEAT_REQUEST(0x21),
CONDITIONS_NOT_CORRECT(0x22),
REQUEST_SEQUENCE_ERROR(0x24),
NO_RESPONSE_FROM_SUBNET_COMPONENT(0x25),
FAILURE_PREVENTS_EXECUTION_OF_REQUESTED_ACTION(0x26),
REQUEST_OUT_OF_RANGE(0x31),
SECURITY_ACCESS_DENIED(0x33),
INVALID_KEY(0x35),
EXCEED_NUMBER_OF_ATTEMPTS(0x36),
REQUIRED_TIME_DELAY_NOT_EXPIRED(0x37),
UPLOAD_DOWNLOAD_NOT_ACCEPTED(0x70),
TRANSFER_DATA_SUSPENDED(0x71),
GENERAL_PROGRAMMING_FAILURE(0x72),
WRONG_BLOCK_SEQUENCE_COUNTER(0x73),
REQUEST_CORRECTLY_RECEIVED_RESPONSE_PENDING(0X78),
SUB_FUNCTION_NOT_SUPPORTED_IN_ACTIVE_SESSION(0x7E),
SERVICE_NOT_SUPPORTED_IN_ACTIVE_SESSION(0x7F),
RPM_TOO_HIGH(0x81),
RPM_TOO_LOW(0x82),
ENGINE_IS_RUNNING(0x83),
ENGINE_IS_NOT_RUNNING(0x84),
ENGINE_RUN_TIME_TOO_LOW(0x85),
TEMPERATURE_TOO_HIGH(0x86),
TEMPERATURE_TOO_LOW(0x87),
VEHICLE_SPEED_TOO_HIGH(0x88),
VEHICLE_SPEED_TOO_LOW(0x89),
THROTTLE_PEDAL_TOO_HIGH(0x8A),
THROTTLE_PEDAL_TOO_LOW(0x8B),
TRANSMISSION_RANGE_NOT_IN_NEUTRAL(0x8C),
TRANSMISSION_RANGE_NOT_IN_GEAR(0x8D),
BRAKE_SWITCH_ES_NOT_CLOSED(0x8F),
SHIFTER_LEVER_NOT_IN_PARK(0x90),
TORQUE_CONVERTER_CLUTCH_LOCKED(0x91),
VOLTAGE_TOO_HIGH(0x92),
VOLTAGE_TOO_LOW(0x93);
private int code;
private static final Map<Integer, NegativeResponseCode> lookup = new HashMap<>();
static {
for (NegativeResponseCode c : NegativeResponseCode.values()) {
lookup.put(c.code(), c);
}
}
private NegativeResponseCode(int value) {
this.code = value;
}
public int code() {
return this.code;
}
public static NegativeResponseCode get(int value) {
return lookup.get(value);
}
public String hexCodeString() {
return "0x" + Integer.toHexString(this.code).toUpperCase(Locale.US);
}
public String toDocumentationString() {
String result = this.toString().toLowerCase(Locale.US);
String und = "_";
while (result.contains(und)) {
int underscoreIndex = result.indexOf(und);
result = result.substring(0, underscoreIndex) +
String.valueOf(result.charAt(underscoreIndex + 1)).toUpperCase(Locale.US)
+ result.substring(underscoreIndex + 2);
}
return result;
}
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeValue(getValue());
out.writeSerializable(getNegativeResponseCode());
}
@Override
protected void readFromParcel(Parcel in) {
super.readFromParcel(in);
mValue = (Double) in.readValue(Double.class.getClassLoader());
mNegativeResponseCode = (NegativeResponseCode) in.readSerializable();
}
protected DiagnosticResponse(Parcel in) {
readFromParcel(in);
}
protected DiagnosticResponse() { }
}