【HomeKit】从HomeKit架构层细化到HomeKit ADK集成

news2025/2/26 6:26:24

前言:这篇文章是对于苹果协议文件《HomeKit ADK Integration Guide - Addendum for
Televisions》的学习,针对版本为ADK 6.0电视。描述了将HomeKit ADK的电视简介集成到目标平台中所需的步骤。

总说明

此配置文件用于控制启用Airplay的电视,并需要AirPlay视频SDK来构建AirPlay共享键存储库和MFi软件身份验证示例。ADK公开了一个PAL API,AirPlayTEE,以启用与AirPlay共享密钥存储的集成。这使得将Ed25519长期密钥、设备ID和AirPlay和HomeKit之间共享的配对存储在一个单独的可信执行环境中。所提供的示例假设AirPlay视频公开了一个插座机制和一个回调机制,允许HomeKit电视与AirPlay视频通信。通信机制用于更新HomeKit能够更改的配置,例如电视的配置名称。SDK示例提供了一个通过命令行与电视服务和特征进行交互的接口。这在开发和测试过程中很有用。

1.1.HomeKit电视和AirPlay视频集成概述

这个HomeKit版本提供的电视样本提供了与AirPlay视频的集成。HomeKit电视和AirPlay视频共享相同的Ed25519长期密钥、设备ID和配对,使这两种服务成为相同的附件。Ed25519长期密钥和配对需要驻留在加密安全存储中。同时访问这些秘密需要在AirPlay视频和HomeKit之间的同步。以下资源与电视个人资料相关:

  1. AirPlay视频共享键存储界面。
  2. AirPlay视频MFi软件认证示例。
  3. 为了访问配对键,AirPlay视频使用共享键商店提供的功能。所提供的示例使用一个文件来共享Ed25519的长期秘密、配对和设备ID。
  4. HomeKit使用双平台的AirPlayTEE平台API来存储配对、设备ID和Ed25519长期密钥。所提供的默认实现使用了AirPlay共享密钥存储接口。特定于HomeKit的配置和配置存储在一个单独的HomeKit键值存储中。
  5. 根据AirPlay中的实现,秘密存储在共享的平面文件或硬件受信任的执行环境中。默认的实现使用了一个基于平面文件的密钥链——这需要一个锁定机制,以确保HomeKit和AirPlay都能够安全地修改密钥链的内容。
  6. AirPlay视频直接使用共享密钥存储界面访问它的配对。

请注意,AirPlay视频和HomeKit的配对键并不是静态配置的。相反,它们是在使用附件时生成/交换的。

1.2.HomeKit平台AirPlayTEE界面

HAPPlatformAirPlayTEE接口允许供应商将可信的执行环境插入到HomeKit应用程序中。当附件在运行时,配对指数应该是稳定的。在所提供的实现中,AirPlayTEE接口使用AirPlay共享密钥存储程序API来读取和读写到AirPlay共享密钥存储程序中。

1.3.AirPlay视频插座接口

电视应用程序使用以下界面来配置和控制AirPlay视频:
1、可配置的AirPlay视频属性:

  • HomeKit启用
  • HomeKit访问
  • 控制级别配置名称
  • 安全模式
  • 密码

2、控制AirPlay视频的操作:

  • 重置配对——删除所有的配对播放视频特定的
  • 重置身份——删除设备id和长期密钥存储在播放视频
  • 启动服务器——启动播放视频服务器
  • 停止服务器——停止播放视频服务器
  • 配对开始——通知播放视频配对开始
  • 配对完成——通知播放视频配对完成
  • 设置代码改变——通知播放视频设置代码改变
  • 显示播放设置——通知播放视频显示视频设置

该接口在HirPlay.h中公开,显示在HomeKit侧,并在AirPlay中作为一个套接字通信机制实现

1.4.AirPlay视频回调界面

电视应用程序使用以下界面进行HomeKit和播放视频之间的通知和响应:
1.从AirPlay视频到HomeKit的通知

  • 播放视频开始
  • 播放视频停止
  • 取消配对请求-播放视频请求HomeKit解除配对和工厂重置
  • 更新设置-播放视频通知HomeKit更新的值为可配置的播放视频属性
  • 请求HomeKit日志-播放视频请求HomeKit的日志,如果可用的话

1.5.软件认证

