【问题标题】:Control relay over USB from AndroidAndroid 通过 USB 控制继电器
【发布时间】:2015-10-27 09:40:28
【问题描述】:

我有这个 USB Relay,我想通过 Android 手机进行控制。

(有一个类似的帖子here,但它解释了如何从 Linux shell 执行此操作。通过查看该代码,我认为我能够解决它 - 显然不是。)

lsusb 中的设备列表:

总线 002 设备 011:ID 16c0:05df VOTI 设备描述符: b长度 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0(在接口级别定义) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 8 idVendor 0x16c0 VOTI idProduct 0x05df bcd设备 1.00 iManufacturer 1 iProduct 2 iSerial 0 bNumConfigurations 1 配置描述符: b长度 9 bDescriptorType 2 wTotalLength 34 bNumInterfaces 1 b配置值 1 配置 0 bm属性 0x80 (总线供电) 最大功率 20mA 接口描述符: b长度 9 bDescriptorType 4 b接口编号 0 b备用设置 0 bNumEndpoints 1 bInterfaceClass 3 人机接口设备 bInterfaceSubClass 0 无子类 bInterfaceProtocol 0 无 接口 0 HID 设备描述符: b长度 9 bDescriptorType 33 bcdHID 1.01 bCountryCode 0 不支持 bNumDescriptors 1 bDescriptorType 34 报告 wDescriptorLength 22 报告描述符: ** 不可用 ** 端点描述符: b长度 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bm属性 3 传输类型中断 同步类型 无 使用类型数据 wMaxPacketSize 0x0008 1x 8 字节 b 间隔 20

我觉得奇怪的是终点被定义为“EP IN”。在我看来,它应该是“EP OUT”,因为方向应该是“host->device”。

无论如何,我使用 Android USB 管理器创建连接,然后为基于中断的端点初始化 USbRequest。 Android 权限和所有处理,以便设备成功连接。

用于发送数据的片段。它按照 Android 指南在单独的线程中运行:

UsbRequest request = new UsbRequest();
synchronized (mUsbLock) {
    if (mUsbConnection != null && mUsbEndPointIn != null) {
        if (!request.initialize(mUsbConnection, mUsbEndPointIn)) {
            Log.e(TAG, "Unable to initialize UsbRequest. Thread exits");
            return;
        } else {
            if (DEBUG) {
                Log.d(TAG, String.format("Usb request is initialized"));
            }
        }
    } else {
        Log.e(TAG, "Usb communication is not up and running. The worker thread should never be started.");
        return;
    }
}
mRunning.set(true);
while (mRunning.get()) {
    if (DEBUG) {
        Log.d(TAG, String.format("Waiting for data to be sent to end point"));
    }
    WorkPackage wp = mWorkQueue.take();
    // send the package.
    byte[] data = wp.getData();
    if (!request.queue(ByteBuffer.wrap(data), data.length)) {
        Log.e(TAG, "Unable to queue to send data on UsbRequest.");
        continue;
    } else {
        if (DEBUG) {
            Log.d(TAG, String.format("Usb request is queued on end point, ep=%s", printUsbEndpoint(mUsbEndPointIn)));
        }
    }
}

似乎一切都很好,没有发生错误,请求在端点排队,但什么也没有发生。我没有收到任何关于请求已处理的消息。

由于供应商不会发布开/关命令,我尝试了基于 Linux 帖子(上图)的变体。似乎没有一个工作。供应商仅发布 Windows 二进制库。

发送8字节包(根据最大包):

public static byte[] SET_RELAY_ON = {(byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
public static byte[] SET_RELAY_OFF = {(byte) 0xfd, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};

帮助表示赞赏。

【问题讨论】:

    标签: android usb


    【解决方案1】:

    所以,我想出了如何做到这一点。我会在这里写下解决方案,以防其他人遇到类似问题。

    我不得不窥探 USB 流量以了解实际发送的内容。原来定义的中断端点根本没有被使用。因此,与设备的通信不是基于中断,而是使用端点 0 上的控制传输类型。

    因此,使用 Android USB API 可以转换为:

    打开设备(设备->主机方向):

    int r = mUsbConnection.controlTransfer(0xa1, 0x01, 0x0300, 0x00, buffer, buffer.length, 500);
    

    打开继电器'1'(主机->设备方向)。

    byte[] buffer = {(byte) 0xff, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
    int r = mUsbConnection.controlTransfer(0x21, 0x09, 0x0300, 0x00, buffer, buffer.length, 500);
    

    注意,缓冲区中的第二个参数 (0x01) 是继电器编号(如果板上有 >1 个继电器)。我只有一个。

    关闭继电器'1'(主机->设备方向):

    byte[] buffer = {(byte) 0xfd, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
    int r = mUsbConnection.controlTransfer(0x21, 0x09, 0x0300, 0x00, buffer, buffer.length, 500);
    

    【讨论】:

    • 好节目!这需要有根的 Android 设备吗?
    • @Protectorone nope
    • @MagnusJohansson 您好 Magnus,我也在尝试这样做,您是否在任何地方分享了您的完整代码? :-)
    猜你喜欢
    • 2011-03-15
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 2014-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多