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 {// 将输入数据转换为Uint8Arrayconst 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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中安证件OCR识别技术助力鸿蒙生态:智能化证件识别新体验

在数字化和智能化的浪潮中&#xff0c;伴随国产化战略的深入推进&#xff0c;国产操作系统和软件生态的建设逐渐走向成熟。鸿蒙操作系统&#xff08;HarmonyOS Next&#xff09;作为华为推出的重要操作系统&#xff0c;凭借其开放、灵活和高效的特点&#xff0c;正在加速在多个…

PDF与PDF/A的区别及如何使用Python实现它们之间的相互转换

目录 概述 PDF/A 是什么&#xff1f;与 PDF 有何不同&#xff1f; 用于实现 PDF 与 PDF/A 相互转换的 Python 库 Python 实现 PDF 转 PDF/A 将 PDF 转换为 PDF/A-1a 将 PDF 转换为 PDF/A-1b 将 PDF 转换为 PDF/A-2a 将 PDF 转换为 PDF/A-2b 将 PDF 转换为 PDF/A-3a 将…

面向对象(二)——类和对象(上)

1 类的定义 做了关于对象的很多介绍&#xff0c;终于进入代码编写阶段。 本节中重点介绍类和对象的基本定义&#xff0c;属性和方法的基本使用方式。 【示例】类的定义方式 // 每一个源文件必须有且只有一个public class&#xff0c;并且类名和文件名保持一致&#xff01; …

【HarmonyOS】鸿蒙应用地理位置获取,地理名称获取

【HarmonyOS】鸿蒙应用地理位置获取&#xff0c;地理名称获取 一、前言 首先要理解地理专有名词&#xff0c;当我们从系统获取地理位置&#xff0c;一般会拿到地理坐标&#xff0c;是一串数字&#xff0c;并不是地理位置名称。例如 116.2305&#xff0c;33.568。 这些数字坐…

关于数据库数据国际化方案

方案一&#xff1a;每个表设计一个翻译表 数据库国际化的应用场景用到的比较少&#xff0c;主要用于对数据库的具体数据进行翻译&#xff0c;在需要有大量数据翻译的场景下使用&#xff0c;举个例子来说&#xff0c;力扣题目的中英文切换。参考方案可见&#xff1a; https://b…

「Mac畅玩鸿蒙与硬件37」UI互动应用篇14 - 随机颜色变化器

本篇将带你实现一个随机颜色变化器应用。用户点击“随机颜色”按钮后&#xff0c;界面背景会随机变化为淡色系颜色&#xff0c;同时显示当前的颜色代码&#xff0c;页面还会展示一只猫咪图片作为装饰&#xff0c;提升趣味性。 关键词 UI互动应用随机颜色生成状态管理用户交互…

跟着官方文档快速入门RAGAS

官网: Ragas Ragas&#xff08;Retrieval-Augmented Generation, RAG&#xff09;是一个基于简单手写提示的评估框架&#xff0c;通过这些提示全自动地衡量答案的准确性、 相关性和上下文相关性。这种评估方法不需要访问人工注释的数据集或参考答案&#xff0c;使得评估过程更…

掌握 Spring Boot 中的缓存:技术和最佳实践

缓存是一种用于将经常访问的数据临时存储在更快的存储层&#xff08;通常在内存中&#xff09;中的技术&#xff0c;以便可以更快地满足未来对该数据的请求&#xff0c;从而提高应用程序的性能和效率。在 Spring Boot 中&#xff0c;缓存是一种简单而强大的方法&#xff0c;可以…

我谈冈萨雷斯对频域滤波的误解——快速卷积与频域滤波之间的关系

在Rafael Gonzalez和Richard Woods所著的《数字图像处理》中&#xff0c;Gonzalez对频域滤波是有误解的&#xff0c;在频域设计滤波器不是非得图像和滤波器的尺寸相同&#xff0c;不是非得在频域通过乘积实现。相反&#xff0c;FIR滤波器设计都是构造空域脉冲响应。一般的原则是…

AI高中数学教学视频生成技术:利用通义千问、MathGPT、视频多模态大模型,语音大模型,将4个模型融合 ,生成高中数学教学视频,并给出实施方案。

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下AI高中数学教学视频生成技术&#xff1a;利用通义千问、MathGPT、视频多模态大模型&#xff0c;语音大模型&#xff0c;将4个模型融合 &#xff0c;生成高中数学教学视频&#xff0c;并给出实施方案。本文利用专家模…

Linux下,用ufw实现端口关闭、流量控制(二)

本文是 网安小白的端口关闭实践 的续篇。 海量报文&#xff0c;一手掌握&#xff0c;你值得拥有&#xff0c;让我们开始吧&#xff5e; ufw 与 iptables的关系 理论介绍&#xff1a; ufw&#xff08;Uncomplicated Firewall&#xff09;是一个基于iptables的前端工具&#xf…

MySQL之数据完整性

数据的完整性约束可以分为三类: 实体完整性、域完整性和引用完整性。 说来说去&#xff08;说主键&#xff0c;外键&#xff0c;以及⼀些约束&#xff09; 1、实体完整性 &#xff08;实体就是行&#xff09; 什么是关系型数据库&#xff1f; 一个表代表一类事务&#xff0…

echarts的双X轴,父级居中的相关配置

前言&#xff1a;折腾了一个星期&#xff0c;在最后一天中午&#xff0c;都快要放弃了&#xff0c;后来坚持下来&#xff0c;才有下面结果。 这个效果就相当是复合表头&#xff0c;第一行是子级&#xff0c;第二行是父级。 子级是奇数个时&#xff0c;父级label居中很简单&…

配置宝塔php curl 支持http/2 发送苹果apns消息推送

由于宝塔面板默认的php编译的curl未加入http2的支持&#xff0c;如果服务需要使用apns推送等需要http2.0的访问就会失败&#xff0c;所以重新编译php让其支持http2.0 编译方法&#xff1a; 一、安装nghttp2 git clone https://github.com/tatsuhiro-t/nghttp2.git cd nghttp…

记录一次网关异常

记一次网关异常 网关时不时就会出现下面的异常。关键是不知道什么时候就会报错&#xff0c;并且有时候就算什么都不操作&#xff0c;也会导致这个异常。 ERROR org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler - Unexpected error occurred in schedul…

动态艺术:用Python将文字融入GIF动画

文章内容&#xff1a; 在数字媒体的多样化发展中&#xff0c;GIF动画作为一种流行的表达形式&#xff0c;常被用于广告、社交媒体和娱乐。本文通过一个具体的Python编程示例&#xff0c;展示了如何将文字以动态形式融入到GIF动画中&#xff0c;创造出具有视觉冲击力的动态艺术…

@antv/x6 再vue中 ,自定义图形,画流程图、数据建模、er图等图形

X6 是基于 HTML 和 SVG 的图编辑引擎&#xff0c;提供低成本的定制能力和开箱即用的内置扩展&#xff0c;方便我们快速搭建 DAG 图、ER 图、流程图、血缘图等应用。 最终效果图 1.安装 npm install antv/x6 --save //x6主要包 npm install antv/x6-vue-shape //使用vue组…

2.4特征预处理(机器学习)

2.4特征预处理 2.4.1 什么是特征预处理 通过 一些转换函数将特征数据转换成更加适合算法模型的特征数据过程。 1 包含内容 数值型数据的无量纲化&#xff1a; 归一化 标准化 2 特征预处理API sklearn.preprocessing 为什么要进行归一化/标准化&#xff1f; 特征的单…

前端、后端、测试?如何选择

目录 一、前端开发 &#xff08;一&#xff09;职业概述 &#xff08;二&#xff09;需学习的技术 二、后端开发 &#xff08;一&#xff09;职业概述 &#xff08;二&#xff09;需学习的技术 三、测试 &#xff08;一&#xff09;职业概述 &#xff08;二&#xff0…

AI - 谈谈RAG中的查询分析(2)

AI - 谈谈RAG中的查询分析&#xff08;2&#xff09; 大家好&#xff0c;RAG中的查询分析是比较有趣的一个点&#xff0c;内容丰富&#xff0c;并不是一句话能聊的清楚的。今天接着上一篇&#xff0c;继续探讨RAG中的查询分析&#xff0c;并在功能层面和代码层面持续改进。 功…