HomeKit依赖于MFiServerTEETask API,作为AirPlay视频SDK的一部分交付,用于软件认证。用于软件身份验证的相关MFi密钥和用于DRM的FairPray秘密是特定于AirPlay的,不需要使用SharedKeyStore接口进行同步。

1.6.单进程

HomeKit包含在播放进程中,而不是单独运行。AirPlay负责创建和管理HomeKit ADK主线程。这就需要将ADK构建为一个库,而不是一个独立的应用程序。在运行make时,请使用“静态”或“共享”目标来生成必要的库。

1.7.动态二维码生成

对于支持显示的配件,设置代码连续生成,每5分钟或每次配对尝试后更改一次。

  • 如果在应用程序初始化期间启用了显示功能,则会自动启动配对模式
  • HAPPlatformAccessorySetupDisplayUpdateSetupPayload通知设置代码更改时(例如每5分钟),向用户显示的二维码必须相应更新。c中的示例代码使用控制台,必须适应使用显示器。
  • 对于具有复杂UI界面的附件,新的API功能HAPPlatformAccessorySetupDisplayHandleStartPairing会在注册配对尝试时通知附件,并可用于引导用户进入显示设置有效负载的配对屏幕。
  • 同样地,HAPPlatformAccessorySetupDisplayHandleStopPairing表示配对尝试何时中止或成功。可以使用HAPAccessoryServerIsPaired API来确定配对是否成功

电视示例使用AirPlay插座通信模式将更新后的二维码发送到AirPlay

1.8.软件认证

HomeKit依赖于作为AirPlay视频SDK的一部分提供的软件认证。用于软件身份验证的相关MFi密钥和用于DRM的FairPray秘密是特定于AirPlay的,不需要使用SharedKeyStore接口进行同步。


2.启用电视配置文件

在使用电视档案时,可以禁用某些ADK功能。当使用示例Makefile时,可以使用“配置文件=电视”构建选项来完成,并导致在HAP和PAL中关闭以下功能:

  • HAP_FEATURE_CAMERA
  • HAP_FEATURE_MICROPHONE
  • HAP_FEATURE_SPEAKER
  • HAP_FEATURE_WIFI_ROUTER
  • HAP_FEATURE_NFC

如果附件需要,这些功能可以安全地单独重新启用。例如,一些配件可能想要使用NFC配对

3.从HomeKit ADK迁移到电视2.x(或更低)到3.0(或更高)

3.1概述

从ADK 3.0开始,ADK现在将只是作为AirPlay共享键存储平台界面的客户端。这样,就可以将AirPlay共享键存储集成到硬件受信任的执行环境中。假定供应商使用由AirPlay视频提供的HomeKit UI功能。

迁移由在ADK/ Applications/Television/ImportLegacySharedKeyStoreFormat.c中定义并在App.c中调用的导入遗留共享密钥存储格式函数控制。假设电视用的HomeKit ADK是用-DHAVE_AIRPLAY_TEE=1和-DHAP_FEATURE_KEY_EXPORT=1编译的。如果升级前的HomeKit ADK的当前版本已经是3.0或更高版本,则不需要迁移。在App.c中调用的导入遗留共享密钥存储格式的调用可以被注释掉。

3.2.迁移过程

电视的HomeKit ADK包含一个PAL模块,它可以理解AirPlay共享键存储的密钥链格式,并能够将数据迁移到HomeKit键值存储中。

