WebHID API演示Demo教程:设备列表,设备连接,数据读写

1. 简介

WebHID API允许网页应用直接与HID(人机接口设备)进行通信。本教程将演示如何创建一个基础的WebHID应用,实现以下功能:

  • 显示和获取HID设备列表
  • 连接/断开HID设备
  • 读取设备数据
  • 向设备发送数据

在这里插入图片描述

2. 兼容性和前提条件

2.1 浏览器支持

  • 主要支持Chrome浏览器
  • 需要在安全上下文中运行(HTTPS或localhost)

2.2 权限要求

  • 需要用户明确授权才能访问HID设备
  • 某些操作系统可能需要额外的权限设置

3. 项目结构

项目包含两个主要文件:

├── index.html    // 页面结构和样式
└── hid-demo.js   // WebHID功能实现

在这里插入图片描述

4. 实现步骤

4.1 创建基础HTML结构

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>HID Device Communication</title>
  <style>
    #output {
      width: 100%;
      height: 200px;
      margin: 10px 0;
      padding: 5px;
      border: 1px solid #ccc;
      overflow-y: auto;
    }
    /* ... 其他样式 ... */
  </style>
</head>
<body>
  <h1>WebHID API 演示</h1>
  
  <button id="connectButton">连接新HID设备</button>
  
  <h2>已连接设备列表:</h2>
  <ul id="deviceList"></ul>
  
  <div class="input-group">
    <input type="text" id="sendData" placeholder="输入要发送的数据(用逗号分隔的数字)">
    <button id="sendButton">发送数据</button>
  </div>
  
  <h2>输出日志:</h2>
  <pre id="output"></pre>

  <script src="hid-demo.js"></script>
</body>
</html>

4.2 实现WebHID核心功能

4.2.1 初始化和获取设备列表
let currentDevice = null;

document.addEventListener('DOMContentLoaded', () => {
  // 获取已授权的设备
  navigator.hid.getDevices()
    .then(devices => {
      updateDeviceList(devices);
    })
    .catch(error => {
      console.error('Error getting devices:', error);
    });
});
4.2.2 连接新设备
document.getElementById('connectButton').addEventListener('click', async () => {
  try {
    const devices = await navigator.hid.requestDevice({
      filters: [] // 空过滤器显示所有设备
    });
    
    if (devices.length > 0) {
      updateDeviceList(devices);
    }
  } catch (error) {
    console.error('Error connecting to device:', error);
  }
});
4.2.3 设备连接/断开处理
async function toggleConnect(device) {
  try {
    if (device.opened) {
      await device.close();
      currentDevice = null;
      appendToOutput(`设备已断开: ${device.productName}`);
    } else {
      await device.open();
      currentDevice = device;
      appendToOutput(`设备已连接: ${device.productName}`);
      
      // 监听设备输入报告
      device.addEventListener('inputreport', event => {
        const {data, reportId} = event;
        const value = new Uint8Array(data.buffer);
        appendToOutput(`收到数据 (报告ID ${reportId}): ${Array.from(value)}`);
      });
    }
    
    // 刷新设备列表显示
    const devices = await navigator.hid.getDevices();
    updateDeviceList(devices);
  } catch (error) {
    console.error('Error toggling device connection:', error);
    appendToOutput(`操作失败: ${error.message}`);
  }
}
4.2.4 数据发送功能
document.getElementById('sendButton').addEventListener('click', async () => {
  if (!currentDevice || !currentDevice.opened) {
    alert('请先连接设备!');
    return;
  }

  const data = document.getElementById('sendData').value;
  try {
    const dataArray = new Uint8Array(data.split(',').map(x => parseInt(x.trim())));
    await currentDevice.sendReport(0, dataArray);
    appendToOutput('已发送数据: ' + data);
  } catch (error) {
    console.error('Error sending data:', error);
    appendToOutput('发送数据失败: ' + error.message);
  }
});

5. 使用说明

5.1 连接设备

  1. 点击"连接新HID设备"按钮
  2. 在弹出的系统对话框中选择要连接的设备
  3. 设备将显示在已连接设备列表中

