文档文档

JavaScript 客户端库入门程序

按照此分步教程,使用 InfluxData 客户端库和您最喜欢的框架或语言构建物联网 (IoT) 应用程序。

在本教程中,您将使用 InfluxDB API 和客户端库来构建现代应用程序,并学习以下内容

  • InfluxDB 核心概念。
  • 应用程序如何与设备和 InfluxDB 交互。
  • 如何对应用程序和设备进行 API 身份验证。
  • 如何安装客户端库。
  • 如何在 InfluxDB 中写入和查询数据。

目录

设置 InfluxDB

如果您尚未这样做,请创建 InfluxDB Cloud 帐户安装 InfluxDB OSS

IoT Starter 示例应用程序假定以下先决条件

  • InfluxDB 组织 ID
  • 一个 API 令牌(例如,一个完全访问令牌),该令牌对存储桶具有读写权限
  • 一个名为 iot_center存储桶,用于存储来自设备的时间序列数据
  • 一个名为 iot_center_devices存储桶,用于存储设备元数据和 API 令牌 ID

对生产应用程序使用受限令牌

对于生产应用程序,创建并使用具有最小权限的 读写 令牌,并且仅将其与单个客户端或应用程序一起使用。

IoT Starter 介绍

应用程序架构有四个层

  • InfluxDB API:InfluxDB v2 API。
  • IoT 设备:虚拟或物理设备将 IoT 数据写入 InfluxDB API。
  • UI:向服务器发送请求并在浏览器中渲染视图。
  • API:接收来自 UI 的请求,向 InfluxDB 发送请求,并处理来自 InfluxDB 的响应。

有关本教程中引用的完整代码,请参阅 influxdata/iot-api-js 存储库

安装 Yarn

如果您尚未安装 yarn,请按照适用于您的 Node.js 版本的 Yarn 包管理器安装说明进行操作。

  • 要检查已安装的 yarn 版本,请在您的终端中输入以下代码

    yarn --version
    
    • Copy
    • Fill window

创建应用程序

创建一个将包含您的 iot-api 项目的目录。以下示例代码在您的主目录中创建一个 iot-api 目录,并切换到新目录

mkdir ~/iot-api-apps
cd ~/iot-api-apps
  • Copy
  • Fill window

按照以下步骤使用 Next.js 创建 JavaScript 应用程序

  1. 在您的 ~/iot-api-apps 目录中,打开一个终端并输入以下命令,从 NextJS learn-starter 模板创建 iot-api-js 应用程序

    yarn create-next-app iot-api-js --example "https://github.com/vercel/next-learn/tree/master/basics/learn-starter"
    
    • Copy
    • Fill window
  2. 安装完成后,在您的终端中输入以下命令以进入您的 ./iot-api-js 目录并启动开发服务器

    cd iot-api-js
    yarn dev -p 3001
    
    • Copy
    • Fill window

要查看应用程序,请在您的浏览器中访问 https://127.0.0.1:3001

安装 InfluxDB 客户端库

InfluxDB 客户端库提供以下 InfluxDB API 交互

  • 使用 Flux 语言查询数据。
  • 将数据写入 InfluxDB。
  • 在后台批量处理数据。
  • 在失败时自动重试请求。
  1. 在您的终端中输入以下命令以安装客户端库

    yarn add @influxdata/influxdb-client
    
    • Copy
    • Fill window
  2. 在您的终端中输入以下命令以安装 @influxdata/influxdb-client-apis,即管理 API,用于创建、修改和删除授权、存储桶、任务和其他 InfluxDB 资源

    yarn add @influxdata/influxdb-client-apis
    
    • Copy
    • Fill window

有关客户端库的更多信息,请参阅 influxdata/influxdb-client-js 仓库

配置客户端库

InfluxDB 客户端库需要来自您的 InfluxDB 环境的配置属性。通常,您将以下属性作为应用程序的环境变量提供

  • INFLUX_URL
  • INFLUX_TOKEN
  • INFLUX_ORG
  • INFLUX_BUCKET
  • INFLUX_BUCKET_AUTH

Next.js 使用 env 模块为您的应用程序提供环境变量。

./.env.development 文件已进行版本控制,并包含您的开发环境的非机密默认设置。

# .env.development

INFLUX_URL=https://127.0.0.1:8086
INFLUX_BUCKET=iot_center
INFLUX_BUCKET_AUTH=iot_center_devices
  • Copy
  • Fill window

要配置未添加到版本控制的密钥和设置,请创建一个 ./.env.local 文件并设置变量 - 例如,设置您的 InfluxDB 令牌和组织

# .env.local