在电视示例中实现了以下迁移过程:

  1. 如果不存在一个单独的HomeKit键值存储,则将创建该键值存储。HomeKit键值存储区的默认位置是文件夹。在当前的工作目录中。以前,HomeKit密钥值存储区共同位于AirPlay共享键存储区密钥链文件中。使用导入遗留共享密钥存储格式函数开始迁移。
  2. 平台共享键存储中的函数HAPPlatformSharedKeyStoreMigrate被调用来将Kit数据从共享键链文件导入到HomeKit键值存储中。AirPlay共享键存储密键链文件的位置由定义KEYCHAINS_PATH和KEYCHAIN_DEFAULT_FILENAME(默认值: ~/Library/Keychains/sharedKeyStore.keychain)控制。
  3. 当成功导入所有HomeKit数据后,HomePlay数据将从共享键存储的密钥链文件中删除。
  4. 成功提取后,迁移代码在域kAppKeyValueStoreDomain_Configuration上设置一个标志,在HomeKit键值存储中设置kAppKeyValueStoreKey_SharedKeyStoreMigrated。
  5. 高速平台中的功能HAPPlatformAirPlayTEEMigrateKeyValueStore被调用来将HomeKit LTSK、HomeKit设备ID和HomeKit配对从HomeKit键值存储迁移到AirPlayTEE PAL模块,该模块使用AirPlay共享键存储平台实现。此时,还可以提供一种将LTSK、设备ID和配对存储在硬件可信的执行环境中的实现。
  6. 当HomeKit LTSK、HomeKit设备ID和HomeKit配对被成功迁移时,它们将从HomeKit键值存储中删除。
  7. 成功迁移后,在域kAppKeyValueStoreDomain_Configuration和键kAppKeyValueStoreKey_AirPlayTEEMigrated的HomeKit键值存储中设置一个标志,以指示Ed25519 LTSK、设备ID和配对已迁移到HomeKit AirPlayTEE PAL模块API。

注意:
8. 所提供的示例不迁移由AirPlay拥有的配对。
9. •在ADK 2.1或ADK 2.2中对HAP平台存储价值存储
10. •模块API所做的任何更改和适应都需要集成到HAP平台共享键存储中,以便迁移成功。如果导入Home共享密钥存储格式失败,
11. •HomeKit ADK将中止。在重新启动时,应用程序将重试迁移过程。

4.用树莓派播放电视

一个树莓派可以被用来展示一个电视配件。本节将描述在树莓派上构建和运行带有集成的ADK电视配置文件的AirPlay视频演示应用程序所需的步骤。

4.1.编译

如何构建空气播放演示与集成的ADK使用码头工人

  1. 下载AirPlaySDK从MFi门户
  2. 提取到$(ADK_ROOT)/外部/ADK/src/
  3. 编译静态ADK库
make TARGET=Raspi PROFILE=Television HOMEKITSTORE_DIR=/home/pi/.HomeKitStore" stati
  1. 静态编译播放启用ADK
make TARGET=RaspiEmu shell
 cd ./External/AirplaySDK/src/AirPlaySDK
  make -C PlatformPOSIX debug=1 stub=1 os=linux adk=1 -j8 platform=raspi shared=0 
ADK_ROOT={PATH_TO_ADK} all

4.2.使用树莓派运行

  • 将所有二进制文件推到设备上。
/Tools/install.sh \ 
 -d raspi \ 
 -a External/AirplayVideoSDK/src/AirPlaySDK/AirPlaySDK/build/Debug-linux/airplaydemo \ 
 -n raspberrypi \ 
 -p raspberry \ 
 -i \ 
 -k
  • 运行开始播放,集成ADK电视简介导出
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:.
./airplaydemo —config {path to Airplay video config.ini file}

5.在Ubuntu上看电视

本节将描述在Ubuntu上构建和运行带有集成的ADK电视配置文件的AirPlay视频演示应用程序所需的步骤(推荐值为18.04)。

5.1.编译

如何构建播放演示与集成ADK

  • 使用本地Ubuntu下载从MFi门户
  • 编译静态ADK库
目标=Linux配置文件=电视静态
  • 提取AirPlaySDK
  • 播放编译播放与ADK启用
cd {PATH_TO_AIRPLAY}
 make -C PlatformPOSIX debug=1 stub=1 os=linux adk=1 -j8 ADK_ROOT={PATH_TO_ADK} 
shared=0 all

5.2在Ubuntu上运行

  1. 创建资源调配文件
 ./Tools/provision_raspi.sh --category 31 --display --product-num E3644573 --setup-code 
111-22-333 ~/.HomeKitStore
  1. 运行应用程序
{PATH_TO_AIRPLAY}/build/Debug-linux/airplaydemo —config {path to Airplay video config.ini file}

6.在Raspi上播放电视与模拟Airplay

本节将描述在没有播放的树莓派上构建电视示例应用程序所需的步骤。这将有有限的功能,但可以帮助调试HomeKit代码本身

6.1.编译

如何构建电视应用程序

  • 编译ADK
make TARGET=Raspi USE_DISPLAY=1 apps

6.2.在Raspi上运行

  1. 创建配置文件,并将二进制文件推送到设备上
