View in English

  • 打开菜单 关闭菜单
  • Apple Developer
搜索
关闭搜索
  • Apple Developer
  • 新闻
  • 探索
  • 设计
  • 开发
  • 分发
  • 支持
  • 账户
在“”范围内搜索。

快捷链接

5 快捷链接

视频

打开菜单 关闭菜单
  • 专题
  • 相关主题
  • 所有视频
  • 关于

更多视频

  • 简介
  • 概要
  • 转写文稿
  • 代码
  • 使用 EnergyKit 优化家庭用电量

    了解如何在你的 App 中支持 EnergyKit,以便用户可以优化家庭用电量。这可以帮助用户在电力更清洁、更便宜的时段运行电器或为电动汽车充电。详细了解如何进行设置,如何生成充电计划,以及如何通过用电量反馈向用户提供能耗洞察信息等详情。

    章节

    • 0:00 - 简介
    • 2:08 - 启用 EnergyKit
    • 3:28 - 生成充电计划
    • 7:35 - 洞察信息
    • 14:58 - 后续步骤

    资源

    • Apple 2030
    • Optimizing home electricity usage
      • 高清视频
      • 标清视频

    相关视频

    WWDC25

    • 完成后台任务
    • 探索 SwiftUI 中的并发机制
  • 搜索此视频…

    大家好 我是 Dakshil 很高兴向大家介绍 EnergyKit 家庭使用的电力 在一天之中来自不同的来源 这可能包括太阳能和 风能等可再生能源 或者煤炭和天然气等化石燃料 为此 我们首先在“家庭”App 中 推出了“电网预测”功能 它让美国本土的用户可以查看 电网在一天中的哪些时段 可以提供来源相对清洁的电力 我们还让“家庭”App 中的 “能源”类别更具个性化和可操作性 方法是将用户的家庭用电情况直接 整合到使用体验中 这些功能都依托于 EnergyKit 我们很高兴将这个框架提供给大家 用于住宅应用程序方面的开发 EnergyKit 支持将当地的 电网洞察信息整合到 你的 App 中 从而帮助用户减少用电量 或调整用电时间 达到省钱的目的 例如 如果你是一个电动汽车制造商 或智能恒温器制造商 EnergyKit 可以帮助你选择用电时间 让你能够优先考虑更清洁 且可能更便宜的时段 例如 EnergyKit 可以帮助 电动汽车制造商 将充电时间调整到电网电力更清洁 且可能更便宜的时段 在本次讲座中 我们将介绍如何 将 EnergyKit 整合到你的 App 中 你将学习如何获取用电指导 以及调整 App 管理的 电动汽车充电计划 此外 我们还将展示如何 利用 EnergyKit 洞察信息 打造出色的用户体验

    首先我们来看看如何 帮助用户开始使用 EnergyKit

    要将 EnergyKit 整合到你的 App 中 首先需要用户选择启用 “清洁能源充电”体验 并为他们希望使用更清洁 电力的每个充电地点选择这个体验 在我们的示例 App 中 有一个充电地点列表 其中列出了你为电动汽车充电的位置 我们添加了一个开关 以便用户选择 在这个地点充电时 为他们的电动汽车启用 “清洁能源充电”体验

    EnergyVenue 是一个实体场所 由你的 App 控制的设备 将在这里使用电网电力并且 场所的所有者已通过“家庭”App 或 EnergyKit 用户引导流程 创建了一个家庭环境 在用户启用“清洁能源充电”后 我们会检索这个地点附近的 EnergyVenue 列表 如果用户选择了场地 你应该永久保留 所选场地到充电地点的映射 直到他们选择停用 建议在本地存储 场地的唯一标识符 用户每次启动 App 时 你都要检查所选场地是否存在 你可以使用之前保存的 场地标识符来检索所选场地 现在 你已确定用户想要使用 清洁能源充电功能 并选择了 EnergyVenue 下一步是制定清洁能源充电计划 要制定清洁能源充电计划 你需要获取预测信息 来引导计划的制定 我们将这种预测信息称为 “用电指导” 这种指导是基于多种信息生成的 包括家庭地点、 有关相应地点的电网信息 如碳排放 或是否有可再生能源正在发电 以及可能存在的公共事业账户信息 有两种类型的指导操作可供选择: 减少和调整 “减少”指导操作用于 旨在减少用电量的设备 例如智能恒温器 “调整”指导操作用于 电动汽车等设备 可以将它们的用电时间 从一个时段调整到另一个时段 但所用电量保持不变 我们来看一个例子 这个示意图显示了一个 EnergyVenue 所对应的用电指导 指导值的范围为从 0 到 1 由 Y 轴表示 其中较低的值表示电力较清洁的时段 如果提供了电费方案信息 则同时也可能是较便宜的时段 在我们的示例中 用户已将 公共事业账户加入“家庭”App 并且采用了分时电费方案 这个方案在下午 4 点 到 9 点之间电价较贵 汽车在下午 6:30 左右接通电源 你的充电偏好可能知道 用户在早上 9 点左右 为汽车断开电源 或充电截止时间为早上 9 点

    因此充电时段为 下午 6:30 到第二天早上 9 点

    如果不对充电计划应用指导 汽车可能会在下午 6:30 立即开始充电 从清洁度和费用角度来看 这并非最有利的选择 但是 我们可以通过选择时间 来优化充电计划 确保在更清洁且可能 更便宜的时段为汽车充电

    让我们来看看 如何为所选 EnergyVenue 获取这种用电指导 首先将一个 名为 streamGuidance 的方法 添加到 EnergyVenueManager 当我们获得更新时 我们会将它存储在 guidance 变量中

    我们需要创建一个查询 来检索我们用例的指导 对于电动汽车 建议的操作类型是调整用电时间 我们现在已准备好检索 针对相应 EnergyVenue 的指导 ElectricityGuidance 有一个 sharedService 辅助函数 后者应该用于检索指导 你会得到一个 AsyncSequence 这个结果会在 EnergyKit 收到更新的指导后进行更新 如需了解更多信息 请观看视频 “揭秘 SwiftUI 中的并发机制” 如果你不需要持续监听更新 可以在第一次获取指导后跳出循环 你可以从 Task 调用 streamGuidance 如果 App 需要在后台进行更新 则应从后台任务处理程序 调用这个方法 如果 App 具有交互式充电小组件 你还可以利用这个小组件 在 App 未运行时 及时更新指导 如需了解更多信息 请观看视频 “完成后台任务”

    现在 你可以循环遍历指导值 以确定更理想的充电时间 借助 EnergyKit 洞察信息 你可以通过 便于用户理解的格式提供电力信息 你可以使用提供的洞察信息告诉用户 他们为车辆充电所用的电力有多少 是在清洁电力时段 从而帮助减少 家庭用电的碳排放 车辆的用电按电网清洁度进行分类 并分为以下三类: clean、reduce 和 avoid 你还可以告知用户 相对便宜时段的用电量 车辆的用电按电费方案进行分类 (如果有电费方案的话) 并分为以下五类: superOffPeak、offPeak、partialPeak、 onPeak 和 criticalPeak

    电费方案也称为电价表 下一个问题是: 这些洞察信息是如何运作的? 洞察信息受多种因素的综合影响 用于根据提供的指导来调整用电 时间或减少用电量的算法 将决定受控设备是否 在更清洁或更便宜的时段用电 设备用电时所在电网的状态 取决于多种因素 例如电力需求 在网的可再生能源发电机、 电网排放情况等 如果用户已将公共事业账户 加入“家庭”App 并且采用了分时电费方案 系统可将用电量 归属到不同的使用时段 并返回用电的相对成本 还有最重要的一点是 你的设备如何以及何时用电 这取决于设备的行为、 用户交互 以及你的 App 如何将指导应用于设备 对于电动汽车制造商来说 这将是汽车的 充电会话行为 为了就车辆充电时所用电力的 清洁度和相对成本生成洞察信息 你的 App 必须 向 EnergyKit 提交反馈 我们将这种反馈称为 LoadEvent 你应该在车辆充电期间定期创建事件 在充电会话期间 车辆的充电状态会发生变化 充电会话开始时 创建一个事件来表示车辆在会话 开始时的状态 在车辆充电过程中 定期创建事件 当车辆以稳定的速率充电时 我们建议每 15 分钟创建一个事件 如果发生重大事件 比如会话暂停、 由于应用了新的指导集 而导致充电计划发生变化 或功耗快速变化 请同样创建事件 充电会话结束时 使用表示车辆最终状态的事件 关闭会话 为了让 EnergyKit 为创建的事件 生成洞察信息 你需要将事件提交给 EnergyKit 你可以在事件发生时提交事件 也可以定期分批提交 甚至可以在充电会话结束时批量提交 建议批量提交事件以提高性能 请勿在充电会话之间提交事件 让我们来看看如何 创建和提交这些事件 对于一个充电会话 最重要的信息是: 电池的充电状态、 特定时刻的功耗、 以及自充电会话开始以来的累计能耗 当车辆开始充电时 我们认为这是会话的开始

    这个事件表示车辆在充电会话 开始时的初始状态 这个指导状态指示会话是否已开始 因为充电计划遵循了 由指导令牌表示的 用电指导 这个令牌对于检索到已生效 的指导信息的手机而言是唯一的 并将用于在这台手机上创建事件 随着充电的进行 会话被标记为 active 充电会话结束后 会话将以 end 事件关闭 这个事件代表车辆在充电会话 结束时的最终状态 在示例 App 中 我们会创建 LoadEvent 并缓存它们 直到我们可以批量提交 这些批处理事件将提交到 车辆充电时所在的 EnergyVenue 你提交的事件 将根据 Apple 的隐私政策 存储在设备上的 Core Data 中 并通过端到端加密备份到 CloudKit 这些数据还将与已共享 HomeKit 家庭且共享的家庭 与提交事件的 EnergyVenue 相关联的所有用户共享 现在 我们终于拥有了 生成洞察信息所需的所有信息 为了检索洞察信息 我们首先创建一个查询 并在这个查询中指出我们感兴趣的是 清洁度和可能存在的相对成本 方面的洞察信息 在我们的示例 App 中 我们想要显示 前一天的用电量摘要 创建查询后 我们可以获取车辆在之前的某个 充电场地的洞察信息 我们会得到一个 AsyncStream 由于我们是对某一天的 洞察信息感兴趣 我们可以根据需要过滤这个流 检索到的洞察信息 现在可用于创建摘要 你的 App 现已整合 EnergyKit 在本次讲座中 我们介绍了与 EnergyKit 进行交互的各个环节 对于用户引导环节 我们了解了 用户如何与你的 App 交互 以选择 EnergyVenue 然后 我们介绍了如何 使用所选 EnergyVenue 获取用电指导 并依据指导生成充电计划

    生成充电计划后 我们基于车辆的充电过程 介绍了需要将 LoadEvent 作为反馈提交给 EnergyKit 以推动生成洞察信息 最后 我们探讨了如何请求 根据检索到的指导和 App 提交的反馈生成的洞察信息 从而为用户提供出色的体验 你可以下载本次讲座附带的示例 App 也可以 前往 developer.apple.com/cn 访问相应 EnergyKit 文档 Apple 致力于保护环境 你可以访问 apple.com.cn/2030 进一步了解相关信息 我们期待看到 你使用 EnergyKit 构建的出色 App

    • 3:13 - Retrive an EnergyVenue

      // Retrieve an EnergyVenue
      
      import EnergyKit
      import Foundation
      
      @Observable final class EnergyVenueManager  {
      
          let venue: EnergyVenue
      
          init?(venueID: UUID) async {
              guard let energyVenue = await EnergyVenue.venue(for: venueID) else {
                  return nil
              }
              venue = energyVenue
          }
      }
    • 6:03 - Fetch Electricity Guidance at a selected EnergyVenue

      // Fetch ElectricityGuidance
      
      import EnergyKit
      import Foundation
      
      @Observable final class EnergyVenueManager  {
          // The current active guidance.
          var guidance: ElectricityGuidance?
      
          fileprivate func streamGuidance(
              venueID: UUID,
              update: (_ guidance: ElectricityGuidance) -> Void
          ) async throws {
              let query = ElectricityGuidance.Query(suggestedAction: .shift)
              for try await currentGuidance in ElectricityGuidance.sharedService.guidance(
                  using: query,
                  at: venueID
              ) {
                  update(currentGuidance)
                	break
              }
          }
      }
    • 7:00 - Start monitoring Electricity Guidance

      // Fetch ElectricityGuidance
      
      import EnergyKit
      import Foundation
      
      @Observable final class EnergyVenueManager  {
          // The task used to stream guidance.
          private var streamGuidanceTask: Task<(), Error>?
      
          ///Start streaming guidance and store the value in the observed property 'guidance'.
          func startGuidanceMonitoring() {
             streamGuidanceTask?.cancel()
              streamGuidanceTask = Task.detached { [weak self] in
                  if let venueID = self?.venue.id {
                      try? await self?.streamGuidance(venueID: venueID) { guidance in
                          self?.guidance = guidance
                          if Task.isCancelled {
                              return
                          }
                      }
                  }
              }
          }
      }
    • 11:30 - Update charging measurements

      // Update charging measurements
      
      import EnergyKit
      
      // A controller that handles an electric vehicle
      @Observable class ElectricVehicleController {
          fileprivate func chargingMeasurement() -> ElectricVehicleLoadEvent.ElectricalMeasurement {
              let stateOfCharge = Int(configuration.state.stateOfCharge.rounded(.down))
              let power = Measurement<UnitPower>(
                  value: configuration.properties.chargingPower * 1000000,
                  unit: .milliwatts
              )
              let energy = Measurement<UnitEnergy>(
                  value: configuration.state.cummulativeEnergy * 1000000,
                  unit: .EnergyKit.milliwattHours
              )
              return ElectricVehicleLoadEvent.ElectricalMeasurement(
                  stateOfCharge: stateOfCharge,
                  direction: .imported,
                  power: power,
                  energy: energy
              )
          }
      }
    • 11:50 - Start a session

      // Start a session
      
      import EnergyKit
      
      // A controller that handles an electric vehicle
      @Observable class ElectricVehicleController {
          // The session
          var session: ElectricVehicleLoadEvent.Session?
      
          // The current guidance stored at the EV
          var currentGuidance: ElectricityGuidance
      
          // Whether the EV is following guidance
          var isFollowingGuidance: Bool = true
      
          fileprivate func beginSession() {
              session = ElectricVehicleLoadEvent.Session(
                  id: UUID(),
                  state: .begin,
                  guidanceState: .init(
                      wasFollowingGuidance: isFollowingGuidance,
                      guidanceToken: currentGuidance.guidanceToken
                  )
              )
          }
      }
    • 12:25 - Update a session

      // Update a session
      
      import EnergyKit
      
      // A controller that handles an electric vehicle
      @Observable class ElectricVehicleController {
          fileprivate func updateSession() {
              if let session {
                  self.session = ElectricVehicleLoadEvent.Session(
                      id: session.id,
                      state: .active,
                      guidanceState: .init(
                          wasFollowingGuidance:
                          isFollowingGuidance,
                          guidanceToken:
                          currentGuidance.guidanceToken
                      )
                  )
              }
          }
      }
    • 12:31 - End a session

      // End a session
      
      import EnergyKit
      
      // A controller that handles an electric vehicle.
      @Observable class ElectricVehicleController {
          fileprivate func endSession() {
              if let session {
                  self.session = ElectricVehicleLoadEvent.Session(
                      id: session.id,
                      state: .end,
                      guidanceState: .init(
                          wasFollowingGuidance:
                          isFollowingGuidance,
                          guidanceToken:
                          currentGuidance.guidanceToken
                      )
                  )
              }
          }
      }
    • 12:43 - Create a load event

      // Create a ElectricVehicleLoadEvent
      
      @Observable class ElectricVehicleController {
          fileprivate func createLoadEvent(
              sessionState: ElectricVehicleLoadEvent.Session.State
          ) {
              switch sessionState {
              case .begin:
                  beginSession()
              case .active:
                  updateSession()
              case .end:
                  endSession()
              @unknown default:
                  fatalError()
              }
              if let session {
                  let event = ElectricVehicleLoadEvent(
                      timestamp: configuration.state.timestamp,
                      measurement: chargingMeasurement(),
                      session: session,
                      deviceID: configuration.properties.vehicleID
                  )
                 events.append(event)
              }
          }
      }
    • 12:50 - Submit events

      // Submit events
      
      import EnergyKit
      
      // A controller that handles an electric vehicle
      @Observable class ElectricVehicleController {
          // EnergyVenue
          // The venue at which the EV uses energy
          var currentVenue: EnergyVenue
      
          // Electric EV Events
          // The list of generated EV load events
          var events = [ElectricVehicleLoadEvent]()
          
          func submitEvents() async throws {
              try await currentVenue.submitEvents(events)
          }
      }
    • 13:25 - Create an insight query

      // Create an insight query
      
      import EnergyKit
      
      @Observable final class EnergyVenueManager  {
          func createInsightsQuery(on date: Date) -> ElectricityInsightQuery {
              return ElectricityInsightQuery(
                  options: .cleanliness.union(.tariff),
                  range: self.dayInterval(date: date),
                  granularity: .daily,
                  flowDirection: .imported
              )
          }
      }
    • 13:43 - Request insights

      // Request an insights
      
      import EnergyKit
      
      @Observable final class EnergyVenueManager  {
          func generateInsights(for vehicleIdentifier: String, on date: Date) async throws ->
    ElectricityInsightRecord<Measurement<UnitEnergy>>? {
              let query = createInsightsQuery(on: date)
              return try await ElectricityInsightService.shared.energyInsights(
                  forDeviceID: vehicleIdentifier,
                  using: query,
                  atVenue: self.venue.id
              ).first { record in
                  return record.range.start == query.range.start
              }
          }
      }
    • 0:00 - 简介
    • 借助 EnergyKit 框架,你可以将本地电网洞察整合到你的 App 中,以便用户在使用智能恒温器等设备或为电动汽车充电时可以减少用电量、节省资金并优先使用更清洁的能源。

    • 2:08 - 启用 EnergyKit
    • 要加入 EnergyKit,用户需要选择在特定地点启用清洁能源充电功能。你的 App 会检索地点 (称为 EnergyVenue) 并存储其标识符。

    • 3:28 - 生成充电计划
    • EnergyKit 会根据地点、电网信息和公共事业数据提供用电指导,以制定清洁能源充电计划。它可以建议“减少”操作 (对于智能恒温器等设备) 或“调整”操作 (对于电动汽车充电等用途)。用电指导优先考虑更清洁、更便宜的非高峰时段,从而减少成本和对环境的影响。

    • 7:35 - 洞察信息
    • EnergyKit 洞察信息有助于简化向用户呈现用电信息的过程,并可以根据电网清洁度对用电进行分类。 为了让电动汽车制造商获得洞察,App 会以 LoadEvents 的形式向 EnergyKit 提供反馈,跟踪充电会话期间的进度。通过批处理和提交这些事件,EnergyKit 可以准确地分析充电数据。

    • 14:58 - 后续步骤
    • 在你的 App 中采用 EnergyKit 来管理电量。更多详细信息,请参阅本讲座随附的示例代码。

