Skip to content

Commit

Permalink
Add a tab in Enabler to view received CAN messages.
Browse files Browse the repository at this point in the history
Half of #152, need to add a detail view.
  • Loading branch information
peplin committed Aug 17, 2014
1 parent dd25944 commit d7a4b2b
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 4 deletions.
29 changes: 29 additions & 0 deletions enabler/res/layout/can_message_list_fragment.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<!-- The frame layout is here since we will be showing either
the empty view or the list view. -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" >
<!-- Here is the list. Since we are using a ListActivity, we
have to call it "@android:id/list" so ListActivity will
find it -->
<ListView android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false"/>

<!-- Here is the view to show if the list is empty -->
<TextView android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="No CAN messages received."/>

</FrameLayout>

</LinearLayout>
32 changes: 32 additions & 0 deletions enabler/res/layout/can_message_list_item.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:minHeight="?android:attr/listPreferredItemHeightSmall">

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/can_message_bus"
android:layout_width="24dp"
android:layout_height="wrap_content"
/>

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/can_message_id"
android:layout_width="48dp"
android:layout_height="wrap_content"
android:paddingLeft="6dp"
/>

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/can_message_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="6dp"
/>

</LinearLayout>
84 changes: 84 additions & 0 deletions enabler/src/com/openxc/enabler/CanMessageAdapter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.openxc.enabler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.openxc.messages.CanMessage;

public class CanMessageAdapter extends BaseAdapter {
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();

private Map<Integer, CanMessage> mMessages;
private List<CanMessage> mValues;
private Context mContext;

public CanMessageAdapter(Context context) {
mContext = context;
mMessages = new LinkedHashMap<>();
}

public void add(CanMessage message) {
ThreadPreconditions.checkOnMainThread();
mMessages.put(message.getId(), message);
mValues = new ArrayList<>(mMessages.values());
Collections.sort(mValues);
notifyDataSetChanged();
}

@Override
public int getCount() {
return mMessages.size();
}

@Override
public CanMessage getItem(int position) {
return mValues.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = LayoutInflater.from(mContext)
.inflate(R.layout.can_message_list_item, parent, false);
}

CanMessage message = getItem(position);

TextView busView = (TextView) convertView.findViewById(R.id.can_message_bus);
busView.setText("" + message.getBus());

TextView idView = (TextView) convertView.findViewById(R.id.can_message_id);
idView.setText("0x" + Integer.toHexString(message.getId()));

TextView dataView = (TextView) convertView.findViewById(R.id.can_message_data);
dataView.setText("0x" + bytesToHex(message.getData()));

return convertView;
}

public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}
98 changes: 98 additions & 0 deletions enabler/src/com/openxc/enabler/CanMessageViewFragment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.openxc.enabler;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;

import com.openxc.VehicleManager;
import com.openxc.messages.CanMessage;
import com.openxc.messages.KeyMatcher;
import com.openxc.messages.VehicleMessage;

public class CanMessageViewFragment extends ListFragment {
private static String TAG = "CanMessageView";

private VehicleManager mVehicleManager;
private CanMessageAdapter mAdapter;

private VehicleMessage.Listener mListener = new VehicleMessage.Listener() {
@Override
public void receive(final VehicleMessage message) {
if(message instanceof CanMessage) {
getActivity().runOnUiThread(new Runnable() {
public void run() {
mAdapter.add(message.asCanMessage());
}
});
}
}
};

private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
Log.i(TAG, "Bound to VehicleManager");
mVehicleManager = ((VehicleManager.VehicleBinder)service
).getService();

// TODO would be nice to be able to register to receive a specific
// type, sorta like we do with Measurement -
// addListener(CanMessage.class, listener), for example
mVehicleManager.addListener(KeyMatcher.getWildcardMatcher(),
mListener);
}

public void onServiceDisconnected(ComponentName className) {
Log.w(TAG, "VehicleService disconnected unexpectedly");
mVehicleManager = null;
}
};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new CanMessageAdapter(getActivity());
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View v = inflater.inflate(R.layout.can_message_list_fragment,
container, false);
return v;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setListAdapter(mAdapter);
}

@Override
public void onResume() {
super.onResume();
getActivity().bindService(
new Intent(getActivity(), VehicleManager.class),
mConnection, Context.BIND_AUTO_CREATE);
}

@Override
public void onPause() {
super.onPause();
if(mVehicleManager != null) {
Log.i(TAG, "Unbinding from vehicle service");
getActivity().unbindService(mConnection);
mVehicleManager = null;
}
}
}
7 changes: 4 additions & 3 deletions enabler/src/com/openxc/enabler/OpenXcEnablerActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
public class OpenXcEnablerActivity extends FragmentActivity {
private static String TAG = "OpenXcEnablerActivity";

static final int NUM_TABS = 2;
private EnablerFragmentAdapter mAdapter;
private ViewPager mPager;

Expand Down Expand Up @@ -87,15 +86,15 @@ public boolean onCreateOptionsMenu(Menu menu) {
}

public static class EnablerFragmentAdapter extends FragmentPagerAdapter {
private static final String[] mTitles = { "Status", "Dashboard" };
private static final String[] mTitles = { "Status", "Dashboard", "CAN" };

public EnablerFragmentAdapter(FragmentManager fm) {
super(fm);
}

@Override
public int getCount() {
return NUM_TABS;
return mTitles.length;
}

@Override
Expand All @@ -109,6 +108,8 @@ public Fragment getItem(int position) {
return new StatusFragment();
} else if(position == 1) {
return new VehicleDashboardFragment();
} else if(position == 2) {
return new CanMessageViewFragment();
}
return new StatusFragment();
}
Expand Down
14 changes: 14 additions & 0 deletions enabler/src/com/openxc/enabler/ThreadPreconditions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.openxc.enabler;

import android.os.Looper;

public class ThreadPreconditions {
public static void checkOnMainThread() {
if (BuildConfig.DEBUG) {
if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
throw new IllegalStateException("This method should be called from the Main Thread");
}
}
}
}

19 changes: 18 additions & 1 deletion openxc/src/com/openxc/messages/CanMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;

public class CanMessage extends KeyedMessage {
public class CanMessage extends KeyedMessage implements Comparable<CanMessage> {
public static final String ID_KEY = "id";
public static final String BUS_KEY = "bus";
public static final String DATA_KEY = "data";
Expand Down Expand Up @@ -64,6 +64,23 @@ public static boolean containsRequiredFields(Set<String> fields) {
return fields.containsAll(sRequiredFields);
}

@Override
public int compareTo(CanMessage other) {
if(getBus() < other.getBus()) {
return -1;
} else if(getBus() > other.getBus()) {
return 1;
} else {
if(getId() < other.getId()) {
return -1;
} else if(getId() > other.getId()) {
return 1;
}
}
return 0;
}


@Override
public boolean equals(Object obj) {
if(!super.equals(obj) || !(obj instanceof CanMessage)) {
Expand Down

0 comments on commit d7a4b2b

Please sign in to comment.