【驱动教程系列】如何在Ruff开发板上使用USB存储设备


(jerry) #1

如何在Ruff开发板上使用USB存储设备

准备工作

  • 确认开发板上的 RuffOS 大于等于1.5版本, 可以通过 rap system info 命令来查看
  • 确认 PC 端的 SDK 版本大于等于1.5版本
  • 一个 U 盘,确保其是 FAT32 格式

使用步骤

准备项目

在一个新的文件夹下执行如下命令,创建一个新的工程

rap init

此命令会下载开发板板载设备的驱动。如果看到如下信息

Downloading package "ruff-v1-sys-usb"...

恭喜你,你已经成功一半了。有了这个驱动,你就可以直接在应用代码中使用 $('#usb') 操作 USB 的相关功能。

注意 如果你希望在旧应用上使用 USB,请在 package.json 中,将 ruff-mbd-v1 的版本升级到4.1.2,再执行 rap install

安装 USB 存储模块

安装存储驱动,执行如下命令

rap install ruff-v1-usb-storage-manager --save

因为 USB 设备的差异性,这里采用模块安装的方式,而不是通常的 rap device add

编写应用

下面是一段示例代码:

'use strict';

var fs = require('fs');
var path = require('path');
var StorageManager = require('ruff-v1-usb-storage-manager');
var storageManager = new StorageManager();

$.ready(function (error) {
    if (error) {
        console.log(error);
        return;
    }

    $('#usb').install(storageManager);
    storageManager.on('mount', function (storage) {
       // storage is mounted

      // save data in the storage
      var filePath = path.join(storage.partitions[0].path, 'test.txt');
      fs.writeFileSync(filePath, 'hello world\n');

      // eject the storage from the system before unplugging the storage
      storage.eject();

      // check whether the storage is successfully ejected
      console.log(storage.ejected);
    });

    storageManager.on('unmount', function (storage) {
      // storage is unmounted
    });
});

在这段代码里

  • $('#usb') 表示的是系统的 USB 管理器
  • $('#usb').install(storageManager),可以将存储驱动与 USB 关联在一起。如果你的应用中用到多种 USB 设备,可以在这里安装多个不同的 USB Manager。
  • storageManager 可以处理设备的插拔事件,USB 存储设备插入时,会产生 mount 事件,拔下时,会产生 unmount 事件。
storageManager('mount', function(storage) {
});
	
storageManager('unmount', function(storage) {
});
  • 下面的代码在 U 盘的第一个分区中创建一个test.txt文件,并且写入hello world
var filePath = path.join(storage.partitions[0].path, 'test.txt');
fs.writeFileSync(filePath, 'hello world\n');
  • 下面的代码是调用 storage 的eject()方法,将 storage 安全地从系统中移除,然后可以将 U 盘拔下。
storage.eject();
console.log(storage.ejected);

部署测试

执行如下命令,将应用部署在开发板上

rap deploy -s

好,插上 U 盘,开始你的测试吧!


【驱动教程系列】如何在Ruff开发板上使用USB摄像头
(ccpwufan) #2

Ruff只有一个USB口,能否使用USB HUB连接多个USB设备?


(jerry) #3

USB 是总线协议,理论上是可以使用 HUB 的。
我在测试的时候就使用了 HUB,因为板子上的 USB 距离供电的MicroUSB 口太近了,U 盘插不进去 :joy:


(ccpwufan) #4

Hi Jerry, 我用U盘搭配摄像头,拍出来的照片是损坏的打不开,偶尔能打开但是只有半幅照片,而且log里面发现mount事件发生好几次,为什么呢?

storageManager.on('mount', function (storage) {
   // storage is mounted
    //myStorage = storage;
  // save data in the storage
  // eject the storage from the system before unplugging the storage
  //storage.eject();    
    filePath = path.join(storage.partitions[0].path, 'test12.jpg');
    console.log(filePath);
  // check whether the storage is successfully ejected
  //console.log(storage.ejected);
    console.log("storage is mounted");
});

cameraManager.on('mount', function (camera) {
    var resolution = {
        width: 800,
        height: 600
    };
    console.log("camera is mounted");
    var picture = camera.capture(resolution);
    picture.on('data', function (data) {
        // ...
        
        //console.log(filePath);
        fs.writeFileSync(filePath, data);
        console.log("write jpg");
        //storage.eject();                    
    });    


});    

Log:

Nov 03 22:25:06: /mnt/sda1/test12.jpg
Nov 03 22:25:06: storage is mounted
Nov 03 22:25:09: camera is mounted
Nov 03 22:25:13: write jpg
Nov 03 22:25:13: write jpg
Nov 03 22:25:14: write jpg
write jpg
Nov 03 22:25:14: write jpg


(jerry) #5

log 中并没有表现出 mount 事件发生多次,data 事件触发了多次,这是因为 picture 的 data 事件并没有把整个图像传过来,而是以流的形式传输,所以每次 data 事件上报的数据只是图像的一部分。picture 还有 end 事件,表示图像数据传输完毕,data 事件不再触发。

你使用了 fs.writeFileSync,文件中的旧数据被覆盖了,所以保存得到的文件总是不完整的,应该的使用 fs.writeSync 这个方法。


正确的使用方法如下:
function savePicture(savePath, name){
    var pos = 0;
    var fd = fs.openSync(path.join(savePath, name), 'w');
    var picture = camera.capture(resolution);
    picture.on('data', function (data) {
        try {
            fs.writeSync(fd, data, 0, data.length, pos);
        } catch (error) {
            console.log(error);
        }
        pos += data.length;
    });
    picture.on('end', function () {
        console.log('save picture finish');
        fs.closeSync(fd);
    });
}

一个小建议,为了确保在拍照的时候,storage 已经 mount 成功,最好在 storageManager 的 `mount` 事件和 cameraManager 的 `mount` 事件都发生后,再调用 camera 的相关方法。

(ccpwufan) #6

谢谢Jerry:slight_smile: