Android Open Source - HarleyDroid J1850






From Project

Back to project page HarleyDroid.

License

The source code is released under:

GNU General Public License

If you think the Android project HarleyDroid listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

//
// HarleyDroid: Harley Davidson J1850 Data Analyser for Android.
///*from   w w  w.  ja v a  2  s. c  o m*/
// Copyright (C) 2010-2012 Stelian Pop <stelian@popies.net>
// Based on various sources, especially:
//  minigpsd by Tom Zerucha <tz@execpc.com>
//  AVR J1850 VPW Interface by Michael Wolf <webmaster@mictronics.de>
//
// 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 3 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, see <http://www.gnu.org/licenses/>.
//

package org.harleydroid;

import java.util.Arrays;

import android.annotation.SuppressLint;
import android.util.Log;

public class J1850 {
  private static final boolean D = false;
  private static final String TAG = J1850.class.getSimpleName();

  public static final int MAXBUF = 1024;
  // last reading of odometer ticks
  private static int odolast = 0;
  // accumulated odometer ticks (deals with overflow at 0xffff)
  private static int odoaccum = 0;
  // last reading of fuel ticks
  private static int fuellast = 0;
  // accumulated fuel ticks (deals with overflow at 0xffff)
  private static int fuelaccum = 0;

  private static byte[] vin = { '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-' };
  private static byte[] ecmPN = { '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-' };
  private static byte[] ecmCalID = { '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-' };

  public static void resetCounters() {
    odolast = odoaccum = 0;
    fuellast = fuelaccum = 0;
    Arrays.fill(vin, (byte)'-');
    Arrays.fill(ecmPN, (byte)'-');
    Arrays.fill(ecmCalID, (byte)'-');
  }

  static byte[] bytes_to_hex(byte[] in) {
    byte out[] = new byte[MAXBUF];
    int inidx = 0, outidx = 0;

    while (inidx < in.length) {
      int digit0, digit1;

      while (inidx < in.length &&
          Character.digit((char)in[inidx], 16) == -1)
        inidx++;
      if (inidx >= in.length)
        break;
      digit0 = Character.digit((char)in[inidx++], 16);

      while (inidx < in.length &&
          Character.digit((char)in[inidx], 16) == -1)
        inidx++;
      if (inidx >= in.length)
        break;
      digit1 = Character.digit((char)in[inidx++], 16);

      out[outidx++] = (byte) (digit0 * 16 + digit1);
    }
    byte[] ret = new byte[outidx];
    System.arraycopy(out, 0, ret, 0, outidx);
    return ret;
  }

  public static byte crc(byte[] in) {
    int i, j;
    byte crc = (byte)0xff;

    for (i = 0; i < in.length; i++) {
      byte c = in[i];
      for (j = 0; j < 8; ++j) {
        byte poly = 0;
        if ((0x80 & (crc ^ c)) != 0)
          poly = 0x1d;
        crc = (byte) (((crc << 1) & 0xff) ^ poly);
        c <<= 1;
      }
    }
    return crc;
  }

