☰
Windows-universal-samples 中的 PowerGrid 电网预测示例:获取预测、订阅更新与查找最优时段
2026/9/25 3:36:50 网站建设 项目流程
  • 示例工程

【免费下载链接】Windows-universal-samples

API samples for the Universal Windows Platform.

项目地址:https://gitcode.com/gh_mirrors/wi/Windows-universal-samples
点击查看免费下载

本指南以 Samples/PowerGrid/README.md 为主线,深入讲解 Windows Universal Platform(UWP)下Windows.Devices.Power.PowerGridForecast电网预测 API 的完整用法。你将掌握如何获取电网预测数据、订阅ForecastUpdated更新通知、以及在指定时间范围内筛选最低严重级别时段,并看到 C# 与 C++/WinRT 两套语言实现中对应的源码级细节。

示例概述

PowerGrid 示例展示了如何调用 Windows 11 的 PowerGrid Forecast(电网预测)API。根据官方 README,该示例覆盖三个核心主题:

  • Obtaining the power grid forecast:获取电网预测数据;
  • Registering for ForecastUpdated notifications:注册预测更新通知;
  • Looking for the lowest severity in a specified timeframe:在指定时间段内寻找严重级别(Severity)最低的时段。

预测数据由系统按固定时间块(block)组织:每个块都有一个起止时间(由StartTime与BlockDuration决定)、一个严重级别数值Severity,以及一个布尔标志IsLowUserExperienceImpact,用来标记该时段是否属于“低用户体验影响”窗口(例如适合执行耗电任务或后台更新的时段)。

该示例是 Windows-universal-samples 大型 UWP 示例集合中的一员,需要在 Visual Studio 中构建、在 Windows 11 上运行。示例包含两个场景,注册逻辑位于各语言的SampleConfiguration文件中:

  • Find best time(Scenario1_FindBest):在用户指定的“未来 N 小时”内寻找严重级别最低的时间块;
  • Display full forecast(Scenario2_PrintFullForecast):把整份预测按时间块逐条展示在列表中。

C# 的注册代码见 Samples/PowerGrid/cs/SampleConfiguration.cs,C++/WinRT 版本见 Samples/PowerGrid/cppwinrt/SampleConfiguration.cpp,两个版本都把FEATURE_NAME定义为"PowerGrid",并分别把两个场景的Type(C#)或xaml_typename(C++/WinRT)注册进导航列表。

系统要求与构建环境

README 明确给出了示例的运行前提,这也是 PowerGridForecast API 的最低要求:

  • Windows 11 SDK(build 26100 或更高);
  • Windows 11(build 26100 或更高)。

Package.appxmanifest中的目标设备族配置与此一致:C# 与 C++/WinRT 两个工程都把TargetDeviceFamily的MinVersion和MaxVersionTested设置为10.0.26100.0,见 Samples/PowerGrid/cs/Package.appxmanifest 与 Samples/PowerGrid/cppwinrt/Package.appxmanifest。因此若要在低于 build 26100 的系统中编译或运行,API 将不可用。

构建步骤(README 原文要点):

  1. 如果下载的是示例 ZIP 压缩包,务必解压整个归档,而不是只解压要构建的那一个子目录——整个示例集合共享SharedContent等公共依赖;
  2. 启动 Microsoft Visual Studio,选择File > Open > Project/Solution;
  3. 在解压目录下依次进入Samples子目录、本示例子目录(PowerGrid)、再进入首选语言子目录(cs或cppwinrt),双击其中的解决方案文件(.sln),例如 Samples/PowerGrid/cs/PowerGrid.sln 或 Samples/PowerGrid/cppwinrt/PowerGrid.sln;
  4. 按Ctrl+Shift+B,或选择Build > Build Solution完成构建。

运行方式取决于需求:

  • 仅部署:选择Build > Deploy Solution;
  • 部署并调试运行:按F5,或选择Debug > Start Debugging;
  • 部署但不调试运行:按Ctrl+F5,或选择Debug > Start Without Debugging。

示例目录结构

