CanBus的数据帧的获取和初始解析

关于怎么打开串口,请参考 点击打开链接

1,开线程监听串口数据

package com.android.server;

import android.util.Log;
import java.io.File;

public class ProcessCanBusThread extends Thread{

   	private static final String TAG = "ProcessCanBusThread";
	private boolean flag = false;
	ICanBusDataCallBack mICanBusDataCallBack; //数据上报应用层的interface
	public ProcessCanBusThread(ICanBusDataCallBack mICanBusDataCallBack){
		this.mICanBusDataCallBack = mICanBusDataCallBack;
		this.start();
	}
	
	@Override
	public void run() {
		super.run();
		while (!isInterrupted()) {

			byte[] result = SystemParse.readCanBus();//数据过多,可以适当延时
			if(result!=null){
				if(null != mICanBusDataCallBack){
					mICanBusDataCallBack.processReceiveBusData(result ,result.length);//数据上报
				}
			}
		}
	}
}

2,跟踪readCanBus方法

	private static byte[] g_mcucom_bakdata = new byte[256];
	private static int g_cancom_baklen;
	private static byte[] g_cancom_bakdata = new byte[256];
	public static boolean flag;
	public static byte[] readCanBus(){
		int size = 0;
		byte[] buffer = new byte[1024];
		if(mCanInputStream!=null){
			try {
				size = mCanInputStream.read(buffer);
				if (size > 0) {
					if(g_cancom_baklen>0){
						size += g_cancom_baklen; 
						byte[] tempbuffer = new byte[size];
						for(int i=0;i<g_cancom_baklen;i++){
							tempbuffer[i] = g_cancom_bakdata[i];
						}
						for(int i=g_cancom_baklen;i<size;i++){
							tempbuffer[i] = buffer[i-g_cancom_baklen];
						}
						g_cancom_baklen = 0;
						return onCanDataReceived(tempbuffer, size);
					}else{
						return onCanDataReceived(buffer, size);
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}else{
			Log.e(TAG, "=====the canbus port is error====");
		}
		return null;
	}

3,跟踪onCanDataReceived方法

	// 2E       21        02       Data0    Data1     DataN  CheckSum
	//HeadCode  DataType  Length   Data0    Data1     DataN  CheckSum
	//Length   =Data0+    Data1+   DataN
	//ChechSum =(DataType+ Length+  Data0+   Data1+    DataN)^0xFF
	private static byte[] onCanDataReceived(final byte[] buffer ,final int size){
		byte[] datacheck = new byte[4];
		int starti;
		for(int i=0;i<size;i++){
			datacheck[0] = buffer[i];
			starti = i;		
			if(datacheck[0]==(byte)0x2e){
				i++;
				if(i>=size){
					for(int k=starti;k<size;k++){
						g_cancom_bakdata[k-starti] = buffer[k];
						g_cancom_baklen++;
					}
					return null;
				}
				if(i>=size-1){
					for(int k=starti;k<size;k++){
						g_cancom_bakdata[k-starti] = buffer[k];
						g_cancom_baklen++;
					}
					return null;
				}
				datacheck[1] = buffer[i+1];//len
					
				if(datacheck[1]>0){
					if((starti+datacheck[1]+4)<=size){
						//i++;
						byte[] tempdata = new byte[datacheck[1]+2];
						for(int j=0;j<(datacheck[1]+2);j++){
							tempdata[j] = buffer[i++];
							datacheck[2] += (byte) tempdata[j];								
						}
						datacheck[2] ^= 0xFF;
						if(datacheck[2]==buffer[i]){
							g_cancom_baklen = 0;
							response((int)0xff);//给canbus回0xff表示该帧数据正确
							return tempdata;
						}else{
						}
					}else{
						for(int k=starti;k<size;k++){
							g_cancom_bakdata[k-starti] = buffer[k];
							g_cancom_baklen++;
						}
					}
				}
			}
		}
		return null;
	}
public static void response(int hex){
		if (mOutputStream != null){
			try{
				mCanOutputStream.write(hex);
			} catch (IOException e) {
				Log.e(TAG, "SendCanCommand IOException occurred: " + e);
			}
		}
	}

到这里,基本上canbus发过来的每帧数据都能接收到,现在就是上报到应用层,通过ICanBusDataCallBack

Android系统中services中的数据怎么通过jni或者外部提供的接口(Manger class)上报的,这里就不过多解释了。

下面看应用层收到数据后的处理(譬如空调的显示,车门信息,车辆状态等)

请先下载该apk 点击打开链接(关于数据解析apk)

找到CanBusService.java类

package com.md.zcanbus.stack;

import android.app.Service;
import android.commcu.CanComDataPtr;
import android.commcu.McuSerialManager;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;

import com.md.CUtils;
import com.md.CanBusImpl;
import com.md.source.SystemFreq;
import com.md.source.SystemModel;
import com.md.source.SystemTime;
import com.md.source.SystemVox;
/**
 * modify 20170503 for CanBus
 * @author md
 */
public class CanBusService extends Service {

	private static McuSerialManager gMCM = McuSerialManager.getInstance();
	
	private static RemoteCallbackList<ICanBusService> callbacks;
	private ICanBusService cb;
	public static CanBusService reference = new CanBusService();
	public CanBusService() {}
	
	public static CanBusService getReference(){
		synchronized (reference) {
			if(reference==null){
				reference = new CanBusService();
			}
		}
		return reference;
	}
	
	public void registerCallback(ICanBusService canllImpl) {
		callbacks = new RemoteCallbackList<ICanBusService>();
		if(callbacks!=null) callbacks.register(canllImpl);
		Log.d("md", "registerCallback   :"+ callbacks);
	}

	public void unregisterCallback() {
		if(callbacks!=null && cb!=null) callbacks.unregister(cb);
	}
	
	@Override
	public void onDestroy() {
		unregisterCallback();
		super.onDestroy();
	}
	
	public void requestCanData(){
		CUtils.init();
		gMCM.sendCanBusMultiData(0x90, (byte)0x24);
		gMCM.sendCanBusMultiData(0x90, (byte)0x41);
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
//		CanBusService busService = CanBusService.getReference();
		registerCallback(CanBusImpl.getInstance().getCallBack(getApplicationContext()));
		onActionListener();
		requestCanData();
		return super.onStartCommand(intent, flags, startId);
	}
	
    public void onActionListener(){
    	if(null==gMCM){
    		gMCM = McuSerialManager.getInstance();
    	}
    	gMCM.setCanbusDataListener(onActionListener,1);
    }
    
    McuSerialManager.CanbusDataListener onActionListener = new McuSerialManager.CanbusDataListener() {

		@Override
		public int onAction(int arg0, byte[] arg1) {
			Message message = new Message();
			message.what = arg0;
			message.obj = arg1;
			handler.sendMessage(message);
			return 0;
		}
	};
	
	Handler handler = new Handler(){

		@Override
		public void handleMessage(Message msg) {
			int ptr = msg.what;
			byte[] result = (byte[]) msg.obj;
			if(callbacks!=null) {
				int i = callbacks.beginBroadcast();
				while(i > 0){
					i--;
					cb = callbacks.getBroadcastItem(i);
				}
			}
			try {
				switch (ptr) {
				case CanComDataPtr.CANBUS_PTR_0X00:
					Config.bs00 = bytes(result, Config.bs00);
					if(cb!=null) cb.notify_CANBUS_PTR_0X00();
					break;
				case CanComDataPtr.CANBUS_PTR_0X01:
					Config.bs01 = bytes(result, Config.bs01);
					if(cb!=null) cb.notify_CANBUS_PTR_0X01();
					break;
				case CanComDataPtr.CANBUS_PTR_0X02:
					Config.bs02 = bytes(result, Config.bs02);
					if(cb!=null) cb.notify_CANBUS_PTR_0X02();
					break;
				        .
				        .代码过多省略
				        .
					break;
				default:
					break;
				}
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			if(callbacks!=null) callbacks.finishBroadcast();
		}
	};
	
	private void startDelay(){
		Log.d("md", "==startDelay==");
		Thread thread =new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				requestCanData();
			}
		});
		try {
			thread.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public byte[] bytes(byte[] bs,byte[] result){
		result = new byte[bs.length-2];
		for (int i = 2; i < bs.length; i++) {
			result[i-2] = bs[i];
		}
		return result;
	}
}

其中重要的是handler,handler中message包含canbus给过来的每一帧数据,ptr是该帧的data[0],自己在services那层处理好

McuSerialManager.CanbusDataListener的public int onAction(int ptr, byte[] others)

到此,数据就获取完全

详情如下

里面的详细方法说明就略过了。

 

资料下载点击打开链接

备注: 以上的串口通信可以直接写在apk中,不用在services层处理,也可以根据自己的实际情况,如果services层用到CanBus中的数据,最好写在services层,方便全局控制。

更详细的demo,后续有需要的话,再传上来。

希望能帮到各位。。。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值