OpenWeatherKit

Linux Swift macOS

此软件包是围绕 WeatherKit REST API 的 Swift 封装。 它的目的是为 Apple 当前不支持的平台提供原生的 Swift WeatherKit 替代方案。 此软件包的 API 几乎与 Apple 的 WeatherKit 相同。

💻 支持的平台

⚙️ 设置

REST API 需要在每个请求中发送一个签名的 JWT。 要设置此项,您需要

Apple 开发者门户设置

App 标识符

  1. 前往 标识符
  2. 在左上方,点击添加按钮 (+),选择“服务 ID”,然后点击“继续”。
  3. 注册一个服务 ID。
  4. 记下标识符(稍后您需要用到它)
  5. 点击“继续”,查看注册信息,然后点击“注册”。

密钥

  1. 前往 密钥
  2. 在左上方,点击添加按钮 (+)
  3. 为您的密钥命名,勾选“WeatherKit”框
  4. 点击“继续”,查看注册信息,然后点击“注册”。
  5. 记下密钥 ID(稍后您需要用到它)
  6. 下载私钥

JWT

WeatherKit REST API 要求在每个请求中发送 JSON Web Token (JWT)。 实现生成 JWT 所需的逻辑超出了目前 OpenWeatherKit 项目的范围。 有关 JWT 的一般信息,请访问 https://jwt.net.cn

话虽如此,推荐用于处理此任务的软件包是 Vapor 的 jwt-kit。 以下是如何设置它

实现符合 JWTPayload 的模型

import JWTKit

struct Payload: JWTPayload, Equatable {
    enum CodingKeys: String, CodingKey {
        case expiration = "exp"
        case issued = "iat"
        case issuer = "iss"
        case subject = "sub"
    }

    let expiration: ExpirationClaim
    let issued: IssuedAtClaim
    let issuer: IssuerClaim
    let subject: SubjectClaim

    func verify(using signer: JWTKit.JWTSigner) throws {}
}

生成 JWT

struct JWTProvider {
    static func generate() -> String {
        let signers = JWTSigners()
        try signers.use(.es256(key: ECDSAKey.private(pem: PRIVATE_KEY_FROM_DEV_PORTAL))

        let payload = Payload(
            expiration: .init(value: .distantFuture),
            issued: .init(value: .now),
            issuer: TEAM_ID,
            subject: SERVICE_IDENTIFIER
        )

        return try! signers.sign(payload, kid: KEY_ID)
    }
}

注意变量

PRIVATE_KEY_FROM_DEV_PORTAL:私钥文件的内容,包括 -----BEGIN PRIVATE KEY----------END PRIVATE KEY-----

TEAM_ID:在开发者门户的“成员资格详细信息”中找到

SERVICE_IDENTIFIER:先前记录的反向域名

KEY_ID:服务密钥的 ID

🌤️ 用法

初始化服务

必须使用 JWT 生成闭包(以及可选的语言)来初始化服务。

let weatherService = WeatherService(
    configuration: .init(jwt: JWTProvider.generate)
)

获取完整的天气预报

let weather = try await weatherService
    .weather(
        for: Location(
            latitude: 37.541290,
            longitude: -77.511429),
        countryCode: "US"
    )

获取部分天气预报

let (dailyForecast, hourlyForecast, alerts) = try await weatherService
    .weather(
        for: Location(
            latitude: 37.541290,
            longitude: -77.511429),
        including: .daily, .hourly, .alerts(countryCode: "US")
    )

获取可用性

请注意,分钟级预报和警报并非在所有地区都可用。 使用 .availability 查询检查它们的可用性。

let availability = try await weatherService
    .weather(
        for: Location(
            latitude: 37.541290,
            longitude: -77.511429),
        including: .availability
    )

用于国家/地区代码的地理编码(仅限 Apple 平台)

当在 Apple 平台上使用该库时,不需要 countryCode 参数。 在内部,该库将使用 CoreLocation 对位置进行反向地理编码以确定国家/地区代码。 如果无法确定国家/地区,则会抛出错误。

📝 归属

使用此软件包时,请注意 Apple 的归属指南

可以使用以下方法访问归属信息

let attribution = weatherService.attribution

请注意,此属性使用来自 WeatherKit 的信息返回静态的 WeatherAttribution 实例,并且不保证其准确或完整。