本示例按语言拆分源码,XAML 界面则统一放在共享目录:

Samples/PowerGrid/ ├── README.md # 官方说明文档 ├── cs/ # C# 实现 │ ├── SampleConfiguration.cs # 场景注册 │ ├── Scenario1_FindBest.xaml.cs │ ├── Scenario2_PrintFullForecast.xaml.cs │ ├── PowerGrid.csproj / PowerGrid.sln │ └── Package.appxmanifest ├── cppwinrt/ # C++/WinRT 实现 │ ├── SampleConfiguration.cpp / .h │ ├── Scenario1_FindBest.cpp / .h │ ├── Scenario2_PrintFullForecast.cpp / .h │ ├── Project.idl # 场景类的 IDL 声明 │ └── Package.appxmanifest └── shared/ # 两种语言共用的 XAML ├── Scenario1_FindBest.xaml └── Scenario2_PrintFullForecast.xaml

C++/WinRT 版本通过 Samples/PowerGrid/cppwinrt/Project.idl 声明两个页面类以及ForecastItem运行时类(含DateTimeString、SeverityString、LowImpactString三个只读属性),供 XAML 数据绑定使用。

核心 API:PowerGridForecast 与 PowerGridData

示例核心对象来自Windows.Devices.Power命名空间:

  • PowerGridForecast:代表一份电网预测。关键成员:
    • GetForecast():静态方法,同步获取当前预测;若系统暂时拿不到数据,返回的Forecast集合为空(示例据此判断“No forecast available”);
    • ForecastUpdated:静态事件,当系统发布新预测时触发,可用于主动刷新 UI;
    • StartTime:预测中第一个时间块的开始时间(DateTimeOffset/DateTime);
    • BlockDuration:单个时间块的长度(TimeSpan),示例 UI 中以“分钟”展示;
    • Forecast:PowerGridData的只读集合,每个元素对应一个时间块。
  • PowerGridData:单个时间块的数据,包含:
    • Severity:该块的严重级别(double),数值越低表示越适合执行高耗电任务;
    • IsLowUserExperienceImpact:布尔值,标记该时段对用户体验的影响是否较低。

场景一:在指定时间段内查找最低严重级别时段

Scenario1_FindBest演示“在指定时间范围内寻找最低严重级别”这一核心场景。其界面(Samples/PowerGrid/shared/Scenario1_FindBest.xaml)包含三个输入控件:

  • 文本框HoursAheadTextBox(默认值12):向前查看的小时数;
  • 复选框LowUXImpactCheckBox(默认勾选):是否仅考虑低用户体验影响时段;
  • 按钮FindBest(Find best time):触发查询。

C# 实现位于 Samples/PowerGrid/cs/Scenario1_FindBest.xaml.cs,核心流程如下:

// 收集用户输入 if (!uint.TryParse(HoursAheadTextBox.Text, out uint lookAheadHours)) { rootPage.NotifyUser("Unable to parse hours to look ahead", NotifyType.ErrorMessage); return; } TimeSpan lookAhead = TimeSpan.FromHours(lookAheadHours); bool restrictToLowUXImpact = LowUXImpactCheckBox.IsChecked.Value; // 计算放到后台线程,避免阻塞 UI await Task.Run(() => { gridForecast = PowerGridForecast.GetForecast(); DateTimeOffset startTime = DateTimeOffset.Now; DateTimeOffset endTime = startTime + lookAhead; int startBlock = GetForecastIndexContainingTime(gridForecast, startTime); int endBlock = GetForecastIndexContainingTime(gridForecast, endTime + gridForecast.BlockDuration); for (int index = startBlock; index < endBlock; ++index) { PowerGridData data = gridForecast.Forecast[index]; // 限制到低影响时段时,跳过非低影响块 if (restrictToLowUXImpact && !data.IsLowUserExperienceImpact) { continue; } // 只有严重级别更低的块才被采纳 if (data.Severity >= lowestSeverity) { continue; } lowestSeverity = data.Severity; timeWithLowestSeverity = gridForecast.StartTime + new TimeSpan(index * gridForecast.BlockDuration.Ticks); } });

