当前位置: 首页 > news >正文

Qt与Hid设备通信

什么是HID?

HID(Human Interface Device)是‌直接与人交互的电子设备‌,通过标准化协议实现用户与计算机或其他设备的通信,典型代表包括键盘、鼠标、游戏手柄等。‌

为什么HID要与qt进行通信?

我这里的应用场景是数位板与我自己写的上位机进行通信,用户可以在上位机软件中手动设置数位板上按键代表的快捷键。

如何通信?

1. 引入 hidapi 库

hidapi库是一个第三方库需要下载。下载完编译之后把 hidapi.h,hidapi.dll,hidapi.lib放到项目根目录下。

hid设备初始化有以下几个步骤:

2. 初始化 hidapi

hid_init()

3. 枚举和选择设备

void enumerateDevices() {struct hid_device_info *devs = hid_enumerate(0x0, 0x0); // 参数为VID和PID,0x0表示匹配所有struct hid_device_info *cur_dev = devs;while (cur_dev) {printf("Device Found\n  type: %04hx %04hx\n  path: %s\n  serial_number: %ls",cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);printf("\n");printf("  Manufacturer: %ls\n", cur_dev->manufacturer_string);printf("  Product: %ls\n", cur_dev->product_string);printf("  Release: %hx\n", cur_dev->release_number);printf("  Interface Number: %d\n\n", cur_dev->interface_number);cur_dev = cur_dev->next;}hid_free_enumeration(devs);
}

4. 打开设备

hid_device *handle;
handle = hid_open(0x1234, 0x5678, NULL); // 替换为设备的VID和PID

5. 设置非阻塞模式(可选)

int res = hid_set_nonblocking(handle, 1); // 参数为1表示非阻塞模式
if (res < 0) {// 处理设置失败的情况
}

 6. 读取和写入数据

// 读取数据
unsigned char buf[256];
int res = hid_read(handle, buf, sizeof(buf));
if (res < 0) {// 处理读取错误
} else {// 处理读取到的数据
}// 写入数据
unsigned char data[] = {0x00, 0x01, 0x02}; // 示例数据
res = hid_write(handle, data, sizeof(data));
if (res < 0) {// 处理写入错误
}

 7. 关闭设备和释放资源

hid_close(handle);
hid_exit();

示例代码整合