# INFLUX_TOKEN
# InfluxDB API token used by the application server to send requests to InfluxDB.
# For convenience in development, use an **All Access** token.

INFLUX_TOKEN=29Xx1KH9VkASPR2DSfRfFd82OwGD...

# INFLUX_ORG
# InfluxDB organization ID you want to use in development.

INFLUX_ORG=48c88459ee424a04
  • Copy
  • Fill window

在您的终端中输入以下命令以重启并加载 .env 文件

  1. CONTROL+C 停止应用程序。
  2. yarn dev 启动应用程序。

Next.js 设置了您可以在 process.env 对象中访问的变量 - 例如

console.log(process.env.INFLUX_ORG)
  • Copy
  • Fill window

构建 API

您的应用程序 API 提供服务器端 HTTP 端点,用于处理来自 UI 的请求。每个 API 端点负责以下操作

  1. 监听 HTTP 请求(来自 UI)。
  2. 将请求转换为 InfluxDB API 请求。
  3. 处理 InfluxDB API 响应并处理错误。
  4. 使用状态和数据(对于 UI)进行响应。

创建 API 以列出设备

添加 /api/devices API 端点,该端点检索、处理和列出设备。/api/devices 使用 /api/v2/query InfluxDB API 端点在 INFLUX_BUCKET_AUTH 中查询已注册的设备。

处理设备信息请求

  1. 创建一个 ./pages/api/devices/[[...deviceParams]].js 文件来处理对 /api/devices/api/devices/<deviceId>/measurements/ 的请求。

  2. 在该文件中,导出一个 Next.js 请求 handler 函数。请参阅示例

在 Next.js 中,文件名模式 [[...param]].js 创建一个捕获所有 API 路由。要了解更多信息,请参阅 Next.js 动态 API 路由

检索和列出设备

INFLUX_BUCKET_AUTH 中检索已注册的设备并处理查询结果。

  1. 创建一个 Flux 查询,该查询获取每个包含 deviceauth 测量值的序列的最后一行。以下示例查询返回包含 key 字段(授权 ID)的行,并排除包含 token 字段的行(以避免将令牌暴露给 UI)。

    // Flux query finds devices
     from(bucket:`${INFLUX_BUCKET_AUTH}`)
          |> range(start: 0)
          |> filter(fn: (r) => r._measurement == "deviceauth" and r._field != "token")
          |> last()
    
    • Copy
    • Fill window
  2. 使用 QueryApi 客户端将 Flux 查询发送到 POST /api/v2/query InfluxDB API 端点。

创建一个 ./pages/api/devices/_devices.js 文件,其中包含以下内容

import { InfluxDB } from '@influxdata/influxdb-client'
import { flux } from '@influxdata/influxdb-client'

const INFLUX_ORG = process.env.INFLUX_ORG
const INFLUX_BUCKET_AUTH = process.env.INFLUX_BUCKET_AUTH
const influxdb = new InfluxDB({url: process.env.INFLUX_URL, token: process.env.INFLUX_TOKEN})

/**
 * Gets devices or a particular device when deviceId is specified. Tokens
 * are not returned unless deviceId is specified. It can also return devices
 * with empty/unknown key, such devices can be ignored (InfluxDB authorization is not associated).
 * @param deviceId optional deviceId
 * @returns promise with an Record<deviceId, {deviceId, createdAt, updatedAt, key, token}>.
 */
 export async function getDevices(deviceId) {
  const queryApi = influxdb.getQueryApi(INFLUX_ORG)
  const deviceFilter =
    deviceId !== undefined
      ? flux` and r.deviceId == "${deviceId}"`
      : flux` and r._field != "token"`
  const fluxQuery = flux`from(bucket:${INFLUX_BUCKET_AUTH})
    |> range(start: 0)
    |> filter(fn: (r) => r._measurement == "deviceauth"${deviceFilter})
    |> last()`
  const devices = {}

  return await new Promise((resolve, reject) => {
    queryApi.queryRows(fluxQuery, {
      next(row, tableMeta) {
        const o = tableMeta.toObject(row)
        const deviceId = o.deviceId
        if (!deviceId) {
          return
        }
        const device = devices[deviceId] || (devices[deviceId] = {deviceId})
        device[o._field] = o._value
        if (!device.updatedAt || device.updatedAt < o._time) {
          device.updatedAt = o._time
        }
      },
      error: reject,
      complete() {
        resolve(devices)
      },
    })
  })
}
  • Copy
  • Fill window

_devices 模块导出一个 getDevices(deviceId) 函数,该函数查询已注册的设备,处理数据,并返回一个包含结果的 Promise。如果您将该函数作为 getDevices()(不带 deviceId)调用,它将检索所有 deviceauth 数据点,并返回一个包含 { DEVICE_ID: ROW_DATA } 的 Promise。

