如何用C语言实现 IoT Core

news2024/11/25 23:25:37

涂鸦 IoT Core SDK 使用 C 语言实现,支持涂鸦设备模型协议,适用于开发者自主开发硬件设备逻辑业务接入涂鸦。

功能概述

涂鸦 IoT Core SDK 提供设备激活、发送上下行 DP 和固件 OTA 升级等基础业务接口封装。SDK 不依赖具体设备平台及操作系统环境,也可以运行在单任务环境。仅需要支持 TCP/IP 协议栈及提供 SDK 必要的系统依赖接口,即可完成接入。

开发步骤

第一步:下载 SDK

先在在 涂鸦 GitHub 仓库 下载 IoT Core SDK。

该 SDK 的 C 代码文件通过以下目录结构提供:

文件说明
certs设备私钥,设备证书,服务端 CA 根证书
docs参考文档
libraries外部依赖库,包含 MQTT client、HTTP client、mbedTLS 等
interface平台必要移植接口,SDK 功能接口
includeSDK 有文件,包含了 SDK API
srcSDK 源代码
platform平台移植接口适配
utils通用工具模块
examples例程

第二步:配置设备信息

首先需要在涂鸦 IoT 开发平台创建产品,获取授权信息,然后将产品和授权相关信息写入到代码中,实现云服务的接入。详细步骤如下:

  1. 登录 涂鸦 IoT 开发平台。

  2. 单击 创建产品

    IoT Core SDK(C)

  3. 选择 行业解决方案 > 智慧工业 > 工业网关 品类。

    IoT Core SDK(C)

  4. 在 智能化方式 区域选择 生态设备接入,并填写产品相关信息,完成产品创建。

    IoT Core SDK(C)

  5. 在 功能定义 界面,单击 添加功能 并填写相关参数,完成产品功能定义。

    IoT Core SDK(C)

  6. 在 设备开发 界面,选择并下载 SDK 方案,单击 下一步 进入激活信息获取页面。

    IoT Core SDK(C)

  7. 领取授权码,然后单击 注册设备。设备相应信息会显示在下方。

    涂鸦提供免费的授权码供测试使用,可以免费领取 2 个激活码。

    IoT Core SDK(C)

  8. 将注册的设备信息,填写到 examples/subdevice_basic_demo/subdevice_basic_demo.c 文件中,编译并运行 Demo 即可连接云服务,关于编译的具体流程,请参考下文编译执行章节内容。

    IoT Core SDK(C)

    const char productId[] = "rwosj58aaqjk **** ";
    const char deviceId[] = "6c95875d0f5ba69607 **** ";
    const char deviceSecret[] = " ******************* ";
    

    可通过购买授权码,在设备管理页面进行设备注册,获取 productIddeviceIddeviceSecret 等信息。

第三步:编译执行(Ubuntu)

本小节以 Ubuntu 系统为例,介绍 SDK 编译步骤。本节介绍同样适用于 Debian 系统。

  1. 安装 make 等相关环境依赖。

    sudo apt-get install make cmake
    
  2. 进入获取到的 SDK 文件内,新建一个 build 文件夹并且进入该文件夹,输入 cmake.. 先进行环境编译,再输入 make 开始编译固件。编译完成后,固件会生成在 build 文件夹下的 bin 文件夹。

    mkdir build && cd build
    cmake ..
    make
    
  3. 进入 bin 文件夹,运行 Demo。SDK 内置了基础的通信 Demo 代码,例如子设备管理基础 Demo。

    ./bin/subdevice_basic_demo
    
  4. 在设备端查看运行接口。

    以下日志显示设备与云端连接成功。

    IoT Core SDK(C)

  5. 设备成功连接到涂鸦 IoT 开发平台后,单击进行刷新,设备状态会显示为在线。

    IoT Core SDK(C)

