package com.openvehicles.OVMS.ui.settings; import android.content.Context; import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.openvehicles.OVMS.R; import com.openvehicles.OVMS.api.ApiService; import com.openvehicles.OVMS.api.OnResultCommandListener; import com.openvehicles.OVMS.entities.CarData; import com.openvehicles.OVMS.ui.BaseFragment; import com.openvehicles.OVMS.ui.utils.Ui; import com.openvehicles.OVMS.utils.CarsStorage; public class FeaturesFragment extends BaseFragment implements OnResultCommandListener, OnItemClickListener { private FeaturesAdapter mAdapter; private ListView mListView; private int mEditPosition; private CarData mCarData; private ApiService mService; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // get data of car to edit: mEditPosition = getArguments().getInt("position", -1); if (mEditPosition >= 0) { mCarData = CarsStorage.get().getStoredCars().get(mEditPosition); } mListView = new ListView(container.getContext()); mListView.setOnItemClickListener(this); createProgressOverlay(inflater, container, false); return mListView; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); SherlockFragmentActivity activity = getSherlockActivity(); activity.setTitle(R.string.Features); } @Override public void onServiceAvailable(ApiService pService) { mService = pService; } @Override public void update(CarData pCarData) { requestData(); } private void requestData() { // only start request once: if (mAdapter != null) return; // create storage adapter: mAdapter = new FeaturesAdapter(); mListView.setAdapter(mAdapter); // send request: showProgressOverlay(); mService.sendCommand("1", this); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Context context = parent.getContext(); final int fn = position; Ui.showPinDialog(context, mAdapter.getTitleRow(context, position), Long.toString(id), R.string.Set, false, new Ui.OnChangeListener<String>() { @Override public void onAction(String pData) { int val = TextUtils.isEmpty(pData) ? 0 : Integer.parseInt(pData); sendCommand(String.format("2,%d,%d", fn, val), FeaturesFragment.this); mAdapter.setFeature(fn, val); } }); } @Override public void onResultCommand(String[] result) { if (result.length <= 1) { return; } int command = Integer.parseInt(result[0]); int resCode = Integer.parseInt(result[1]); if (command == 2) { cancelCommand(); switch (resCode) { case 0: Toast.makeText(getActivity(), getString(R.string.msg_ok), Toast.LENGTH_SHORT).show(); break; case 1: // failed Toast.makeText(getActivity(), getString(R.string.err_failed, result[2]), Toast.LENGTH_SHORT).show(); break; case 2: // unsupported Toast.makeText(getActivity(), getString(R.string.err_unsupported_operation), Toast.LENGTH_SHORT).show(); break; case 3: // unimplemented Toast.makeText(getActivity(), getString(R.string.err_unimplemented_operation), Toast.LENGTH_SHORT).show(); break; } return; } if (command != 1) return; // Not for us switch (resCode) { case 0: if (result.length > 4) { int fn = Integer.parseInt(result[2]); int fm = Integer.parseInt(result[3]); int fv = Integer.parseInt(result[4]); stepProgressOverlay(fn + 1, fm); if (fn < FeaturesAdapter.FEATURES_MAX) { mAdapter.setFeature(fn, fv); } if (fn == (fm - 1)) { cancelCommand(); } } break; case 1: // failed Toast.makeText(getActivity(), getString(R.string.err_failed, result[2]), Toast.LENGTH_SHORT).show(); cancelCommand(); break; case 2: // unsupported Toast.makeText(getActivity(), getString(R.string.err_unsupported_operation), Toast.LENGTH_SHORT).show(); cancelCommand(); break; case 3: // unimplemented Toast.makeText(getActivity(), getString(R.string.err_unimplemented_operation), Toast.LENGTH_SHORT).show(); cancelCommand(); } } private class FeaturesAdapter extends BaseAdapter { public static final int FEATURES_MAX = 16; // Standard features: private static final int FEATURE_SPEEDO = 0x00; // Speedometer feature private static final int FEATURE_STREAM = 0x08; // Location streaming feature private static final int FEATURE_MINSOC = 0x09; // Minimum SOC feature private static final int FEATURE_CARBITS = 0x0E; // Various ON/OFF features (bitmap) private static final int FEATURE_CANWRITE = 0x0F; // CAN bus can be written to // Renault Twizy: private static final int FEATURE_KICKDOWN_THRESHOLD = 0x01; // Kickdown threshold (pedal change) private static final int FEATURE_KICKDOWN_COMPZERO = 0x02; // Kickdown pedal compensation zero point private static final int FEATURE_SUFFSOC = 0x0A; // Charge alert: sufficient SOC private static final int FEATURE_SUFFRANGE = 0x0B; // Charge alert: sufficient range private static final int FEATURE_MAXRANGE = 0x0C; // Max ideal range (100% SOC) // The FEATURE_CARBITS feature is a set of ON/OFF bits to control different // miscelaneous aspects of the system. The following bits are defined: //private static final int FEATURE_CB_2008 = 0x01; // Set to 1 to mark the car as 2008/2009 //private static final int FEATURE_CB_SAD_SMS = 0x02; // Set to 1 to suppress "Access Denied" SMS //private static final int FEATURE_CB_SOUT_SMS = 0x04; // Set to 1 to suppress all outbound SMS private LayoutInflater mInflater; private final int[] mFeature = new int[FEATURES_MAX]; @Override public int getCount() { return FEATURES_MAX; } @Override public Object getItem(int position) { return mFeature[position]; } @Override public long getItemId(int position) { return mFeature[position]; } public void setFeature(int key, int val) { if (key > (FEATURES_MAX-1)) return; mFeature[key] = val; notifyDataSetChanged(); } public String getTitleRow(Context context, int position) { // Renault Twizy: if (mCarData.car_type.equals("RT")) { switch (position) { case FEATURE_KICKDOWN_THRESHOLD: return context.getString(R.string.lb_ft_rt_kickdown_threshold, position); case FEATURE_KICKDOWN_COMPZERO: return context.getString(R.string.lb_ft_rt_kickdown_compzero, position); case FEATURE_SUFFSOC: return context.getString(R.string.lb_ft_rt_suffsoc, position); case FEATURE_SUFFRANGE: return context.getString(R.string.lb_ft_rt_suffrange, position); case FEATURE_MAXRANGE: return context.getString(R.string.lb_ft_rt_maxrange, position); case FEATURE_SPEEDO: return String.format("#%d:", position); default: // fall through to standard } } // Standard: switch (position) { // Standard features: case FEATURE_SPEEDO: return context.getString(R.string.lb_ft_digital_speedo, position); case FEATURE_STREAM: return context.getString(R.string.lb_ft_gps_stream, position); case FEATURE_MINSOC: return context.getString(R.string.lb_ft_minimum_soc, position); case FEATURE_CARBITS: return context.getString(R.string.lb_ft_car_bits, position); case FEATURE_CANWRITE: return context.getString(R.string.lb_ft_can_write, position); default: return String.format("#%d:", position); } } @Override public View getView(int position, View convertView, ViewGroup parent) { Context context = parent.getContext(); if (convertView == null) { if (mInflater == null) { mInflater = LayoutInflater.from(context); } convertView = mInflater.inflate(R.layout.item_keyvalue, null); } TextView tv = (TextView) convertView.findViewById(android.R.id.text1); tv.setText(getTitleRow(context, position)); tv = (TextView) convertView.findViewById(android.R.id.text2); tv.setText(Integer.toString(mFeature[position])); return convertView; } } }