为了发送查询并处理结果,getDevices(deviceId) 函数使用 QueryAPI queryRows(query, consumer) 方法。queryRows 执行 query 并将带注释的 CSV 结果作为 Observable 提供给 consumerqueryRows 具有以下 TypeScript 签名

queryRows(
  query: string | ParameterizedQuery,
  consumer: FluxResultObserver<string[]>
): void
  • Copy
  • Fill window

您提供的 consumer 必须实现 FluxResultObserver 接口,并提供以下回调函数

  • next(row, tableMeta):处理下一行和表格元数据 - 例如,准备响应。
  • error(error):接收和处理错误 - 例如,通过拒绝 Promise。
  • complete():当所有行都已使用完时发出信号 - 例如,通过解析 Promise。

要了解有关 Observers 的更多信息,请参阅 RxJS 指南

创建 API 以注册设备

在此应用程序中,已注册设备是一个包含您的设备 ID、授权 ID 和 API 令牌的数据点。API 令牌和授权权限允许设备查询和写入 INFLUX_BUCKET。在本节中,您将添加 API 端点,该端点处理来自 UI 的请求,在 InfluxDB 中创建授权,并将已注册的设备写入 INFLUX_BUCKET_AUTH 存储桶。要了解有关 API 令牌和授权的更多信息,请参阅 管理 API 令牌

应用程序 API 使用以下 /api/v2 InfluxDB API 端点

  • POST /api/v2/query:在 INFLUX_BUCKET_AUTH 中查询已注册的设备。
  • GET /api/v2/buckets:获取 INFLUX_BUCKET 的存储桶 ID。
  • POST /api/v2/authorizations:为设备创建授权。
  • POST /api/v2/write:将设备授权写入 INFLUX_BUCKET_AUTH
  1. 添加一个 ./pages/api/devices/create.js 文件来处理对 /api/devices/create 的请求。

  2. 在该文件中,导出一个 Next.js 请求 handler 函数,该函数执行以下操作

    1. 接受请求正文中的设备 ID。
    2. 查询 INFLUX_BUCKET_AUTH,如果设备存在授权,则响应错误。
    3. 为设备创建授权.
    4. 将设备 ID 和授权写入 INFLUX_BUCKET_AUTH.
    5. 当写入请求完成时,响应 HTTP 200

请参阅示例.

为设备创建授权

在本节中,您将创建一个具有对 INFLUX_BUCKET-权限的授权,并接收设备的 API 令牌。以下示例使用以下步骤创建授权

  1. 使用配置实例化 AuthorizationsAPI 客户端和 BucketsAPI 客户端。
  2. 检索存储桶 ID。
  3. 使用客户端库向 /api/v2/authorizations InfluxDB API 端点发送 POST 请求。

./api/devices/create.js 中,添加以下 createAuthorization(deviceId) 函数

import { InfluxDB } from '@influxdata/influxdb-client'
import { getDevices } from './_devices'
import { AuthorizationsAPI, BucketsAPI } from '@influxdata/influxdb-client-apis'
import { Point } from '@influxdata/influxdb-client'

const INFLUX_ORG = process.env.INFLUX_ORG
const INFLUX_BUCKET_AUTH = process.env.INFLUX_BUCKET_AUTH
const INFLUX_BUCKET = process.env.INFLUX_BUCKET

const influxdb = new InfluxDB({url: process.env.INFLUX_URL, token: process.env.INFLUX_TOKEN})

/**
 * Creates an authorization for a supplied deviceId
 * @param {string} deviceId client identifier
 * @returns {import('@influxdata/influxdb-client-apis').Authorization} promise with authorization or an error
 */
async function createAuthorization(deviceId) {
  const authorizationsAPI = new AuthorizationsAPI(influxdb)
  const bucketsAPI = new BucketsAPI(influxdb)
  const DESC_PREFIX = 'IoTCenterDevice: '

  const buckets = await bucketsAPI.getBuckets({name: INFLUX_BUCKET, orgID: INFLUX_ORG})
  const bucketId = buckets.buckets[0]?.id
  
  return await authorizationsAPI.postAuthorizations(
    {
      body: {
              orgID: INFLUX_ORG,
              description: DESC_PREFIX + deviceId,
              permissions: [
                {
                  action: 'read',
                  resource: {type: 'buckets', id: bucketId, orgID: INFLUX_ORG},
                },
                {
                  action: 'write',
                  resource: {type: 'buckets', id: bucketId, orgID: INFLUX_ORG},
                },
              ],
            },
    }
  )

}
  • Copy
  • Fill window

