Documentation

JavaScript 客户端库入门

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

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

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

目录

设置 InfluxDB

如果你还没有,创建一个 InfluxDB Cloud 帐户安装 InfluxDB OSS

物联网入门示例应用假设以下前提条件:

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

在生产应用中使用受限令牌

对于生产应用程序,创建并使用一个 读写 令牌,拥有最小的权限,并且仅在单个客户端或应用程序中使用它。

介绍IoT入门

应用程序架构分为四层:

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

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

安装Yarn

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

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

    yarn --version
    

创建应用程序

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

mkdir ~/iot-api-apps
cd ~/iot-api-apps

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

  1. 在你的 ~/iot-api-apps 目录中,打开终端并输入以下命令,从 NextJS learn-starter template 创建 iot-api-js 应用:

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

    cd iot-api-js
    yarn dev -p 3001
    

要查看应用程序,请在浏览器中访问 http://localhost:3001

安装 InfluxDB 客户端库

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

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

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

    yarn add @influxdata/influxdb-client-apis
    

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

配置客户端库

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

  • INFLUX_URL
  • INFLUX_TOKEN
  • INFLUX_ORG
  • INFLUX_BUCKET
  • INFLUX_BUCKET_AUTH

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

./.env.development 文件是有版本控制的,包含了你的 开发 环境的非秘密默认设置。

# .env.development

INFLUX_URL=http://localhost:8086
INFLUX_BUCKET=iot_center
INFLUX_BUCKET_AUTH=iot_center_devices

要配置未添加到版本控制的秘密和设置,创建一个 ./.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

在终端中输入以下命令以重新启动并加载 .env 文件:

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

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

console.log(process.env.INFLUX_ORG)

构建API

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

  1. 监听来自用户界面的HTTP请求。
  2. 将请求转换为 InfluxDB API 请求。
  3. 处理InfluxDB API响应并处理错误。
  4. 响应状态和数据(用于用户界面)。

创建API以列出设备

添加 /api/devices API 端点,用于检索、处理和列出设备。 /api/devices 使用 /api/v2/query InfluxDB API 端点查询 INFLUX_BUCKET_AUTH 以获取注册设备。

处理设备信息请求

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

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

在 Next.js 中,文件名模式 [[...param]].js 创建了一个 捕获所有 的 API 路由。 要了解更多,请参见 Next.js dynamic API routes

检索和列出设备

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

  1. 创建一个Flux查询,获取每个包含series的最后一行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()
    
  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)
      },
    })
  })
}

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

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

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

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

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

要了解更多关于观察者的内容,请参见RxJS指南

创建注册设备的API

在这个应用中,注册设备 是一个包含您的设备ID、授权ID和API令牌的点。 API令牌和授权权限允许设备查询和写入INFLUX_BUCKET。 在这一部分,您添加处理来自UI请求的API端点,在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. Accept a device ID in the request body.
    2. Query INFLUX_BUCKET_AUTH and respond with an error if an authorization exists for the device.
    3. Create an authorization for the device.
    4. Write the device ID and authorization to INFLUX_BUCKET_AUTH.
    5. Respond with HTTP 200 when the write request completes.

查看示例

为设备创建授权

在本节中,您将创建对 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},
                },
              ],
            },
    }
  )

}

要创建一个具有 - 权限的授权,您需要桶 ID。 要检索桶 ID, createAuthorization(deviceId) 调用 BucketsAPI getBuckets 函数,该函数发送一个 GET 请求到 /api/v2/buckets InfluxDB API 端点。 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
  }
}

createDevice(device_id) 接受一个 device_id 并按照以下步骤将数据写入 INFLUX_BUCKET_AUTH

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

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

元素名称
测量deviceauth
标签deviceId设备 ID
字段key授权ID
字段token授权(API)令牌

安装并运行用户界面

influxdata/iot-api-ui 是一个独立的 Next.js React 用户界面,使用您的应用程序 API 向 InfluxDB 写入和查询数据。iot-api-ui 使用 Next.js rewrites 将所有请求路由到 /api/ 路径下的您的 API。

要安装和运行用户界面,请执行以下操作:

  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
    
  2. ../.env.development 文件包含您可以编辑或覆盖的默认配置设置(通过 ./.env.local 文件)。

  3. 要启动用户界面,请在终端中输入以下命令:

    yarn dev
    

    要查看设备列表并注册设备,请在浏览器中访问 http://localhost:3000/devices

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



Flux的未来

Flux 正在进入维护模式。您可以像现在一样继续使用它,而无需对您的代码进行任何更改。

阅读更多

InfluxDB 3 开源版本现已公开Alpha测试

InfluxDB 3 Open Source is now available for alpha testing, licensed under MIT or Apache 2 licensing.

我们将发布两个产品作为测试版的一部分。

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

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