void MainWindow::HidInit()
{// 1. 初始化HIDAPIif (hid_init() != 0) {qDebug() << "[错误] HIDAPI初始化失败";return;}else{qDebug() << "[正确] HIDAPI初始化成功";}// 2. 枚举设备qDebug() << "[调试] 开始枚举HID设备...";hid_device_info *devs = hid_enumerate(0x0, 0x0);if (!devs) {qDebug() << "[错误] 无法枚举HID设备,可能没有HID设备连接";hid_exit();return;}hid_device_info *cur_dev = devs;char* devicePath = nullptr;bool deviceFound = false;int deviceCount = 0; // 用于统计发现的HID设备数量qDebug() << "[调试] 开始遍历HID设备列表...";while (cur_dev) {deviceCount++;// 打印所有HID设备信息,用于调试qDebug().nospace() << "[调试] 设备 #" << deviceCount<< ": VID=0x" << QString::number(cur_dev->vendor_id, 16).toUpper()<< ", PID=0x" << QString::number(cur_dev->product_id, 16).toUpper();// << ", 路径=" << QString::fromWCharArray(cur_dev->path);if (cur_dev->vendor_id == TARGET_VID && cur_dev->product_id == TARGET_PID) {devicePath = _strdup(cur_dev->path);deviceFound = true;qDebug() << "\n[信息] 找到目标设备:";qDebug() << "路径:" << devicePath;qDebug() << "制造商:" << (cur_dev->manufacturer_string ? QString::fromWCharArray(cur_dev->manufacturer_string) : "N/A");qDebug() << "产品名:" << (cur_dev->product_string ? QString::fromWCharArray(cur_dev->product_string) : "N/A");qDebug() << "接口号:" << cur_dev->interface_number;break;}cur_dev = cur_dev->next;}qDebug() << "[调试] 遍历完成,共发现" << deviceCount << "个HID设备";hid_free_enumeration(devs);if (!deviceFound) {qDebug() << "[错误] 未找到目标设备 (VID: 0x" << QString::number(TARGET_VID, 16).toUpper()<< ", PID: 0x" << QString::number(TARGET_PID, 16).toUpper() << ")";hid_exit();return;}// 3. 打开设备qDebug() << "[调试] 尝试打开目标设备...";hid_device* handle = hid_open_path(devicePath);if (!handle) {qDebug() << "[错误] 无法打开设备:" << QString::fromWCharArray(hid_error(nullptr));free(devicePath);hid_exit();return;}// 3. 打开设备handle = hid_open_path(devicePath);if (!handle) {qDebug() << "[错误] 无法打开设备:" << QString::fromWCharArray(hid_error(nullptr));free(devicePath);hid_exit();return;}// 设置非阻塞模式hid_set_nonblocking(handle, 1);qDebug() << "\n[信息] 设备已成功打开";// 4. 尝试通信const int REPORT_SIZE = 65; // 64字节数据 + 1字节报告IDunsigned char buf[REPORT_SIZE] = {0};// 尝试不同报告ID (0x00-0xFF)for (int report_id = 0x00; report_id <= 0xFF; report_id++) {// 4.1 尝试特性报告buf[0] = report_id;buf[1] = 0x01; // 示例命令qDebug() << "\n[调试] 尝试报告ID: 0x" << QString::number(report_id, 16).toUpper();int res = hid_send_feature_report(handle, buf, REPORT_SIZE);if (res > 0) {qDebug() << "[成功] 特性报告发送成功 (ID: 0x"<< QString::number(report_id, 16).toUpper() << ")";break;} else if (report_id == 0xFF) {qDebug() << "[警告] 所有特性报告尝试失败";}// 4.2 尝试输出报告res = hid_write(handle, buf, REPORT_SIZE);if (res > 0) {qDebug() << "[成功] 输出报告发送成功 (ID: 0x"<< QString::number(report_id, 16).toUpper() << ")";break;} else if (report_id == 0xFF) {qDebug() << "[警告] 所有输出报告尝试失败";}}// 5. 读取响应 (5秒超时)qDebug() << "\n[信息] 等待设备响应...";int timeout_ms = 5000;QElapsedTimer timer;timer.start();while (timer.elapsed() < timeout_ms) {int res = hid_read(handle, buf, REPORT_SIZE);if (res > 0) {qDebug() << "[成功] 收到" << res << "字节数据:";// 打印接收到的数据 (十六进制格式)QString hexData;for (int i = 0; i < res; i++) {hexData += "0x" + QString::number(buf[i], 16).toUpper().rightJustified(2, '0') + " ";if ((i+1) % 8 == 0) hexData += "\n";}qDebug() << hexData;break;} else if (res == 0) {QThread::msleep(100); // 避免CPU占用过高} else {qDebug() << "[错误] 读取失败:" << QString::fromWCharArray(hid_error(handle));break;}}if (timer.elapsed() >= timeout_ms) {qDebug() << "[警告] 读取超时,未收到响应";}// 6. 清理资源hid_close(handle);free(devicePath);hid_exit();qDebug() << "\n[信息] HID通信结束";
}

 运行效果演示(我接入的是wacom数位板):

 全是0xFF为未激活状态(初始状态)。

总结操作流程

  1. 确认设备功能与协议:明确设备是输入型(主动上报)还是命令型(需指令触发)。
  2. 发送测试指令:若无文档,通过简单指令试探设备响应模式。
  3. 解析数据结构:根据响应数据的变化规律,逆向推导字节含义(如坐标、状态、校验等)。
  4. 编写业务逻辑:基于解析结果,实现数据处理或控制功能(如鼠标模拟、设备配置等)。

解析报告数据

如何解析

用以下结构来存储报告:

