Matter mDNS 服务发现指南:深入解析 connectedhomeip 中的 MdnsDiscovery 工具

发布时间:2026/9/19 13:04:14

Matter mDNS 服务发现指南:深入解析 connectedhomeip 中的 MdnsDiscovery 工具 Matter mDNS 服务发现指南深入解析 connectedhomeip 中的 MdnsDiscovery 工具【免费下载链接】connectedhomeipMatter (formerly Project CHIP) creates more connections between more objects, simplifying development for manufacturers and increasing compatibility for consumers, guided by the Connectivity Standards Alliance.项目地址: https://gitcode.com/GitHub_Trending/co/connectedhomeip导读MdnsDiscovery是 Matterconnectedhomeip仓库中面向 mDNS 服务发现的核心 Python 工具类用于在本地网络IPv6上发现 Matter 设备的四种核心角色服务——commissioner管理员、commissionable node可配网节点、operational node已入网节点与 Thread border router边界路由器底层基于python-zeroconf库实现异步多播 DNS 查询。本文将以 README.md 为主线结合仓库内 mdns_discovery.py 及其配套模块的源码实现系统讲解该工具的设计结构、四大服务发现方法、DNS 记录PTR/SRV/TXT/A/AAAA直查能力、发现流程的内部机制以及配套的 mDNS 值校验断言与网络工具函数。读完本文你将掌握在 Matter 集成测试与日常调试中利用MdnsDiscovery完成服务发现、记录查询与结果校验的完整实战方案。背景Matter 的 mDNS 服务发现为何重要Matter 设备在本地网络上的互相发现依赖mDNS多播 DNS与 DNS-SDDNS Service Discovery。设备入网后会在本地网络宣告自身的服务控制器controller同样通过 mDNS 找到这些服务。MdnsDiscovery正是为这类发现场景提供统一异步接口的工具它既支持高层语义的服务查询如找所有可配网设备也支持直接访问低层 DNS 记录PTR、SRV、TXT、A、AAAA满足测试场景中对原始记录验证的需求。从源码看该工具被广泛用于 Matter 的 Python 集成测试用例中例如TC_SC_4_1.py 使用MdnsDiscovery().get_ptr_records()对 Discriminator Subtype 发起 PTR 记录查询验证开放配网窗口期间公告的 subtype 记录commissioning.py 中的_is_device_operational_via_dnssd()与_is_device_commissionable_via_dnssd()分别调用get_operational_services()和get_commissionable_services()在建立 CASE 会话前先通过 DNS-SD 判断设备当前状态避免不必要的超时等待。这些实际用法证明该模块不是孤立的示例代码而是 Matter 测试基础设施中可复用的发现能力组件。模块结构与目录说明MdnsDiscovery位于 src/python_testing/mdns_discovery目录结构如下 mdns_discovery/ ├── data_classes/ # 服务信息与查询结果的容器MdnsServiceInfo / PtrRecord / AaaaRecord 等 ├── enums/ # 服务类型等枚举定义MdnsServiceType ├── service_listeners/ # 发现会话期间使用的服务监听器MdnsServiceListener ├── tests/ # 断言函数及其他方法的单元测试test_asserts.py ├── utils/ # 工具函数IPv6 过滤与断言等network.py / asserts.py ├── mdns_async_service_info.py # 支持查询指定 mDNS 记录类型的封装MdnsAsyncServiceInfo / AddressResolverIPv6 └── mdns_discovery.py # mDNS 发现操作的主入口MdnsDiscovery各模块职责清晰enums/mdns_service_type.py定义了 Matter 的四种核心 mDNS 服务类型MdnsServiceType枚举data_classes定义了三种可序列化数据容器MdnsServiceInfo完整服务信息、PtrRecordPTR 记录与AaaaRecordIPv6 地址记录均继承自JsonSerializable以支持 JSON 输出见 mdns_service_info.pyservice_listeners/mdns_service_listener.py实现了一个内部asyncio.Event驱动的服务监听器用于在记录查询前同步等待服务 add/update 事件mdns_async_service_info.py对zeroconf.ServiceInfo做了子类化重写async_request以禁用缓存、强制发起全新网络查询并提供仅解析 AAAAIPv6记录的AddressResolverIPv6。核心 API 总览MdnsDiscovery类在初始化时mdns_discovery.py会通过get_host_ipv6_addresses()自动采集本机全部可用的 IPv6 接口地址含 link-local 时附带%接口名作用域并以_discovered_services字典保存发现结果、以asyncio.Event同步发现过程。其公开 API 可分为三大类1. 服务发现方法高层语义查询方法作用底层服务类型get_operational_services()发现已入网的 operational Matter 节点_matter._tcp.local.get_commissioner_services()发现 Matter 管理员commissioner_matterd._udp.local.get_commissionable_services()发现可配网的 Matter 设备_matterc._udp.local.get_border_router_services()发现 Thread 边界路由器_meshcop._udp.local.get_all_services()发现网络上任意类型的 mDNS 服务动态扫描全部服务类型discover()上述发现方法共用的底层 mDNS 发现引擎由参数决定四个 Matter 角色方法实现高度一致调用discover(service_types[...], query_serviceTrue, append_resultsTrue, ...)随后从self._discovered_services按服务类型取值返回list[MdnsServiceInfo]。这四种服务类型值定义于 mdns_service_type.py与 Matter 规范中四个角色的公告类型一一对应。2. 记录查询方法低层 DNS 记录直查方法查询记录类型说明get_ptr_records(service_types)PTR对给定服务类型执行 browse返回发现的 PTR 记录列表get_srv_record(service_name, service_type)SRV解析指定服务实例的目标主机与端口get_txt_record(service_name, service_type)TXT解析指定服务实例的 TXT 键值元数据get_quada_records(hostname)AAAA通过主机名解析设备 IPv6 地址其中get_srv_record与get_txt_record的内部实现仅改变query_record_types参数{_TYPE_SRV}或{_TYPE_TXT}统一走_query_service_info()私有方法get_quada_records则使用AddressResolverIPv6单独解析 AAAA 记录。3. 服务类型发现方法方法作用get_all_service_types()扫描网络返回全部被公告的 mDNS 服务类型含非 Matter 服务get_commissionable_subtypes()在全部服务类型中过滤出开放配网窗口期间公告的 commissionable subtype._sub._matterc._udp.local.get_commissionable_subtypes()的实现mdns_discovery.py先调用get_all_service_types()再筛选以_开头且包含._sub._matterc._udp.local.的服务类型返回的正是_L\d长判别器、_S\d短判别器、_V\d厂商、_T\d设备类型等配网 subtype。快速上手两个最小可运行示例示例一发现 operational 节点import asyncio from mdns_discovery.mdns_discovery import MdnsDiscovery async def main(): mdns MdnsDiscovery() # 发现 operational 节点_matter._tcp.local. services await mdns.get_operational_services() # 打印基本信息 for service in services: print(fInstance: {service.instance_name}) print(fAddresses: {service.addresses}) print(fPort: {service.port}) print(---) asyncio.run(main())示例二查询指定服务实例的 SRV 记录import asyncio from mdns_discovery.mdns_discovery import MdnsDiscovery async def main(): mdns MdnsDiscovery() service_name B7322C948581262F-0000000012344321._matter._tcp.local. # 查询 SRV 记录 srv_record await mdns.get_srv_record( service_nameservice_name, service_typeMdnsServiceType.OPERATIONAL.value, log_outputTrue ) # 打印主机名 print(fHostname: {srv_record.hostname}) asyncio.run(main())注意operational 实例名遵循{16位压缩Fabric ID}-{16位节点ID}格式如B7322C948581262F-0000000012344321这一点在 asserts.py 中的assert_valid_operational_instance_name有严格校验见下文。discover()统一发现引擎的内部机制discover()是全部服务发现方法的引擎签名与参数语义如下mdns_discovery.py参数默认值语义service_typesNone要浏览的特定服务类型列表如[_matterc._udp.local.]all_servicesFalse为True时动态发现网络上的全部 mDNS 服务类型discovery_timeout_sec15DISCOVERY_TIMEOUT_SECbrowse 阶段等待公告的最大秒数query_serviceFalse为True时对每个发现的 PTR 记录进一步查询完整服务信息query_timeout_sec10QUERY_TIMEOUT_SEC记录查询阶段的最大等待秒数仅在query_serviceTrue时生效append_resultsFalse为True时将结果追加到_discovered_services否则先清空再存储。仅在query_serviceTrue时生效log_outputFalse为True时将发现结果以 JSON 格式打印到控制台该方法带有一组参数合法性校验违反即抛ValueErrorall_services与service_types不能同时指定service_types不能是空列表query_timeout_sec仅在query_serviceTrue时允许非默认值append_results仅在query_serviceTrue时允许为True。发现过程源码级拆解discover(query_serviceTrue) │ ▼ 确定要浏览的类型列表all_services 时先扫描全部服务类型 │ ▼ async with AsyncZeroconf(interfacesself.interfaces) as azc: ├── 创建 AsyncServiceBrowser(zeroconf, type_, handlers[_on_service_state_change]) ├── 后台任务 _monitor_discovery_silence()连续 2 秒无新服务即提前结束 ├── await wait_for(self._event.wait(), timeoutdiscovery_timeout_sec) │ └── 每个 Added 状态的服务触发 _on_service_state_change()收集 PTR 记录 └── 若 query_serviceTrue ├── 用 Semaphore(5) 限制最多 5 个并发查询 ├── 对每条 PTR 调用 _query_service_info()SRV/TXT/A/AAAA 全查 └── 结果按服务类型存入 self._discovered_services ▼ 返回 list[MdnsServiceInfo]或 dict 映射几个值得注意的工程细节静默提前结束_monitor_discovery_silence()mdns_discovery.py每 0.5 秒轮询一次只要已经发现过至少一个服务、且超过DISCOVERY_SILENCE_THRESHOLD_SEC2 秒没有新服务出现就提前置位事件结束 browse。TC_SC_4_1 等测试用例的注释也印证了这一点Browses that get an answer end early via MdnsDiscoverys discovery-silence。这使发现过程在典型局域网上远快于 15 秒上限并发保护记录查询阶段通过Semaphore(5)将并发 mDNS 查询限制为 5 个避免在设备较多时对系统造成过载去重_on_service_state_change()只响应ServiceStateChange.Added并以 service name 集合去重防止重复 PTR 记录。记录查询内部流程_query_service_info()mdns_discovery.py是所有记录查询的核心私有方法流程如下_query_service_info(service_type, service_name, query_record_types) │ ▼ async with AsyncZeroconf(...) as azc: ├── 注册 MdnsServiceListener等待服务 add/update 事件 │ wait_for_service_update超时 SERVICE_LISTENER_TIMEOUT_SEC5 秒 ├── 构造 MdnsAsyncServiceInfo设置要查询的记录类型集合 ├── service_info.async_request(zc, timeout_msquery_timeout_sec*1000) └── 移除监听器成功则包装为 MdnsServiceInfo 返回 ▼ returns MdnsServiceInfo | None其中的MdnsAsyncServiceInfo.async_request()重写自zeroconf.ServiceInfo与基类实现的关键差异见 mdns_async_service_info.py绕过 known-answer 缓存每次调用先清空zc.cache、zc.question_history与自身缓存强制发起一次全新的网络查询保证拿到新鲜数据QU 优先 QM 兜底首次发送以单播优先as_quTrue的查询随后始终发送组播QM查询确保覆盖所有应答者防重复问题抑制后续重试间隔取_DUPLICATE_QUESTION_INTERVAL与初始延迟 随机偏移中的较大者避免因同一问题重发过快被设备抑制应答完成后的滞留监听记录齐备后再等待 300–500 ms 随机时长被动捕获迟到的 SRV/TXT/AAAA/A 应答循环以_is_complete与绝对截止时间now_ms timeout_ms双条件控制超时返回False。各记录查询方法流程示意get_srv_record/get_txt_record以get_srv_record为例get_srv_record(service_name, service_type) │ ▼ _query_service_info(..., query_record_types{SRV}) ├── 添加服务监听器add_service_listener ├── async_request(...) 发起 SRV 查询 └── 返回 MdnsServiceInfo 对象 ▼ returns MdnsServiceInfo | Noneget_quada_recordsAAAA 解析get_quada_records(hostname) │ ▼ addr_resolver AddressResolverIPv6(serverhostname) │ ├── addr_resolver.async_request(...) │ └── 发起 AAAA 记录的 mDNS 查询_query_record_types{_TYPE_AAAA} │ └── addr_resolver.ip_addresses_by_version(IPVersion.V6Only) └── 提取解析出的 IPv6 地址 ▼ returns list[AaaaRecord]get_ptr_records纯 PTR 浏览不做完整解析get_ptr_records(service_types) │ ▼ discover(query_serviceFalse) │ └── 启动 AsyncServiceBrowser(...) └── 每个服务触发 _on_service_state_change(...) ├── 收集 PTR 记录信息 └── 存入 self._discovered_services ▼ returns list[PtrRecord]get_all_service_typesget_all_service_types() │ ▼ AsyncZeroconfServiceTypes.async_find(...) │ └── 扫描所有被公告的 mDNS 服务类型超时返回空列表 ▼ returns List[str]get_commissionable_subtypesget_commissionable_subtypes() │ ▼ get_all_service_types() │ └── 发现所有被公告的 mDNS 服务类型 ▼ 筛选包含 ._sub._matterc._udp.local. 的 subtype ▼ returns List[str]数据模型MdnsServiceInfo、PtrRecord 与 AaaaRecordMdnsDiscovery的三类返回容器定义在 data_classes 目录均实现json_dict()序列化基类见 json_serializable.py配合log_outputTrue时可输出结构化的 JSON 发现报告。MdnsServiceInfo对zeroconf的AsyncServiceInfo的轻量包装mdns_service_info.py通过属性映射暴露常用字段属性对应底层字段说明service_namename完整服务实例名service_typetype服务类型含 subtype 时含._sub.段instance_name由 name/type 推导去掉服务类型后缀后的实例名subtype 场景取._sub.之后的基类型hostnameserver服务主机名addressesparsed_addresses()已解析的 IP 地址列表portport服务端口txtdecoded_propertiesTXT 记录的键值字典priority/weight/interface_index/host_ttl/other_ttl同名字段SRV/TTL 等低层元数据PtrRecordPTR 记录的容器ptr_record.py构造时自动从service_type与service_name推导instance_name若服务类型含._sub.取其后基类型如_matter._tcp.local.再从服务名中剥离得到纯实例名如A6666A3E45CF5655。AaaaRecordIPv6 地址记录容器aaaa_record.py在__post_init__中完成大量地址分类元数据的生成address压缩格式 IPv6 地址剥离去 zone index如%eth0interface将 scope id 映射为接口名通过socket.if_nameindex()type_infois_global/is_link_local/is_loopback/is_multicast分类标志special_typesteredo/sixtofour/is_reserved/ipv4_mapped等特殊地址类型metamax_prefixlen与 packed 十六进制字节。发现结果示例以下为 README 与源码共同展示的典型发现结果样例有助于理解各字段含义。AsyncZeroconfServiceTypes 返回的服务类型示例_matterd._udp.local. _matter._tcp.local. _V65521._sub._matterd._udp.local. _IM7322C948581262F._sub._matter._tcp.local._IM...为 operational 节点公告的实例名 subtype_V65521...为 vendor subtype。AsyncServiceBrowser 返回的 PTR 记录信息示例service_type: _matterd._udp.local. service_name: A6666A3E45CF5655._matterd._udp.local. instance_name: A6666A3E45CF5655async_request 解析出的完整服务信息示例service_name: 354D34458F15657D._matterd._udp.local. service_type: _V65521._sub._matterd._udp.local. instance_name: 354D34458F15657D hostname: 00155DD54A04.local. port: 5550 addresses: [172.30.139.182, fe80::215:5dev:fed5:4a04] txt: {VP: 6552132769} priority: 0 interface_index: 2 weight: 0 host_ttl: 120 other_ttl: 4500mDNS 值校验断言utils/asserts.pyasserts.py 提供了一套面向 mDNS 发现测试的校验助手。所有断言基于Mobly框架from mobly import asserts失败时抛出TestFailure并且错误消息会明确指出违反的具体约束便于测试快速定位失败原因。所有函数都带not_none_args装饰器保证参数不为None。典型用法from mdns_discovery.utils.asserts import assert_valid_dn_key assert_valid_dn_key(Kitchen)断言函数清单类别函数校验内容示例实例名assert_valid_operational_instance_name两个 16 位大写十六进制段、以连字符分隔如B7322C948581262F-0000000012344321实例名assert_valid_commissionable_instance_name16 位大写十六进制如DD200C20D25AE5F7主机名assert_valid_hostname12Ethernet/Wi-Fi MAC或 16Thread MAC位大写十六进制前缀 合法域名后缀如B75AFB458ECD.local.配网 subtypeassert_valid_long_discriminator_subtype_L0-4095._sub._matterc._udp.local.12 位判别器无前导零配网 subtypeassert_valid_short_discriminator_subtype_S0-15._sub._matterc._udp.local.4 位判别器无前导零配网 subtypeassert_valid_vendor_subtype_V0-65535._sub._matterc._udp.local.16 位厂商 ID配网 subtypeassert_valid_devtype_subtype_T0-4294967295._sub._matterc._udp.local.32 位设备类型TXT 键assert_valid_d_keyDiscriminator12 位十进制、无前导零、≤4095TXT 键assert_valid_vp_keyVendor ID[Product ID]分隔至多一个如132456TXT 键assert_valid_cm_keyCommissioning Mode仅允许0/1/2/3TXT 键assert_valid_dt_keyDevice Type32 位十进制TXT 键assert_valid_dn_keyDevice NameUTF-8 编码 ≤ 32 字节TXT 键assert_valid_ri_keyRotating Device Identifier大写十六进制≤ 100 字符TXT 键assert_valid_ph_keyPairing Hint0 且仅低 23 位有效TXT 键assert_valid_pi_keyPairing InstructionUTF-8 编码 ≤ 128 字节TXT 键assert_valid_jf_keyJoint Fabric仅 0-3 位有效且满足位组合约束TXT 键通用assert_valid_sii_keySession Idle Interval毫秒、≤ 3600000TXT 键通用assert_valid_sai_keySession Active Interval毫秒、≤ 3600000TXT 键通用assert_valid_sat_keySession Active Threshold≤ 65535TXT 键通用assert_valid_t_keyTransport 模式DUT 与 PICS 的 TCP 支持必须一致TCP 支持时允许{4,6}否则仅{0}位 0 保留必须为 0TXT 键通用assert_valid_icd_keyICD 标志仅允许0/1身份属性assert_valid_vendor_idVendor ID16 位、无前导零、≤65535身份属性assert_valid_product_idProduct ID16 位、无前导零、≤65535服务类型assert_is_commissionable_type必须等于_matterc._udp.local.服务类型assert_is_commissioner_type必须等于_matterd._udp.local.服务类型assert_is_operational_type必须等于_matter._tcp.local.服务类型assert_is_border_router_type必须等于_meshcop._udp.local.地址assert_valid_ipv6_addresses列表中每个地址必须是合法 IPv6记录存在性assert_txt_record_present异步指定实例与类型的 TXT 记录存在且至少含一个键值对其中两个断言与测试中的 TCP 能力判定关系密切assert_txt_record_present(instance_name, service_type)先构造{instance_name}.{service_type.value}完整 QNAME调用MdnsDiscovery().get_txt_record()获取记录然后校验记录非空且含键值对assert_valid_t_key用于将 DUT 实际公告的T键与 PICSProtocol Implementation Conformance Statement中声明的 TCP 支持对齐TCP 支持时T ∈ {4, 6}IPv4/IPv6仅 MRP 时T 0此外 DUT 与 PICS 的 TCP 支持必须一致否则直接断言失败。utils/network.py中的is_dut_tcp_supported()与之配套T 键缺失、为空或为0视为仅支持 MRP不支持 TCP其他值视为支持 TCP。单元测试见 tests/test_asserts.py采用unittest框架对每个断言的正反用例正确值通过、错误类型/空串/缺尾点/边界值失败做了系统覆盖。例如TestAssertIsBorderRouterType验证了正确值通过、错误服务类型失败、空串失败、缺少尾随点失败等场景并检查失败消息包含期望值。网络工具函数utils/network.pynetwork.py 提供两个支持 mDNS 测试的网络工具get_host_ipv6_addresses()扫描本机所有网络适配器的 IPv6 地址并过滤不可用项network.py跳过回环地址::1link-local 地址fe80::/10必须附带接口作用域%接口名如fe80::xxxx%eth0才能用于通信ULAfd00::/8与全局地址2000::/3可直接使用保留纯地址若完全找不到可用 IPv6 地址则返回InterfaceChoice.All交由 Zeroconf 使用默认接口选择策略。该函数返回的地址列表正是MdnsDiscovery.__init__中self.interfaces的来源确保 mDNS 查询绑定到正确的 IPv6 接口。使用示例from mdns_discovery.utils.network import get_host_ipv6_addresses addr_list get_host_ipv6_addresses() for addr in addr_list: print(addr)is_dut_tcp_supported()异步函数通过查询 DUT 的 operational 服务 TXT 记录判断其是否支持 TCPnetwork.py构造MdnsDiscovery()并调用get_txt_record(service_nameinstance_qname, service_typeOPERATIONAL.value)读取 TXT 记录中的T键缺失、空串或0→ 返回False仅 MRP 支持不支持 TCP其他值 → 返回True。在 Matter 测试框架中的真实应用MdnsDiscovery不是孤立的演示代码而是 Matter Python 测试体系中的实际组件。以下是仓库内的真实调用场景1. DNS-SD 状态预检commissioning.py_is_device_operational_via_dnssd()在建立 CASE 会话前先做 DNS-SD 预检compressed_fabric_id dev_ctrl.GetCompressedFabricId() expected_instance_name f{compressed_fabric_id:016X}-{node_id:016X} mdns MdnsDiscovery() services await mdns.get_operational_services( discovery_timeout_secdiscovery_timeout_sec, log_outputFalse ) for service in services: if service.instance_name expected_instance_name: return True其核心思想是从设备控制器取得 compressed fabric ID 与 node ID构造期望的 operational 实例名{fabric:016X}-{node:016X}再通过get_operational_services()遍历已发现服务匹配。匹配成功即认为设备已在该 fabric 上处于 operational 状态从而避免不必要的 CASE 超时。同理_is_device_commissionable_via_dnssd()通过get_commissionable_services()检测设备是否正处于配网模式。2. Discriminator Subtype 验证TC_SC_4_1.pyTC_SC_4_1 测试用例构造 Discriminator Subtypediscriminator_subtype f_L{discriminator}._sub.{MdnsServiceType.COMMISSIONABLE.value} assert_valid_long_discriminator_subtype(discriminator_subtype)随后调用ptr_records await MdnsDiscovery().get_ptr_records( service_types[discriminator_subtype], log_outputTrue ) asserts.assert_equal(len(ptr_records), 1, ...)验证开放配网窗口期间网络上恰好公告一条与判别器匹配的 subtype PTR 记录。这展示了「断言构造 → PTR 查询 → 结果校验」的完整测试闭环。3. 其他测试用例引用mdns_discovery还被 TC_CADMIN_1_15、TC_CNET_4_12、TC_DD_3_24、TC_ICDM_5_1、TC_JFADMIN_2_2、TC_SC_4_3、TC_SC_4_6、TC_SC_4_7 以及 commissioning.py 等模块引用覆盖管理员、网络、DD、ICD、联合 Fabric、SC 等多个测试域的 mDNS 验证需求。环境依赖与使用前提该模块位于 src/python_testing/mdns_discovery导入路径为mdns_discovery.*运行环境需将src/python_testing加入PYTHONPATH依赖python-zeroconfzeroconf/zeroconf.asyncio与ifaddr接口枚举两个第三方库断言模块依赖Mobly测试框架mobly.asserts、mobly.signals.TestFailure发现过程基于IPv6运行主机必须配置至少一个可用的 IPv6 接口地址链路本地或路由地址均可否则get_host_ipv6_addresses()会退回 Zeroconf 默认接口选择所有方法均为异步async def需要在asyncio事件循环中调用可用asyncio.run()。总结与进一步阅读MdnsDiscovery为 Matter 生态提供了一套完整、可控、可验证的 mDNS 服务发现方案高层方法直接对应 Matter 规范的四种角色服务类型低层记录查询暴露 PTR/SRV/TXT/AAAA 原始记录discover()引擎内置静默提前结束、并发限制与缓存绕过机制兼顾效率与数据新鲜度配套断言库则把 Matter 规范中对实例名、subtype、TXT 键值的格式约束固化为可复用的测试校验器。若要深入了解每个方法的完整参数说明可直接阅读 mdns_discovery.py 中的内联 docstringMatter 规范中对实例名、hostname 与 TXT 键的构造要求可对照 asserts.py 中各断言的 docstring 与约束实现完整的断言正反用例可查看 test_asserts.py。【免费下载链接】connectedhomeipMatter (formerly Project CHIP) creates more connections between more objects, simplifying development for manufacturers and increasing compatibility for consumers, guided by the Connectivity Standards Alliance.项目地址: https://gitcode.com/GitHub_Trending/co/connectedhomeip创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/19 12:59:14