./Tools/install.sh \ 
 -d raspi \ 
 -a Output/Raspi-armv6k-unknown-linux-gnueabihf/Debug/IP/Applications/Television.OpenSSL\ 
 -n raspberrypi \ 
 -p raspberry \ 
 -i \ 
 -k
  1. 运行应用程序
./Television.OpenSSL

7.其他编译选项

本节将描述电视示例应用程序支持的其他ADK编译选项。以下选项可用于修改应用程序的行为。ADK做出选项:

在这里插入图片描述

8.电视用的PAL模块

8.1.基于证书的身份验证

基于PAL/POSIX/HAPPlatformMFiSWAuth.c中提供的基于AirPlay视频MFiServerTEETask实现的演示实现。

要编译启用了基于证书的身份验证的电视示例附件,请使用以下命令:

make TARGET=Raspi PROFILE=Television apps

使目标=Raspi配置文件=电视应用程序

ADK不附带测试证书

8.2.AirPlay视频共享钥匙存储器界面

以下PALAPi可以使HomeKit集成到AirPlay共享KeyStore中:

• HAPPlatformAirPlayTEEGetDeviceID
• HAPPlatformAirPlayTEESignBytes
• HAPPlatformAirPlayTEEGetLTPK
• HAPPlatformAirPlayTEEPairingAdd
• HAPPlatformAirPlayTEEPairingSetPermissions
• HAPPlatformAirPlayTEEPairingRead
• HAPPlatformAirPlayTEEPairingRemove
• HAPPlatformAirPlayTEEPairingsEnumerateCallback
• HAPPlatformAirPlayTEEResetPairings
• HAPPlatformAirPlay

请参见文件PAL/POSIX/hAPARPARPLAyTEE.h和PAL/PAR/HAPARPLAyTEE.c集成。

注意:如果访问底层TEE的速度很慢,那么可能可以在HAP平台格式的AirPlayTEE接口中缓存对、Ed25519 LTPK和设备ID。所提供的实现已经包含了一种缓存配对索引的机制。

8.3.AirPlay视频 Socket机制

HomeKit SDK提供了一个AirPlay视频插座机制。它使用一个本地文件系统套接字与AirPlay视频(/tmp/AirPlay控制器)通信。文件系统套接字可以通过在电视和AirPraySDK中设置AIRPLAY2_CONTROLLER_SOCKET_PATH定义来配置。AirPlay视频中的服务器端在AirPlay控制器中实现了。AirPlayControllerClient.{c/h},客户端在AirPlay.c中的电视应用程序中实现。电视应用程序还实现了一个简单的本地测试实现。如果平台不支持文件系统套接字,则该实现可以用于提供基于网络的套接字。

套接字机制使用简单的TLV8消息来进行通信,而不需要进行身份验证。必须确保只有电视应用程序连接到插座。

8.4.自定义唤醒配置

有两个唤醒配置服务可用,但一次只能在附件上启用一个。通过在构建/makkefile8.5中设置= USE_CUSTOM_LPM = 0,可以禁用自定义唤醒配置服务。

8.5唤醒局域网/无线局域网配置

通过禁用自定义唤醒配置(参见第8.4节)和在构建/创建文件中设置USE_WOLAN_LPM = 1,可以启用局域网/无线局域网上的唤醒配置服务。

总结
提供了局域网/无无线局域网低功耗模式功能,以帮助实现和集成ADK IP附件的低功耗模式,如电视。这个功能可以与或没有奖金睡眠代理一起使用。

为了启用此功能,ADK提供了:

  • HAP特性,使Homekit能够在附件上配置低功耗模式设置。
  • HAP级功能还准备进入和退出LPM的附件。
  • 一个到mDNS响应器的接口,它将用一个奖金睡眠代理(BSP)注册附件。

注:供应商负责将附件置于低功耗模式(LPM)中。传统上,将设备放入LPM中意味着只有它的网络接口卡是活动的,以便寻找神奇的数据包(这会唤醒它)。

请阅读HAP规范,了解支持的睡眠配置特征,详细信息,这将提供如何在附件上配置局域网/无线局域网设置的说明。

Bonjour睡眠代理