5.2 数据收发

  1. 连接设备后,设备发送的数据会自动显示在输出日志中
  2. 在输入框中输入要发送的数据(格式:逗号分隔的数字,如 1,2,3,4
  3. 点击"发送数据"按钮发送数据

6. 注意事项

  1. 数据格式

    • 发送数据需要使用逗号分隔的数字格式
    • 不同设备可能需要特定的数据格式,请参考设备文档
  2. 报告ID

    • 当前示例使用默认报告ID (0)
    • 某些设备可能需要特定的报告ID,需要相应修改代码
  3. 错误处理

    • 所有操作都包含错误处理
    • 错误信息会显示在输出日志中
  4. 安全性

    • 必须在HTTPS或localhost环境下运行
    • 需要用户明确授权才能访问设备

7. 调试建议

  1. 使用Chrome开发者工具监控控制台输出
  2. 检查设备连接状态和错误信息
  3. 验证数据格式是否符合设备要求
  4. 确保设备驱动正确安装

8. 扩展建议

  1. 添加设备过滤器,只显示特定类型的设备
  2. 实现自定义数据格式转换
  3. 添加数据可视化功能
  4. 实现设备自动重连机制

9. 参考资源

  • WebHID API MDN文档
  • HID接口规范
  • HIDDevice接口

完整Demo

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HID Device Communication</title>
  <style>
    #output {
      width: 100%;
      height: 200px;
      margin: 10px 0;
      padding: 5px;
      border: 1px solid #ccc;
      overflow-y: auto;
    }
    #deviceList {
      margin: 10px 0;
    }
    #deviceList li {
      margin: 5px 0;
      padding: 5px;
      border: 1px solid #eee;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    .input-group {
      margin: 10px 0;
    }
  </style>
</head>
<body>
  <h1>WebHID API 演示</h1>
  
  <button id="connectButton">连接新HID设备</button>
  
  <h2>已连接设备列表:</h2>
  <ul id="deviceList"></ul>
  
  <div class="input-group">
    <input type="text" id="sendData" placeholder="输入要发送的数据(用逗号分隔的数字)">
    <button id="sendButton">发送数据</button>
  </div>
  
  <h2>输出日志:</h2>
  <pre id="output"></pre>

  <script src="hid-demo.js"></script>
</body>
</html>

let currentDevice = null;

document.addEventListener('DOMContentLoaded', () => {
  // 获取已授权的设备
  navigator.hid.getDevices()
    .then(devices => {
      updateDeviceList(devices);
    })
    .catch(error => {
      console.error('Error getting devices:', error);
    });

  // 连接新设备按钮事件
  document.getElementById('connectButton').addEventListener('click', async () => {
    try {
      // 请求连接HID设备
      const devices = await navigator.hid.requestDevice({
        filters: [] // 空过滤器显示所有设备
      });
      
      if (devices.length > 0) {
        updateDeviceList(devices);
      }
    } catch (error) {
      console.error('Error connecting to device:', error);
    }
  });

  // 发送数据按钮事件
  document.getElementById('sendButton').addEventListener('click', async () => {
    if (!currentDevice || !currentDevice.opened) {
      alert('请先连接设备!');
      return;
    }

    const data = document.getElementById('sendData').value;
    console.log('发送数据: ' + data);
    try {
      // 将输入数据转换为Uint8Array
      const dataArray = new Uint8Array(data.split(',').map(x => parseInt(x.trim())));
      await currentDevice.sendReport(5, dataArray);
      appendToOutput('已发送数据: ' + data);
      console.log('已发送数据: ' + data);
    } catch (error) {
      console.error('Error sending data:', error);
      appendToOutput('发送数据失败: ' + error.message);
    }
  });
});

// 更新设备列表显示
function updateDeviceList(devices) {
  const deviceList = document.getElementById('deviceList');
  deviceList.innerHTML = '';
  
  devices.forEach(device => {
    const li = document.createElement('li');
    li.textContent = `${device.productName} (VID: ${device.vendorId}, PID: ${device.productId})`;
    
    const connectBtn = document.createElement('button');
    connectBtn.textContent = device.opened ? '断开' : '连接';
    connectBtn.addEventListener('click', () => toggleConnect(device));
    
    li.appendChild(connectBtn);
    deviceList.appendChild(li);
  });
}

// 连接/断开设备
async function toggleConnect(device) {
  try {
    if (device.opened) {
      await device.close();
      currentDevice = null;
      appendToOutput(`设备已断开: ${device.productName}`);
    } else {
      await device.open();
      currentDevice = device;
      appendToOutput(`设备已连接: ${device.productName}`);
      
      // 监听设备输入报告
      device.addEventListener('inputreport', event => {
        const {data, reportId} = event;
        const value = new Uint8Array(data.buffer);
        appendToOutput(`收到数据 (报告ID ${reportId}): ${Array.from(value)}`);
      });
    }
    
    // 刷新设备列表显示
    const devices = await navigator.hid.getDevices();
    updateDeviceList(devices);
  } catch (error) {
    console.error('Error toggling device connection:', error);
    appendToOutput(`操作失败: ${error.message}`);
  }
}