N_m3u8DL-RE:m3u8视频下载快速完整指南

N_m3u8DL-RE:m3u8视频下载快速完整指南 【免费下载链接】N_m3u8DL-RE Cross-Platform, modern and powerful stream downloader for MPD/M3U8/ISM. English/简体中文/繁體中文. 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8DL-RE 把只能在浏览…

2026/9/19 12:59:14

25MHz可综合MIPS五级流水线CPU工程实现

简介:本资源是一份面向数字电路与计算机体系结构初学者的MIPS流水线CPU Verilog实现详解文档,聚焦于理解并动手实现5级流水线架构中的关键问题。内容系统讲解数据冒险(含一阶/二阶相关)、数据转发机制、控制冒险及延迟分支策略等核…

2026/9/19 12:59:14

VS Code 配置 Markdown 编译器:从零搭建高效写作工作流

这么多年来,VS Code 一直是我写 Markdown 的主力编辑器。很多人一看到“配置 Markdown 编译器”这几个字就发怵,觉得是不是又要装一堆插件、改一堆配置。实际上,Markdown 不是说不需要“编译”,而是这里的编译过程和 C/C、Java 那…

2026/9/19 14:09:18

手搓的 OpenClaw 每轮喂 8 个 MD 提示词,模型 Base URL 填 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 14:09:18