  @SuppressLint("DefaultLocale")
  public static boolean parse(byte[] buffer, HarleyData hd) {
    byte[] in;
    int x;
    int y;

    in = bytes_to_hex(buffer);

    /*
    System.out.print("BUF: ");
    for (int i = 0; i < in.length; i++)
      System.out.print(Integer.toHexString(in[i]) + " ");
    System.out.println("");
     */

    if (crc(in) != (byte)0xc4) {
      hd.setBadCRC(buffer);
      return false;
    }

    x = y = 0;
    if (in.length >= 4)
      x = ((in[0] << 24) & 0xff000000) |
          ((in[1] << 16) & 0x00ff0000) |
          ((in[2] <<  8) & 0x0000ff00) |
           (in[3]        & 0x000000ff);
    if (in.length >= 6)
      y = ((in[4] << 8) & 0x0000ff00) |
           (in[5]       & 0x000000ff);

    if (x == 0x281b1002) {
      hd.setRPM(y);
    } else if (x == 0x48291002) {
      hd.setSpeed(y);
    } else if (x == 0xa8491010) {
      hd.setEngineTemp((int)in[4] & 0xff);
    } else if (x == 0xa83b1003) {
      if (in[4] != 0) {
        int gear = 0;
        while ((in[4] >>= 1) != 0)
          gear++;
        hd.setGear(gear);
      } else
        hd.setGear(-1);
    } else if ((x == 0x48da4039) && ((in[4] & 0xfc) == 0)) {
      hd.setTurnSignals(in[4] & 0x03);
    } else if ((x & 0xffffff7f) == 0xa8691006) {
      odolast = y - odolast;
      if (odolast < 0)  // ...could also test for (x & 0x80)
        odolast += 65536;
      odoaccum += odolast;
      odolast = y;
      hd.setOdometer(odoaccum);
    } else if ((x & 0xffffff7f) == 0xa883100a) {
      fuellast = y - fuellast;
      if (fuellast < 0)  // ...could also test for (x & 0x80)
        fuellast += 65536;
      fuelaccum += fuellast;
      fuellast = y;
      hd.setFuel(fuelaccum);
    } else if ((x & 0xffffff7f) == 0xa8836112) {
      hd.setFuelGauge(in[4] & 0x0f,
          ((in[3] & 0x80) != 0) ? true : false);
    } else if ((x & 0xffffff5d) == 0x483b4000) {
      if (((int)in[3] & 0xff) == 0x20)
        hd.setNeutral(false);
      else if (((int)in[3] & 0xff) == 0xA0)
        hd.setNeutral(true);
      hd.setClutch((in[3] & 0x80) != 0);
    } else if ((x & 0xffffff7f) == 0x68881003) {
      if ((in[3] & 0x80) != 0)
        hd.setCheckEngine(true);
      else
        hd.setCheckEngine(false);
    } else if (x == 0x0c10f13c) {
      /* this is the read block command, answers are below... */
    } else if (x == 0x0cf1107c) {
      switch (in[4]) {
      case 0x01:
        System.arraycopy(in, 5, ecmPN, 0, 6);
        hd.setECMPN(new String(ecmPN).trim());
        break;
      case 0x02:
        System.arraycopy(in, 5, ecmPN, 6, 6);
        hd.setECMPN(new String(ecmPN).trim());
        break;
      case 0x03:
        System.arraycopy(in, 5, ecmCalID, 0, 6);
        hd.setECMCalID(new String(ecmCalID).trim());
        break;
      case 0x04:
        System.arraycopy(in, 5, ecmCalID, 6, 6);
        hd.setECMCalID(new String(ecmCalID).trim());
        break;
      case 0x0b:
        hd.setECMSWLevel((int)in[5] & 0xff);
        break;
      case 0x0f:
        System.arraycopy(in, 5, vin, 0, 6);
        hd.setVIN(new String(vin).trim());
        break;
      case 0x10:
        System.arraycopy(in, 5, vin, 6, 6);
        hd.setVIN(new String(vin).trim());
        break;
      case 0x11:
        System.arraycopy(in, 5, vin, 12, 5);
        hd.setVIN(new String(vin).trim());
        break;
      default:
        hd.setUnknown(buffer);
      }
    } else if ((x & 0xff0fffff) == 0x6c00f119) {
      /* this is the get DTC command, answers are below... */
      if (D) Log.d(TAG, "DTC start");
    } else if ((x & 0xffff0fff) == 0x6cf10059) {
      if (in[4] != 0 || in[5] != 0) {
        String dtc = "";
        switch ((in[4] & 0xc0) >> 6) {
          case 0: dtc = "P"; break;
          case 1: dtc = "C"; break;
          case 2: dtc = "B"; break;
          case 3: dtc = "U"; break;
        }
        dtc += Integer.toString((in[4] & 0x30) >> 4, 16);
        dtc += Integer.toString(in[4] & 0x0f, 16);
        dtc += Integer.toString((in[5] & 0xf0) >> 4, 16);
        dtc += Integer.toString(in[5] & 0x0f, 16);
        dtc = dtc.toUpperCase();
        if (in[2] == 0x10) {
          /* historic DTC */
          if (D) Log.d(TAG, "historic DTC: " + dtc);
          hd.addHistoricDTC(dtc);
        } else if (in[2] == 0x40) {
          /* current DTC */
          if (D) Log.d(TAG, "current DTC: " + dtc);
          hd.addCurrentDTC(dtc);
        } else
          hd.setUnknown(buffer);
      }
    } else if ((x & 0xff0fffff) == 0x6c00f114) {
      if (D) Log.d(TAG, "DTC clear request");
    } else if ((x & 0xffff0fff) == 0x6cf10054) {
      if (D) Log.d(TAG, "DTC clear reply");
    } else
      hd.setUnknown(buffer);
    return true;
  }

  /*
  public static void main(String[] args) {
    // RPM at 1000 RPM
    //String line = "28 1B 10 02 0f a0 d7";
    // Speed at 100 km/h
    String line = "48 29 10 02 32 00 0f";

    byte[] in = line.getBytes();
    byte[] out = bytes_to_hex(in);

    System.out.print("Input: ");
    for (int i = 0; i < out.length; i++)
      System.out.print(String.format("0x%02x ", out[i]));
    System.out.println("");

    System.out.println("CRC: " + String.format("0x%02x", crc(out)));

    byte[] out_without_crc = new byte[out.length - 1];
    System.arraycopy(out, 0, out_without_crc, 0, out.length - 1);

    System.out.println("Need CRC byte: " + String.format("0x%02x", ~crc(out_without_crc)));

    HarleyData data = new HarleyData();
    if (parse(in, data))
      System.out.println(data);
    else
      System.out.println("Parse error");
  }
  */
}




Java Source Code List

org.harleydroid.About.java
org.harleydroid.ELM327Interface.java
org.harleydroid.EmulatorInterface.java
org.harleydroid.Eula.java
org.harleydroid.Gauge.java
org.harleydroid.HarleyDataDashboardListener.java
org.harleydroid.HarleyDataDiagnosticsListener.java
org.harleydroid.HarleyDataRawListener.java
org.harleydroid.HarleyData.java
org.harleydroid.HarleyDroidDashboardView.java
org.harleydroid.HarleyDroidDashboard.java
org.harleydroid.HarleyDroidDiagnosticsView.java
org.harleydroid.HarleyDroidDiagnostics.java
org.harleydroid.HarleyDroidGPS.java
org.harleydroid.HarleyDroidInterface.java
org.harleydroid.HarleyDroidLogger.java
org.harleydroid.HarleyDroidService.java
org.harleydroid.HarleyDroidSettings.java
org.harleydroid.HarleyDroid.java
org.harleydroid.J1850Interface.java
org.harleydroid.J1850.java
org.harleydroid.NonBlockingBluetoothSocket.java
org.harleydroid.VINDecoder.java