1、项目简述

第二次玩硬件了,第一次是通过局域网控制门的开关,这次是通过ZB(大概就是这么叫,具体名字不清楚)控制灯的开关,感觉控制硬件也就是给硬件发个byte数组而已。

这里有个框架usb-serial-for-android 可以直接使用,但是里面并没有教你怎么写数据,我还是一个一个类里面找write相关方法,后来终于找到了是通过UsbSerialPort类下的write(final byte[] src, final int timeoutMillis)方法实现数据的发送的。

2、实现后的感想

这个demo感觉挺难测试的,而且一旦发现问题,很难找到问题所在。

测试难在于,电脑上的模拟器是没法测试的(反正我的模拟器是测试失败的),因为模拟器访问不到电脑的USB接口,在手机上也是很难测试,因为手机是没法给外部接口供电的,除非你有这样一根带供电功能的OTG线。

android usb列表命令 usb-serial-for-android_ide

所以我们测试对象就是一些安卓设备,比如说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下载

【点击下载】

没写注释,真是抱歉