胎心仪语音+蓝牙双模协同设计原理与WT2801A4实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 14:09:18

基于语音识别与PLC的温室灌溉控制系统设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 14:09:18

工业质检无监督异常检测:PatchCore在MVTec AD的实战与调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 14:09:18

MySQL服务启动报错1067?用netstat排查端口占用并解决

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 14:04:18

Your inspiring proposal title

Your inspiring proposal title 【免费下载链接】minikube Run Kubernetes locally 项目地址: https://gitcode.com/gh_mirrors/mi/minikube First proposed: Authors: $full_name (github-handle), $full_name2 (github_handle2) Reviewer Priorities Please review …

2026/9/18 14:13:01

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/19 0:03:10

验证 OpenSpec 兼容性,Cursor 的 Token 从 TaoToken 出

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 0:03:10

书桌角落的 Mac mini,OpenClaw 通过 TaoToken 跑任务。

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/19 0:03:10

oh-my-hermes:打造跨工具的命令编排与插件化工作流

1. 项目概述与设计初衷1.1 它到底是什么先说结论:oh-my-hermes 是一个面向开发者日常终端操作的效率工具套件,核心定位是“把分散在各类命令行工具里的高频操作,统一收拢成一套插件化、可编排的工作流”。项目灵感来源很明显——oh-my-zsh 重…

2026/9/18 14:13:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/18 14:13:02

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/18 14:13:02

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码