Jts/api guides (#3862)

* - Add tutorial that guides a developer through building a simplified IoT
  center app with client libraries.
- device registration and authorization.
- write and query--explain batch writes with the JS client library.

* - feat: queries and visualizations with Giraffe library. queryToTable, Giraffe table.

* feat(api-guide): revise intro, auth, example headings.

* feat(api-guide): describe resources. describe auth and API tokens.

- API basics

* fix: influxdb and iot center setup

* fix: update registration steps to include the new INFLUX_BUCKET_AUTH flow.

* feat(api-guides): Add client library example to fetch routes.

- install, links.
- replace use of getIoTAuthorizations with query from getDevices.
- breakdown create device API requests.
- initial commit of API guide using Next.js with Influx client libraries. Project source at https://github.com/jstirnaman/nextjs-iot-starter.
- explain the flow to register a device. Remove unused example code. TODO: document the setup and UI.
- Add UI code samples. Revise headings. Explain API purpose.
- UI component fixes and refactor. Input field takes a device ID, queries, and re-renders the list with results. Registration button submits device ID for a new authorization.

* feat(api-guide): add iot-starter guide index page, fix errors

- add the iot-starter directory and index page
- fix tag errors and links.

* feat: IoT starter navigation.

* feat(api-guide): nav and intros.

* wip: rearrange, move full examples to top of section and link to explainers.

* chore: Shared intro shortcode for iot-starter tutorials.

* fix: intros, navigation, and config instruction

- Add intro shortcode for tutorials to share.
- Organize navigation for language-specific tutorials (would prefer to unify as much as possible).
- Update environment variable config instruction.

* Feature/api guide python client (#4023)

* adding placeholders into code

* create_device not tested yet

* everything working except flux query and filter query

* fix: replace download button with spec link. (#4013)

- Closes #3810 - Remove download button and add a link to the spec source in Github.

* Enterprise 1.9.7 release notes (#4007)

* added not under flux updates

* updates based on feedback

* changed release notes date

* added requested update

* added detail about script builder (#3995)

* added detail about script builder

* Update content/chronograf/v1.9/guides/querying-data.md

Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>

Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>

* fix: async writes and deletes (#4015)

- Correct handling of writes and deletes in cloud vs. oss (async vs. sync).
- Cleanup redundancy in Troubleshooting.
- Closes https://github.com/influxdata/DAR/issues/291

Co-authored-by: lwandzura <51929958+lwandzura@users.noreply.github.com>

* Collect user feedback per page and restructure modals (#4014)

* WIP feedback forms

* WIP complete feedback lifecycles

* finalize page feedback interactions

Co-authored-by: kelseiv <47797004+kelseiv@users.noreply.github.com>

* Revert "Enterprise 1.9.7 release notes (#4007)" (#4017)

This reverts commit c6f4a99d72.

* hotfix: fix cli homebrew package name, closes #4022

* docs: add python iot guide

* fix: remove .idea files

* fix: remove .idea files and package-lock

* fix: initial batch of fixes

* fix: finished PR changes

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

* Update content/influxdb/v2.2/api-guide/iot-starter/_index.md

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>

* Update content/influxdb/v2.2/api-guide/iot-starter/python.md

Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>

* Update content/influxdb/v2.2/api-guide/iot-starter/_index.md

Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>

* Update content/influxdb/v2.2/api-guide/iot-starter/_index.md

Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>

* Update content/influxdb/v2.2/api-guide/iot-starter/_index.md

Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>

* Delete _index.md

Co-authored-by: Sunbrye Ly <sunbryely@Sunbryes-MacBook-Pro.local>
Co-authored-by: Jason Stirnaman <jstirnaman@influxdata.com>
Co-authored-by: lwandzura <51929958+lwandzura@users.noreply.github.com>
Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>
Co-authored-by: kelseiv <47797004+kelseiv@users.noreply.github.com>
Co-authored-by: Scott Anderson <scott@influxdata.com>
Co-authored-by: Sunbrye Ly <sunbryely@Sunbryes-MBP.lan>

* chore: replace UI code with GH links, fix navigation.

* feat: API client library tutorials

- Cleanup py and js tutorials.
- JS is still WIP.
- Fix nav.

* fix: Revise Node.js tutorial.

* fix: Revise Python tutorial.

* fix: Remove last bullet since Node.js tutorial isn't that far yet.

* Update content/influxdb/v2.2/api-guide/tutorials/client-library-starter/_index.md

Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>

* Update content/influxdb/v2.2/api-guide/tutorials/client-library-starter/nodejs.md

Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>

* wip: Install and run the UI.

* docs: fix instructions and move UI docs to iot-api-ui README.

* fix: Update JS and Py tutorials with common UI.

* fix: Update code samples in nodejs and python IoT starter tutorials.

* fix: fixup.

* fix: Cleanup code tabs.

* fix: update toc

* fix: iot-starter

Fix examples.
Cleanup.

* fix: python restart

* fix: Cleanup.

* chore: add repo links

* Add cloud, fix frontmatter.

* fix: Remove links to sections.

Co-authored-by: sunbryely-influxdata <101659702+sunbryely-influxdata@users.noreply.github.com>
Co-authored-by: Sunbrye Ly <sunbryely@Sunbryes-MacBook-Pro.local>
Co-authored-by: lwandzura <51929958+lwandzura@users.noreply.github.com>
Co-authored-by: Scott Anderson <sanderson@users.noreply.github.com>
Co-authored-by: kelseiv <47797004+kelseiv@users.noreply.github.com>
Co-authored-by: Scott Anderson <scott@influxdata.com>
Co-authored-by: Sunbrye Ly <sunbryely@Sunbryes-MBP.lan>
pull/4130/head
Jason Stirnaman 2022-06-15 19:15:46 -05:00 committed by GitHub
parent bb10438c0b
commit 9e33fe690a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 1344 additions and 4 deletions

2
.gitignore vendored
View File

@ -9,3 +9,5 @@ node_modules
/content/influxdb/*/api/*.html /content/influxdb/*/api/*.html
/api-docs/redoc-static.html* /api-docs/redoc-static.html*
.vscode/* .vscode/*
.idea
package-lock.json

View File

@ -0,0 +1,13 @@
---
title: InfluxDB API client library tutorials
seotitle: Get started with InfluxDB API client libraries
description: Follow step-by-step tutorials to for InfluxDB API client libraries in your favorite framework or language.
weight: 4
menu:
influxdb_cloud:
name: Client library tutorials
parent: Develop with the API
influxdb/cloud/tags: [api]
---
{{< children >}}

View File

@ -0,0 +1,13 @@
---
title: InfluxDB API client library starter
seotitle: Starter tutorial for InfluxDB API client libraries
description: Follow step-by-step tutorials to build an IoT dashboard with API client libraries in your favorite framework or language.
weight: 4
menu:
influxdb_cloud:
name: Client library starter
parent: Client library tutorials
influxdb/cloud/tags: [api]
---
{{% duplicate-oss %}}

View File

@ -0,0 +1,16 @@
---
title: JavaScript client library starter
seotitle: Use JavaScript client library to build a sample application
list_title: JavaScript client library starter
description: >
Build a JavaScript application that writes, queries, and manages devices with the
InfluxDB client library.
menu:
influxdb_cloud:
identifier: client-library-starter-js
name: JavaScript
parent: Client library starter
influxdb/cloud/tags: [api, javascript, nodejs]
---
{{% duplicate-oss %}}

View File

@ -0,0 +1,17 @@
---
title: Python client library starter
seotitle: Use Python client library to build a sample application
list_title: Python
description: >
Build an application that writes, queries, and manages devices with the InfluxDB
client library for Python.
weight: 3
menu:
influxdb_cloud:
identifier: client-library-starter-py
name: Python
parent: Client library starter
influxdb/cloud/tags: [api, python]
---
{{% duplicate-oss %}}

View File

@ -12,20 +12,28 @@ influxdb/v2.2/tags: [api]
The InfluxDB v2 API provides a programmatic interface for interactions with InfluxDB. The InfluxDB v2 API provides a programmatic interface for interactions with InfluxDB.
Access the InfluxDB API using the `/api/v2/` endpoint. Access the InfluxDB API using the `/api/v2/` endpoint.
## Developer guides
- [API starter guide](/influxdb/v2.2/api-guide/starter/)
## InfluxDB client libraries ## InfluxDB client libraries
InfluxDB client libraries are language-specific packages that integrate with the InfluxDB v2 API. InfluxDB client libraries are language-specific packages that integrate with the InfluxDB v2 API.
For information about supported client libraries, see [InfluxDB client libraries](/{{< latest "influxdb" >}}/api-guide/client-libraries/). For tutorials and information about client libraries, see [InfluxDB client libraries](/{{< latest "influxdb" >}}/api-guide/client-libraries/).
## InfluxDB v2 API documentation ## InfluxDB v2 API documentation
<a class="btn" href="/influxdb/v2.2/api/">InfluxDB OSS {{< current-version >}} API documentation</a> <a class="btn" href="/influxdb/v2.2/api/">InfluxDB OSS {{< current-version >}} API documentation</a>
#### View InfluxDB API documentation locally ### View InfluxDB API documentation locally
InfluxDB API documentation is built into the `influxd` service and represents InfluxDB API documentation is built into the `influxd` service and represents
the API specific to the current version of InfluxDB. the API specific to the current version of InfluxDB.
To view the API documentation locally, [start InfluxDB](/influxdb/v2.2/get-started/#start-influxdb) To view the API documentation locally, [start InfluxDB](/influxdb/v2.2/get-started/#start-influxdb)
and visit the `/docs` endpoint in a browser ([localhost:8086/docs](http://localhost:8086/docs)). and visit the `/docs` endpoint in a browser ([localhost:8086/docs](http://localhost:8086/docs)).
## InfluxDB v1 compatibility API documentation ## InfluxDB v1 compatibility API documentation
The InfluxDB v2 API includes [InfluxDB 1.x compatibility endpoints](/influxdb/v2.2/reference/api/influxdb-1x/) The InfluxDB v2 API includes [InfluxDB 1.x compatibility endpoints](/influxdb/v2.2/reference/api/influxdb-1x/)
that work with InfluxDB 1.x client libraries and third-party integrations like that work with InfluxDB 1.x client libraries and third-party integrations like
[Grafana](https://grafana.com) and others. [Grafana](https://grafana.com) and others.

View File

@ -1,11 +1,11 @@
--- ---
title: API Quick Start title: API Quick Start
seotitle: Use the InfluxDB API seotitle: Use the InfluxDB API
description: Interact with InfluxDB 1 using a rich API for writing and querying data and more. description: Interact with InfluxDB using a rich API for writing and querying data and more.
weight: 3 weight: 3
menu: menu:
influxdb_2_2: influxdb_2_2:
name: Quick Start name: Quick start
parent: Develop with the API parent: Develop with the API
aliases: aliases:
- /influxdb/v2.2/tools/api/ - /influxdb/v2.2/tools/api/

View File

@ -0,0 +1,13 @@
---
title: InfluxDB API client library tutorials
seotitle: Get started with InfluxDB API client libraries
description: Follow step-by-step tutorials to for InfluxDB API client libraries in your favorite framework or language.
weight: 4
menu:
influxdb_2_2:
name: Client library tutorials
parent: Develop with the API
influxdb/v2.2/tags: [api]
---
{{< children >}}

View File

@ -0,0 +1,30 @@
---
title: InfluxDB API client library starter
seotitle: Starter tutorial for InfluxDB API client libraries
description: Follow step-by-step tutorials to build an IoT dashboard with API client libraries in your favorite framework or language.
weight: 4
menu:
influxdb_2_2:
name: Client library starter
parent: Client library tutorials
influxdb/v2.2/tags: [api]
---
Follow step-by-step tutorials to build an Internet-of-Things (IoT) application with InfluxData client libraries and your favorite framework or language.
InfluxData and the user community maintain client libraries for developers who want to take advantage of:
- Idioms for InfluxDB requests, responses, and errors.
- Common patterns in a familiar programming language.
- Faster development and less boilerplate code.
These tutorials walk through using the InfluxDB API and
client libraries to build a modern application as you learn the following:
- InfluxDB core concepts.
- How the application interacts with devices and InfluxDB.
- How to authenticate apps and devices to the API.
- How to install a client library.
- How to write and query data in InfluxDB.
- How to use the InfluxData UI libraries to format data and create visualizations.
{{< children >}}

View File

@ -0,0 +1,508 @@
---
title: JavaScript client library starter
seotitle: Use JavaScript client library to build a sample application
list_title: JavaScript client library starter
description: >
Build a JavaScript application that writes, queries, and manages devices with the
InfluxDB client library.
menu:
influxdb_2_2:
identifier: client-library-starter-js
name: JavaScript
parent: Client library starter
influxdb/v2.2/tags: [api, javascript, nodejs]
---
{{% api/iot-starter-intro %}}
## Contents
- [Contents](#contents)
- [Set up InfluxDB](#set-up-influxdb)
- [Authenticate with an InfluxDB API token](#authenticate-with-an-influxdb-api-token)
- [Introducing IoT Starter](#introducing-iot-starter)
- [Create the application](#create-the-application)
- [Install InfluxDB client library](#install-influxdb-client-library)
- [Configure the client library](#configure-the-client-library)
- [Build the API](#build-the-api)
- [Create the API to list devices](#create-the-api-to-list-devices)
- [Handle requests for device information](#handle-requests-for-device-information)
- [Retrieve and list devices](#retrieve-and-list-devices)
- [Create the API to register devices](#create-the-api-to-register-devices)
- [Create an authorization for the device](#create-an-authorization-for-the-device)
- [Write the device authorization to a bucket](#write-the-device-authorization-to-a-bucket)
- [Install and run the UI](#install-and-run-the-ui)
## Set up InfluxDB
If you haven't already, [create an InfluxDB Cloud account](https://www.influxdata.com/products/influxdb-cloud/) or [install InfluxDB OSS](https://www.influxdata.com/products/influxdb/).
### Authenticate with an InfluxDB API token
For convenience in development,
[create an _All-Access_ token](/influxdb/v2.2/security/tokens/create-token/)
for your application. This grants your application full read and write
permissions on all resources within your InfluxDB organization.
{{% note %}}
For a production application, create and use a
{{% cloud-only %}}custom{{% /cloud-only %}}{{% oss-only %}}read-write{{% /oss-only %}}
token with minimal permissions and only use it with your application.
{{% /note %}}
## Introducing IoT Starter
The application architecture has four layers:
- **InfluxDB API**: InfluxDB v2 API.
- **IoT device**: Virtual or physical devices write IoT data to the InfluxDB API.
- **UI**: Sends requests to the server and renders views in the browser.
- **API**: Receives requests from the UI, sends requests to InfluxDB, and processes responses from InfluxDB.
{{% note %}}
For the complete code referenced in this tutorial, see the [influxdata/iot-api-js repository](https://github.com/influxdata/iot-api-js).
{{% /note %}}
## Create the application
Create a directory that will contain your `iot-api` projects.
The following example code creates an `iot-api` directory in your home directory
and changes to the new directory:
```bash
mkdir ~/iot-api-apps
cd ~/iot-api-apps
```
Use [Next.js](https://nextjs.org/), a framework for full-stack JavaScript applications, to create your application.
1. In your `~/iot-api-apps` directory, open a terminal and enter the following commands to create the `iot-api-js` app from the NextJS [learn-starter template](https://github.com/vercel/next-learn/tree/master/basics/learn-starter):
```bash
npx create-next-app iot-api-js --use-npm --example "https://github.com/vercel/next-learn/tree/master/basics/learn-starter"
```
2. After the installation completes, enter the following commands in your terminal to go into your `./iot-api-js` directory and start the development server:
```bash
cd iot-api-js
npm run dev -p 3001
```
To view the application, visit <http://localhost:3001> in your browser.
## Install InfluxDB client library
The InfluxDB client library provides the following InfluxDB API interactions:
- Query data with the Flux language.
- Write data to InfluxDB.
- Batch data in the background.
- Retry requests automatically on failure.
1. Enter the following command into your terminal to install the client library:
```bash
npm i @influxdata/influxdb-client
```
2. Enter the following command into your terminal to install `@influxdata/influxdb-client-apis`, the _management APIs_ that create, modify, and delete authorizations, buckets, tasks, and other InfluxDB resources:
```bash
npm i @influxdata/influxdb-client-apis
```
For more information about the client library, see the [influxdata/influxdb-client-js repo](https://github.com/influxdata/influxdb-client-js).
## Configure the client library
InfluxDB client libraries require configuration properties from your InfluxDB environment.
Typically, you'll provide the following properties as environment variables for your application:
- `INFLUX_URL`
- `INFLUX_TOKEN`
- `INFLUX_ORG`
- `INFLUX_BUCKET`
- `INFLUX_BUCKET_AUTH`
Next.js uses the `env` module to provide environment variables to your application.
The `./.env.development` file is versioned and contains non-secret default settings for your _development_ environment.
```bash
# .env.development
INFLUX_URL=http://localhost:8086
INFLUX_BUCKET=iot_center
INFLUX_BUCKET_AUTH=iot_center_devices
```
To configure secrets and settings that aren't added to version control,
create a `./.env.local` file and set the variables--for example, set your InfluxDB token and organization:
```sh
# .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
```
Enter the following commands into your terminal to restart and load the `.env` files:
1. `CONTROL+C` to stop the application.
2. `npm run dev` to start the application.
Next.js sets variables that you can access in the `process.env` object--for example:
```ts
console.log(process.env.INFLUX_ORG)
```
## Build the API
Your application API provides server-side HTTP endpoints that process requests from the UI.
Each API endpoint is responsible for the following:
1. Listen for HTTP requests (from the UI).
2. Translate requests into InfluxDB API requests.
3. Process InfluxDB API responses and handle errors.
4. Respond with status and data (for the UI).
## Create the API to list devices
Add the `/api/devices` API endpoint that retrieves, processes, and lists devices.
`/api/devices` uses the `/api/v2/query` InfluxDB API endpoint to query `INFLUX_BUCKET_AUTH` for a registered device.
### Handle requests for device information
1. Create a `./pages/api/devices/[[...deviceParams]].js` file to handle requests for `/api/devices` and `/api/devices/<deviceId>/measurements/`.
2. In the file, export a Next.js request `handler` function.
[See the example](https://github.com/influxdata/iot-api-js/blob/18d34bcd59b93ad545c5cd9311164c77f6d1995a/pages/api/devices/%5B%5B...deviceParams%5D%5D.js).
{{% note %}}
In Next.js, the filename pattern `[[...param]].js` creates a _catch-all_ API route.
To learn more, see [Next.js dynamic API routes](https://nextjs.org/docs/api-routes/dynamic-api-routes).
{{% /note %}}
### Retrieve and list devices
Retrieve registered devices in `INFLUX_BUCKET_AUTH` and process the query results.
1. Create a Flux query that gets the last row of each [series](/influxdb/v2.2/reference/glossary#series) that contains a `deviceauth` measurement.
The example query below returns rows that contain the `key` field (authorization ID) and excludes rows that contain a `token` field (to avoid exposing tokens to the UI).
```js
// Flux query finds devices
from(bucket:`${INFLUX_BUCKET_AUTH}`)
|> range(start: 0)
|> filter(fn: (r) => r._measurement == "deviceauth" and r._field != "token")
|> last()
```
2. Use the `QueryApi` client to send the Flux query to the `POST /api/v2/query` InfluxDB API endpoint.
Create a `./pages/api/devices/_devices.js` file that contains the following:
{{< code-tabs-wrapper >}}
{{% code-tabs %}}
[Node.js](#nodejs)
{{% /code-tabs %}}
{{% code-tab-content %}}
{{% truncate %}}
```ts
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)
},
})
})
}
```
{{% /truncate %}}
{{% caption %}}[iot-api-js/pages/api/devices/_devices.js getDevices(deviceId)](https://github.com/influxdata/iot-api-js/blob/18d34bcd59b93ad545c5cd9311164c77f6d1995a/pages/api/devices/_devices.js){{% /caption %}}
{{% /code-tab-content %}}
{{< /code-tabs-wrapper >}}
The `_devices` module exports a `getDevices(deviceId)` function that queries
for registered devices, processes the data, and returns a Promise with the result.
If you invoke the function as `getDevices()` (without a _`deviceId`_),
it retrieves all `deviceauth` points and returns a Promise with `{ DEVICE_ID: ROW_DATA }`.
To send the query and process results, the `getDevices(deviceId)` function uses the `QueryAPI queryRows(query, consumer)` method.
`queryRows` executes the `query` and provides the Annotated CSV result as an Observable to the `consumer`.
`queryRows` has the following TypeScript signature:
```ts
queryRows(
query: string | ParameterizedQuery,
consumer: FluxResultObserver<string[]>
): void
```
{{% caption %}}[@influxdata/influxdb-client-js QueryAPI](https://github.com/influxdata/influxdb-client-js/blob/3db2942432b993048d152e0d0e8ec8499eedfa60/packages/core/src/QueryApi.ts){{% /caption %}}
The `consumer` that you provide must implement the [`FluxResultObserver` interface](https://github.com/influxdata/influxdb-client-js/blob/3db2942432b993048d152e0d0e8ec8499eedfa60/packages/core/src/results/FluxResultObserver.ts) and provide the following callback functions:
- `next(row, tableMeta)`: processes the next row and table metadata--for example, to prepare the response.
- `error(error)`: receives and handles errors--for example, by rejecting the Promise.
- `complete()`: signals when all rows have been consumed--for example, by resolving the Promise.
To learn more about Observers, see the [RxJS Guide](https://rxjs.dev/guide/observer).
## Create the API to register devices
In this application, a _registered device_ is a point that contains your device ID, authorization ID, and API token.
The API token and authorization permissions allow the device to query and write to `INFLUX_BUCKET`.
In this section, you add the API endpoint that handles requests from the UI, creates an authorization in InfluxDB,
and writes the registered device to the `INFLUX_BUCKET_AUTH` bucket.
To learn more about API tokens and authorizations, see [Manage API tokens](/influxdb/v2.2/security/tokens/)
The application API uses the following `/api/v2` InfluxDB API endpoints:
- `POST /api/v2/query`: to query `INFLUX_BUCKET_AUTH` for a registered device.
- `GET /api/v2/buckets`: to get the bucket ID for `INFLUX_BUCKET`.
- `POST /api/v2/authorizations`: to create an authorization for the device.
- `POST /api/v2/write`: to write the device authorization to `INFLUX_BUCKET_AUTH`.
1. Add a `./pages/api/devices/create.js` file to handle requests for `/api/devices/create`.
2. In the file, export a Next.js request `handler` function that does the following:
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](#create-an-authorization-for-the-device).
4. [Write the device ID and authorization to `INFLUX_BUCKET_AUTH`](#write-the-device-authorization-to-a-bucket).
5. Respond with `HTTP 200` when the write request completes.
[See the example](https://github.com/influxdata/iot-api-js/blob/25b38c94a1f04ea71f2ef4b9fcba5350d691cb9d/pages/api/devices/create.js).
### Create an authorization for the device
In this section, you create an authorization with _read_-_write_ permission to `INFLUX_BUCKET` and receive an API token for the device.
The example below uses the following steps to create the authorization:
1. Instantiate the `AuthorizationsAPI` client and `BucketsAPI` client with the configuration.
2. Retrieve the bucket ID.
3. Use the client library to send a `POST` request to the `/api/v2/authorizations` InfluxDB API endpoint.
In `./api/devices/create.js`, add the following `createAuthorization(deviceId)` function:
{{< code-tabs-wrapper >}}
{{% code-tabs %}}
[Node.js](#nodejs)
{{% /code-tabs %}}
{{% code-tab-content %}}
{{% truncate %}}
```ts
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},
},
],
},
})
}
```
{{% /truncate %}}
{{% caption %}}[iot-api-js/pages/api/devices/create.js](https://github.com/influxdata/iot-api-js/blob/42a37d683b5e4df601422f85d2c22f5e9d592e68/pages/api/devices/create.js){{% /caption %}}
{{% /code-tab-content %}}
{{< /code-tabs-wrapper >}}
To create an authorization that has _read_-_write_ permission to `INFLUX_BUCKET`, you need the bucket ID.
To retrieve the bucket ID,
`createAuthorization(deviceId)` calls the `BucketsAPI getBuckets` function that sends a `GET` request to
the `/api/v2/buckets` InfluxDB API endpoint.
`createAuthorization(deviceId)` then passes a new authorization in the request body with the following:
- Bucket ID.
- Organization ID.
- Description: `IoTCenterDevice: DEVICE_ID`.
- List of permissions to the bucket.
To learn more about API tokens and authorizations, see [Manage API tokens](/influxdb/v2.2/security/tokens/).
Next, [write the device authorization to a bucket](#write-the-device-authorization-to-a-bucket).
### Write the device authorization to a bucket
With a device authorization in InfluxDB, write a point for the device and authorization details to `INFLUX_BUCKET_AUTH`.
Storing the device authorization in a bucket allows you to do the following:
- Report device authorization history.
- Manage devices with and without tokens.
- Assign the same token to multiple devices.
- Refresh tokens.
To write a point to InfluxDB, use the InfluxDB client library to send a `POST` request to the `/api/v2/write` InfluxDB API endpoint.
In `./pages/api/devices/create.js`, add the following `createDevice(deviceId)` function:
{{< code-tabs-wrapper >}}
{{% code-tabs %}}
[Node.js](#nodejs)
{{% /code-tabs %}}
{{% code-tab-content %}}
```ts
/** 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
}
}
```
{{% caption %}}[iot-api-js/pages/api/devices/create.js](https://github.com/influxdata/iot-api-js/blob/25b38c94a1f04ea71f2ef4b9fcba5350d691cb9d/pages/api/devices/create.js){{% /caption %}}
{{% /code-tab-content %}}
{{< /code-tabs-wrapper >}}
`createDevice(device_id)` takes a _`device_id`_ and writes data to `INFLUX_BUCKET_AUTH` in the following steps:
1. Initialize `InfluxDBClient()` with `url`, `token`, and `org` values from the configuration.
2. Initialize a `WriteAPI` client for writing data to an InfluxDB bucket.
3. Create a `Point`.
4. Use `writeApi.writePoint(point)` to write the `Point` to the bucket.
The function writes a point with the following elements:
| Element | Name | Value |
|:------------|:-----------|:--------------------------|
| measurement | | `deviceauth` |
| tag | `deviceId` | device ID |
| field | `key` | authorization ID |
| field | `token` | authorization (API) token |
## Install and run the UI
`influxdata/iot-api-ui` is a standalone [Next.js React](https://nextjs.org/docs/basic-features/pages) UI that uses your application API to write and query data in InfluxDB.
`iot-api-ui` uses Next.js _[rewrites](https://nextjs.org/docs/api-reference/next.config.js/rewrites)_ to route all requests in the `/api/` path to your API.
To install and run the UI, do the following:
1. In your `~/iot-api-apps` directory, clone the [`influxdata/iot-api-ui` repo](https://github.com/influxdata/iot-api-ui) and go into the `iot-api-ui` directory--for example:
```bash
cd ~/iot-api-apps
git clone git@github.com:influxdata/iot-api-ui.git
cd ./iot-app-ui
```
2. The `./.env.development` file contains default configuration settings that you can
edit or override (with a `./.env.local` file).
3. To start the UI, enter the following command into your terminal:
```bash
yarn dev
```
To view the list and register devices, visit <http://localhost:3000/devices> in your browser.
To learn more about the UI components, see [`influxdata/iot-api-ui`](https://github.com/influxdata/iot-api-ui).

View File

@ -0,0 +1,583 @@
---
title: Python client library starter
seotitle: Use Python client library to build a sample application
list_title: Python
description: >
Build an application that writes, queries, and manages devices with the InfluxDB
client library for Python.
weight: 3
menu:
influxdb_2_2:
identifier: client-library-starter-py
name: Python
parent: Client library starter
influxdb/v2.2/tags: [api, python]
---
{{% api/iot-starter-intro %}}
- How to use the InfluxData UI libraries to format data and create visualizations.
## Contents
- [Contents](#contents)
- [Set up InfluxDB](#set-up-influxdb)
- [Authenticate with an InfluxDB API token](#authenticate-with-an-influxdb-api-token)
- [Introducing IoT Starter](#introducing-iot-starter)
- [Create the application](#create-the-application)
- [Install InfluxDB client library](#install-influxdb-client-library)
- [Configure the client library](#configure-the-client-library)
- [Build the API](#build-the-api)
- [Create the API to register devices](#create-the-api-to-register-devices)
- [Create an authorization for the device](#create-an-authorization-for-the-device)
- [Write the device authorization to a bucket](#write-the-device-authorization-to-a-bucket)
- [Create the API to list devices](#create-the-api-to-list-devices)
- [Create IoT virtual device](#create-iot-virtual-device)
- [Write telemetry data](#write-telemetry-data)
- [Query telemetry data](#query-telemetry-data)
- [Define API responses](#define-api-responses)
- [Install and run the UI](#install-and-run-the-ui)
## Set up InfluxDB
If you haven't already, [create an InfluxDB Cloud account](https://www.influxdata.com/products/influxdb-cloud/) or [install InfluxDB OSS](https://www.influxdata.com/products/influxdb/).
### Authenticate with an InfluxDB API token
For convenience in development,
[create an _All-Access_ token](/influxdb/v2.2/security/tokens/create-token/)
for your application. This grants your application full read and write
permissions on all resources within your InfluxDB organization.
{{% note %}}
For a production application, create and use a
{{% cloud-only %}}custom{{% /cloud-only %}}{{% oss-only %}}read-write{{% /oss-only %}}
token with minimal permissions and only use it with your application.
{{% /note %}}
## Introducing IoT Starter
The application architecture has four layers:
- **InfluxDB API**: InfluxDB v2 API.
- **IoT device**: Virtual or physical devices write IoT data to the InfluxDB API.
- **UI**: Sends requests to the server and renders views in the browser.
- **API**: Receives requests from the UI, sends requests to InfluxDB,
and processes responses from InfluxDB.
{{% note %}}
For the complete code referenced in this tutorial, see the [influxdata/iot-api-python repository](https://github.com/influxdata/iot-api-python).
{{% /note %}}
## Create the application
Create a directory that will contain your `iot-api` projects.
The following example code creates an `iot-api` directory in your home directory
and changes to the new directory:
```bash
mkdir ~/iot-api-apps
cd ~/iot-api-apps
```
Use [Flask](https://flask.palletsprojects.com/), a lightweight Python web
framework,
to create your application.
1. In your `~/iot-api-apps` directory, open a terminal and enter the following commands to create and navigate into a new project directory:
```bash
mkdir iot-api-python && cd $_
```
2. Enter the following commands in your terminal to create and activate a Python virtual environment for the project:
```bash
# Create a new virtual environment named "virtualenv"
# Python 3.8+
python -m venv virtualenv
# Activate the virtualenv (OS X & Linux)
source virtualenv/bin/activate
```
3. After activation completes, enter the following commands in your terminal to install Flask with the `pip` package installer (included with Python):
```bash
pip install Flask
```
4. In your project, create a `app.py` file that:
1. Imports the Flask package.
2. Instantiates a Flask application.
3. Provides a route to execute the application.
```python
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
```
{{% caption %}}[influxdata/iot-api-python app.py](https://github.com/influxdata/iot-api-python/blob/main/app.py){{% /caption %}}
Start your application.
The following example code starts the application
on `http://localhost:3001` with debugging and hot-reloading enabled:
```bash
export FLASK_ENV=development
flask run -h localhost -p 3001
```
In your browser, visit <http://localhost:3001> to view the “Hello World!” response.
## Install InfluxDB client library
The InfluxDB client library provides the following InfluxDB API interactions:
- Query data with the Flux language.
- Write data to InfluxDB.
- Batch data in the background.
- Retry requests automatically on failure.
Enter the following command into your terminal to install the client library:
```bash
pip install influxdb-client
```
For more information about the client library, see the [influxdata/influxdb-client-python repo](https://github.com/influxdata/influxdb-client-python).
## Configure the client library
InfluxDB client libraries require configuration properties from your InfluxDB environment.
Typically, you'll provide the following properties as environment variables for your application:
- `INFLUX_URL`
- `INFLUX_TOKEN`
- `INFLUX_ORG`
- `INFLUX_BUCKET`
- `INFLUX_BUCKET_AUTH`
To set up the client configuration, create a `config.ini` in your project's top
level directory and paste the following to provide the necessary InfluxDB credentials:
```ini
[APP]
INFLUX_URL = <INFLUX_URL>
INFLUX_TOKEN = <INFLUX_TOKEN>
INFLUX_ORG = <INFLUX_ORG_ID>
INFLUX_BUCKET = iot_center
INFLUX_BUCKET_AUTH = iot_center_devices
```
{{% caption %}}[/iot-api-python/config.ini](https://github.com/influxdata/iot-api-python/blob/main/config.ini){{% /caption %}}
Replace the following:
- **`<INFLUX_URL>`**: your InfluxDB instance URL.
- **`<INFLUX_TOKEN>`**: your InfluxDB [API token](#authorization) with permission to query (_read_) buckets
and create (_write_) authorizations for devices.
- **`<INFLUX_ORG_ID>`**: your InfluxDB organization ID.
## Build the API
Your application API provides server-side HTTP endpoints that process requests from the UI.
Each API endpoint is responsible for the following:
1. Listen for HTTP requests (from the UI).
2. Translate requests into InfluxDB API requests.
3. Process InfluxDB API responses and handle errors.
4. Respond with status and data (for the UI).
## Create the API to register devices
In this application, a _registered device_ is a point that contains your device ID, authorization ID, and API token.
The API token and authorization permissions allow the device to query and write to `INFLUX_BUCKET`.
In this section, you add the API endpoint that handles requests from the UI, creates an authorization in InfluxDB,
and writes the registered device to the `INFLUX_BUCKET_AUTH` bucket.
To learn more about API tokens and authorizations, see [Manage API tokens](/influxdb/v2.2/security/tokens/)
The application API uses the following `/api/v2` InfluxDB API endpoints:
- `POST /api/v2/query`: to query `INFLUX_BUCKET_AUTH` for a registered device.
- `GET /api/v2/buckets`: to get the bucket ID for `INFLUX_BUCKET`.
- `POST /api/v2/authorizations`: to create an authorization for the device.
- `POST /api/v2/write`: to write the device authorization to `INFLUX_BUCKET_AUTH`.
### Create an authorization for the device
In this section, you create an authorization with _read_-_write_ permission to `INFLUX_BUCKET` and receive an API token for the device.
The example below uses the following steps to create the authorization:
1. Instantiate the `AuthorizationsAPI` client and `BucketsAPI` client with the configuration.
2. Retrieve the bucket ID.
3. Use the client library to send a `POST` request to the `/api/v2/authorizations` InfluxDB API endpoint.
Create a `./api/devices.py` file that contains the following:
{{< code-tabs-wrapper >}}
{{% code-tabs %}}
[Python](#python)
{{% /code-tabs %}}
{{% code-tab-content %}}
{{% truncate %}}
```python
# Import the dependencies.
import configparser
from datetime import datetime
from uuid import uuid4
# Import client library classes.
from influxdb_client import Authorization, InfluxDBClient, Permission, PermissionResource, Point, WriteOptions
from influxdb_client.client.authorizations_api import AuthorizationsApi
from influxdb_client.client.bucket_api import BucketsApi
from influxdb_client.client.query_api import QueryApi
from influxdb_client.client.write_api import SYNCHRONOUS
from api.sensor import Sensor
# Get the configuration key-value pairs.
config = configparser.ConfigParser()
config.read('config.ini')
def create_authorization(device_id) -> Authorization:
influxdb_client = InfluxDBClient(url=config.get('APP', 'INFLUX_URL'),
token=os.environ.get('INFLUX_TOKEN'),
org=os.environ.get('INFLUX_ORG'))
authorization_api = AuthorizationsApi(influxdb_client)
# get bucket_id from bucket
buckets_api = BucketsApi(influxdb_client)
buckets = buckets_api.find_bucket_by_name(config.get('APP', 'INFLUX_BUCKET')) # function returns only 1 bucket
bucket_id = buckets.id
org_id = buckets.org_id
desc_prefix = f'IoTCenterDevice: {device_id}'
org_resource = PermissionResource(org_id=org_id, id=bucket_id, type="buckets")
read = Permission(action="read", resource=org_resource)
write = Permission(action="write", resource=org_resource)
permissions = [read, write]
authorization = Authorization(org_id=org_id, permissions=permissions, description=desc_prefix)
request = authorization_api.create_authorization(authorization)
return request
```
{{% /truncate %}}
{{% caption %}}[iot-api-python/api/devices.py](https://github.com/influxdata/iot-api-python/blob/d389a0e072c7a03dfea99e5663bdc32be94966bb/api/devices.py#L145){{% /caption %}}
To create an authorization that has _read_-_write_ permission to `INFLUX_BUCKET`, you need the bucket ID.
To retrieve the bucket ID, `create_authorization(deviceId)` calls the
`BucketsAPI find_bucket_by_name` function that sends a `GET` request to
the `/api/v2/buckets` InfluxDB API endpoint.
`create_authorization(deviceId)` then passes a new authorization in the request body with the following:
- Bucket ID.
- Organization ID.
- Description: `IoTCenterDevice: DEVICE_ID`.
- List of permissions to the bucket.
To learn more about API tokens and authorizations, see [Manage API tokens](/influxdb/v2.2/security/tokens/).
Next, [write the device authorization to a bucket](#write-the-device-authorization-to-a-bucket).
### Write the device authorization to a bucket
With a device authorization in InfluxDB, write a point for the device and authorization details to `INFLUX_BUCKET_AUTH`.
Storing the device authorization in a bucket allows you to do the following:
- Report device authorization history.
- Manage devices with and without tokens.
- Assign the same token to multiple devices.
- Refresh tokens.
To write a point to InfluxDB, use the InfluxDB client library to send a `POST` request to the `/api/v2/write` InfluxDB API endpoint.
In `./api/devices.py`, add the following `create_device(device_id)` function:
{{< code-tabs-wrapper >}}
{{% code-tabs %}}
[Python](#python)
{{% /code-tabs %}}
{{% code-tab-content %}}
```python
def create_device(device_id=None):
influxdb_client = InfluxDBClient(url=config.get('APP', 'INFLUX_URL'),
token=config.get('APP', 'INFLUX_TOKEN'),
org=config.get('APP', 'INFLUX_ORG'))
if device_id is None:
device_id = str(uuid4())
write_api = influxdb_client.write_api(write_options=SYNCHRONOUS)
point = Point('deviceauth') \
.tag("deviceId", device_id) \
.field('key', f'fake_auth_id_{device_id}') \
.field('token', f'fake_auth_token_{device_id}')
client_response = write_api.write(bucket=config.get('APP', 'INFLUX_BUCKET_AUTH'), record=point)
# write() returns None on success
if client_response is None:
return device_id
# Return None on failure
return None
```
{{% caption %}}[iot-api-python/api/devices.py](https://github.com/influxdata/iot-api-python/blob/f354941c80b6bac643ca29efe408fde1deebdc96/api/devices.py#L47){{% /caption %}}
{{% /code-tab-content %}}
{{< /code-tabs-wrapper >}}
`create_device(device_id)` takes a _`device_id`_ and writes data to `INFLUX_BUCKET_AUTH` in the following steps:
1. Initialize `InfluxDBClient()` with `url`, `token`, and `org` values from the configuration.
2. Initialize a `WriteAPI` client for writing data to an InfluxDB bucket.
3. Create a `Point`.
4. Use `write_api.write()` to write the `Point` to the bucket.
5. Check for failures--if the write was successful, `write_api` returns `None`.
6. Return _`device_id`_ if successful; `None` otherwise.
The function writes a point with the following elements:
| Element | Name | Value |
|:------------|:-----------|:--------------------------|
| measurement | | `deviceauth` |
| tag | `deviceId` | device ID |
| field | `key` | authorization ID |
| field | `token` | authorization (API) token |
Next, [create the API to list devices](#create-the-api-to-list-devices).
## Create the API to list devices
Add the `/api/devices` API endpoint that retrieves, processes, and lists registered devices.
1. Create a Flux query that gets the last row of each [series](/influxdb/v2.2/reference/glossary#series) that contains a `deviceauth` measurement.
The example query below returns rows that contain the `key` field (authorization ID) and excludes rows that contain a `token` field (to avoid exposing tokens to the UI).
```js
// Flux query finds devices
from(bucket:`${INFLUX_BUCKET_AUTH}`)
|> range(start: 0)
|> filter(fn: (r) => r._measurement == "deviceauth" and r._field != "token")
|> last()
```
2. Use the `QueryApi` client to send the Flux query to the `POST /api/v2/query` InfluxDB API endpoint.
In `./api/devices.py`, add the following:
{{< code-tabs-wrapper >}}
{{% code-tabs %}}
[Python](#python)
{{% /code-tabs %}}
{{% code-tab-content %}}
{{% truncate %}}
```python
def get_device(device_id=None) -> {}:
influxdb_client = InfluxDBClient(url=config.get('APP', 'INFLUX_URL'),
token=os.environ.get('INFLUX_TOKEN'),
org=os.environ.get('INFLUX_ORG'))
# Queries must be formatted with single and double quotes correctly
query_api = QueryApi(influxdb_client)
device_filter = ''
if device_id:
device_id = str(device_id)
device_filter = f'r.deviceId == "{device_id}" and r._field != "token"'
else:
device_filter = f'r._field != "token"'
flux_query = f'from(bucket: "{config.get("APP", "INFLUX_BUCKET_AUTH")}") ' \
f'|> range(start: 0) ' \
f'|> filter(fn: (r) => r._measurement == "deviceauth" and {device_filter}) ' \
f'|> last()'
response = query_api.query(flux_query)
result = []
for table in response:
for record in table.records:
try:
'updatedAt' in record
except KeyError:
record['updatedAt'] = record.get_time()
record[record.get_field()] = record.get_value()
result.append(record.values)
return result
```
{{% /truncate %}}
{{% caption %}}[iot-api-python/api/devices.py get_device()](https://github.com/influxdata/iot-api-python/blob/9bf44a659424a27eb937d545dc0455754354aef5/api/devices.py#L30){{% /caption %}}
{{% /code-tab-content %}}
{{< /code-tabs-wrapper >}}
The `get_device(device_id)` function does the following:
1. Instantiates a `QueryApi` client and sends the Flux query to InfluxDB.
2. Iterates over the `FluxTable` in the response and returns a list of tuples.
## Create IoT virtual device
Create a `./api/sensor.py` file that generates simulated weather telemetry data.
Follow the [example code](https://github.com/influxdata/iot-api-python/blob/f354941c80b6bac643ca29efe408fde1deebdc96/api/sensor.py) to create the IoT virtual device.
Next, generate data for virtual devices and [write the data to InfluxDB](#write-telemetry-data).
## Write telemetry data
In this section, you write telemetry data to an InfluxDB bucket.
To write data, use the InfluxDB client library to send a `POST` request to the `/api/v2/write` InfluxDB API endpoint.
The example below uses the following steps to generate data and then write it to InfluxDB:
1. Initialize a `WriteAPI` instance.
2. Create a `Point` with the `environment` measurement and data fields for temperature, humidity, pressure, latitude, and longitude.
3. Use the `WriteAPI write` method to send the point to InfluxDB.
In `./api/devices.py`, add the following `write_measurements(device_id)` function:
{{< code-tabs-wrapper >}}
{{% code-tabs %}}
[Python](#python)
{{% /code-tabs %}}
{{% code-tab-content %}}
```python
def write_measurements(device_id):
influxdb_client = InfluxDBClient(url=config.get('APP', 'INFLUX_URL'),
token=config.get('APP', 'INFLUX_TOKEN'),
org=config.get('APP', 'INFLUX_ORG'))
write_api = influxdb_client.write_api(write_options=SYNCHRONOUS)
virtual_device = Sensor()
coord = virtual_device.geo()
point = Point("environment") \
.tag("device", device_id) \
.tag("TemperatureSensor", "virtual_bme280") \
.tag("HumiditySensor", "virtual_bme280") \
.tag("PressureSensor", "virtual_bme280") \
.field("Temperature", virtual_device.generate_measurement()) \
.field("Humidity", virtual_device.generate_measurement()) \
.field("Pressure", virtual_device.generate_measurement()) \
.field("Lat", coord['latitude']) \
.field("Lon", coord['latitude']) \
.time(datetime.utcnow())
print(f"Writing: {point.to_line_protocol()}")
client_response = write_api.write(bucket=config.get('APP', 'INFLUX_BUCKET'), record=point)
# write() returns None on success
if client_response is None:
# TODO Maybe also return the data that was written
return device_id
# Return None on failure
return None
```
{{% caption %}}[iot-api-python/api/devices.py write_measurement()](https://github.com/influxdata/iot-api-python/blob/f354941c80b6bac643ca29efe408fde1deebdc96/api/devices.py){{% /caption %}}
{{% /code-tab-content %}}
{{< /code-tabs-wrapper >}}
## Query telemetry data
In this section, you retrieve telemetry data from an InfluxDB bucket.
To retrieve data, use the InfluxDB client library to send a `POST` request to the `/api/v2/query` InfluxDB API endpoint.
The example below uses the following steps to retrieve and process telemetry data:
1. Query `environment` measurements in `INFLUX_BUCKET`.
2. Filter results by `device_id`.
3. Return CSV data that the [`influxdata/giraffe` UI library](https://github.com/influxdata/giraffe) can process.
In `./api/devices.py`, add the following `get_measurements(device_id)` function:
{{< code-tabs-wrapper >}}
{{% code-tabs %}}
[Python](#python)
{{% /code-tabs %}}
{{% code-tab-content %}}
```python
def get_measurements(query):
influxdb_client = InfluxDBClient(url=config.get('APP', 'INFLUX_URL'),
token=os.environ.get('INFLUX_TOKEN'), org=os.environ.get('INFLUX_ORG'))
query_api = QueryApi(influxdb_client)
result = query_api.query_csv(query,
dialect=Dialect(
header=True,
delimiter=",",
comment_prefix="#",
annotations=['group', 'datatype', 'default'],
date_time_format="RFC3339"))
response = ''
for row in result:
response += (',').join(row) + ('\n')
return response
```
{{% caption %}}[iot-api-python/api/devices.py get_measurements()](https://github.com/influxdata/iot-api-python/blob/9bf44a659424a27eb937d545dc0455754354aef5/api/devices.py#L122){{% /caption %}}
{{% /code-tab-content %}}
{{< /code-tabs-wrapper >}}
## Define API responses
In `app.py`, add API endpoints that match incoming requests and respond with the results of your modules.
In the following `/api/devices/<device_id>` route example, `app.py` retrieves _`device_id`_ from `GET` and `POST` requests, passes it to the `get_device(device_id)` method and returns the result as JSON data with CORS `allow-` headers.
{{< code-tabs-wrapper >}}
{{% code-tabs %}}
[Python](#python)
{{% /code-tabs %}}
{{% code-tab-content %}}
```python
@app.route('/api/devices/<string:device_id>', methods=['GET', 'POST'])
def api_get_device(device_id):
if request.method == "OPTIONS": # CORS preflight
return _build_cors_preflight_response()
return _corsify_actual_response(jsonify(devices.get_device(device_id)))
```
{{% caption %}}[iot-api-python/app.py](https://github.com/influxdata/iot-api-python/blob/9bf44a659424a27eb937d545dc0455754354aef5/app.py){{% /caption %}}
{{% /code-tab-content %}}
{{< /code-tabs-wrapper >}}
Enter the following commands into your terminal to restart the application:
1. `CONTROL+C` to stop the application.
2. `flask run -h localhost -p 3001` to start the application.
To retrieve devices data from your API, visit <http://localhost:3001/api/devices> in your browser.
## Install and run the UI
`influxdata/iot-api-ui` is a standalone [Next.js React](https://nextjs.org/docs/basic-features/pages) UI that uses your application API to write and query data in InfluxDB.
`iot-api-ui` uses Next.js _[rewrites](https://nextjs.org/docs/api-reference/next.config.js/rewrites)_ to route all requests in the `/api/` path to your API.
To install and run the UI, do the following:
1. In your `~/iot-api-apps` directory, clone the [`influxdata/iot-api-ui` repo](https://github.com/influxdata/iot-api-ui) and go into the `iot-api-ui` directory--for example:
```bash
cd ~/iot-api-apps
git clone git@github.com:influxdata/iot-api-ui.git
cd ./iot-app-ui
```
2. The `./.env.development` file contains default configuration settings that you can
edit or override (with a `./.env.local` file).
3. To start the UI, enter the following command into your terminal:
```bash
yarn dev
```
To view the list and register devices, visit <http://localhost:3000/devices> in your browser.
To learn more about the UI components, see [`influxdata/iot-api-ui`](https://github.com/influxdata/iot-api-ui).

View File

@ -0,0 +1,10 @@
Follow this step-by-step tutorial to build an Internet-of-Things (IoT) application with InfluxData client libraries and your favorite framework or language.
In this tutorial, you'll use the InfluxDB API and
client libraries to build a modern application as you learn the following:
- InfluxDB core concepts.
- How the application interacts with devices and InfluxDB.
- How to authenticate apps and devices to the API.
- How to install a client library.
- How to write and query data in InfluxDB.

View File

@ -0,0 +1,49 @@
import { flux } from '@influxdata/influxdb-client'
import influxdb from '../_influxdb'
const INFLUX_ORG = process.env.INFLUX_ORG
const INFLUX_BUCKET_AUTH = process.env.INFLUX_BUCKET_AUTH
/**
* 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 = {}
console.log(`*** QUERY *** \n ${fluxQuery}`)
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() {
console.log(JSON.stringify(devices))
resolve(devices)
},
})
})
}

View File

@ -0,0 +1,78 @@
import { getDevices } from './devices/_devices'
import influxdb from '../_influxdb'
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
export default async function handler(req, res) {
try {
const deviceId = JSON.parse(req.body)?.deviceId
const devices = await createDevice(deviceId)
res.status(200).json(
Object.values(devices)
.filter((x) => x.deviceId && x.key) // ignore deleted or unknown devices
.sort((a, b) => a.deviceId.localeCompare(b.deviceId))
)
} catch(err) {
res.status(500).json({ error: `failed to load data: ${err}` })
}
}
/** 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 authorization
}
}
/**
* 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},
},
],
},
})
}