【译】基于cordovarduino插件的安卓设备OTG串口通信

2,194 阅读5分钟

作者:xseignard 译者:Joe爷 来源:github.com/xseignard/c…

翻译的目的:查了很多资料,网上确实有一些关于串口的资料,但是cordovarduino插件涉及到设备的一些术语,查阅起来还是有点不太方便。于是简单简述下该插件的一些基本要点及注意事项(撸码不易,请笔芯点个赞)。

简单对比下Node SerialPort 与 cordovarduino的区别

  • Node SerialPort是一个很强大的串口通信库,主要运行于node环境,当我们npm install它的时候,我们可以看到里边有很多的依赖,例如fs,path。所以在选型的时候, Node SerialPort只适用于服务端,浏览器端,桌面应用程序等。关于Node SerialPort的更多了解,可以去其官方文档查阅。
  • 而cordovarduino则是基于Cordova/Phonegap运行的一个插件,通过手机OTG转串口跟设备进行串口通信,进而发送给设备指令和接收指令。

描述

这个Cordova/Phonegap插件允许使用USB(OTG)从你的Android设备到你的Arduino板或其他USB驱动的IO串行设备进行双向串行通信。 这意味着Arduino的一些项目可以使用手机上的可充电功能为其设备供电,并且可以双向通信。

安装

在cordova工程根目录, cordova plugin add cordovarduino

如何使用

首先这里已经确定你已经建好Cordova项目,并且已经用了上面的命令安装好了cordovarduino插件。 该插件的API大概步骤如下:

1、第一次操作,我们肯定是要跟系统请求使用串口的权限,请求的结果会弹出类似这样的一个提示框。贴上代码:serial.requestPermission(function success(), function error());

2、然后我们就可以愉快地打开串口了: serial.open(opts, function success(), function error());

opts是一个JSON对象,其属性有如下几个:

  let opts = {
   baudRate:9600//波特率默认9600
   dataBits: 8//数据位默认8位
   stopBits: 1//停止位默认1
   parity: 0//校验位默认0
   dtr:false//数据终端准备好,默认flase,有一些arduino板,该属性可能需要设置为true
   rts: false//请求发送RTS,默认flase,有一些arduino板,该属性可能需要设置为true
   sleepOnPause:true //休眠模式,默认true。如果设置为fasle的话,当app进入后台或者屏幕熄灭的时候,串口功能还是一直处于打开状态的;反之,串口则会关闭。
   }

3、串口处于开启状态后,就可以进行读写操作。

 serial.write(data, function success(), function error());
 serial.read(function success(buffer), function error());

data是要写入串口的字符串表示形式。buffer 则是读取回来的数据。

除了使用serial.write,我们还可以使用 serial.writeHex来发送16进制的数据。

4、当我们向串口发送数据的时候,我们也可以通过注册回调,来监听设备返回的数据,代码如下:

serial.registerReadCallback(
	function success(data){
		var view = new Uint8Array(data);
		console.log(view);
	},
	function error(){
		new Error("Failed to register read callback");
	});

view返回来的数据,这里是以类数组的形式来显示

5、最后可以手动关闭串口了。 serial.close(function success(), function error())

简单的例子

该例子先向系统请求操作权限,然后以9600波特率打开串口并写入字符串“1”,成功或者失败都有相应的回调:

var errorCallback = function(message) {
    alert('Error: ' + message);
};

serial.requestPermission(
	function(successMessage) {
    	serial.open(
        	{baudRate: 9600},
            function(successMessage) {
        		serial.write(
                	'1',
                    function(successMessage) {
                    	alert(successMessage);
                    },
                    errorCallback
        		);
        	},
        	errorCallback
    	);
    },
    errorCallback
);

一个完整的例子

1、index.html如下:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Hello World</title>
    </head>
    <body>
        <div class="app">
            <h1>Potentiometer value</h1>
            <p>Value <span id="pot">...</span></p>
            <p id="delta">...</p>
            <button id="on">On</button>
            <button id="off">Off</button>
        </div>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

2、index.js如下:

var app = {
    initialize: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        var potText = document.getElementById('pot');
        var delta = document.getElementById('delta');
        var on = document.getElementById('on');
        var off = document.getElementById('off');
        var open = false;
        var str = '';
        var lastRead = new Date();

        var errorCallback = function(message) {
            alert('Error: ' + message);
        };
        // 首先请求操作权限
        serial.requestPermission(
            // 获取操作权限成功后
            function(successMessage) {
                // 打开串口
                serial.open(
                    {baudRate: 9600},
                    // 串口已被打开
                    function(successMessage) {
                        open = true;
                        // 注册一个read回调
                        serial.registerReadCallback(
                            function success(data){
                                // 解码收到的信息 to do something
                                var view = new Uint8Array(data);
                            },
                            //read错误回调
                            errorCallback
                        );
                    },
                    // 打开串口失败的回调
                    errorCallback
                );
            },
            // 没有操作权限的回调
            errorCallback
        );

        on.onclick = function() {
            console.log('click');
            if (open) serial.write('1');
        };
        off.onclick = function() {
            if (open) serial.write('0');
        }
    }
};

app.initialize();

注意的点:

1、当上面的操作权限获取失败的话,加上你不知道你的设备具体是什么设备,反正就是对设备不了解。但是在确保该设备可以通过串口桌面应用程序跟你设备通信的情况下,我们能通过生产商编号vid和生产商内部的产品编号pid来取得相应的操作权限。

serial.requestPermission({vid: '1d50', pid: '607d'}, function success(), function error()); //16进制

或者

serial.requestPermission({vid: 7504, pid: 24701}, function success(), function error()); //整数

那么vid和pid怎么获得呢?

  • 如果在linux的话,通过使用“lsusb”,来查询vid和pid
  • 如果在windows环境下,我们可以通过点击 电脑属性 → 设备管理器 → 该设备所在的端口,然后双击它,弹出窗口,找到详细信息的一栏的设备实例路径,就可以知道设备的vid和pid了。截图如下:

2、此外,我们还可以在window环境下,查找到设备的驱动。目前该插件支持的驱动有:

  • CdcAcmSerialDriver
  • Ch34xSerialDriver
  • Cp21xxSerialDriver
  • FtdiSerialDriver
  • ProlificSerialDriver 该插件默认CdcAcmSerialDriver 为驱动程序,所以在不知道是什么设备的情况下,我们可以通过以下代码来这样操作
serial.requestPermission({
        vid: '1a86', //这是我们自己板的vid
        pid: '7523', //这是我们自己板的pid
        driver: 'Ch34xSerialDriver' //这是我们自己板的驱动
    },
    function success(),
    function error()
);

延伸阅读

cordova文档