package com.openxc.messages; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import android.os.Parcel; import com.google.common.base.MoreObjects; import com.google.gson.annotations.SerializedName; /** * A VehicleMessage that is a low-level CAN message. * * A CAN message is keyed on the bus and message ID. */ public class CanMessage extends KeyedMessage { protected static final String ID_KEY = "id"; protected static final String BUS_KEY = "bus"; protected static final String DATA_KEY = "data"; @SerializedName(BUS_KEY) private int mBusId; @SerializedName(ID_KEY) private int mId; @SerializedName(DATA_KEY) private byte[] mData = new byte[8]; private static final String[] sRequiredFieldsValues = new String[] { BUS_KEY, ID_KEY, DATA_KEY }; private static final Set<String> sRequiredFields = new HashSet<>( Arrays.asList(sRequiredFieldsValues)); public CanMessage(int canBus, int id, byte[] data) { mBusId = canBus; mId = id; setPayload(data); } public int getBusId() { return mBusId; } public int getId() { return mId; } public byte[] getData() { return mData; } private void setPayload(byte[] data) { if(data != null) { System.arraycopy(data, 0, mData, 0, data.length); } } @Override public MessageKey getKey() { if(super.getKey() == null) { HashMap<String, Object> key = new HashMap<>(); key.put(BUS_KEY, getBusId()); key.put(ID_KEY, getId()); setKey(new MessageKey(key)); } return super.getKey(); } public static boolean containsRequiredFields(Set<String> fields) { return fields.containsAll(sRequiredFields); } /** * Sort by bus, then by message ID. */ @Override public int compareTo(VehicleMessage other) { CanMessage otherMessage = (CanMessage) other; if(getBusId() < otherMessage.getBusId()) { return -1; } else if(getBusId() > otherMessage.getBusId()) { return 1; } else { if(getId() < otherMessage.getId()) { return -1; } else if(getId() > otherMessage.getId()) { return 1; } } return 0; } @Override public boolean equals(Object obj) { if(!super.equals(obj) || !(obj instanceof CanMessage)) { return false; } final CanMessage other = (CanMessage) obj; return mId == other.mId && mBusId == other.mBusId && Arrays.equals(mData, other.mData); } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("timestamp", getTimestamp()) .add("bus", getBusId()) .add("id", getId()) .add("data", Arrays.toString(getData())) .toString(); } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeInt(getBusId()); out.writeInt(getId()); out.writeByteArray(getData()); } @Override public void readFromParcel(Parcel in) { super.readFromParcel(in); mBusId = in.readInt(); mId = in.readInt(); in.readByteArray(mData); } protected CanMessage(Parcel in) { readFromParcel(in); } }