package com.openvehicles.OVMS.api;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Date;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Base64;
import android.util.Log;
import com.openvehicles.OVMS.BaseApp;
import com.openvehicles.OVMS.R;
import com.openvehicles.OVMS.entities.CarData;
import com.openvehicles.OVMS.entities.CarData.DataStale;
import com.luttu.AppPrefes;
public class ApiTask extends AsyncTask<Void, Object, Void> {
private static final String TAG = "ApiTask";
private Socket mSocket;
private Cipher mTxCipher, mRxCipher, mPmCipher;
private byte[] mPmDigestBuf;
private PrintWriter mOutputstream;
private BufferedReader mInputstream;
private boolean isLoggedIn = false;
private final CarData mCarData;
private final OnUpdateStatusListener mListener;
private final Random sRnd = new Random();
private boolean isShuttingDown = false;
AppPrefes appPrefes;
private enum MsgType {
msgUpdate, msgError, msgCommand, msgLoginBegin, msgLoginComplete
}
public ApiTask(CarData pCarData, OnUpdateStatusListener pListener) {
mCarData = pCarData;
mListener = pListener;
Log.v(TAG, "Create TCPTask");
}
public boolean isLoggedIn() {
return isLoggedIn;
}
@Override
protected void onProgressUpdate(Object... pParam) {
if (mListener == null) return;
MsgType state = (MsgType) pParam[0];
switch (state) {
case msgUpdate:
mListener.onUpdateStatus();
break;
case msgLoginBegin:
mListener.onLoginBegin();
break;
case msgLoginComplete:
mListener.onLoginComplete();
break;
case msgError:
mListener.onServerSocketError((Throwable)pParam[1]);
break;
case msgCommand:
mListener.onResultCommand((String)pParam[1]);
break;
}
}
@Override
protected Void doInBackground(Void... params) {
String rx, msg;
while (!isShuttingDown) {
try {
// (re-)open socket connection
connInit();
while (mSocket.isConnected()) {
// read & decrypt message
rx = mInputstream.readLine().trim();
msg = new String(mRxCipher.update(Base64.decode(rx, 0))).trim();
Log.d(TAG, String.format("RX: %s (%s)", msg, rx));
if (msg.substring(0, 5).equals("MP-0 ")) {
// is valid message (for protocol version 0):
handleMessage(msg.substring(5));
} else {
Log.d(TAG, "Unknown protection scheme");
// sleep for 100 ms to prevent DoS by invalid data
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// ignore
}
}
}
// reconnect if not shutting down:
continue;
} catch (SocketException e) {
// connection lost, attempt to reconnect
try {
mSocket.close();
mSocket = null;
} catch (Exception ex) {
// ignore
}
continue;
} catch (IOException e) {
// reader closed or I/O error
e.printStackTrace();
publishProgress(MsgType.msgError, e);
break;
} catch (Exception e) {
// other error
e.printStackTrace();
publishProgress(MsgType.msgError, e);
break;
}
}
Log.d(TAG, "Terminating AsyncTask");
return null;
}
public void ping() {
String msg = "TX: MP-0 A";
mOutputstream.println(Base64.encodeToString(mTxCipher.update(msg.getBytes()), Base64.NO_WRAP));
Log.d(TAG, msg);
}
public void connClose() {
try {
Log.d(TAG, "connClose() requested");
isShuttingDown = true;
if ((mSocket != null) && mSocket.isConnected()) {
mSocket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean sendCommand(String command) {
Log.i(TAG, "TX: " + command);
if (!isLoggedIn) {
Log.w(TAG, "Server not ready. TX aborted.");
return false;
}
try {
mOutputstream.println(Base64.encodeToString(mTxCipher.update(command.getBytes()), Base64.NO_WRAP));
} catch (Exception e) {
publishProgress(MsgType.msgError, e);
}
return true;
}
private void connInit() {
isLoggedIn = false;
publishProgress(MsgType.msgLoginBegin);
Log.d(TAG, "connInit() requested");
isShuttingDown = false;
String shared_secret = mCarData.sel_server_password;
String vehicleID = mCarData.sel_vehicleid;
String b64tabString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char[] b64tab = b64tabString.toCharArray();
// generate session client token
String client_tokenString = "";
for (int cnt = 0; cnt < 22; cnt++) {
client_tokenString += b64tab[sRnd.nextInt(b64tab.length - 1)];
}
byte[] client_token = client_tokenString.getBytes();
try {
Mac client_hmac = Mac.getInstance("HmacMD5");
javax.crypto.spec.SecretKeySpec sk = new javax.crypto.spec.SecretKeySpec(
shared_secret.getBytes(), "HmacMD5");
client_hmac.init(sk);
byte[] hashedBytes = client_hmac.doFinal(client_token);
String client_digest = Base64.encodeToString(hashedBytes, Base64.NO_WRAP);
mSocket = new Socket(mCarData.sel_server, 6867);
mOutputstream = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())), true);
Log.d(TAG, String.format("TX: MP-A 0 %s %s %s", client_tokenString, client_digest, vehicleID));
mOutputstream.println(String.format("MP-A 0 %s %s %s", client_tokenString, client_digest, vehicleID));
mInputstream = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
// get server welcome message
String[] serverWelcomeMsg = null;
try {
serverWelcomeMsg = mInputstream.readLine().trim().split("[ ]+");
} catch (Exception e) {
Log.e(TAG, "ERROR response server welcome message", e);
publishProgress(MsgType.msgError, e);
return;
}
Log.d(TAG, String.format("RX: %s %s %s %s", serverWelcomeMsg[0], serverWelcomeMsg[1],
serverWelcomeMsg[2], serverWelcomeMsg[3]));
String server_tokenString = serverWelcomeMsg[2];
byte[] server_token = server_tokenString.getBytes();
byte[] server_digest = Base64.decode(serverWelcomeMsg[3], 0);
if (!Arrays.equals(client_hmac.doFinal(server_token), server_digest)) {
// server hash failed
Log.d(TAG, String.format(
"Server authentication failed. Expected %s Got %s",
Base64.encodeToString(client_hmac
.doFinal(serverWelcomeMsg[2].getBytes()),
Base64.NO_WRAP), serverWelcomeMsg[3]));
} else {
Log.d(TAG, "Server authentication OK.");
}
// generate client_key
String server_client_token = server_tokenString + client_tokenString;
byte[] client_key = client_hmac.doFinal(server_client_token.getBytes());
Log.d(TAG, String.format("Client version of the shared key is %s - (%s) %s",
server_client_token, toHex(client_key).toLowerCase(),
Base64.encodeToString(client_key, Base64.NO_WRAP)));
// generate ciphers
mRxCipher = Cipher.getInstance("RC4");
mRxCipher.init(Cipher.DECRYPT_MODE, new javax.crypto.spec.SecretKeySpec(client_key, "RC4"));
mTxCipher = Cipher.getInstance("RC4");
mTxCipher.init(Cipher.ENCRYPT_MODE, new javax.crypto.spec.SecretKeySpec(client_key, "RC4"));
// prime ciphers
String primeData = "";
for (int cnt = 0; cnt < 1024; cnt++) primeData += "0";
mRxCipher.update(primeData.getBytes());
mTxCipher.update(primeData.getBytes());
Log.i(TAG, String.format("Connected to %s. Ciphers initialized. Listening...", mCarData.sel_server));
//OLD loginComplete();
isLoggedIn = true;
publishProgress(MsgType.msgLoginComplete);
} catch (UnknownHostException e) {
e.printStackTrace();
publishProgress(MsgType.msgError, e);
} catch (IOException e) {
e.printStackTrace();
publishProgress(MsgType.msgError, e);
} catch (NullPointerException e) {
// notifyServerSocketError(e);
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private void handleMessage(String msg) {
Context mContext = BaseApp.getApp();
Log.i(TAG, "handleMessage: " + msg);
char code = msg.charAt(0);
String cmd = msg.substring(1);
appPrefes = new AppPrefes(mContext, "ovms");
if (code == 'E') {
// We have a paranoid mode message
char innercode = msg.charAt(1);
if (innercode == 'T') {
// Set the paranoid token
Log.v(TAG, "ET MSG Received: " + msg);
try {
String pmToken = msg.substring(2);
Mac pm_hmac = Mac.getInstance("HmacMD5");
javax.crypto.spec.SecretKeySpec sk = new javax.crypto.spec.SecretKeySpec(
mCarData.sel_server_password.getBytes(), "HmacMD5");
pm_hmac.init(sk);
mPmDigestBuf = pm_hmac.doFinal(pmToken.getBytes());
Log.d(TAG, "Paranoid Mode Token Accepted. Entering Privacy Mode.");
} catch (Exception e) {
Log.e("ERR", e.getMessage());
e.printStackTrace();
}
} else if (innercode == 'M') {
// Decrypt the paranoid message
Log.v(TAG, "EM MSG Received: " + msg);
code = msg.charAt(2);
cmd = msg.substring(3);
byte[] decodedCmd = Base64.decode(cmd,
Base64.NO_WRAP);
try {
mPmCipher = Cipher.getInstance("RC4");
mPmCipher.init(Cipher.DECRYPT_MODE,
new javax.crypto.spec.SecretKeySpec(mPmDigestBuf,
"RC4"));
// prime ciphers
String primeData = "";
for (int cnt = 0; cnt < 1024; cnt++)
primeData += "0";
mPmCipher.update(primeData.getBytes());
cmd = new String(mPmCipher.update(decodedCmd));
} catch (Exception e) {
Log.d("ERR", e.getMessage());
e.printStackTrace();
}
// notify main process of paranoid mode detection
if (!mCarData.sel_paranoid) {
Log.d(TAG, "Paranoid Mode Detected");
mCarData.sel_paranoid = true;
publishProgress(MsgType.msgUpdate);
}
}
}
Log.v(TAG, code + " MSG Received: " + cmd);
switch (code) {
case 'Z': // Number of connected cars
{
mCarData.server_carsconnected = Integer.parseInt(cmd);
publishProgress(MsgType.msgUpdate);
break;
}
case 'S': // STATUS
{
String[] dataParts = cmd.split(",\\s*");
if (dataParts.length >= 8) {
Log.v(TAG, "S MSG Validated");
mCarData.car_soc_raw = Integer.parseInt(dataParts[0]);
mCarData.car_soc = String.format("%d%%",mCarData.car_soc_raw);
mCarData.car_distance_units_raw = dataParts[1].toString();
mCarData.car_distance_units = (mCarData.car_distance_units_raw.equals("M"))?"m":"km";
mCarData.car_speed_units = (mCarData.car_distance_units_raw.equals("M"))
?mContext.getText(R.string.mph).toString()
:mContext.getText(R.string.kph).toString();
mCarData.car_charge_linevoltage_raw = Integer.parseInt(dataParts[2]);
mCarData.car_charge_linevoltage = String.format("%d%s", mCarData.car_charge_linevoltage_raw,"V");
mCarData.car_charge_current_raw = Integer.parseInt(dataParts[3]);
mCarData.car_charge_current = String.format("%d%s",mCarData.car_charge_current_raw,"A");
mCarData.car_charge_voltagecurrent = String.format("%d%s %d%s",
mCarData.car_charge_linevoltage_raw,"V",
mCarData.car_charge_current_raw,"A");
mCarData.car_charge_state_s_raw = dataParts[4].toString();
mCarData.car_charge_state = mCarData.car_charge_state_s_raw;
mCarData.car_mode_s_raw = dataParts[5].toString();
mCarData.car_charge_mode = mCarData.car_mode_s_raw;
mCarData.car_range_ideal_raw = Integer.parseInt(dataParts[6]);
mCarData.car_range_ideal = String.format("%d%s",mCarData.car_range_ideal_raw,mCarData.car_distance_units);
mCarData.car_range_estimated_raw = Integer.parseInt(dataParts[7]);
mCarData.car_range_estimated = String.format("%d%s",mCarData.car_range_estimated_raw,mCarData.car_distance_units);
mCarData.stale_status = DataStale.Good;
}
if (dataParts.length >= 15) {
mCarData.car_charge_currentlimit_raw = Integer.parseInt(dataParts[8]);
mCarData.car_charge_currentlimit = String.format("%d%s",mCarData.car_charge_currentlimit_raw,"A");
mCarData.car_charge_duration_raw = Integer.parseInt(dataParts[9]);
mCarData.car_charge_b4byte_raw = Integer.parseInt(dataParts[10]);
mCarData.car_charge_kwhconsumed = Integer.parseInt(dataParts[11]);
mCarData.car_charge_substate_i_raw = Integer.parseInt(dataParts[12]);
mCarData.car_charge_state_i_raw = Integer.parseInt(dataParts[13]);
mCarData.car_charge_mode_i_raw = Integer.parseInt(dataParts[14]);
}
if (dataParts.length >= 18) {
mCarData.car_charge_timermode_raw = Integer.parseInt(dataParts[15]);
mCarData.car_charge_timer = (mCarData.car_charge_timermode_raw > 0);
mCarData.car_charge_timerstart_raw = Integer.parseInt(dataParts[16]);
mCarData.car_charge_time = ""; // TODO: Implement later
mCarData.car_stale_chargetimer_raw = Integer.parseInt(dataParts[17]);
if (mCarData.car_stale_chargetimer_raw < 0)
mCarData.stale_chargetimer = DataStale.NoValue;
else if (mCarData.car_stale_chargetimer_raw == 0)
mCarData.stale_chargetimer = DataStale.Stale;
else
mCarData.stale_chargetimer = DataStale.Good;
}
if (dataParts.length >= 19) {
mCarData.car_CAC = Double.parseDouble(dataParts[18]);
}
if (dataParts.length >= 27) {
mCarData.car_chargefull_minsremaining = Integer.parseInt(dataParts[19]);
mCarData.car_chargelimit_minsremaining = Integer.parseInt(dataParts[20]);
mCarData.car_chargelimit_rangelimit_raw = Integer.parseInt(dataParts[21]);
mCarData.car_chargelimit_rangelimit = String.format("%d%s",
mCarData.car_chargelimit_rangelimit_raw, mCarData.car_distance_units);
mCarData.car_chargelimit_soclimit = Integer.parseInt(dataParts[22]);
mCarData.car_coolingdown = Integer.parseInt(dataParts[23]);
mCarData.car_cooldown_tbattery = Integer.parseInt(dataParts[24]);
mCarData.car_cooldown_timelimit = Integer.parseInt(dataParts[25]);
mCarData.car_chargeestimate = Integer.parseInt(dataParts[26]);
}
if (dataParts.length >= 30) {
mCarData.car_chargelimit_minsremaining_range = Integer.parseInt(dataParts[27]);
mCarData.car_chargelimit_minsremaining_soc = Integer.parseInt(dataParts[28]);
mCarData.car_max_idealrange_raw = Integer.parseInt(dataParts[29]);
mCarData.car_max_idealrange = String.format("%d%s",
mCarData.car_max_idealrange_raw, mCarData.car_distance_units);
}
Log.v(TAG, "Notify Vehicle Status Update: " + mCarData.sel_vehicleid);
publishProgress(MsgType.msgUpdate);
break;
}
case 'T': // TIME
{
if (cmd.length() > 0) {
mCarData.car_lastupdate_raw = Long.parseLong(cmd);
mCarData.car_lastupdated = new Date(System.currentTimeMillis() - mCarData.car_lastupdate_raw * 1000);
publishProgress(MsgType.msgUpdate);
} else
Log.w(TAG, "T MSG Invalid");
break;
}
case 'L': // LOCATION
{
String[] dataParts = cmd.split(",\\s*");
if (dataParts.length >= 2) {
Log.v(TAG, "L MSG Validated");
mCarData.car_latitude = Double.parseDouble(dataParts[0]);
mCarData.car_longitude = Double.parseDouble(dataParts[1]);
}
if (dataParts.length >= 6) {
mCarData.car_direction = Integer.parseInt(dataParts[2]);
mCarData.car_altitude = Integer.parseInt(dataParts[3]);
mCarData.car_gpslock_raw = Integer.parseInt(dataParts[4]);
mCarData.car_gpslock = (mCarData.car_gpslock_raw > 0);
mCarData.car_stale_gps_raw = Integer.parseInt(dataParts[5]);
if (mCarData.car_stale_gps_raw < 0)
mCarData.stale_gps = DataStale.NoValue;
else if (mCarData.car_stale_gps_raw == 0)
mCarData.stale_gps = DataStale.Stale;
else
mCarData.stale_gps = DataStale.Good;
}
publishProgress(MsgType.msgUpdate);
break;
}
case 'D': // Doors and switches
{
String[] dataParts = cmd.split(",\\s*");
if (dataParts.length >= 9) {
Log.v(TAG, "D MSG Validated");
int dataField = Integer.parseInt(dataParts[0]);
mCarData.car_doors1_raw = dataField;
mCarData.car_frontleftdoor_open = ((dataField & 0x1) == 0x1);
mCarData.car_frontrightdoor_open = ((dataField & 0x2) == 0x2);
mCarData.car_chargeport_open = ((dataField & 0x4) == 0x4);
mCarData.car_pilot_present = ((dataField & 0x8) == 0x8);
mCarData.car_charging = ((dataField & 0x10) == 0x10);
// bit 5 is always 1
mCarData.car_handbrake_on = ((dataField & 0x40) == 0x40);
mCarData.car_started = ((dataField & 0x80) == 0x80);
dataField = Integer.parseInt(dataParts[1]);
mCarData.car_doors2_raw = dataField;
mCarData.car_bonnet_open = ((dataField & 0x40) == 0x40);
mCarData.car_trunk_open = ((dataField & 0x80) == 0x80);
mCarData.car_headlights_on = ((dataField & 0x20) == 0x20);
mCarData.car_valetmode = ((dataField & 0x10) == 0x10);
mCarData.car_locked = ((dataField & 0x08) == 0x08);
mCarData.car_lockunlock_raw = Integer.parseInt(dataParts[2]);
mCarData.car_temp_pem_raw = Integer.parseInt(dataParts[3]);
mCarData.car_temp_motor_raw = Integer.parseInt(dataParts[4]);
mCarData.car_temp_battery_raw = Integer.parseInt(dataParts[5]);
if (appPrefes.getData("showfahrenheit").equals("on"))
{
mCarData.car_temp_pem = String.format("%.0f\u00B0F",(mCarData.car_temp_pem_raw*(9.0/5.0))+32.0);
mCarData.car_temp_motor = String.format("%.0f\u00B0F",(mCarData.car_temp_motor_raw*(9.0/5.0))+32.0);
mCarData.car_temp_battery = String.format("%.0f\u00B0F",(mCarData.car_temp_battery_raw*(9.0/5.0))+32.0);
}
else
{
mCarData.car_temp_pem = String.format("%d\u00B0C",mCarData.car_temp_pem_raw);
mCarData.car_temp_motor = String.format("%d\u00B0C",mCarData.car_temp_motor_raw);
mCarData.car_temp_battery = String.format("%d\u00B0C",mCarData.car_temp_battery_raw);
}
mCarData.car_tripmeter_raw = Integer.parseInt(dataParts[6]);
mCarData.car_tripmeter = String.format("%.1f%s",(float)mCarData.car_tripmeter_raw/10,mCarData.car_distance_units);
mCarData.car_odometer_raw = Integer.parseInt(dataParts[7]);
mCarData.car_odometer = String.format("%.1f%s",(float)mCarData.car_odometer_raw/10,mCarData.car_distance_units);
mCarData.car_speed_raw = Integer.parseInt(dataParts[8]);
mCarData.car_speed = String.format("%d%s", mCarData.car_speed_raw,mCarData.car_speed_units);
mCarData.stale_environment = DataStale.Good;
if (dataParts.length >= 14) {
mCarData.car_parking_timer_raw = Long.parseLong(dataParts[9]);
mCarData.car_parked_time = new Date((new Date()).getTime() - mCarData.car_parking_timer_raw * 1000);
mCarData.car_temp_ambient_raw = Integer.parseInt(dataParts[10]);
if (appPrefes.getData("showfahrenheit").equals("on"))
mCarData.car_temp_ambient = String.format("%.0f\u00B0F",(mCarData.car_temp_ambient_raw*(9.0/5.0))+32.0);
else
mCarData.car_temp_ambient = String.format("%d\u00B0C",mCarData.car_temp_ambient_raw);
dataField = Integer.parseInt(dataParts[11]);
mCarData.car_doors3_raw = dataField;
mCarData.car_coolingpump_on = ((dataField & 0x02) == 0x02);
mCarData.car_stale_car_temps_raw = Integer.parseInt(dataParts[12]);
if (mCarData.car_stale_car_temps_raw < 0)
mCarData.stale_car_temps = DataStale.NoValue;
else if (mCarData.car_stale_car_temps_raw == 0)
mCarData.stale_car_temps = DataStale.Stale;
else
mCarData.stale_car_temps = DataStale.Good;
mCarData.car_stale_ambient_temp_raw = Integer.parseInt(dataParts[13]);
if (mCarData.car_stale_ambient_temp_raw < 0)
mCarData.stale_ambient_temp = DataStale.NoValue;
else if (mCarData.car_stale_ambient_temp_raw == 0)
mCarData.stale_ambient_temp = DataStale.Stale;
else
mCarData.stale_ambient_temp = DataStale.Good;
}
if (dataParts.length >= 16) {
mCarData.car_12vline_voltage = Double.parseDouble(dataParts[14]);
dataField = Integer.parseInt(dataParts[15]);
mCarData.car_doors4_raw = dataField;
mCarData.car_alarm_sounding = ((dataField & 0x02) == 0x02);
}
if (dataParts.length >= 18) {
mCarData.car_12vline_ref = Double.parseDouble(dataParts[16]);
dataField = Integer.parseInt(dataParts[17]);
mCarData.car_doors5_raw = dataField;
mCarData.car_charging_12v = ((dataField & 0x10) == 0x10);
}
publishProgress(MsgType.msgUpdate);
}
break;
}
case 'F': // VIN and Firmware
{
String[] dataParts = cmd.split(",\\s*");
if (dataParts.length >= 3) {
Log.v(TAG, "F MSG Validated");
mCarData.car_firmware = dataParts[0].toString();
mCarData.car_vin = dataParts[1].toString();
mCarData.car_gps_signal_raw = Integer.parseInt(dataParts[2]);
int car_gsmdbm = 0;
if (mCarData.car_gps_signal_raw <= 31)
car_gsmdbm = -113 + (mCarData.car_gps_signal_raw*2);
mCarData.car_gsm_signal = String.format("%d%s", car_gsmdbm," dbm");
if ((car_gsmdbm < -121)||(car_gsmdbm >= 0))
mCarData.car_gsm_bars = 0;
else if (car_gsmdbm < -107)
mCarData.car_gsm_bars = 1;
else if (car_gsmdbm < -98)
mCarData.car_gsm_bars = 2;
else if (car_gsmdbm < -87)
mCarData.car_gsm_bars = 3;
else if (car_gsmdbm < -76)
mCarData.car_gsm_bars = 4;
else
mCarData.car_gsm_bars = 5;
mCarData.stale_firmware = DataStale.Good;
}
if (dataParts.length >= 5) {
mCarData.car_canwrite = (Integer.parseInt(dataParts[3])>0);
mCarData.car_type = dataParts[4].toString();
}
if (dataParts.length >= 6) {
mCarData.car_gsmlock = dataParts[5].toString();
}
publishProgress(MsgType.msgUpdate);
}
case 'f': // OVMS Server Firmware
{
String[] dataParts = cmd.split(",\\s*");
if (dataParts.length >= 1) {
Log.v(TAG, "f MSG Validated");
mCarData.server_firmware = dataParts[0].toString();
publishProgress(MsgType.msgUpdate);
}
break;
}
case 'W': // TPMS
{
String[] dataParts = cmd.split(",\\s*");
if (dataParts.length >= 9) {
Log.v(TAG, "W MSG Validated");
mCarData.car_tpms_fr_p_raw = Double.parseDouble(dataParts[0]);
mCarData.car_tpms_fr_t_raw = Double.parseDouble(dataParts[1]);
mCarData.car_tpms_rr_p_raw = Double.parseDouble(dataParts[2]);
mCarData.car_tpms_rr_t_raw = Double.parseDouble(dataParts[3]);
mCarData.car_tpms_fl_p_raw = Double.parseDouble(dataParts[4]);
mCarData.car_tpms_fl_t_raw = Double.parseDouble(dataParts[5]);
mCarData.car_tpms_rl_p_raw = Double.parseDouble(dataParts[6]);
mCarData.car_tpms_rl_t_raw = Double.parseDouble(dataParts[7]);
mCarData.car_tpms_fl_p = String.format("%.1f%s",mCarData.car_tpms_fl_p_raw, "psi");
mCarData.car_tpms_fr_p = String.format("%.1f%s",mCarData.car_tpms_fr_p_raw, "psi");
mCarData.car_tpms_rl_p = String.format("%.1f%s",mCarData.car_tpms_rl_p_raw, "psi");
mCarData.car_tpms_rr_p = String.format("%.1f%s",mCarData.car_tpms_rr_p_raw, "psi");
if (appPrefes.getData("showfahrenheit").equals("on"))
{
mCarData.car_tpms_fl_t = String.format("%.0f%s",(mCarData.car_tpms_fl_t_raw*(9.0/5.0))+32.0, "\u00B0F");
mCarData.car_tpms_fr_t = String.format("%.0f%s",(mCarData.car_tpms_fr_t_raw*(9.0/5.0))+32.0, "\u00B0F");
mCarData.car_tpms_rl_t = String.format("%.0f%s",(mCarData.car_tpms_rl_t_raw*(9.0/5.0))+32.0, "\u00B0F");
mCarData.car_tpms_rr_t = String.format("%.0f%s",(mCarData.car_tpms_rr_t_raw*(9.0/5.0))+32.0, "\u00B0F");
}
else
{
mCarData.car_tpms_fl_t = String.format("%.0f%s",mCarData.car_tpms_fl_t_raw, "\u00B0C");
mCarData.car_tpms_fr_t = String.format("%.0f%s",mCarData.car_tpms_fr_t_raw, "\u00B0C");
mCarData.car_tpms_rl_t = String.format("%.0f%s",mCarData.car_tpms_rl_t_raw, "\u00B0C");
mCarData.car_tpms_rr_t = String.format("%.0f%s",mCarData.car_tpms_rr_t_raw, "\u00B0C");
}
mCarData.car_stale_tpms_raw = Integer.parseInt(dataParts[8]);
if (mCarData.car_stale_tpms_raw < 0)
mCarData.stale_tpms = DataStale.NoValue;
else if (mCarData.car_stale_tpms_raw == 0)
mCarData.stale_tpms = DataStale.Stale;
else
mCarData.stale_tpms = DataStale.Good;
publishProgress(MsgType.msgUpdate);
}
break;
}
case 'a': {
Log.v(TAG, "Server acknowleged ping");
break;
}
case 'c': {
Log.i(TAG, "c MSG Validated");
publishProgress(MsgType.msgCommand, cmd);
break;
}
}
}
private String toHex(byte[] bytes) {
BigInteger bi = new BigInteger(1, bytes);
return String.format("%0" + (bytes.length << 1) + "X", bi);
}
public interface OnUpdateStatusListener {
public void onUpdateStatus();
public void onServerSocketError(Throwable e);
public void onResultCommand(String pCmd);
public void onLoginBegin();
public void onLoginComplete();
}
}