A Bonjour Sleep Proxy acts as the accessory’s proxy when it’s in low power state and responds to all the
requests intended for the accessory after successful registration of the accessory. This also includes
responding to the mDNS requests which allows the accessory to stay in low power state and suspend its
network activities while tricking other devices in the network that it’s still active and reachable.
The BSP can wake up the suspended accessory by sending a magic packet when a connection/request is
targeted for one of the services the accessory has registered with the BSP. HomeKit resident controllers
such as ATVs and HomePods offer BSPs by default and can manage the suspended IP accessories. The
BSP is also an open standard that is implemented on other devices like routers.

当配件处于低功率状态时,奖金睡眠代理作为配件的代理,并在成功注册配件后响应所有请求。这还包括响应mDNS请求,这允许附件保持在低功耗状态,并暂停其网络活动,同时欺骗网络中的其他设备,使它仍然是活动的和可访问的。当连接/请求针对附件注册的服务时,BSP可以通过发送魔法包来唤醒挂起的附件。HomeKit居民控制器,如atv和HomePods默认提供bsp,并可以管理挂起的IP配件。BSP也是一个开放标准,可以在路由器上实现其他设备。

需要进行的供应商代码修改

1.在附件上实现低功率模式。

2.关于何时输入LPN的选择将根据供应商的实现情况而有所不同。当需要进入低功耗模式时,更新休眠附件的运行状态,并在进入低功耗模式之前调用提供的HAP功能(输入低功率模式())。这将关闭所有打开的TCP会话,并更新Bonjour记录,以使用唤醒号(w#)而不是配置号(c#)。

3.当附件从低功耗模式唤醒时,更新休眠附件的运行状态,并调用提供的HAP功能(())。这将更新Bonjour记录,使其使用配置号(c#),而不是唤醒号(w#)。

4.可选:在将附件置于低功耗模式之前,请使用BSP进行注册。休眠状态可以通过其AF_UNIX低功率模式控制插座通信到基于mDNSRanperder的服务发现,从而将已注册的附件服务传输到本地网络上的Bonjour休眠代理服务器。

树莓派低功率模式模拟

要启用树莓派低功耗模式模拟,请在构建/制造文件中设置USE_WOLAN_LPM = 1、USE_WOLAN_SIMULATION = 1和HAP_TESTING = 1。为了测试目的,我们为树莓派提供了一个基于防火墙的电源管理器模拟。

这并打算在实际部署中使用。该实现实际上并没有实现真正的电源管理api。相反,睡眠状态是通过使用网络过滤器安装防火墙规则来模拟的,它可以在睡眠时阻止所有的ARP和IP流量。因此,实现不能依赖标准网络行为在唤醒后重新声明IP地址,所以每次模拟唤醒时,它都会发送ARP和NDP NA包。

局域网唤醒支持也使用侦听器套接字进行模拟,该套接字扫描使用非官方的WoL以太类型0x0842发送的WoL魔法数据包。其他的WoL数据包不被仿真处理,尽管真实的硬件也会支持不同的数据包。

模拟的睡眠状态通过其AF_UNIX低功率模式控制插座通信给基于mDNSRappender的服务发现。这使得我们的注册服务在睡眠时保持在网络上的可用性,通过将它们转移到本地网络上的奖金睡眠代理服务器。当客户试图连接到我们广告中宣传的DNS-SD服务时,奖金睡眠代理就会发送一个魔法包来唤醒我们。

请注意,唤醒也可能出现在其他原因上(例如,当BSP离线时)。在这种情况下,应用程序有责任重新进入低功耗模式,例如等待短时间来查看客户端在醒来后是否连接到相关的广告服务。唤醒我们的原因只能用这样的启发式方法来确定。

利用树莓派LPM模拟的调用流

1.注册回调,以通知应用程序在电源状态中的更改。

在这种情况下,回调是处理电源管理器的睡眠状态已改变。

//观察电源管理器
HAPPlatformPowerManagerDelegate
电源管理器委托;(电源管理代表,电源管理代表)
powerManagerDelegate.handleSleepStateChanged=处理电源管理器休眠状态改变;

2.要通知电源管理器,配件需要睡眠(支持树莓派LPM模拟)
HAPPlatformPowerManagerSleep(accessoryConfiguration.powerManager);
//调用此函数后,将触发处理电源管理器睡眠状态更改(电源管理器状态的注册代理)。

3.通知附件电源管理器要进入休眠(输入LPM)
调用注册通知附件电源状态更改的委托,处理电源管理器休眠状态更改。睡眠状态将为“kHAPPlatformPowerManagerSleepState_EnteringSleep”.

使用这个回调,ADK能够防止附件睡觉,直到我们通过调用ADK提供的函数HAPPlatformPowerManagerSetPreventSleep.来执行所有必要的清理活动此功能将把电视设置为非活动状态,关闭所有打开的TCP会话,并将Bonjour文本记录从使用配置号(c#)更新为唤醒号(w#)。所有其他附件特定的清理都需要由供应商来实施。

4.电源管理器通知附件已开始唤醒(退出LPM)

睡眠状态更改()被调用。睡眠状态将是“kHAPPlatformPowerManagerSleepState_Awake”。

使用此回调,应用程序休眠操作状态状态将更新为已配置。所提供的ADK提供的功能是,()将把奖金文本记录从使用唤醒号(w#)更新为配置号(c#)。所有其他附件特定的唤醒需要由供应商实施。

5.附件通知电源管理器,它是时候唤醒了(退出LPM)

这是通过调用树莓派LPM模拟函数HAPPlatformPowerManagerExitSleep.来完成的必要时的一个例子是,当使用遥控器来打开电视时。

8.6.集成说明

以下集成说明是成功利用电视档案的ADK实现的关键:

  1. 电视示例应用程序使用它自己的一个单独的键值存储区来存储其配置数据。电视键值存储的默认位置是<工作目录>/。家庭小猫商店,或简单的家庭,应用程序/电视。HomeKit的配置需要直接进入电视密钥值存储。
  2. 工厂重置需要全局应用。
  • 详细的重置步骤如下(请参见电视示例中的App.c -附件服务器处理更新状态):

1。停止HomeKit操作。
2.停止播放播放视频。
3.重置空气播放视频配对。

4.重置AirPlay视频标识(即,从共享密钥存储库中删除kSharedKeyStoreLocalIdentifier,kSharedKeyStoreLocalPublicKey和kSharedKeyStoreLocalPrivateKey)。

5.HomeKit重置(HAPRestoreFactorySettings,平台键价值存储购买域,HAPRestoreFactorySettings,恢复平台组件设置)。
6.开始播放播放视频。
7.触发器kAirPlayProperty_HomeKitAccessControlEnabled是错误的。
8.启动HomeKit。

  • 需要按照提供的示例代码完全停止该服务器。
  • 在AirPlay视频中设置kAirPlayProperty_HomeKitAccessControlEnabled为false将触发HomeKit中的重置。当AirPlay视频中触发动作kAirPlayCommand_UnpairHomeKit时,AirPlay视频的补丁将kAirPlayProperty_HomeKitAccessControlEnabled设置为false。
  • 只有在所有内容都干净停止后,才可以调用
  • 恢复数设置,这将共享键存储的HomeKit特定部分重置为出厂设置。
  • 平台存储域0x40包含需要在工厂重置时保存的供应数据——如果必要,此行为可以在◦平台附件安装程序中进行调整。
  1. libhap.a需要大约2 KB的安全闪存来存储16对的所有密钥(仅IP,没有标记认证)。键值对的存储可以在文件中或直接在芯片闪存或EEPROM存储器上。基于键值存储的闪存实现可能需要比HAP多两倍的闪存。可能需要额外的闪存,例如,因为在删除旧扇区之前必须写入闪存扇区的副本(参见键值存储章节)

8.7.未配对配件的Bonjour名称

用户可以在电视上更改未配对配件的名称,这样的名称更改必须反映在Bonjour上。在ADK中,在第一次启动附件服务器之前,将HAPAccesory结构的名称属性设置为新值。

static const HAPAccessory accessory = {
 .aid = 1,
 .category = kHAPAccessoryCategory_Televisions,
 .name = "Acme Television", // <<- This is the Bonjour name, and also what
is put as Name into Accessory Information Service. Once HAP is running it is
immutable.
 .manufacturer = "Acme",
 .model = "Television1,1",
 .serialNumber = "099DB48E9E28",
 .firmwareVersion = "1",
 .hardwareVersion = "1",
 .services = (const HAPService *const[]) {
 &accessoryInformationService,
 &hapProtocolInformationService,
 &pairingService,
 &televisionService,
 &inputSourceHomeScreenService,
 &inputSourceTunerService,
 &inputSourceHDMI0Service,
 &inputSourceHDMI1Service,
 &inputSourceHDMI2Service,
 &inputSourceCompositeVideoService,
 &inputSourceSVideoService,
 &inputSourceComponentVideoService,
 &speakerService,
 &microphoneService,
 &occupancySensorService,
 &lightSensorService,
 &accessControlService,
 NULL
 },
 .callbacks = {
 .identify = IdentifyAccessory
 }
}

一旦HAPAncseroryServer第一次在一个给定的附件上运行,其名称必须不再更改以满足HAP规范在第9.1节附件信息中要求附件名称即使在解除/重新/固件更新和工厂重置中都是不可变的。就ADK而言,在停止辅助服务器的时候,在技术上可以设置新的名称(例如,您可以停止HomeKit服务器,更改名称,并重新启动HomeKit服务器)

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

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

相关文章

高通Android 13默认切换免提功能

1、测试部反馈 由于平板本身没有听筒功能 因此考虑工厂直接切换到免提功能 2、修改路径 frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp 3、编译源码ok 拨打紧急号码 可以正常切换到免提功能 其他mtk平台可能不一样 具体以项目实际为准 相关链接 构建…

ESP32编译及运行错误记录

1、打印格式不对 一般都是因为日志中某个参数打印格式不匹配造成。 ESP_LOGI(TAG, "[APP] Free memory: %lu bytes", esp_get_free_heap_size());//将之前的%d 改为%lu 2、配置载不对 这里选择了蓝牙模块需要引入蓝牙组件才能编译通过 idf.py menuconfig Component…

项目中的MD5、盐值加密

首先介绍一下MD5&#xff0c;而项目中用的是MD5和盐值来确保密码的安全性&#xff1b; 1. md5简介 md5的全称是md5信息摘要算法&#xff08;英文&#xff1a;MD5 Message-Digest Algorithm &#xff09;&#xff0c;一种被广泛使用的密码散列函数&#xff0c;可以产生一个128位…

css-盒模型

巧妙运用margin负值盒模型和怪异盒模型(border padding 包含在内)display: block 能让textarea input 水平尺寸自适应父容器? – 不能 * {box-sizing: border-box; // bs: bb }<textarea/> 是替换元素,尺寸由内部元素决定,不受display水平影响. 当然可以直接设置宽度10…

React(三):脚手架、组件化、生命周期、父子组件通信、插槽、Context

React&#xff08;三&#xff09;一、脚手架安装和创建1.安装脚手架2.创建脚手架3.看看脚手架目录4.运行脚手架二、脚手架下从0开始写代码三、组件化1.类组件2.函数组件四、React的生命周期1.认识生命周期2.图解生命周期&#xff08;1&#xff09;Constructor&#xff08;2&…

Allegro如何导入第一方网表操作指导

Allegro如何导入第一方网表操作指导 在启动PCB设计之前,网表的导入是首要的流程,第一方网表内容如下图 如何将第一方网表导入到PCB中,具体操作如下 点击File点击Import

【项目】用户管理系统

一、需求分析完成一个简单的用户信息管理系统&#xff0c;超级管理员可以登录本系统&#xff0c;查询用户信息、实现用户的管理功能。1.1功能&#xff1a;主要操作和管理的对象&#xff1a;用户。用户分为两类&#xff1a;超级管理员/普通用户。登录功能&#xff08;只针对超管…

深入理解多进程

多进程 一、进程状态 二、创建子进程 - fork 1、函数接口 #include <unistd.h>pid_t fork(void);2、基本概述 成功后&#xff0c;子进程的 PID 在父进程中返回&#xff0c;在子进程中返回 0。 失败时&#xff0c;在父进程中返回 -1&#xff0c;不创建子进程&#xff0c…

MyBatis——进阶操作(2)

标签 if标签 当提交的表单中有些为非必填项&#xff0c;用户并没有上传这些属性的值&#xff0c;那么程序可以上传NUll&#xff0c;也可以用if标签判断用户有没有上传这个值 <if test"参数!null">操作 </if>其中test中填写一条语句&#xff0c;如果得…

uniapp实现地图点聚合功能

前言 在工作中接到的一个任务&#xff0c;在app端实现如下功能&#xff1a; 地图点聚合地图页面支持tab切换&#xff08;设备、劳务、人员&#xff09;支持人员搜索显示分布 但是uniapp原有的map标签不支持点聚合功能&#xff08;最新的版本支持了点聚合功能&#xff09;&am…

爬虫碎碎念

20230304 - &#xff08;非专业人士&#xff0c;简单记录自己的需求和思考&#xff09; 0. 引言 平时看到一些网站的照片什么的&#xff0c;有那种批量下载的需求&#xff0c;当然有些也是视频网站的图片介绍什么的&#xff0c;也即是说&#xff0c;我需要把这些网站的照片批…

剑指 Offer II 013. 二维子矩阵的和

题目链接 剑指 Offer II 013. 二维子矩阵的和 mid 题目描述 给定一个二维矩阵 matrix&#xff0c;以下类型的多个请求&#xff1a; 计算其子矩形范围内元素的总和&#xff0c;该子矩阵的左上角为 (row1, col1)&#xff0c;右下角为 (row2, col2)。 实现 NumMatrix类&#xf…

测开:前端基础-css

一、CSS介绍和引用 1.1 css概述 层叠样式表&#xff0c;是一种样式表语言&#xff0c;用来描述HTML和XML文档的呈现。 CSS 用于简化HTML标签&#xff0c;把关于样式部分的内容提取出来&#xff0c;进行单独的控制&#xff0c;使结构与样式分离开发。 CSS 是以HTML为基础&…

docker环境下安装jenkins

前言 废话不多说&#xff0c;上来就是干&#xff0c;jenkins是干嘛用的&#xff0c;小白的话&#xff0c;自己去查&#xff0c;首先我的环境时centos7&#xff0c;自己在vmware建立的一套centos虚拟机环境。docker版本如图所示: 第一步 其实可以先查看一下又那些镜像jenkin…

DC-5 靶场学习

文章目录环境配置&#xff1a;信息搜集&#xff1a;漏洞测试&#xff1a;漏洞利用&#xff1a;提权&#xff1a;得到flag&#xff1a;下载地址&#xff1a;环境配置&#xff1a; 直接将其与攻击机放在同一网段。 信息搜集&#xff1a; arp-scan -l nmap -sP 192.168.28.0/24漏…

基于SSH的网上图书俱乐部的设计与实现

技术&#xff1a;Java、JSP等摘要&#xff1a;网上图书俱乐部是一个虚拟的书友会&#xff0c;该平台是为了给那些爱好读书的人提供一个网上交流的场所。以服务广大读者朋友为主&#xff0c;强调互动性、知识性、趣味性&#xff0c;是读书、会友的好去处&#xff0c;读者可以在线…

【Spring学习】Spring自定义标签详细步骤

目录标题前言一、自定义标签步骤1、定义属性POJO2、定义XSD文件描述组件内容3、定义标签解析器4、注册标签解析器5、定义spring.handlers和spring.schemas文件6、user.xml文件配置7、测试类二、仓库位置总结前言 Spring中除了http://www.springframework.org/schema/beans命名…

pytorch-在竞赛中去摸索用法,用房价预测比赛了解数据处理流程

实战Kaggle比赛&#xff1a;房价预测 让我们动手实战一个Kaggle比赛&#xff1a;房价预测House Prices - Advanced Regression Techniques | Kaggle。本文将提供未经调优的数据的预处理、模型的设计和超参数的选择。通过动手操作、仔细观察实验现象、认真分析实验结果并不断调…

5分钟被美团面试官请出去,3年测试经验被这几个题问到心虚

5分钟前&#xff1a;“哥们我去美团面试了&#xff01;祝我好运~”5分钟后&#xff1a;“刚从美团走出来&#xff0c;被自动化测试的一些面试题难到了…”“越想越觉得可惜回想面试经过&#xff0c;在几个关键的问题没有给到面试官想要的答案。”“我不是不会&#xff0c;我都干…

工业互联网标识解析二节节点平台_能源管理工业互联网大数据平台

能源管理工业互联网大数据平台项目&#xff0c;是由吉佳通达负责建设的&#xff0c;通过建设形成能源管理的数字化产业基地&#xff0c;推动能源数字化转型升级&#xff0c;形成大数据运营平台。以能源管理与各个企业节点进行数据对接后&#xff0c;利用工业互联网唯一标识身份…