1、项目简述
第二次玩硬件了,第一次是通过局域网控制门的开关,这次是通过ZB(大概就是这么叫,具体名字不清楚)控制灯的开关,感觉控制硬件也就是给硬件发个byte数组而已。
这里有个框架usb-serial-for-android 可以直接使用,但是里面并没有教你怎么写数据,我还是一个一个类里面找write相关方法,后来终于找到了是通过UsbSerialPort类下的write(final byte[] src, final int timeoutMillis)方法实现数据的发送的。
2、实现后的感想
这个demo感觉挺难测试的,而且一旦发现问题,很难找到问题所在。
测试难在于,电脑上的模拟器是没法测试的(反正我的模拟器是测试失败的),因为模拟器访问不到电脑的USB接口,在手机上也是很难测试,因为手机是没法给外部接口供电的,除非你有这样一根带供电功能的OTG线。
所以我们测试对象就是一些安卓设备,比如说Android电视之类的。
3、操作步骤
(1)当你在初始界面获得到串口信息时
(2)点击一个串口,可以进入到另一个Activity里去
(3)在这里你就可以通过UsbSerialPort的write进行写数据了。
说的是这么简单,但是实际上第一次接触的猿友应该是会感到很迷茫的。
4、主要代码
public void writeData(String data) {
if(mSerialPort == null) return;
try {
//这里需要对数据做一次处理,可能是因为接收方(台灯)那边需要对数据解析,不一定每个接收方都需要处理,PS:我在这里就踩了个坑了
byte[] bytes = StringToBytes.getFCSData(data.getBytes());
int result = mSerialPort.write(bytes, 1000);
} catch (IOException e) {
e.printStackTrace();
}
}
这个就是我写数据时的代码,通过UsbSerialPort进行写数据,但是我写之前,先对传进来的字符串进行处理,不处理的话,发送到灯上的数据是没有用的,发送成功了,灯也不会亮。在此,我可是踩到了个大坑的。
因为这个demo要集成到项目中去,所以我把代码整理了一下,只需要在初始化一下,然后调用WriteData方法,即可发送数据了(前提是你得访问到了串口),具体代码如下:
/**
* Created by Administrator on 2017-03-27.
* Author jiangxiaochang
*/
public class DeviceManager {
private static final int MESSAGE_REFRESH = 101;
private static final long REFRESH_TIMEOUT_MILLIS = 5000;
private List<UsbSerialPort> mPortList = new ArrayList<>();
private UsbManager mUsbManager;
private UsbSerialPort mSerialPort;
private SerialInputOutputManager mSerialIoManager;
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
public Context mContext;
public DeviceManager(Context context) {
mUsbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
mContext = context;
}
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_REFRESH:
refreshDeviceList();
mHandler.sendEmptyMessageDelayed(MESSAGE_REFRESH, REFRESH_TIMEOUT_MILLIS);
break;
default:
super.handleMessage(msg);
break;
}
}
};
public void resume() {
mHandler.sendEmptyMessage(MESSAGE_REFRESH);
}
public void pause() {
mHandler.removeMessages(MESSAGE_REFRESH);
}
private void refreshDeviceList() {
new AsyncTask<Void, Void, List<UsbSerialPort>>() {
@Override
protected List<UsbSerialPort> doInBackground(Void... params) {
SystemClock.sleep(1000);
final List<UsbSerialDriver> drivers =
UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager);
final List<UsbSerialPort> result = new ArrayList<UsbSerialPort>();
for (final UsbSerialDriver driver : drivers) {
final List<UsbSerialPort> ports = driver.getPorts();
result.addAll(ports);
}
return result;
}
@Override
protected void onPostExecute(List<UsbSerialPort> result) {
mPortList.clear();
mPortList.addAll(result);
if (!result.isEmpty()) {
mSerialPort = mPortList.get(0);
//获取到一次即可,随后删除消息
mHandler.removeMessages(MESSAGE_REFRESH);
initPort();
}
}
}.execute((Void) null);
}
private void initPort() {
UsbDeviceConnection connection = mUsbManager.openDevice(mSerialPort.getDriver().getDevice());
if (connection == null) {
return;
}
try {
mSerialPort.open(connection);
//默认参数
//sPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
//串口调试参数
mSerialPort.setParameters(38400, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
} catch (IOException e) {
try {
mSerialPort.close();
} catch (IOException e2) {
// Ignore.
}
mSerialPort = null;
return;
}
onDeviceStateChange();
}
public void writeData(String data) {
if(mSerialPort == null) return;
try {
byte[] bytes = StringToBytes.getFCSData(data.getBytes());
int result = mSerialPort.write(bytes, 1000);
Toast.makeText(mContext, data + ":" + result, Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
}
private void stopIoManager() {
if (mSerialIoManager != null) {
mSerialIoManager.stop();
mSerialIoManager = null;
}
}
private void startIoManager() {
if (mSerialPort != null) {
mSerialIoManager = new SerialInputOutputManager(mSerialPort, mListener);
mExecutor.submit(mSerialIoManager);
}
}
private void onDeviceStateChange() {
stopIoManager();
startIoManager();
}
private final SerialInputOutputManager.Listener mListener =
new SerialInputOutputManager.Listener() {
@Override
public void onRunError(Exception e) {
}
@Override
public void onNewData(final byte[] data) {
}
};
}
在我的Activity中是这样写的,就是这样了。
public class MainActivity extends Activity {
DeviceManager mManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mManager = new DeviceManager(this);
findViewById(R.id.LightOn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mManager.writeData("LightOn");
}
});
}
@Override
protected void onResume() {
super.onResume();
mManager.resume();
}
@Override
protected void onPause() {
super.onPause();
mManager.pause();
}
}
注:建议第一次接触的人,还是先去看看usb-serial-for-android 这个框架,能获取到串口设备后,再来看看我写的方法。
5、Demo下载
【点击下载】
没写注释,真是抱歉