package com.openvehicles.OVMS.ui; import android.content.res.Configuration; import android.os.Bundle; import android.util.Log; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.LayoutInflater; //import android.view.Menu; //import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.luttu.AppPrefes; import com.openvehicles.OVMS.R; import com.openvehicles.OVMS.api.OnResultCommandListener; import com.openvehicles.OVMS.entities.CarData; import com.openvehicles.OVMS.entities.CarData.DataStale; import com.openvehicles.OVMS.ui.utils.Ui; import com.openvehicles.OVMS.utils.CarsStorage; public class CarFragment extends BaseFragment implements OnClickListener, OnResultCommandListener { private static final String TAG = "CarFragment"; private CarData mCarData; Menu optionsMenu; AppPrefes appPrefes; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // init car data: mCarData = CarsStorage.get().getSelectedCarData(); appPrefes = new AppPrefes(getActivity(), "ovms"); // inflate layout: View rootView = inflater.inflate(R.layout.fragment_car, null); if (mCarData.car_type.equals("RT")) { // layout changes for Renault Twizy: // exchange "Homelink" by "Profile": ImageView icon = (ImageView) rootView.findViewById(R.id.tabCarImageHomelink); if (icon != null) icon.setImageResource(R.drawable.ic_drive_profile); TextView label = (TextView) rootView.findViewById(R.id.txt_homelink); if (label != null) label.setText(R.string.textPROFILE); } setHasOptionsMenu(true); return rootView; } @Override public void onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.car_options, menu); optionsMenu = menu; // set checkbox: optionsMenu.findItem(R.id.mi_show_fahrenheit) .setChecked(appPrefes.getData("showfahrenheit").equals("on")); } @Override public void onPrepareOptionsMenu(com.actionbarsherlock.view.Menu menu) { super.onPrepareOptionsMenu(menu); if (mCarData != null && mCarData.car_type != null) { menu.findItem(R.id.mi_power_stats).setVisible(mCarData.car_type.equals("RT")); } } @Override public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) { int menuId = item.getItemId(); boolean newState = !item.isChecked(); switch (menuId) { case R.id.mi_power_stats: Bundle args = new Bundle(); BaseFragmentActivity.show(getActivity(), PowerFragment.class, args, Configuration.ORIENTATION_UNDEFINED); return true; case R.id.mi_show_fahrenheit: appPrefes.SaveData("showfahrenheit", newState ? "on" : "off"); item.setChecked(newState); return true; default: return false; } } @Override public void update(CarData pCarData) { mCarData = pCarData; getSherlockActivity().invalidateOptionsMenu(); updateLastUpdatedView(pCarData); updateCarBodyView(pCarData); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); registerForContextMenu(findViewById(R.id.btn_wakeup)); registerForContextMenu(findViewById(R.id.txt_homelink)); registerForContextMenu(findViewById(R.id.tabCarImageHomelink)); findViewById(R.id.btn_lock_car).setOnClickListener(this); findViewById(R.id.btn_valet_mode).setOnClickListener(this); } @Override public void registerForContextMenu(View view) { super.registerForContextMenu(view); view.setOnClickListener(this); } @Override public void onClick(View v) { if (mCarData == null) return; final int dialogTitle, dialogButton; boolean isPinEntry; switch (v.getId()) { case R.id.btn_lock_car: // get dialog mode & labels: if (mCarData.car_type.equals("RT")) { dialogTitle = R.string.lb_lock_mode_twizy; dialogButton = mCarData.car_locked ? (mCarData.car_valetmode ? R.string.lb_valet_mode_extend_twizy : R.string.lb_unlock_car_twizy) : R.string.lb_lock_car_twizy; isPinEntry = false; } else { dialogTitle = mCarData.car_locked ? R.string.lb_unlock_car : R.string.lb_lock_car; dialogButton = dialogTitle; isPinEntry = true; } // show dialog: Ui.showPinDialog(getActivity(), dialogTitle, dialogButton, isPinEntry, new Ui.OnChangeListener<String>() { @Override public void onAction(String pData) { String cmd; int resId; if (mCarData.car_locked) { resId = dialogButton; cmd = "22," + pData; } else { resId = dialogButton; cmd = "20," + pData; } sendCommand(resId, cmd, CarFragment.this); } }); break; case R.id.btn_valet_mode: // get dialog mode & labels: if (mCarData.car_type.equals("RT")) { dialogTitle = R.string.lb_valet_mode_twizy; dialogButton = mCarData.car_valetmode ? (mCarData.car_locked ? R.string.lb_unvalet_unlock_twizy : R.string.lb_valet_mode_off_twizy) : R.string.lb_valet_mode_on_twizy; isPinEntry = false; } else { dialogTitle = R.string.lb_valet_mode; dialogButton = mCarData.car_valetmode ? R.string.lb_valet_mode_off : R.string.lb_valet_mode_on; isPinEntry = true; } // show dialog: Ui.showPinDialog(getActivity(), dialogTitle, dialogButton, isPinEntry, new Ui.OnChangeListener<String>() { @Override public void onAction(String pData) { String cmd; int resId; if (mCarData.car_valetmode) { resId = dialogButton; cmd = "23," + pData; } else { resId = dialogButton; cmd = "21," + pData; } sendCommand(resId, cmd, CarFragment.this); } }); break; default: v.performLongClick(); } } private static final int MI_WAKEUP = Menu.FIRST; private static final int MI_HL_01 = Menu.FIRST + 1; private static final int MI_HL_02 = Menu.FIRST + 2; private static final int MI_HL_03 = Menu.FIRST + 3; private static final int MI_HL_DEFAULT = Menu.FIRST + 4; @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); switch (v.getId()) { case R.id.btn_wakeup: if (mCarData.car_type.equals("RT")) break; // no wakeup support for Twizy menu.setHeaderTitle(R.string.lb_wakeup_car); menu.add(0, MI_WAKEUP, 0, R.string.Wakeup); menu.add(R.string.Cancel); break; case R.id.tabCarImageHomelink: case R.id.txt_homelink: if (mCarData.car_type.equals("RT")) { // Renault Twizy: use Homelink for profile switching: menu.setHeaderTitle(R.string.textPROFILE); menu.add(0, MI_HL_DEFAULT, 0, R.string.Default); } else { menu.setHeaderTitle(R.string.textHOMELINK); } menu.add(0, MI_HL_01, 0, "1"); menu.add(0, MI_HL_02, 0, "2"); menu.add(0, MI_HL_03, 0, "3"); menu.add(R.string.Cancel); break; } } @Override public boolean onContextItemSelected(android.view.MenuItem item) { switch (item.getItemId()) { case MI_WAKEUP: sendCommand(R.string.msg_wakeup_car, "18", this); return true; case MI_HL_01: sendCommand(R.string.msg_issuing_homelink, "24,0", this); return true; case MI_HL_02: sendCommand(R.string.msg_issuing_homelink, "24,1", this); return true; case MI_HL_03: sendCommand(R.string.msg_issuing_homelink, "24,2", this); return true; case MI_HL_DEFAULT: sendCommand(R.string.msg_issuing_homelink, "24", this); return true; default: return false; } } @Override public void onResultCommand(String[] result) { if (result.length <= 1) return; int command = Integer.parseInt(result[0]); int resCode = Integer.parseInt(result[1]); String cmdMessage = getSentCommandMessage(result[0]); switch (resCode) { case 0: // ok Toast.makeText(getActivity(), cmdMessage + " => " + getString(R.string.msg_ok), Toast.LENGTH_SHORT).show(); break; case 1: // failed Toast.makeText(getActivity(), cmdMessage + " => " + getString(R.string.err_failed, result[2]), Toast.LENGTH_SHORT).show(); break; case 2: // unsupported Toast.makeText(getActivity(), cmdMessage + " => " + getString(R.string.err_unsupported_operation), Toast.LENGTH_SHORT).show(); break; case 3: // unimplemented Toast.makeText(getActivity(), cmdMessage + " => " + getString(R.string.err_unimplemented_operation), Toast.LENGTH_SHORT).show(); break; } cancelCommand(); } // This updates the part of the view with times shown. // It is called by a periodic timer so it gets updated every few seconds. public void updateLastUpdatedView(CarData pCarData) { if ((pCarData == null) || (pCarData.car_lastupdated == null)) return; // First the last updated section... TextView tv = (TextView)findViewById(R.id.txt_last_updated); long now = System.currentTimeMillis(); long seconds = (now - pCarData.car_lastupdated.getTime()) / 1000; long minutes = (seconds)/60; long hours = minutes/60; long days = minutes/(60*24); Log.d(TAG, "Last updated: " + seconds + " secs ago"); if (pCarData.car_lastupdated == null) { tv.setText(""); tv.setTextColor(0xFFFFFFFF); } else if (minutes == 0) { tv.setText(getText(R.string.live)); tv.setTextColor(0xFFFFFFFF); } else if (minutes == 1) { tv.setText(getText(R.string.min1)); tv.setTextColor(0xFFFFFFFF); } else if (days > 1) { tv.setText(String.format(getText(R.string.ndays).toString(),days)); tv.setTextColor(0xFFFF0000); } else if (hours > 1) { tv.setText(String.format(getText(R.string.nhours).toString(),hours)); tv.setTextColor(0xFFFF0000); } else if (minutes > 60) { tv.setText(String.format(getText(R.string.nmins).toString(),minutes)); tv.setTextColor(0xFFFF0000); } else { tv.setText(String.format(getText(R.string.nmins).toString(),minutes)); tv.setTextColor(0xFFFFFFFF); } // Then the parking timer... // LinearLayout parkinglayoutv = (LinearLayout)findViewById(R.id.tabCarLayoutParking); tv = (TextView)findViewById(R.id.txt_parked_time); if ((!pCarData.car_started) && (pCarData.car_parked_time != null)) { // Car is parked // parkinglayoutv.setVisibility(View.VISIBLE); tv.setVisibility(View.VISIBLE); seconds = (now - pCarData.car_parked_time.getTime()) / 1000; minutes = (seconds)/60; hours = minutes/60; days = minutes/(60*24); if (minutes == 0) tv.setText(getText(R.string.justnow)); else if (minutes == 1) tv.setText("1 min"); else if (days > 1) tv.setText(String.format(getText(R.string.ndays).toString(),days)); else if (hours > 1) tv.setText(String.format(getText(R.string.nhours).toString(),hours)); else if (minutes > 60) tv.setText(String.format(getText(R.string.nmins).toString(),minutes)); else tv.setText(String.format(getText(R.string.nmins).toString(),minutes)); } else { // parkinglayoutv.setVisibility(View.INVISIBLE); tv.setVisibility(View.INVISIBLE); } // The signal strength indicator ImageView iv = (ImageView)findViewById(R.id.img_signal_rssi); iv.setImageResource(Ui.getDrawableIdentifier(getActivity(), "signal_strength_" + pCarData.car_gsm_bars)); } // This updates the main informational part of the view. // It is called when the server gets new data. public void updateCarBodyView(CarData pCarData) { if ((pCarData == null) || (pCarData.car_lastupdated == null)) return; // Now, the car background image ImageView iv = (ImageView)findViewById(R.id.tabCarImageCarOutline); iv.setImageResource(Ui.getDrawableIdentifier(getActivity(), "ol_"+pCarData.sel_vehicle_image)); // "Ambient" box: TextView label = (TextView) findViewById(R.id.tabCarTextAmbientLabel); TextView tv = (TextView) findViewById(R.id.tabCarTextAmbient); if (mCarData.car_type.equals("RT")) { // Renault Twizy: display 12V state label.setText(R.string.text12VBATT); tv.setText(String.format("%.1fV", mCarData.car_12vline_voltage)); if (mCarData.car_12vline_ref <= 1.5) { // charging / calmdown tv.setTextColor(0xFFA9A9FF); } else { Double diff = mCarData.car_12vline_ref - mCarData.car_12vline_voltage; if (diff >= 1.6) tv.setTextColor(0xFFFF0000); else if (diff >= 1.0) tv.setTextColor(0xFFFF6600); else tv.setTextColor(0xFFFFFFFF); } } else { // Standard car: display ambient temperature label.setText(R.string.textAMBIENT); if (pCarData.stale_ambient_temp == DataStale.NoValue) { tv.setText(""); tv.setTextColor(0xFF808080); } else if ((pCarData.stale_ambient_temp == DataStale.Stale) || (!pCarData.car_coolingpump_on)) { tv.setText(pCarData.car_temp_ambient); tv.setTextColor(0xFF808080); } else { tv.setText(pCarData.car_temp_ambient); tv.setTextColor(0xFFFFFFFF); } } // TPMS // String tirePressureDisplayFormat = "%s\n%s"; TextView fltv = (TextView) findViewById(R.id.textFLWheel); TextView fltvv = (TextView) findViewById(R.id.textFLWheelVal); TextView frtv = (TextView) findViewById(R.id.textFRWheel); TextView frtvv = (TextView) findViewById(R.id.textFRWheelVal); TextView rltv = (TextView) findViewById(R.id.textRLWheel); TextView rltvv = (TextView) findViewById(R.id.textRLWheelVal); TextView rrtv = (TextView) findViewById(R.id.textRRWheel); TextView rrtvv = (TextView) findViewById(R.id.textRRWheelVal); iv = (ImageView)findViewById(R.id.tabCarImageCarTPMSBoxes); if (pCarData.stale_tpms == DataStale.NoValue) { iv.setVisibility(View.INVISIBLE); fltv.setText(null); frtv.setText(null); rltv.setText(null); rrtv.setText(null); fltvv.setText(null); frtvv.setText(null); rltvv.setText(null); rrtvv.setText(null); } else { iv.setVisibility(View.VISIBLE); fltv.setText(pCarData.car_tpms_fl_p); frtv.setText(pCarData.car_tpms_fr_p); rltv.setText(pCarData.car_tpms_rl_p); rrtv.setText(pCarData.car_tpms_rr_p); fltvv.setText(pCarData.car_tpms_fl_t); frtvv.setText(pCarData.car_tpms_fr_t); rltvv.setText(pCarData.car_tpms_rl_t); rrtvv.setText(pCarData.car_tpms_rr_t); if (pCarData.stale_tpms == DataStale.Stale) { fltv.setTextColor(0xFF808080); frtv.setTextColor(0xFF808080); rltv.setTextColor(0xFF808080); rrtv.setTextColor(0xFF808080); fltvv.setTextColor(0xFF808080); frtvv.setTextColor(0xFF808080); rltvv.setTextColor(0xFF808080); rrtvv.setTextColor(0xFF808080); } else { fltv.setTextColor(0xFFFFFFFF); frtv.setTextColor(0xFFFFFFFF); rltv.setTextColor(0xFFFFFFFF); rrtv.setTextColor(0xFFFFFFFF); fltvv.setTextColor(0xFFFFFFFF); frtvv.setTextColor(0xFFFFFFFF); rltvv.setTextColor(0xFFFFFFFF); rrtvv.setTextColor(0xFFFFFFFF); } } // Temperatures TextView pemtv = (TextView) findViewById(R.id.tabCarTextPEM); TextView motortv = (TextView) findViewById(R.id.tabCarTextMotor); TextView batterytv = (TextView) findViewById(R.id.tabCarTextBattery); if (pCarData.stale_car_temps == DataStale.NoValue) { pemtv.setText(""); motortv.setText(""); batterytv.setText(""); } else { pemtv.setText(pCarData.car_temp_pem); motortv.setText(pCarData.car_temp_motor); batterytv.setText(pCarData.car_temp_battery); if ((pCarData.stale_car_temps == DataStale.Stale)||(!pCarData.car_coolingpump_on)) { pemtv.setTextColor(0xFF808080); motortv.setTextColor(0xFF808080); batterytv.setTextColor(0xFF808080); } else { pemtv.setTextColor(0xFFFFFFFF); motortv.setTextColor(0xFFFFFFFF); batterytv.setTextColor(0xFFFFFFFF); } } // Odometer tv = (TextView) findViewById(R.id.tabCarTextOdometer); tv.setText(pCarData.car_odometer); // Speed tv = (TextView) findViewById(R.id.tabCarTextSpeed); if (!pCarData.car_started) tv.setText(""); else tv.setText(pCarData.car_speed); // Car Hood iv = (ImageView) findViewById(R.id.tabCarImageCarHoodOpen); iv.setVisibility(pCarData.car_bonnet_open ? View.VISIBLE : View.INVISIBLE); // Left Door iv = (ImageView) findViewById(R.id.tabCarImageCarLeftDoorOpen); iv.setVisibility(pCarData.car_frontleftdoor_open ? View.VISIBLE : View.INVISIBLE); // Right Door iv = (ImageView) findViewById(R.id.tabCarImageCarRightDoorOpen); iv.setVisibility(pCarData.car_frontrightdoor_open ? View.VISIBLE : View.INVISIBLE); // Trunk iv = (ImageView) findViewById(R.id.tabCarImageCarTrunkOpen); iv.setVisibility(pCarData.car_trunk_open ? View.VISIBLE : View.INVISIBLE); // Headlights iv = (ImageView) findViewById(R.id.tabCarImageCarHeadlightsON); iv.setVisibility(pCarData.car_headlights_on ? View.VISIBLE : View.INVISIBLE); // Car locked iv = (ImageView) findViewById(R.id.tabCarImageCarLocked); iv.setImageResource(pCarData.car_locked ? R.drawable.carlock : R.drawable.carunlock); // Valet mode iv = (ImageView) findViewById(R.id.tabCarImageCarValetMode); iv.setImageResource(pCarData.car_valetmode ? R.drawable.carvaleton : R.drawable.carvaletoff); // Charge Port iv = (ImageView) findViewById(R.id.tabCarImageCarChargePortOpen); if (!pCarData.car_chargeport_open) { iv.setVisibility(View.INVISIBLE); } else { iv.setVisibility(View.VISIBLE); if (pCarData.car_charge_substate_i_raw == 0x07) { // We need to connect the power cable iv.setImageResource(R.drawable.roadster_outline_cu); } else if ((pCarData.car_charge_state_i_raw == 0x0d)||(pCarData.car_charge_state_i_raw == 0x0e)||(pCarData.car_charge_state_i_raw == 0x101)) { // Preparing to charge, timer wait, or fake 'starting' state iv.setImageResource(R.drawable.roadster_outline_ce); } else if ((pCarData.car_charge_state_i_raw == 0x01)|| (pCarData.car_charge_state_i_raw == 0x02)|| (pCarData.car_charge_state_i_raw == 0x0f)|| (pCarData.car_charging)) { // Charging iv.setImageResource(R.drawable.roadster_outline_cp); } else if (pCarData.car_charge_state_i_raw == 0x04) { // Charging done iv.setImageResource(R.drawable.roadster_outline_cd); } else if ((pCarData.car_charge_state_i_raw >= 0x15)&&(pCarData.car_charge_state_i_raw <= 0x19)) { // Stopped iv.setImageResource(R.drawable.roadster_outline_cs); } else { // Fake 0x115 'stopping' state, or something else not understood iv.setImageResource(R.drawable.roadster_outline_cp); } } } }