struct TabletData {quint8 reportId;        // 报告IDquint16 x;              // X坐标(0-最大值)quint16 y;              // Y坐标(0-最大值)quint16 pressure;       // 压力值(0-最大值)QList<int> buttons;     // 按下的按钮列表(按钮编号从1开始)
};

 创建一个TabletData 类型的函数:

该函数对报告进行解析,第0字节是报告ID,第1字节是按钮位置........

TabletData HidManager::parseTabletData(const QByteArray& data) {TabletData result;if (data.isEmpty()) return result;result.reportId = data[0];switch (result.reportId) {case 0x11: // 按钮报告(假设按钮在字节1-2)for (int byteIdx = 1; byteIdx < 3; byteIdx++) {if (byteIdx >= data.size()) break;unsigned char byte = data[byteIdx];for (int bitIdx = 0; bitIdx < 8; bitIdx++) {if ((byte & (1 << bitIdx)) != 0) { // 1表示按下result.buttons.append((byteIdx - 1) * 8 + bitIdx + 1);}}}break;case 0x10: // **关键修改**:坐标/压力报告ID改为0x10// 解析坐标和压力(假设坐标在字节1-4,压力在字节5-6)if (data.size() >= 5) {// 小端序解析:低字节在前,高字节在后result.x = static_cast<quint16>(data[1]) | (static_cast<quint16>(data[2]) << 8);result.y = static_cast<quint16>(data[3]) | (static_cast<quint16>(data[4]) << 8);}if (data.size() >= 7) {result.pressure = static_cast<quint16>(data[5]) | (static_cast<quint16>(data[6]) << 8);}result.buttons.clear(); // 坐标报告不含按钮,清空列表break;default:qWarning() << "未知报告ID:" << QString::number(result.reportId, 16);break;}return result;
}

 写一个打印输出函数

void HidManager::handleHidData(const QByteArray& data)
{// 数据为空或与上次完全相同则直接返回static QByteArray lastDataFrame;if (data.isEmpty() || data == lastDataFrame) return;lastDataFrame = data;// 解析数据到结构体TabletData currentData = parseTabletData(data);// 打印原始数据和解析结果(调试用)if (debugMode) { // 可添加调试开关QString hexData;for (int i = 0; i < data.size(); i++) {hexData += "0x" + QString::number((unsigned char)data[i], 16).toUpper().rightJustified(2, '0') + " ";if ((i+1) % 8 == 0) hexData += "\n";}qDebug() << "收到新数据:" << hexData;qDebug() << "解析后数据:"<< "报告ID:" << QString::number(currentData.reportId, 16)<< "坐标: (" << currentData.x << ", " << currentData.y << ")"<< "压力:" << currentData.pressure<< "按钮:" << currentData.buttons;}// 静态变量存储上次数据,用于检测变化static TabletData lastData;// 检查关键数据是否变化(按钮、坐标、压力)bool isButtonChanged = (currentData.buttons != lastData.buttons);bool isPositionChanged = (currentData.x != lastData.x || currentData.y != lastData.y);bool isPressureChanged = (currentData.pressure != lastData.pressure);// 根据变化类型发送不同信号if (isButtonChanged) {emit buttonStateChanged(currentData.buttons);}if (isPositionChanged || isPressureChanged) {emit tabletMoved(currentData.x, currentData.y, currentData.pressure);}// 更新上次数据缓存lastData = currentData;
}

打印输出:

拿wacom数位板举例。以下是连接wacom数位板之后,数位笔滑动之后wacom数位板发送过来的报告:

解析内容

报告第一个字节为报告ID用来区分用户进行的是什么操作

当报告ID为0X10时代表坐标移动

当报告ID为0X11时代表按键按下

例:

按下第一个按键,此时报告ID为0x11,表示按键事件发生。此时第2个字节发生了变化,也就是第一个字节被按下了:

当用数位笔在数位板上滑动之后收到如下报告:

报告ID为0x10,表示坐标发生变化。坐标在字节1-4,压力在字节5-6:

HID设备按键与Qt界面UI按键的快捷键绑定实现

流程图

相关文章:

Qt与Hid设备通信

什么是HID&#xff1f; HID&#xff08;Human Interface Device&#xff09;是‌直接与人交互的电子设备‌&#xff0c;通过标准化协议实现用户与计算机或其他设备的通信&#xff0c;典型代表包括键盘、鼠标、游戏手柄等。‌ 为什么HID要与qt进行通信&#xff1f; 我这里的应…...

QT使用QXlsx读取excel表格中的图片

前言 读取excel表格中的图片的需求比较小众&#xff0c;QXlsx可以操作excel文档&#xff0c;进行图片读取、插入操作&#xff0c;本文主要分享单独提取图片和遍历表格提取文字和图片。 源码下载 github 开发环境准备 把下载的代码中的QXlsx目录&#xff0c;整个拷贝到所创建…...

二叉树进阶

一、二叉搜索树 1.二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它也可以是一棵空树&#xff0c;或是具备以下性质的树&#xff1a; 1.1 若它的左子树不为空&#xff0c;则它左子树上所有节点的值都小于根节点的值。 1.2 若它的右子树不为空&#xff0c;则它右子…...

腾讯 CodeBuddy 杀入 AI 编程赛道,能否撼动海外工具霸主地位?

在 AI 编程助手领域&#xff0c;海外的 Cursor 等工具风头正劲&#xff0c;如今腾讯带着 CodeBuddy 隆重登场&#xff0c;国产 AI 编程助手能否借其之力崛起&#xff1f;让我们一探究竟。 官网&#xff1a; 腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 实战安装教程 …...

项目QT+ffmpeg+rtsp(二)——海康威视相机测试

文章目录 前言一、验证RTSP地址的有效性1.1 使用VLC播放器验证1.2 使用FFmpeg命令行验证1.3 使用Python代码检查网络连接1.4 检查摄像头Web界面1.5 使用RTSP客户端工具二、关于IPV4的地址2.1 原来2.1.1 原因2.2 解决2.3 显示前言 昨晚拿到一个海康威视的相机,是连接上了交换机…...

vscode用python开发maya联动调试设置

如何在VScode里编写Maya Python脚本_哔哩哔哩_bilibili1 包括1&#xff0c;maya的python全面在vscode支持&#xff0c;2&#xff0c;通过mayacode发送到maya&#xff0c;3同步调试 import maya.cmds as cmds 1、让 maya.cmds编译通过 下载Autodesk_Maya_2018_6_Update_DEVK…...

Postman遇到脚本不支持replaceIn函数

目录&#xff1a; 1、问题现象2、代码处理3、执行结果 1、问题现象 2、代码处理 function replaceVariables(template) {// 获取所有变量&#xff08;环境变量全局变量&#xff09;const variables pm.environment.toObject();const globalVars pm.globals.toObject();const…...

精益数据分析(64/126):移情阶段的用户触达策略——从社交平台到精准访谈

精益数据分析&#xff08;64/126&#xff09;&#xff1a;移情阶段的用户触达策略——从社交平台到精准访谈 在创业的移情阶段&#xff0c;精准找到目标用户并开展深度访谈是验证需求的关键。今天&#xff0c;我们结合《精益数据分析》中的方法论&#xff0c;探讨如何利用Twit…...

turn.js与 PHP 结合使用来实现 PDF 文件的页面切换效果

将 Turn.js 与 PHP 结合使用来实现 PDF 文件的页面切换效果&#xff0c;你需要一个中间步骤将 PDF 转换为 Turn.js 可以处理的格式&#xff08;如 HTML 页面或图片&#xff09;。以下是实现这一功能的步骤和示例代码&#xff1a; 步骤 1: 安装必要的库 首先&#xff0c;你需要…...

SQL Server 与 Oracle 常用函数对照表

一、字符串处理函数 SQL Server 函数SQL Server 实例Oracle 函数Oracle 实例输出结果CONCATSELECT CONCAT(A, B, C);CONCATSELECT CONCAT(A, B) FROM DUAL;ABC&#xff08;SQL&#xff09; AB&#xff08;Oracle&#xff09;SUBSTRINGSELECT SUBSTRING(Hello, 2, 3);SUBSTRSEL…...

数据治理新纪元:全面解读TSDDITAI系列评估规范

在数字化转型的浪潮中&#xff0c;数据已成为驱动业务增长和创新的核心要素。然而&#xff0c;如何确保大数据产品、企业、人才及数据资源的优质与合规&#xff0c;成为了摆在行业面前的重大课题。为此&#xff0c;TSDDITAI系列评估规范应运而生&#xff0c;为大数据产业的健康…...

电子电路:什么是色环电阻器,怎么识别和计算阻值?

识别和计算色环电阻的阻值需要掌握颜色编码规则和基本步骤。以下是具体方法及窍门: 一、色环电阻的基本规则 色环数量: 4环电阻:前2环为有效数字,第3环为倍乘(10ⁿ),第4环为误差。5环电阻:前3环为有效数字,第4环为倍乘,第5环为误差。6环电阻(较少见):前3环为有效数…...

UE中的各种旋转

1 直接修改第三人称玩家的角度 注意不是修改玩家的actor或者pawn&#xff0c;而是修改controller的旋转 这只会修改相机的方向&#xff0c;不会修改角色的方向&#xff0c;因为第三人控制器的根物体不受controller控制&#xff0c;而相机弹簧臂受controller控制 如果修改角色…...

游戏引擎学习第289天:将视觉表现与实体类型解耦

回顾并为今天的工作设定基调 我们正在继续昨天对代码所做的改动。我们已经完成了“脑代码&#xff08;brain code&#xff09;”的概念&#xff0c;它本质上是一种为实体构建的自组织控制器结构。现在我们要做的是把旧的控制逻辑迁移到这个新的结构中&#xff0c;并进一步测试…...

NestJS——日志、NestJS-logger、pino、winston、全局异常过滤器

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…...

list重点接口及模拟实现

list功能介绍 c中list是使用双向链表实现的一个容器&#xff0c;这个容器可以实现。插入&#xff0c;删除等的操作。与vector相比&#xff0c;vector适合尾插和尾删&#xff08;vector的实现是使用了动态数组的方式。在进行头删和头插的时候后面的数据会进行挪动&#xff0c;时…...

Linux | mdadm 创建软 RAID

注&#xff1a;本文为 “Linux mdadm RAID” 相关文章合辑。 略作重排&#xff0c;未整理去重。 如有内容异常&#xff0c;请看原文。 Linux 下用 mdadm 创建软 RAID 以及避坑 喵ฅ・&#xfecc;・ฅ Oct 31, 2023 前言 linux 下组软 raid 用 mdadm 命令&#xff0c;multi…...

迁移学习:解锁AI高效学习与泛化能力的密钥

前言 在人工智能&#xff08;AI&#xff09;技术日新月异的今天&#xff0c;迁移学习&#xff08;Transfer Learning&#xff09;作为一项革命性技术&#xff0c;正深刻改变着机器学习领域的格局。 它不仅让模型能够像人类一样“举一反三”&#xff0c;更在加速模型开发、提升性…...

前端-HTML元素

目录 HTML标签是什么&#xff1f; 什么是HTML元素&#xff1f; HTML元素有哪些分类方法&#xff1f; 什么是HTML头部元素 更换路径 注&#xff1a;本文以leetbook为基础 HTML标签是什么&#xff1f; HTML标签是HTML语言中最基本单位和重要组成部分 虽然它不区分大小写&a…...

STM32之蜂鸣器和按键

一、蜂鸣器的原理与应用 基本概念 蜂鸣器是一种一体化结构的电子讯响器&#xff0c;采用直流电压供电&#xff0c;广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。 工作原理 蜂鸣器一般分为两类&#xff1a;有源…...

H3C UIS 超融合管理平台原理解读以及日常运维实操与故障处理

前言&#xff1a;超融合&#xff08;Hyper-Converged Infrastructure, HCI&#xff09;是将计算、存储、网络和虚拟化资源整合到统一硬件平台中&#xff0c;并通过软件定义技术实现资源池化与灵活管理的架构。H3C&#xff08;新华三&#xff09;和华为作为国内领先的ICT厂商&am…...

【强化学习】#5 时序差分学习

主要参考学习资料&#xff1a;《强化学习&#xff08;第2版&#xff09;》[加]Richard S.Suttion [美]Andrew G.Barto 著 文章源文件&#xff1a;https://github.com/INKEM/Knowledge_Base 缩写说明 DP&#xff1a;动态规划GPI&#xff1a;广义策略迭代MC&#xff1a;蒙特卡洛…...

Day119 | 灵神 | 二叉树 | 二叉树的最近共公共祖先

Day119 | 灵神 | 二叉树 | 二叉树的最近共公共祖先 236.二叉树的最近共公共祖先 236. 二叉树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 二叉树的最近公共祖先【基础算法精讲 12】_哔哩哔哩_bilibili 首先我们采用后序遍历 递归函数返回值…...

Elasticsearch 性能优化面试宝典

Elasticsearch 性能优化面试宝典 🚀 目录 设计调优 🏗️写入调优 ⚡查询调优 🔍综合设计 💎总结 📝设计调优 🏗️ 面试题1:索引设计优化 题目: 假设需要设计一个电商商品索引,日增数据量1TB,要求支持多维度查询(名称、分类、价格区间)。请说明索引设计的关…...

mysql数据库-中间件MyCat

1. MyCat简介 在整个 IT 系统架构中&#xff0c;数据库是非常重要&#xff0c;通常又是访问压力较大的一个服务&#xff0c;除了在程序开发的本身做优化&#xff0c;如&#xff1a; SQL 语句优化、代码优化&#xff0c;数据库的处理本身优化也是非常重要的。主从、热备、分表分…...

制作大风车动画

这个案例的风车旋转应用了图形变换来实现&#xff0c;速度和缩放比例应用slider来实现&#xff0c;其中图片的速度&#xff0c;图片大小的信息通过State来定义变量管理&#xff0c;速度和和缩放比例的即时的值通过Prop来管理。 1. 案例效果截图 2. 案例运用到的知识点 2.1. 核…...

嘉立创EDA成图:文件管理

在 工程 文 件夹 中 新建 一 个以 自 己选 手 编号 后 8 位 命名 的 项目 工 程文 件 按要求名字命名&#xff08;这里以日期命名&#xff09; 选择半离线或者全离线 添加路径 1. 新建 图 纸文 件 &#xff0c;文 件 名为 moban.elibz&#xff1b; 点击保存之后打开文件夹有这…...

Vim编辑器命令模式操作指南

Vim 的命令模式&#xff08;即 Normal 模式&#xff09;是 Vim 的核心操作模式&#xff0c;用于执行文本编辑、导航、搜索、保存等操作。以下是命令模式下的常用操作总结&#xff1a; 1. 模式切换 进入命令模式&#xff1a;在任何模式下按 Esc 键&#xff08;可能需要多次按&a…...

jvm安全点(一)openjdk17 c++源码垃圾回收安全点信号函数处理线程阻塞

1. 信号处理入口​​ ​​JVM_HANDLE_XXX_SIGNAL​​ 是 JVM 处理信号的统一入口&#xff0c;负责处理 SIGSEGV、SIGBUS 等信号。​​javaSignalHandler​​ 是实际注册到操作系统的信号处理函数&#xff0c;直接调用 JVM_HANDLE_XXX_SIGNAL。 ​​2. 安全点轮询页的识别​​ …...

手机打电话时由对方DTMF响应切换多级IVR语音应答(二)

手机打电话时由对方DTMF响应切换多级IVR语音应答&#xff08;二&#xff09; --本地AI电话机器人 一、前言 前面的篇章《手机打电话时由对方DTMF响应切换多级IVR语音应答&#xff08;一&#xff09;》中&#xff0c;我们从理论的角度论述了“根据对方按下DTMF值响应多级IVR”…...

【Java ee初阶】HTTP(2)

一、HTTP的方法 方法 说明 支持的HTTP协议版本 GET 获取资源 1.0、1.1 POST 传输实体主体 1.0、1.1 PUT 传输文件 1.0、1.1 HEAD 获得报文首部 1.0、1.1 DELETE 删除文件 1.0、1.1 OPTIONS 询问支持的方法 1.1 TRACE 追踪路径 1.1 CONNECT 要求用隧道…...

计算机视觉与深度学习 | Python实现EMD-SSA-VMD-LSTM-Attention时间序列预测(完整源码和数据)

EMD-SSA-VMD-LSTM-Attention 一、完整代码实现二、代码结构解析三、关键数学公式四、参数调优建议五、性能优化方向六、工业部署建议 以下是用Python实现EMD-SSA-VMD-LSTM-Attention时间序列预测的完整解决方案。该方案结合了四层信号分解技术与注意力增强的深度学习模型&#…...

Java 应用如何实现 HTTPS:加密数据传输的实用指南

Java 应用如何实现 HTTPS&#xff1a;加密数据传输的实用指南 在当今的互联网环境中&#xff0c;数据安全至关重要&#xff0c;HTTPS 作为加密的数据传输协议&#xff0c;为 Java 应用提供了安全通信的保障。本文将深入探讨 Java 应用如何实现 HTTPS&#xff0c;通过详细代码实…...

手机打电话时如何将通话对方的声音在手机上识别成文字

手机打电话时如何将通话对方的声音在手机上识别成文字 --本地AI电话机器人 上一篇&#xff1a;手机打电话时由对方DTMF响应切换多级IVR语音应答&#xff08;一&#xff09; 下一篇&#xff1a;手机打电话时由对方DTMF响应切换多级IVR语音应答&#xff08;二&#xff09; 一、…...

18.自动化生成知识图谱的多维度质量评估方法论

文章目录 一、结构维度评估1.1 拓扑结构评估1.1.1 基础图论指标1.1.2 层级结构指标 1.2 逻辑一致性评估1.2.1 形式逻辑验证1.2.2 约束满足度 二、语义维度评估2.1 语义一致性评估2.1.1 标签语义分析2.1.2 关系语义评估 2.2 语义表示质量2.2.1 嵌入质量2.2.2 上下文语义评估 三、…...

W5500使用ioLibrary库创建TCP客户端

1、WIZnet全硬件TCP/IP协议栈 WIZnet全硬件TCP/IP协议栈,支持TCP,UDP,IPv4,ICMP,ARP,IGMP以及PPPoE协议。 以太网&#xff1a;支持BSD和WIZCHIP&#xff08;W5500/W5300/W5200/W5100/W5100S&#xff09;的SOCKET APIs驱动程序。 互联网&#xff1a; DHCP客户端 DNS客户端 FTP客…...

2025B难题练习

1.启动多任务排序 拓扑排序 每次选入度为0的点 对每次选的点进行排序 package mainimport ("bufio""fmt""os""slices""strings" )func main() {scanner : bufio.NewScanner(os.Stdin)scanner.Scan()text : scanner.Text()…...

20250517让NanoPi NEO core开发板在Ubuntu core16.04.2下支持TF卡的热插拔

20250517让NanoPi NEO core开发板在Ubuntu core16.04.2下支持TF卡的热插拔 2025/5/17 17:52 缘起&#xff1a;实测NanoPi NEO core开发板上电之后&#xff0c;后插入的TF卡不认/不支持热插拔。 Ubuntu core16.04.2 Ubuntu core20.04 Ubuntu core16.04.3 用NanoPi NEO core开发板…...

Vue百日学习计划Day19-20天详细计划-Gemini版

重要提示&#xff1a; 番茄时钟&#xff1a; 每个番茄钟为25分钟学习&#xff0c;之后休息5分钟。每完成4个番茄钟&#xff0c;进行一次15-30分钟的长休息。动手实践&#xff1a; DevTools 的使用和 Git 命令的掌握都需要大量的实际操作。请务必边学边练。环境准备&#xff1a…...

Uniapp、Flutter 和 React Native 全面对比

文章目录 前言Uni-app、Flutter 和 React Native 跨平台框架对比报告1. 性能对比2. 跨平台能力3. 学习曲线4. 社区生态与第三方库5. 原生能力扩展6. UI 渲染能力7. 企业支持与典型使用场景8. 开发效率与工具链 前言 将对 Uniapp、Flutter 和 React Native 进行全面对比&#x…...

【Linux笔记】——线程互斥与互斥锁的封装

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;Linux &#x1f339;往期回顾&#x1f339;&#xff1a;【Linux笔记】——Linux线程封装 &#x1f516;流水不争&#xff0c;争的是滔滔不息 一、线程互斥的概念二、互…...

Linux面试题集合(4)

现有压缩文件:a.tar.gz存在于etc目录&#xff0c;如何解压到data目录 tar -zxvf /etc/a.tar.gz -C /data 给admin.txt创建一个软链接 ln -s admin.txt adminl 查找etc目录下以vilinux开头的文件 find /etc -name vilinux* 查找admin目录下以test开头的文件 find admin -name te…...

Java二叉树题目练习

Java二叉题目练习 相同的树对称二叉树平衡二叉树二叉树的最近公共祖先二叉树的层序遍历二叉树层序遍历 ||二叉树遍历 相同的树 二叉树的题目大多数时候就可以采用递归的方法写 因为二叉树是由根左子树和右子树组成&#xff0c;每一棵左子树和右子树又可以被看成一颗完整的树&am…...

WORD个人简历单页326款模版分享下载

WORD个人简历模版下载&#xff1a;WORD个人简历模版https://pan.quark.cn/s/7e79a822c490...

Linux容器技术详解

容器技术基础 什么是容器 容器是一种轻量级的虚拟化技术&#xff0c;它将应用程序及其依赖&#xff08;库、二进制文件、配置文件等&#xff09;打包在一个独立的单元中&#xff0c;可以在任何支持容器运行时的环境中一致地运行。 Docker官网&#xff1a;https://www.docker…...

显卡、Cuda和pytorch兼容问题

这里写目录标题 驱动与CUDA版本兼容性问题1. **驱动与CUDA版本兼容性问题**2. **任务特性与硬件适配差异**3. **优化策略与框架配置差异**4. **散热与功耗限制**5. **数据传输与CPU瓶颈**排查建议总结 查询PyTorch中实际使用的CUDA版本**1. 查询PyTorch中实际使用的CUDA版本***…...

仅需三张照片即可生成沉浸式3D购物体验?谷歌电商3D方案全解析

随着消费者对线上购物体验的要求不断提高,传统2D图片已难以满足用户“真实感知商品”的需求。尤其在鞋类、家具、服装等高决策成本的商品上,缺乏空间感和交互性的购物方式成为转化率瓶颈。 谷歌敏锐地捕捉到这一趋势,早在2022年起便开始探索通过生成式AI技术实现“低成本、…...

PIC16F877A LCD1602 DHT11 温湿度读取显示代码 MPLAB

#include <xc.h> #include <stdio.h> #include <stdlib.h> #...

PIC16F18877 的主时钟 设置方法

#include <xc.h>// ========== 配置位设置 ========== // #pragma config FEXTOSC = OFF // 使用内部振荡器 #pragma...

西门子 Teamcenter13 Eclipse RCP 开发 1.3 工具栏 单选按钮

西门子 Teamcenter13 Eclipse RCP 开发 1.3 工具栏 单选按钮 1 配置文件2 插件控制3 命令框架 位置locationURI备注菜单栏menu:org.eclipse.ui.main.menu添加到传统菜单工具栏toolbar:org.eclipse.ui.main.toolbar添加到工具栏 style 值含义显示效果push普通按钮&#xff08;默…...