Developer Footer

  • 视频
  • WWDC25
  • 使用 EnergyKit 优化家庭用电量
  • 打开菜单 关闭菜单
    • iOS
    • iPadOS
    • macOS
    • Apple tvOS
    • visionOS
    • watchOS
    打开菜单 关闭菜单
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    打开菜单 关闭菜单
    • 辅助功能
    • 配件
    • App 扩展
    • App Store
    • 音频与视频 (英文)
    • 增强现实
    • 设计
    • 分发
    • 教育
    • 字体 (英文)
    • 游戏
    • 健康与健身
    • App 内购买项目
    • 本地化
    • 地图与位置
    • 机器学习与 AI
    • 开源资源 (英文)
    • 安全性
    • Safari 浏览器与网页 (英文)
    打开菜单 关闭菜单
    • 完整文档 (英文)
    • 部分主题文档 (简体中文)
    • 教程
    • 下载 (英文)
    • 论坛 (英文)
    • 视频
    打开菜单 关闭菜单
    • 支持文档
    • 联系我们
    • 错误报告
    • 系统状态 (英文)
    打开菜单 关闭菜单
    • Apple 开发者
    • App Store Connect
    • 证书、标识符和描述文件 (英文)
    • 反馈助理
    打开菜单 关闭菜单
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program (英文)
    • News Partner Program (英文)
    • Video Partner Program (英文)
    • 安全赏金计划 (英文)
    • Security Research Device Program (英文)
    打开菜单 关闭菜单
    • 与 Apple 会面交流
    • Apple Developer Center
    • App Store 大奖 (英文)
    • Apple 设计大奖
    • Apple Developer Academies (英文)
    • WWDC
    获取 Apple Developer App。
    版权所有 © 2025 Apple Inc. 保留所有权利。
    使用条款 隐私政策 协议和准则