要创建对 INFLUX_BUCKET 具有-权限的授权,您需要存储桶 ID。为了检索存储桶 ID,createAuthorization(deviceId) 调用 BucketsAPI getBuckets 函数,该函数向 /api/v2/buckets InfluxDB API 端点发送 GET 请求。然后 createAuthorization(deviceId) 在请求正文中传递一个新的授权,其中包含以下内容

  • 存储桶 ID。
  • 组织 ID。
  • 描述:IoTCenterDevice: DEVICE_ID
  • 存储桶的权限列表。

要了解有关 API 令牌和授权的更多信息,请参阅 管理 API 令牌

接下来,将设备授权写入存储桶

将设备授权写入存储桶

在 InfluxDB 中完成设备授权后,将设备和授权详情的数据点写入 INFLUX_BUCKET_AUTH。将设备授权存储在存储桶中,您可以执行以下操作:

  • 报告设备授权历史记录。
  • 管理带令牌和不带令牌的设备。
  • 将同一令牌分配给多个设备。
  • 刷新令牌。

要将数据点写入 InfluxDB,请使用 InfluxDB 客户端库向 /api/v2/write InfluxDB API 端点发送 POST 请求。在 ./pages/api/devices/create.js 中,添加以下 createDevice(deviceId) 函数:

/** Creates an authorization for a deviceId and writes it to a bucket */
async function createDevice(deviceId) {
  let device = (await getDevices(deviceId)) || {}
  let authorizationValid = !!Object.values(device)[0]?.key
  if(authorizationValid) {
    console.log(JSON.stringify(device))
    return Promise.reject('This device ID is already registered and has an authorization.')
  } else {
    console.log(`createDeviceAuthorization: deviceId=${deviceId}`)
    const authorization = await createAuthorization(deviceId)
    const writeApi = influxdb.getWriteApi(INFLUX_ORG, INFLUX_BUCKET_AUTH, 'ms', {
      batchSize: 2,
    })
    const point = new Point('deviceauth')
      .tag('deviceId', deviceId)
      .stringField('key', authorization.id)
      .stringField('token', authorization.token)
    writeApi.writePoint(point)
    await writeApi.close()
    return
  }
}
  • Copy
  • Fill window

createDevice(device_id) 接受一个 device_id,并执行以下步骤将数据写入 INFLUX_BUCKET_AUTH

  1. 使用配置中的 urltokenorg 值初始化 InfluxDBClient()
  2. 初始化一个 WriteAPI 客户端,用于将数据写入 InfluxDB 存储桶。
  3. 创建一个 Point
  4. 使用 writeApi.writePoint(point)Point 写入存储桶。

该函数写入一个包含以下元素的数据点:

元素名称
measurementdeviceauth
tagdeviceId设备 ID
fieldkey授权 ID
fieldtoken授权 (API) 令牌

安装并运行 UI

influxdata/iot-api-ui 是一个独立的 Next.js React UI,它使用您的应用程序 API 在 InfluxDB 中写入和查询数据。iot-api-ui 使用 Next.js 重写/api/ 路径中的所有请求路由到您的 API。

要安装和运行 UI,请执行以下操作:

  1. 在您的 ~/iot-api-apps 目录中,克隆 influxdata/iot-api-ui 仓库 并进入 iot-api-ui 目录——例如:

    cd ~/iot-api-apps
    git clone git@github.com:influxdata/iot-api-ui.git
    cd ./iot-app-ui
    
    • Copy
    • Fill window
  2. ./.env.development 文件包含默认配置设置,您可以编辑或覆盖这些设置(使用 ./.env.local 文件)。

  3. 要启动 UI,请在终端中输入以下命令:

    yarn dev
    
    • Copy
    • Fill window

    要查看设备列表和注册设备,请在浏览器中访问 https://127.0.0.1:3000/devices

要了解有关 UI 组件的更多信息,请参阅 influxdata/iot-api-ui


此页面是否对您有帮助?

感谢您的反馈!


Flux 的未来

Flux 即将进入维护模式。您可以继续像当前一样使用它,而无需对代码进行任何更改。

阅读更多

InfluxDB 3 开源版本现已发布公测版

InfluxDB 3 开源版本现已可用于 alpha 测试,根据 MIT 或 Apache 2 许可获得许可。

我们正在发布两个产品作为 alpha 版本的一部分。

InfluxDB 3 Core 是我们的新开源产品。它是一个用于时间序列和事件数据的最新数据引擎。InfluxDB 3 Enterprise 是一个商业版本,它建立在 Core 的基础上,增加了历史查询功能、读取副本、高可用性、可扩展性和细粒度的安全性。

有关如何开始使用的更多信息,请查看