用于访问 Disruptive Technologies 数据的 Swift 库。
此库目前仅通过 Swift Package Manager (SPM) 提供。
要在 Xcode 中将此 Swift 包添加为依赖项
File -> Swift Packages -> Add Package Dependency...
https://github.com/vegather/Disruptive
import Disruptive
导入 Disruptive Swift API如果您想手动将其添加到您的 Swift 项目,您可以将以下依赖项添加到您的 Package.swift
dependencies: [
.package(url: "https://github.com/vegather/Disruptive.git", from: "1.0.0")
]
要使用此 Swift 库,您首先需要使用服务帐户的凭据初始化 Disruptive
结构体的一个实例(请参阅下面的身份验证部分)。这将是您所有对 Disruptive Technologies 服务的请求的入口点。此 Disruptive
实例将自动处理诸如身份验证、分页、速率限制后重新发送事件以及其他可恢复的错误等事项。
在 Disruptive
结构体上实现的端点是异步的,并且会在您提供的闭包中返回结果,该闭包带有一个 Result
类型的参数(阅读更多关于 Result
类型的信息,请访问 Apple 开发者站点)。此 Result
将在 .success
中包含您请求的值(如果无值有意义,则为 Void
),或者在 .failure
中包含 DisruptiveError
。
注意:即使网络/处理在后台队列中完成,带有 Result
的回调也始终在 main
队列上调用。
以下部分将简要介绍 API 最常见的用例。请查看 完整的 Swift API 文档 以获取更多信息。
身份验证通过使用符合 Authenticator
协议的类型初始化 Disruptive
实例来完成。推荐的类型是 OAuth2Authenticator
,它将使用 OAuth2 流程验证服务帐户。一旦通过身份验证,Disruptive
实例将确保它始终具有未过期的访问令牌,并将其添加到请求的 Authorization
标头中,然后再发送请求。如果发出请求时访问令牌已过期,则会在发送请求之前自动获取新的访问令牌。
可以在 DT Studio 中创建服务帐户,方法是单击侧边菜单中 API Integrations
下的 Service Account
选项卡。为服务帐户创建一个新密钥,并务必记下服务帐户的密钥 ID、密钥和电子邮件。请注意,默认情况下,服务帐户无权访问任何资源。请参阅下面关于权限的部分,了解如何授予服务帐户访问您的资源的权限。
以下是如何使用 OAuth2 流程验证服务帐户的示例
import Disruptive
let credentials = ServiceAccountCredentials(email: "<EMAIL>", keyID: "<KEY_ID>", secret: "<SECRET>")
let authenticator = OAuth2Authenticator(credentials: credentials)
let disruptive = Disruptive(authenticator: authenticator)
// All methods called on the disruptive instance will be authenticated
Disruptive API 的访问级别可以用成员、角色和权限来描述。为了使帐户(服务帐户或用户)能够访问资源,它必须是作为该资源父级的项目或组织中的成员。成员对于其所属的项目/组织始终具有角色(例如项目用户、项目管理员等)。这些角色中的每一个都包含一个权限列表,该列表描述了它可以对各种资源执行哪些 CRUD(创建、读取、更新、删除)操作。权限示例包括 "project.read"
、"membership.create"
、"serviceaccount.key.delete"
等。要列出可用的角色和权限,请使用 getRoles
和 getPermissions
函数。
为了使服务帐户能够访问给定的资源,它必须具有该资源的足够权限。默认情况下,服务帐户无权访问任何资源。开始使用服务帐户的最简单方法是在 DT Studio 中授予对相关项目/组织的访问权限。您可以通过在 API Integrations -> Service Accounts
下查看服务帐户时选择 Role in current Project
,从而在当前项目中为其授予角色。您还可以通过转到成员列表(在项目成员的 Project Settings
中),然后使用服务帐户的电子邮件地址将服务帐户添加为成员并选择适当的角色,从而授予其访问其他项目/组织的权限。
一旦您拥有了服务帐户的凭据并创建了 Disruptive
实例,您就可以使用 API 创建新的服务帐户并将它们添加为项目的成员。有关更多详细信息,请参阅 createServiceAccount
和 inviteMember
函数。
有关服务帐户的更多详细信息,请参阅开发者网站上的 服务帐户 文章。
一旦创建了 Disruptive
结构体的实例,它将成为对 Disruptive API 发出请求的主要入口点。有关 Disruptive
结构体上所有可用功能的概述,请参阅 API 参考。
获取资源列表(例如 Device
或 Project
列表)主要有两种方法:您可以一次获取所有资源,也可以一次获取一页。一次获取资源的所有项目更方便,但是如果项目很多,则可能需要很长时间,因为可能需要在后台进行多次网络请求才能自动获取所有页面。
一次获取一页项目在实现上稍微麻烦一些,但可以完全控制一次获取多少项目以及何时获取下一页项目。一次获取一页适用于 Organization
、Project
、Device
、DataConnector
、Member
、ServiceAccount
和 ServiceAccount.Key
。它不适用于 Role
和 Permission
,因为这些项目具有已知的小数量项目需要列出。它也不适用于获取事件,因为可以通过指定开始和结束时间戳来分页事件,以获取两者之间的事件。
以下是这两种获取 Device
列表的方法的示例。
一次获取项目中的所有 Device
disruptive.getAllDevices(projectID: "<PROJECT_ID>") { result in
switch result {
case .success(let devices):
print(devices)
case .failure(let error):
print("Failed to get devices: \(error)")
}
}
一次获取一页 Device
var fetchedDevices = [Device]()
var nextPageToken: String?
func fetchNextPage(pageToken: String?) {
disruptive.getDevicesPage(projectID: "<PROJECT_ID>", pageSize: 25, pageToken: pageToken) { result in
switch result {
case .success(let page):
// Keep track of the page token to use for the next page.
// Note that this will be `nil` when the last page is received.
nextPageToken = page.nextPageToken
// Update the list of all the devices we have found so far
fetchedDevices.append(contentsOf: page.devices)
print("Fetched \(page.devices.count) more devices. \(fetchedDevices.count) devices fetched in total")
case .failure(let error):
print("Failed to get devices: \(error)")
}
}
}
// Fetch the first page
fetchNextPage(pageToken: nil)
// Fetch subsequent pages when it makes sense (for example when pre-fetching data
// for a UITableView). Note that `nextPageToken` will be set to `nil` when the last
// page is received.
if let pageToken = nextPageToken {
fetchNextPage(pageToken: pageToken)
}
获取设备的 historical events (历史事件)类似于获取其他数据列表(如 getOrganizations
或 getProjects
)。您需要指定项目和设备的标识符,以及可选的开始/结束时间和要获取的事件(某些事件类型仅适用于某些设备类型,例如,temperature
事件仅适用于 temperature
传感器)。如果回调中返回的 Result
是 .success
,您将收到一个 Events
类型的值,其中包含每个事件类型的可选事件数组。只有实际返回的事件类型才为非 nil,不一定是 eventTypes
参数中指定的事件类型。
获取温度传感器的 temperature (温度)事件的示例(默认为最近 24 小时)
disruptive.getEvents(projectID: "<PROJECT_ID>", deviceID: "<DEVICE_ID>", eventTypes: [.temperature]) { result in
switch result {
case .success(let events):
if let temperatureEvents = events.temperature {
print(temperatureEvents)
}
case .failure(let error):
print("Failed to get temperature events: \(error)")
}
}
当订阅设备事件时,您有两种选择:订阅单个设备或订阅设备列表。如果您想订阅设备列表,您可以根据设备类型和标签过滤要订阅的设备。无论哪种方式,您都将获得一个 DeviceEventStream
类型的值,该值允许您为各种事件类型设置回调。只有 eventTypes
参数中指定的事件类型才会实际接收回调。
订阅单个温度传感器的 temperature (温度)事件的示例
let stream = disruptive.subscribeToDevice(
projectID : "<PROJECT_ID>",
deviceID : "<DEVICE_ID>",
eventTypes : [.temperature] // optional
)
stream?.onTemperature = { deviceID, temperatureEvent in
print("Got temperature \(temperatureEvent) for device with id \(deviceID)")
}
stream?.onError = { error in
print("Got stream error: \(error)")
}
获取设备的请求具有各种参数来搜索和/或筛选设备。所有这些参数都是可选的(projectID
除外),并且可以根据需要混合和匹配。
当指定检索设备的顺序时,元组中包含字段以及升序/降序标志。此字段的值基于设备的 JSON 结构。要使用的 field
的示例包括 id
(标识符)、type
(设备类型)、labels.name
(displayName)。所有事件都将具有 reported.<event_type>.<field>
格式,例如 reported.networkStatus.signalStrength
。有关哪些字段可用的提示,请参阅 REST API 文档中的 GET Devices
端点。
以下是如何使用所有参数的示例
disruptive.getAllDevices(
projectID : "<PROJECT_ID>",
query : "Air Vent",
deviceIDs : ["<DEVICE_ID>", "<DEVICE_ID>"],
deviceTypes : [.temperature],
labelFilters : ["kit": "perform-compare-establish"],
orderBy : (field: "reported.networkStatus.updateTime", ascending: false))
{ result in
...
}
单个设备可以通过设备的标识符进行查找。如果您通过扫描二维码获得了设备标识符,这将非常有用。这是一个例子
disruptive.getDevice(deviceID: "<DEVICE_ID>") { result in
...
}
可以使用 API 创建和使用模拟设备来发布事件。这使得无需访问物理设备即可测试 API 的其他部分(例如列出设备)并围绕 API 开发解决方案。
以下是如何创建新的模拟温度传感器的示例
disruptive.createEmulatedDevice(
projectID : "<PROJECT_ID>",
deviceType : .temperature,
displayName : "Emulated Temperature Sensor")
{ result in
...
}
以下是如何为模拟传感器发布 TemperatureEvent
的示例
disruptive.publishEmulatedEvent(
projectID : "<PROJECT_ID>",
deviceID : "<DEVICE_ID>",
event : TemperatureEvent(celsius: 42, timestamp: Date()))
{ result in
...
}
获取项目允许您选择性地按组织(按标识符)和基于关键字的查询进行筛选。您也可以忽略这两个参数以获取经过身份验证的帐户可用的所有项目。以下示例将搜索具有指定的组织 ID(例如从 getOrganizations
端点获取)且名称中包含 Building 1
的项目
disruptive.getAllProjects(organizationID: "<ORG_ID>", query: "Building 1") { result in
...
}
以下是如何获取经过身份验证的帐户可用的所有组织的示例
disruptive.getAllOrganizations { result in
...
}
Disruptive.loggingEnabled = true
来启用一些基本调试日志Disruptive Swift 库在 MIT 许可证下发布。查看 LICENSE 了解详细信息。