应用示例

  1. 实例化和初始化一个设备对象 tuya_iot_client_t,用来初始化产品 ID 和授权信息等配置参数。

    /* instantiate the client */
    tuya_mqtt_context_t* client = &client_instance;
    
    /* initialize the client */
    ret = tuya_mqtt_init(client, &(const tuya_mqtt_config_t) {
        .host = "m2.tuyacn.com",
        .port = 8883,
        .cacert = tuya_cacert_pem,
        .cacert_len = sizeof(tuya_cacert_pem),
        .device_id = deviceId,
        .device_secret = deviceSecret,
        .keepalive = 60,
        .timeout_ms = 2000,
        .on_connected = on_connected,
        .on_disconnect = on_disconnect,
        .on_messages = on_messages
    });
    
  2. 定义应用层事件回调,回调函数用于应用层接收 SDK 事件通知,如数据功能点(DP)下发,云端连接状态通知。

    /* Tuya SDK event callback */
    void on_messages(tuya_mqtt_context_t* context, void* user_data, const tuyalink_message_t* msg)
    {
        TY_LOGI("on message id:%s, type:%d, code:%d", msg->msgid, msg->type, msg->code);
        switch (msg->type) {
            case THING_TYPE_MODEL_RSP:
                TY_LOGI("Model data:%s", msg->data_string);
                break;
    
            case THING_TYPE_PROPERTY_SET:
                TY_LOGI("property set:%s", msg->data_string);
                break;
    
            case THING_TYPE_PROPERTY_REPORT_RSP:
                break;
    
            default:
                break;
        }
    printf("\r\n");
    }
    
  3. 启动 TuyaOS SDK 服务。

    ret = tuya_mqtt_connect(client);
    //TuyaOS SDK 服务任务,数据接收处理,设备在线保活等任务处理:
    
  4. 循环调用将当前线程产生给底层的 Link SDK 客户端。

    tuya_mqtt_loop(client);
    
  5. 定义上报函数,调用相关上报接口函数实现数据上报。下方示例为产品连接时,将部分产品数据上报到云端。大家可以根据自己产品的数据上报需求,参考该函数编写自身应用代码。

     void on_connected(tuya_mqtt_context_t* context, void* user_data)
    {
    TY_LOGI("on connected");
    
    /* data model test code */
    tuyalink_thing_data_model_get(context, NULL);
    tuyalink_thing_desired_get(context, NULL, "[\"power\"]");
    tuyalink_thing_property_report(context, NULL, "{\"power\":    {\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_property_report_with_ack(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_event_trigger(context, NULL, "{\"eventCode\":\"boom\",\"eventTime\":1626197189630,\"outputParams\":{\"param1\":100}}");
    tuyalink_thing_batch_report(context, "{\"msgId\":\"45lkj3551234001\",\"time\":1626197189638,\"sys\":{\"ack\":1},\"data\":{\"properties\":{\"power\":{\"value\":11,\"time\":1626197189638}},\"events\":{\"boom\":{\"outputParams\":    {\"param1\":\"10\"},\"eventTime\":1626197189001}}}}");
    }
    
    /*数据上报 API*/
    /* data model code */
    tuyalink_thing_data_model_get(context, NULL);
    tuyalink_thing_desired_get(context, NULL, "[\"power\"]");
    tuyalink_thing_property_report(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_property_report_with_ack(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_event_trigger(context, NULL, "{\"eventCode\":\"boom\",\"eventTime\":1626197189630,\"outputParams\":{\"param1\":100}}");
    tuyalink_thing_batch_report(context, "{\"msgId\":\"45lkj3551234001\",\"time\":1626197189638,\"sys\":{\"ack\":0},\"data\":{\"properties\":{\"power\":{\"value\":11,\"time\":1626197189638}},\"events\":{\"boom\":{\"outputParams\":{\"param1\":\"10\"},\"eventTime\":1626197189001}}}}");}
    /* subdevice code */
    tuyalink_subdevice_bind(context, "[{\"productId\":\"jtwe4q9jrs0bbc8q\",\"nodeId\":\"123456\",\"clientId\":\"123455asdf\"}]");
    tuyalink_subdevice_bind_login(context, "[\"6c17c5ba952143f592b8g1\",\"6c41626e5cea758aees0ik\"]");
    tuyalink_subdevice_bind_logout(context, "[\"6c17c5ba952143f592b8g1\"]");
    tuyalink_subdevice_topo_add(context, "[{\"productId\":\"jtwe4q9jrs0bbc8q\",\"deviceId\":\"6c17c5ba952143f592b8g1\",\"sign\":\"366508ed895644e70a3006bdef2dbe77ef73e18a\",\"signMethod\":\"hmacSha1\",\"timestamp\":\"1636989480\"}]");
    tuyalink_subdevice_topo_delete(context,"[\"6c41626e5cea758aees0ik\"]");
    tuyalink_subdevice_topo_get(context);
    

设备调试

设备成功连接 MQTT 服务器并上线后,可以在涂鸦 IoT 开发平台设备调试页面对设备进行调试。

  1. 进入 设备调试 页面,单击 选择设备,填入上线设备的 DeviceID,即可获取到设备当前定义的功能点合集。

    IoT Core SDK(C)

  2. 设备操作的日志信息都会显示在右侧实时日志处,大家可以通过日志确认设备当前的信息。

    IoT Core SDK(C)

  3. 单击功能点操作列的 获取 选项,可以获取到当前设备的数据。

    IoT Core SDK(C)

  4. 单击功能点操作列的 设置 选项,可以对设备当前的数据进行设置,日志处会显示当前云端下发的 payload 日志信息,通过本地 log 也可以看到云端下发的 payload 信息。

    IoT Core SDK(C)

接口说明

SDK 初始化

接口信息说明
函数原型int tuya_mqtt_init(tuya_mqtt_context_t* context, const tuya_mqtt_config_t* config);
功能描述设备初始化
输入参数
  • context:设备管理句柄
  • config:设备初始化信息配置
输出参数
返回值参考通用错误码

启动服务

接口信息说明
函数原型int tuya_mqtt_connect(tuya_mqtt_context_t* context);
功能描述启动设备 SDK 服务
输入参数context:设备管理句柄
输出参数
返回值参考通用错误码

停止服务

接口信息说明
函数原型int tuya_mqtt_disconnect(tuya_mqtt_context_t* context);
功能描述停止设备 SDK 服务
输入参数context:设备管理句柄
输出参数
返回值参考通用错误码

后台运行服务

接口信息说明
函数原型int tuya_mqtt_loop(tuya_mqtt_context_t* context);
功能描述SDK 后台运行服务
输入参数context:设备管理句柄
输出参数
返回值参考通用错误码
备注需要在程序主循环调用该服务函数

获取设备物模型

接口信息说明
函数原型int tuyalink_thing_data_model_get(tuya_mqtt_context_t* context, const char* device_id);
功能描述使用该函数获取设备的物模型
输入参数
  • context:设备管理句柄
  • device_id:设备 ID
输出参数
返回值参考通用错误码

设备属性上报

接口信息说明
函数原型int tuyalink_thing_property_report(tuya_mqtt_context_t* context, const char* device_id, const char* data);
功能描述设备属性上报
输入参数
  • context:设备管理句柄
  • device_id:设备 ID
输出参数
返回值参考通用错误码

设备属性上报(包含应答)

接口信息说明
函数原型int tuyalink_thing_property_report_with_ack(tuya_mqtt_context_t* context, const char* device_id, const char* data);
功能描述上报设备的属性并得到云端应答
输入参数
  • context:设备管理句柄
  • device_id:设备 ID
  • data:上报的属性数据
输出参数
返回值参考通用错误码

设备事件响应

接口信息说明
函数原型int tuyalink_thing_event_trigger(tuya_mqtt_context_t* context, const char* device_id, const char* data);
功能描述设备事件响应
输入参数
  • context:设备管理句柄
  • device_id:设备 ID
  • data:事件数据
输出参数
返回值参考通用错误码

设备批量上报

接口信息说明
函数原型int tuyalink_thing_batch_report(tuya_mqtt_context_t* context, const char* data);
功能描述设备批量上报数据
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值参考通用错误码

子设备绑定

接口信息说明
函数原型int tuyalink_subdevice_bind(tuya_mqtt_context_t* context, const char* data);
功能描述子设备绑定
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值参考通用错误码

子设备上线

接口信息说明
函数原型int tuyalink_subdevice_bind_login(tuya_mqtt_context_t* context, const char* data);
功能描述子设备上线
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值参考通用错误码

子设备下线

接口信息说明
函数原型int tuyalink_subdevice_bind_logout(tuya_mqtt_context_t* context, const char* data);
功能描述子设备下线
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值参考通用错误码

子设备拓扑添加

接口信息说明
函数原型int tuyalink_subdevice_topo_add(tuya_mqtt_context_t* context, const char* data);
功能描述子设备拓扑添加
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值参考通用错误码

子设备拓扑删除

接口信息说明
函数原型int tuyalink_subdevice_topo_delete(tuya_mqtt_context_t* context, const char* data);
功能描述子设备拓扑删除
输入参数
  • context:设备管理句柄
  • data:数据
输出参数
返回值参考通用错误码

子设备拓扑获取

接口信息说明
函数原型int tuyalink_subdevice_topo_get(tuya_mqtt_context_t* context);
功能描述子设备拓扑获取
输入参数context:设备管理句柄
输出参数
返回值参考通用错误码

Demo 设备例程

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

#include "cJSON.h"
#include "tuya_cacert.h"
#include "tuya_log.h"
#include "tuya_error_code.h"
#include "system_interface.h"
#include "mqtt_client_interface.h"
#include "tuyalink_core.h"

const char productId[] = "3jbcpefnn1jxxxxx";
const char deviceId[] = "6ced2aa564727c01xxxxx";
const char deviceSecret[] = "ac5d367db39xxxxx";

tuya_mqtt_context_t client_instance;

void on_connected(tuya_mqtt_context_t* context, void* user_data)
{
    TY_LOGI("on connected");

    /* data model test code */
    tuyalink_thing_data_model_get(context, NULL);
    tuyalink_thing_desired_get(context, NULL, "[\"power\"]");
    tuyalink_thing_property_report(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_property_report_with_ack(context, NULL, "{\"power\":{\"value\":1234,\"time\":1631708204231}}");
    tuyalink_thing_event_trigger(context, NULL, "{\"eventCode\":\"boom\",\"eventTime\":1626197189630,\"outputParams\":{\"param1\":100}}");
    tuyalink_thing_batch_report(context, "{\"msgId\":\"45lkj3551234001\",\"time\":1626197189638,\"sys\":{\"ack\":0},\"data\":{\"properties\":{\"power\":{\"value\":11,\"time\":1626197189638}},\"events\":{\"boom\":{\"outputParams\":{\"param1\":\"10\"},\"eventTime\":1626197189001}}}}");
}

void on_disconnect(tuya_mqtt_context_t* context, void* user_data)
{
    TY_LOGI("on disconnect");
}

void on_messages(tuya_mqtt_context_t* context, void* user_data, const tuyalink_message_t* msg)
{
    TY_LOGI("on message id:%s, type:%d, code:%d", msg->msgid, msg->type, msg->code);
    switch (msg->type) {
        case THING_TYPE_MODEL_RSP:
            TY_LOGI("Model data:%s", msg->data_string);
            break;

        case THING_TYPE_PROPERTY_SET:
            TY_LOGI("property set:%s", msg->data_string);
            break;

        case THING_TYPE_PROPERTY_REPORT_RSP:
            break;

        default:
            break;
    }
    printf("\r\n");
}

int main(int argc, char** argv)
{
    int ret = OPRT_OK;

    tuya_mqtt_context_t* client = &client_instance;

    ret = tuya_mqtt_init(client, &(const tuya_mqtt_config_t) {
        .host = "m2.tuyacn.com",
        .port = 8883,
        .cacert = tuya_cacert_pem,
        .cacert_len = sizeof(tuya_cacert_pem),
        .device_id = deviceId,
        .device_secret = deviceSecret,
        .keepalive = 60,
        .timeout_ms = 2000,
        .on_connected = on_connected,
        .on_disconnect = on_disconnect,
        .on_messages = on_messages
    });
    assert(ret == OPRT_OK);

    ret = tuya_mqtt_connect(client);
    assert(ret == OPRT_OK);

    for (;;) {
        /* Loop to receive packets, and handles client keepalive */
        tuya_mqtt_loop(client);
    }

    return ret;
}

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

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

相关文章

Java毕业设计-基于SpringBoot的租房网站的设计与实现

大家好&#xff0c;今天为大家打来的是基于SpringBoot的租房网站的设计与实现 博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 一、前言介绍二、主…

如何理解高效IO

目录 前言 1.如何理解高效的IO 2.五种IO模型 3.非阻塞IO 4.非阻塞代码编写 总结 前言 哈喽&#xff0c;很高兴和大家见面&#xff01;今天我们要介绍的关于IO的话题&#xff0c;在计算机中IO是非常常规的操作&#xff0c;例如将数据显示到外设&#xff0c;或者将数据从主…

将本地前端工程中的npm依赖上传到Nexus

【问题背景】 用Nexus搭建了内网的依赖仓库&#xff0c;需要将前端工程中node_modules中的依赖上传到Nexus上&#xff0c;但是node_modules中的依赖已经是解压后的状态&#xff0c;如果直接机械地将其简单地打包上传到Nexus&#xff0c;那么无法通过npm install下载使用。故有…

安防监控系统/视频云存储/监控平台EasyCVR服务器解释器出现变更该如何修改?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

软件测试/测试开发丨利用人工智能ChatGPT批量生成测试数据

点此获取更多相关资料 简介 测试数据是指一组专注于为测试服务的数据&#xff0c;既可以作为功能的输入去验证输出&#xff0c;也可以去触发各类异常场景。 测试数据的设计尤为重要&#xff0c;等价类、边界值、正交法等测试用例设计方法都是为了更全面地设计对应的测试数据…

Immutable.js API 简介

Immutable-js 这个库的实现是深拷贝还是浅拷贝&#xff1f;immutable 来源immutable.js三大特性&#xff1a; 持久化数据结构结构共享惰性操作 Immutable.js 的几种数据类型 immutable 使用 使用 npm 安装 immutable&#xff1a; 常用API介绍 MapListList.isList() 和 Map.isMa…

【Linux】页表讲解(一级、二级) 和 vm_area_struct ## 对于我前面博客内容的补充

对于前5篇进程相关知识的补充 前言正式开始页表讲解缺页中断页表是如何映射的页表的真正面目 vm_area_structmm_structvm_area_stuct 前言 前面我的博客中讲了很多关于进程的知识&#xff0c;但是有一些内容需要做一点补充&#xff0c;补充完后我的下一篇博客就开始讲线程相关…

云原生Kubernetes:pod亲和性与反亲和性

目录 一、理论 1.调度策略 2.亲和性与反亲和性案例 二、实验 1.亲和性与反亲和性 三、问题 1.节点批次打标签错误 2.for循环批量创建pod报错 四、总结 一、理论 1.调度策略 &#xff08;1&#xff09;对比 2.Pod 拓扑分布约束 &#xff08;1&#xff09;概念 使用 …

游戏ip多开安全指南:保障多重账号操作安全性

游戏多开是许多游戏玩家们常用的操作方式&#xff0c;而使用游戏ip进行游戏多开则能够进一步拓展多重账号的应用。然而&#xff0c;对于游戏多开使用游戏ip的安全性&#xff0c;我们也需要保持一定的警惕和注意事项。本文将为您分享有关游戏ip多开的安全指南&#xff0c;助您保…

C++中operator关键字(重载操作符)

转载地址&#xff1a; https://www.cnblogs.com/ZY-Dream/p/10068993.html operator是C的关键字&#xff0c;它和运算符一起使用&#xff0c;表示一个运算符函数&#xff0c;理解时应将operator整体上视为一个函数名。 这是C 扩展运算符功能的方法&#xff0c;虽然样子古怪&a…

vs2022 创建一个同时支持.net480和.net6.0的WPF项目

新建WPF项目&#xff0c;不要选.NET Framework框架的。如下图所示&#xff0c;选择第一个。&#xff08;选择.NET Framework框架改成.net6.0会报错&#xff09; 用记事本打开项目的csproj文件&#xff0c;修改TargetFrameworks标签&#xff0c;如下所示&#xff1a; <Pro…

C++之容器std::stack类empty、size、top、push、emplace、pop、swap应用总结(二百二十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Bootstrap 框架学习笔记(基础)

来自于 Twitter&#xff0c;基于 HTML、CSS、JavaScript。 有关网站&#xff1a;Bootstrap中文网Bootstrap是Twitter推出的一个用于前端开发的开源工具包。它由Twitter的设计师Mark Otto和Jacob Thornton合作开发&#xff0c;是一个CSS/HTML框架。目前&#xff0c;Bootstrap最…

JVM面试题-类加载顺序、双亲委派、类初始化顺序(详解)

类加载器 JVM只会运行二进制文件&#xff0c;类加载器的作用就是将字节码文件加载到JVM中&#xff0c;从而让Java程序能够启动起来。 类加载负责执行类加载&#xff0c;去磁盘进行识别&#xff0c;识别完后加载到内存 类加载器的种类&#xff1a; 从上往下 启动类加载器&…

Unity的配置文件在安卓路径下使用的方法

Unity的配置文件在安卓路径下使用的方法 前言 之前我做过的很多使用配置文件的Unity项目&#xff0c;后面的有些项目也有在安卓路径下读取json文件的需求。这几天有个需求是获取在安卓路径下配置文件里的数据&#xff0c;我在网上查了一些案例&#xff0c;简单实现了这个需求…

swift 约束布局

添加约束布局 背景图瀑全屏 如何三等分 外面view容器没有约束

Laravel Swagger 使用完整教程

Swagger 使用 一、Swagger 基础1、 什么是Swagger2、 安装过程1 、composer安装2、添加服务提供者&#xff0c;引导框架运行时加载&#xff0c;在 app 配置文件&#xff0c;providers 选项中添加(laravel 5以上忽略此步骤)3、配置完成后&#xff0c;通过输入命令 **php artisan…

QT记事本+登陆界面的简单实现

主体头文件 #ifndef JSB_H #define JSB_H#include <QMainWindow> #include <QMenuBar>//菜单栏 #include <QToolBar>//工具栏 #include <QStatusBar>//状态栏 #include <QTextEdit>//文本 #include <QLabel>//标签 #include <QDebug&g…

什么样的应用程序适合使用Flutter开发桌面?

桌面应用开发的现状 在过去&#xff0c;桌面应用程序的开发通常需要使用特定于操作系统的工具和语言&#xff0c;如C、C#、Java等。这导致了高昂的开发成本和维护困难。尽管有一些跨平台桌面开发工具&#xff0c;如Electron和Qt&#xff0c;但它们在性能、用户体验和开发效率方…

Linus Torvalds接受来自微软的Linux Hyper-V升级

微软最近推送了一些变更&#xff0c;旨在改进即将发布的 Linux 内核 6.6 版本对 Hyper-V 的支持。这些改进包括在 Hyper-V 上支持 AMD SEV-SNP guest 和 Intel TDX guest。除了这两项&#xff0c;还有其他一些升级&#xff0c;如改进了 VMBus 驱动程序中的 ACPI&#xff08;高级…