要点分析:

  1. 后台线程调用GetForecast():C# 用Task.Run,C++/WinRT 用co_await winrt::resume_background()(见 Samples/PowerGrid/cppwinrt/Scenario1_FindBest.cpp),目的是不让网络/系统查询阻塞 UI 线程。
  2. 时间块索引换算:GetForecastIndexContainingTime把任意时刻映射为所在块的索引——用(time - StartTime).Ticks / BlockDuration.Ticks计算,并用Math.Max(0, Math.Min(...))(C#)或std::clamp(C++/WinRT)把结果夹在[0, Forecast.Count]之间;同时通过blockDuration == TimeSpan.Zero判断避免除零。C++ 版本用TimeSpan的count()直接比较零值。查询结束块时额外加上一个BlockDuration,保证把“endTime 所在块”也纳入扫描。
  3. 最小严重级别筛选:遍历[startBlock, endBlock)区间,在(可选的)低影响过滤之上,只保留严格更低的Severity,最终得到timeWithLowestSeverity与该块的起始时间。
  4. 结果判定与展示:只有当lowestSeverity <= 1.0时才认为找到了合适时段,此时显示“最佳时间范围”和“最低严重级别”;否则提示Unable to find a good time to do work。

结果格式化在 C# 中通过Windows.Globalization完成:

var dateFormatter = new DateTimeFormatter("shortdate shorttime"); var severityFormatter = new DecimalFormatter() { FractionDigits = 2, IntegerDigits = 1, IsDecimalPointAlwaysDisplayed = true, NumberRounder = new IncrementNumberRounder() { Increment = 0.01 } }; BestTimeRun.Text = dateFormatter.Format(timeWithLowestSeverity) + " to " + dateFormatter.Format(timeWithLowestSeverity + gridForecast.BlockDuration); LowestSeverityRun.Text = severityFormatter.Format(lowestSeverity);

C++/WinRT 版本在 Samples/PowerGrid/cppwinrt/Scenario1_FindBest.cpp 中结构相同,只是通过co_await winrt::resume_foreground(Dispatcher())回到 UI 线程后再更新控件。

场景二:完整打印电网预测

Scenario2_PrintFullForecast演示“获取整份预测”并把每个时间块渲染成表格。界面(Samples/PowerGrid/shared/Scenario2_PrintFullForecast.xaml)包含:

  • Get forecast按钮触发查询;
  • ForecastStartTimeRun:展示预测起始时间;
  • ForecastBlockDurationRun:展示单个时间块时长(分钟);
  • ForecastList(ListView):逐条展示每个时间块的时间、严重级别、是否低影响,行模板通过{x:Bind DateTimeString}等绑定到ForecastItem。

C# 实现见 Samples/PowerGrid/cs/Scenario2_PrintFullForecast.xaml.cs,核心逻辑:

// 后台线程获取预测,避免阻塞 UI PowerGridForecast gridForecast = await Task.Run(() => PowerGridForecast.GetForecast()); // API 无法获取预测时,Forecast 为空集合 if (gridForecast.Forecast.Count == 0) { rootPage.NotifyUser("No forecast available. Try again later.", NotifyType.ErrorMessage); return; } DateTimeOffset blockStartTime = gridForecast.StartTime; TimeSpan blockDuration = gridForecast.BlockDuration; ForecastStartTimeRun.Text = blockStartTime.ToString("F"); ForecastBlockDurationRun.Text = blockDuration.TotalMinutes.ToString(); var items = new List<ForecastItem> { new ForecastItem { DateTimeString = "Date/Time", SeverityString = "Severity", LowImpactString = "Low impact?" } }; var dateFormatter = new DateTimeFormatter("shortdate shorttime"); var severityFormatter = new DecimalFormatter() { /* 同场景一 */ }; foreach (PowerGridData data in gridForecast.Forecast) { items.Add(new ForecastItem { DateTimeString = dateFormatter.Format(blockStartTime), SeverityString = severityFormatter.Format(data.Severity), LowImpactString = data.IsLowUserExperienceImpact.ToString() }); blockStartTime += blockDuration; } ForecastList.ItemsSource = items;

该场景体现了两个值得注意的工程细节:

  1. 空预测的显式处理:GetForecast()并不抛异常,而是返回Forecast.Count == 0的空集合,示例据此提示“No forecast available. Try again later.”,这是处理电网数据暂不可用场景的推荐姿势。
  2. 按块推算时间:列表里的每个时间点并非来自数据本身,而是从StartTime开始按BlockDuration逐块累加得到,与场景一的索引换算互为印证。

订阅 ForecastUpdated 更新通知

两个场景都在页面导航时注册PowerGridForecast.ForecastUpdated事件、离开时注销,实现“新预测到达时提示用户重新查询”。C# 写法:

protected override void OnNavigatedTo(NavigationEventArgs e) { PowerGridForecast.ForecastUpdated += PowerGridForecast_ForecastUpdated; } protected override void OnNavigatedFrom(NavigationEventArgs e) { PowerGridForecast.ForecastUpdated -= PowerGridForecast_ForecastUpdated; } private void PowerGridForecast_ForecastUpdated(object sender, object e) { // 新预测可用,提示用户重新点击查询按钮 rootPage.NotifyUser("New forecast is available, click \"Find best time\" to find a new best time", NotifyType.StatusMessage); }

C++/WinRT 使用事件令牌(event_token)完成注册与注销(见 Samples/PowerGrid/cppwinrt/Scenario1_FindBest.cpp 与 Samples/PowerGrid/cppwinrt/Scenario1_FindBest.h):

// OnNavigatedTo:注册 forecastUpdatedToken = PowerGridForecast::ForecastUpdated( { get_weak(), &Scenario1_FindBest::PowerGridForecast_ForecastUpdated }); // OnNavigatedFrom:注销 PowerGridForecast::ForecastUpdated(forecastUpdatedToken);

get_weak()弱引用可避免页面销毁后事件回调悬空;两个场景的事件处理器都只做 UI 提示,不自动重拉数据,把“何时刷新”的决策权留给用户,这是示例刻意保持的简洁交互设计。

总结与延伸阅读

PowerGrid 示例把电网预测 API 的三种典型用法浓缩为两个场景:一是“找最佳时段”(时间块索引换算 + 最小 Severity 扫描 + 低影响过滤),二是“完整展示预测”(空集合判空 + 按块累加时间戳),并以ForecastUpdated事件串起“预测刷新—用户重查”的闭环。所有界面逻辑共享同一套 XAML,C# 与 C++/WinRT 实现保持对等,可作为接入Windows.Devices.Power.PowerGridForecast的参考模板。

延伸阅读入口:

  • 示例说明文档:Samples/PowerGrid/README.md;
  • 场景一源码:Samples/PowerGrid/cs/Scenario1_FindBest.xaml.cs、Samples/PowerGrid/cppwinrt/Scenario1_FindBest.cpp;
  • 场景二源码:Samples/PowerGrid/cs/Scenario2_PrintFullForecast.xaml.cs、Samples/PowerGrid/cppwinrt/Scenario2_PrintFullForecast.cpp;
  • 界面定义:Samples/PowerGrid/shared/Scenario1_FindBest.xaml、Samples/PowerGrid/shared/Scenario2_PrintFullForecast.xaml。

如需在 Win32 桌面应用中获取电网预测,可参考 Windows-classic-samples 仓库中的同名 PowerGrid 示例(README 的 Related samples 一节已给出指引)。

  • 示例工程

【免费下载链接】Windows-universal-samples

API samples for the Universal Windows Platform.

项目地址:https://gitcode.com/gh_mirrors/wi/Windows-universal-samples
点击查看免费下载
上一篇:cheesesquare项目中的菜单设计:OptionsMenu与ContextMenu实现
下一篇:CANN/asc-devkit:Ascend C SIMD API寄存器左移操作

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询