// 添加输出信息
function appendToOutput(message) {
  const output = document.getElementById('output');
  output.textContent += message + '\n';
  output.scrollTop = output.scrollHeight;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/929995.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

R语言机器学习论文(六):总结

文章目录 介绍参考文献介绍 本文采用R语言对来自进行数据描述、数据预处理、特征筛选和模型构建。 最后我们获得了一个能有效区分乳腺组织的随机森林预测模型,它的性能非常好,这意味着它可能拥有非常好的临床价值。 在本文中,我们利用R语言对来自美国加州大学欧文分校的B…

三、代码管理-Git

文章目录 前言一、Git1. Git 与 SVN 区别2. Git 入门3. 客户端工具4. 主流Git仓库 二、GitLab1. 介绍2. 适合的场景 二、GitHub1. 介绍2. 适合的场景 三、Gitee1. 介绍2. 适合的场景 四、GitCode1. 介绍2. 适合的场景 五、总结 前言 代码托管‌ Git作为目前最为流行的版本控制…

基于51单片机的智能公交车报站系统GPS定位语音播报智能安全检测人数统计

功能描述 1.LCD12864可显示当前年月日&#xff0c;星期&#xff0c;时间&#xff0c; 当前站名&#xff0c;经纬度&#xff0c;是否连接GPS&#xff0c;自动/手动模式&#xff0c; 2.自带GPS定位&#xff0c;可实时显示经纬度&#xff1b; 3.通过DS1302时钟芯片&#xff0c;获…

【数据库系列】Spring Data Neo4j Cypher 查询使用进阶指南

在 Neo4j 中,Cypher 查询语句并不像 MySQL 的 mapper XML 那样直接支持拆分和组织。然而,你可以使用一些策略来管理和重用 Cypher 查询,使其更易于维护和组织。以下是几种方法: 1. 使用 Spring Data Neo4j 的 Repository 接口 通过定义多个查询方法,可以将复杂查询分解为…

UIlicious - 自动化端到端测试

在现代软件开发中&#xff0c;测试自动化已然成为产品交付质量的基石。而端到端测试&#xff08;E2E&#xff09;&#xff0c;作为验证整个应用流畅运行的关键&#xff0c;常常是测试工作中最具挑战性的一环。这时&#xff0c;一款简单高效的自动化测试工具——UIlicious&#…

OpenHarmony-3.HDF框架(2)

OpenHarmony HDF 平台驱动 1.平台驱动概述 系统平台驱动框架是系统驱动框架的重要组成部分&#xff0c;它基于HDF驱动框架、操作系统适配层(OSAL, operating system abstraction layer)以及驱动配置管理机制&#xff0c;为各类平台设备驱动的实现提供标准模型。 系统平台驱动(…

前端 el-table-column 里加上el-form-item 上面有黑色悬浮

如图所示 解决方法&#xff0c;查看你的 el-table-column 是否设置了 show-overflow-tooltip 属性&#xff0c;如果是去掉即可

使用MATLAB从Excel文件读取数据并绘制堆叠柱状图

在数据可视化中&#xff0c;堆叠柱状图是展示多个变量相对比例的非常有效的方法。它通过将每个数据系列堆叠在一起&#xff0c;帮助我们理解不同数据类别在总量中所占的份额。在这篇博客中&#xff0c;我们将学习如何使用MATLAB从Excel文件导入数据&#xff0c;并使用渐变色来绘…

书生浦语第四期--入门岛-第三关

文章目录 1.破冰任务&#xff1a;自我介绍1.1 create new fork1.2 git clone 自己的分支1.3 创建关联分支1.4提交修改 任务2 &#xff1a;创建自己的仓库 1.破冰任务&#xff1a;自我介绍 1.1 create new fork 创建一个自己的分支&#xff0c;在自己分支上进行修改&#xff0…

【AI系统】轻量级CNN模型新进展

CNN 模型小型化&#xff08;下&#xff09; 在本文会接着介绍 CNN 模型的小型化&#xff0c;除了第二篇文章提到的三个模型外&#xff0c;在本章节会继续介绍 ESPNet 系列&#xff0c;FBNet 系列&#xff0c;EfficientNet 系列和 GhostNet 系列。 ESPNet 系列 ESPNetV1 ESP…

鸿蒙HarmonyOS状态管理组件吐槽

吐槽一下鸿蒙系统设计的状态管理组件 一. 定义和作用 状态管理组件其本质作用用来修饰状态变量&#xff0c;这样可以观察到变量在组件内的改变&#xff0c;还可以在不同组件层级间传递&#xff0c;其设计初衷挺好。在声明式UI编程框架中&#xff0c;UI是程序状态的运行结果&a…

unicloud微信小程序云端一体项目DEMO

最近应客户需求&#xff0c;做了一个产品展示的云开发小程序&#xff0c;从了解云开发到应用到实际项目的产品demo&#xff0c;希望大家能从中获取到对自己有用的东西。 说下心得体会吧&#xff0c;一般小项目用这种云开发确实会减少很多开发成本&#xff0c;人力成本&#xf…

爬虫专栏第一篇:深入探索爬虫世界:基础原理、类型特点与规范要点全解析

本专栏会对爬虫进行从0开始的讲解&#xff0c;每一步都十分的细致&#xff0c;如果你感兴趣希望多多点赞收藏关注支持 简介&#xff1a;文章对爬虫展开多方面剖析。起始于爬虫的基本概念&#xff0c;即依特定规则在网络抓取信息的程序或脚本&#xff0c;在搜索引擎信息提取上作…

【Spring】Spring 整合 JUnit

JUnit 是 Java 中一个广泛使用的单元测试框架。它使用简单的注解和断言方法&#xff0c;使开发者能够轻松编写和运行测试用例。在使用 IDEA 创建的 Spring 项目中&#xff0c;JUnit 框架可以方便地进行整合。下面是整合的具体步骤。这里使用一个之前整合 MyBatis 时的 Spring 项…

MATLAB数学建模之画图汇总

MATLAB是一种强大的数学软件&#xff0c;广泛应用于工程计算、控制设计、信号处理等领域。在数学建模中&#xff0c;MATLAB的绘图功能可以帮助我们直观地展示数据和模型结果。 1. 二维数据曲线图 1.1 绘制二维曲线的基本函数 plot函数用于绘制二维平面上的线性坐标曲线图&am…

Linux 远程连接服务

远程连接服务器简介 什么是远程连接服务器 远程连接服务器通过文字或图形接口方式来远程登录系统&#xff0c;让你在远程终端前登录linux主机以取得可操 作主机接口&#xff08;shell&#xff09;&#xff0c;而登录后的操作感觉就像是坐在系统前面一样。 远程连接服务器的功…

Prometheus 采集postgresql监控数据

postgres_exporter 前言 postgres_exporter 是一个用于监控 PostgreSQL 数据库的 Prometheus 导出器。它允许你收集有关 PostgreSQL 数据库性能和状态的指标,并将这些指标暴露给 Prometheus,从而可以在 Grafana 等可视化工具中进行展示和告警。 postgres_exporter download…

windows文件下换行, linux上不换行 解决CR换行符替换为LF notepad++

html文件是用回车换行的&#xff0c;在windows电脑上&#xff0c;显示正常。 文件上传到linux服务器后&#xff0c;文件不换行了。只有一行。而且相关js插件也没法正常运行。 用notepad查看&#xff0c;显示尾部换行符&#xff0c;是CR&#xff0c;这就是原因。CR是不被识别的。…

CTF show 文件上传篇(web151-170,看这一篇就够啦)

目录 一.前言 二.文件上传&#xff08;web151-170&#xff09; 1.web151&#xff08;前端绕过&#xff09; 1.1 编写一句话木马 1.2.寻找突破点 1.3.webshell连接 1.4 利用条件 2.web152&#xff08;MIME头绕过&#xff09; 2.1 知识点 2.2 绕过限制 2.3 利用条件 …

UE5 像素流进行内网https证书创建

确定证书需求 内网 HTTPS 通信通常需要以下内容&#xff1a; 自签名证书&#xff08;适用于内网环境&#xff0c;不需要通过公开的证书颁发机构 CA&#xff09; 或者通过内部的企业 CA 签发的证书&#xff08;更安全&#xff09;。 生成自签名证书 使用工具&#xff08;如 Ope…