该库允许您连接到Home Assistant WebSocket API来发出命令和订阅事件,以及发出REST API请求。未来的计划包括提供身份验证支持。
您可以查看完整的文档。最重要的可用方法集位于HAConnection协议上。此协议是与 Home Assistant 实例通信的主要入口点。
创建连接需要两个信息:服务器 URL 和访问令牌。两者都在尝试建立连接时检索。由于 Home Assistant 实例的连通性可能因当前网络而异,因此每次尝试连接时都会重新查询这些值。
您可以使用暴露的初始化器来获取连接实例
let connection = HAKit.connection(configuration: .init(
connectionInfo: {
// Connection is required to be returned synchronously.
// In a real implementation, handle both URL/connection info without crashing.
try! .init(url: URL(string: "http://homeassistant.local:8123")!)
},
fetchAuthToken: { completion in
// Access tokens are retrieved asynchronously, but be aware that Home Assistant
// has a timeout of 10 seconds for sending your access token.
completion(.success("API_Token_Here"))
}
))
您可以进一步配置此连接的其他属性,例如 callbackQueue
(将调用您的处理程序的位置),以及触发手动连接尝试。有关更多信息,请参见协议。
一旦您调用.connect()
(或自动调用它),并且在您调用.disconnect()
之前,连接将尝试保持连接状态,方法是在网络状态更改时以及断开连接后的重试期后尝试重新连接。
您可以通过配置 HAGlobal
来启用库的日志记录
HAGlobal.log = { text in
// just straight to the console
print($0)
// or something like XCGLogger
log.info("WebSocket: \(text)")
}
这将包括诸如正在发送的命令以及连接的生命周期之类的内容。
有两种类型的请求:一种是具有即时结果的请求,另一种是触发事件直到取消的请求。 这些操作分别是“发送”和“订阅”。 例如,您可能会发送服务调用,但订阅模板的渲染。
发出的请求将继续跨重连重试,直到执行一次,并且订阅将在必要时自动重新注册,直到取消为止。 每个send
或subscribe
都会返回一个HACancellable
令牌,您可以取消该令牌,并且每个订阅处理程序也包括一个令牌。
例如,像HATypedRequest和HATypedSubscription中的其他调用一样,检索当前用户具有提供强类型值的辅助方法。 例如,您可以采用以下两种方式之一来编写它
// with the CurrentUser convenience helper
connection.send(.currentUser()) { result in
switch result {
case let .success(user):
// e.g. user.id or user.name are available on the result object
case let .failure(error):
// an error occurred with the request
}
}
// or issued directly, and getting the raw response
connection.send(.init(type: .currentUser, data: [:])) { result in
switch result {
case let .success(data):
// data is an `HAData` which wraps possible responses and provides decoding
case let .failure(error):
// an error occurred with the request
}
}
// you can also issue REST calls
Current.apiConnection.send(.init(
// this will POST to `/api/template` with the data as the body
type: .rest(.post, "template"),
data: ["template": "{{ now() }}"]
)) { result in
// same result type as sending a WebSocket request
}
同样,可以使用便捷助手或直接方式来订阅事件。
// with the RenderTemplate convenience helper
connection.subscribe(
to: .renderTemplate("{{ states('sun.sun') }} {{ states.device_tracker | count }}"),
initiated: { result in
// when the initiated method is provided, this is the result of the subscription
},
handler: { [textView] cancelToken, response in
// the overall response is parsed for type, but native template rendering means
// the rendered type will be a Dictionary, Array, etc.
textView.text = String(describing: response.result)
// you could call `cancelToken.cancel()` to end the subscription here if desired
}
)
// or issued directly, and getting the raw response
connection.subscribe(
to: .init(type: .renderTemplate, data: [
"template": "{{ states('sun.sun') }} {{ states.device_tracker | count }}"
]),
initiated: { result in
// when the initiated method is provided, this is the result of the subscription
},
handler: { [textView] cancelToken, data in
// data is an `HAData` which wraps possible responses and provides decoding
// the decode methods infer which type you're asking for and attempt to convert
textView.text = try? data.decode("result")
// you could call `cancelToken.cancel()` to end the subscription here if desired
}
)
您还可以调用任何请求或订阅,即使是那些没有围绕其名称的便捷访问器。 事件名称和请求类型符合ExpressibleByStringLiteral
,或者您可以使用原始值来初始化它们。
当不使用便捷包装器时,许多方法会将结果作为 HAData
传递。 这是代替底层字典或数组响应传递的,它具有将字典中的键解码为特定类型的便捷方法。 这与Decodable
相似但不完全相同-许多Home Assistant调用将返回必须保留为Any
的结果,而Swift的JSON编码对此处理不佳。
有关可用方法,请参见HADataDecodable
。
HACache
允许您缓存请求的结果并订阅事件以更新它们。
该库包含一些内置缓存,您可以通过HACachesContainer
通过connection.caches
进行访问。 有关可用缓存的信息,请参见文档。
使用HACachePopulateInfo
完成缓存的填充,其中包含
例如,如果您想发出请求.getStates()
并跟踪所有entityId
let populate = HACachePopulateInfo<Set<String>>(
request: .getStates(),
transform: { info in
return Set(info.incoming.map(\.entityId))
}
)
使用一个或多个HACacheSubscribeInfo
完成缓存值的更新,每个订阅包含
例如,如果您想观看状态更改以更新entityId
let subscribe = HACacheSubscribeInfo<Set<String>>(
subscription: .stateChanged(),
transform: { info in
var entityIds = info.current
if info.incoming.newState == nil {
entityIds.remove(info.incoming.entityId)
} else {
entityIds.insert(info.incoming.entityId)
}
return .replace(entityIds)
}
)
将这两个放在一起,我们可以创建一个缓存,以维护当前已知的entityId
let entityIds = HACache(connection: connection, populate: populate, subscribe: subscribe)
您现在可以订阅缓存中的更改
entityIds.subscribe { token, value in
print("current entity ids are: \(value)")
}
缓存将推迟执行其填充,直到连接已连接并且至少有一个订阅者。 您可以通过shouldResetWithoutSubscribers
属性来控制它是否在没有订阅者的情况下断开与订阅的连接。
此库包含用于编写测试的可选添加项。 有关更多信息,请参见源代码。
此库包含与PromiseKit一起使用的可选添加项。 有关更多信息,请参见源代码。
要安装该库,请将其作为依赖项添加到 Package.swift
中,例如
.package(url: "https://github.com/home-assistant/HAKit", from: Version(0, 4, 2))
要将其添加到 Xcode 项目,您可以通过将 URL 添加到 File > Swift Packages > Add Package Dependency 来完成。 您会发现一些可用的目标
HAKit
,库本身HAKit+PromiseKit
,其中包括 PromiseKit 添加项HAKit+Mocks
,其中包括使编写测试更容易的模拟将以下行添加到您的 Podfile
pod "HAKit", "~> 0.4.4"
# We are working from a fork of Starscream due to a necessary fix, please specify in your podfile
pod 'Starscream', git: 'https://github.com/bgoncal/starscream', branch: 'ha-URLSession-fix'
# pod "HAKit/PromiseKit" # optional, for PromiseKit support
# pod "HAKit/Mocks" # optional, for tests
有关如何构建和修改此库的更多信息,请参见CONTRIBUTING.md。
该库根据Apache 2.0 许可证提供。它还依赖于Starscream,用于在旧版本的iOS上进行WebSocket连接。 Starscream也根据Apache 2.0许可提供。