package org.envirocar.obd.adapter;
import android.util.Base64;
import org.envirocar.core.logging.Logger;
import org.envirocar.obd.commands.request.BasicCommand;
import org.envirocar.obd.commands.request.PIDCommand;
import org.envirocar.obd.commands.request.elm.ConfigurationCommand;
import org.envirocar.obd.commands.request.elm.Timeout;
import org.envirocar.obd.exception.AdapterFailedException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Queue;
import rx.Observable;
/**
* Created by matthes on 02.11.15.
*/
public class ELM327Adapter extends SyncAdapter {
private static final Logger LOG = Logger.getLogger(ELM327Adapter.class);
private Queue<BasicCommand> initCommands;
protected int succesfulCount;
private boolean certifiedConnection;
@Override
protected BasicCommand pollNextInitializationCommand() {
return this.initCommands.poll();
}
@Override
public Observable<Boolean> initialize(InputStream is, OutputStream os) {
this.initCommands = createInitCommands();
return super.initialize(is, os);
}
protected Queue<BasicCommand> createInitCommands() {
Queue<BasicCommand> result = new ArrayDeque<>();
result.add(ConfigurationCommand.instance(ConfigurationCommand.Instance.RESET));
result.add(ConfigurationCommand.instance(ConfigurationCommand.Instance.ECHO_OFF));
result.add(ConfigurationCommand.instance(ConfigurationCommand.Instance.ECHO_OFF));
result.add(ConfigurationCommand.instance(ConfigurationCommand.Instance.LINE_FEED_OFF));
result.add(new Timeout(62));
result.add(ConfigurationCommand.instance(ConfigurationCommand.Instance.SELECT_AUTO_PROTOCOL));
return result;
}
@Override
protected List<PIDCommand> providePendingCommands() {
return super.defaultCycleCommands();
}
@Override
protected boolean analyzeMetadataResponse(byte[] response, BasicCommand sentCommand) throws AdapterFailedException {
String content = new String(response);
LOG.info("Analyzing metadata response: "+ Base64.encodeToString(response, Base64.DEFAULT));
if (sentCommand == null || !(sentCommand instanceof ConfigurationCommand)) {
return false;
}
ConfigurationCommand sent = (ConfigurationCommand) sentCommand;
if (sent.getInstance() == ConfigurationCommand.Instance.ECHO_OFF) {
if (content.contains("ELM327v1.") || content.contains("OK")) {
succesfulCount++;
certifiedConnection = true;
}
}
else if (sent.getInstance() == ConfigurationCommand.Instance.LINE_FEED_OFF) {
if (content.contains("OK")) {
succesfulCount++;
}
}
else if (sent instanceof Timeout) {
if (content.contains("OK")) {
succesfulCount++;
}
}
else if (sent.getInstance() == ConfigurationCommand.Instance.SELECT_AUTO_PROTOCOL) {
if (content.contains("OK")) {
succesfulCount++;
}
}
LOG.info("succesfulCount="+succesfulCount);
return succesfulCount >= 5;
}
@Override
protected byte[] preProcess(byte[] bytes) {
return bytes;
}
@Override
public boolean supportsDevice(String deviceName) {
return deviceName.contains("OBDII") || deviceName.contains("ELM327") || deviceName.toLowerCase().contains("obdlink mx");
}
@Override
public boolean hasCertifiedConnection() {
return certifiedConnection;
}
}