Neowit developer docs
API referenceSupportKnowledge baseStatusApp
  • Overview
  • REST API
    • Introduction
    • Authentication
      • OAuth2
      • Basic Auth
    • Error codes
    • API reference
    • Coordinate systems
    • Query Language
      • Query Language Reference
  • Service Accounts
    • Introduction
    • Creating service accounts
  • Integrations
    • Introduction
    • MQTT
      • Native Sparkplug
      • Custom Starlark
  • Starlark
    • Introduction
    • Modules
      • time module
      • json module
      • math module
      • devices module
      • series module
      • sensors module
  • Tutorials
    • Introduction
    • Create users using API
Powered by GitBook
On this page
  • Introduction
  • Evaluation Context
  • Data Types
  • Function Overloading
  • Binary Operators
  1. REST API

Query Language

The Neowit Query Language is a simple expression language for computing functions of the sensor data saved in the Neowit Platform. The following example averages a set of sensors and filters it to include only business hours.

businesshours(avg(floor3))

Introduction

Neowit stores data collected from devices as time series of sensor data. Each sensor series has an associated sensor type which describes the type of data collected (e.g. Temperature). Because a device can collect data from multiple sensors, a device record is a set of series for each sensor type collected from the device. An expression typically computes a function of these records and returns another record. A record can contain data from multiple devices and thus contain multiple time series with the same sensor type as long as they belong to different devices.

Evaluation Context

Each expression is evaluated in an implicit device context, which consists of identifiers mapping to records and the interval and resolution in the request.

Inputs

Inputs are the identifiers in the expression that resolve to the records being computed on. For example, the input variable floor3 may resolve to a record of many devices and sensor data series.

  • Explicit Inputs are identifiers defined in the request associated with the query expression. They can resolve to individual devices and sensors, or they can in turn resolve to other identifiers transitively.

  • Implicit Inputs are identifiers that are available in every request. They are typically generated by Neowit from metadata gathered from the platform. For example, the floor3 identifier may be generated from a space in the Neowit platform and refer to all sensor data from devices contained within that space.

Intervals

Intervals contain the time range requested (e.g. all of last week) as well as an associated resolution (e.g. hourly). When using aggregation functions, the resolution will be used as the target for which to aggregate or interpolate to. For example, sensor data is typically collected in second resolution, but when calling avg(..) with a requested hourly resolution, the data will be average by the hour. The resulting record will always have the same resolution as requested. If no aggregation was performed in the expression, Neowit will auto-aggregate the resulting record to the target resolution.

Data Types

Each function takes a set of parameters with statically checked data types and has a return data type. A valid expression must always return a record data type, but sub-expressions may return other data types. For example, the function hours(floor3, 9, 17) returns the data in floor3 filtered to only include data for hours between 9 and 17 (for each day). The type signature of the function is hours(rec: record, hoursIndexStart: number, hoursIndexEnd: number): record . The data types available are loosely inspired by JSON.

  • Number: Any integer or floating point number.

  • String

  • Boolean

  • List. Lists may take on any type but they must be homogeneous, i.e. every list item must have the same type, e.g. a list of strings.

  • Series. An individual time series for a (deviceId, sensorId) pair.

  • Record. A set of series.

Backtick Identifiers

Identifiers can be written either as a standard C-like identifier, e.g. floor3_25 or they can be written using backticks which allows them to be represented with arbitrary strings containing whitespace etc, e.g. `Floor 123`

Identifier Lists

A list of identifier, e.g. [floor2, floor3] are automatically resolved to a record containing the data from all the identifiers in the list with an implicit combine(..) function applied to them that aggregates records row-wise.

Function Overloading

Types are never annotated in an expression, but are inferred by the evaluated and statically checked. Each function (and binary operator) may have several overloaded type signatures allowing for inputs of different types to be used with the same function or operator.

Default Values

Some of the parameters to a function have default values making them optional. For example, in the function avg(rec: record, fillna: boolean): record the fillna parameter has a default value of false so that we can simply write avg(floor3).

Allowed Values

Some parameters may have a predefined set of allowed values (effectively enums). For example, in the function agg(rec: record, method: string, fillna: boolean): record The parameter method which specifies the aggregation function to use has a set of allowed values auto, avg ,max , etc.

Binary Operators

In addition to function, expressions can also contain binary operators. These may be either logical or arithmetic. Binary operators are overloaded similar to functions so they work with a range of data types.

Logical Operators

These typically produce records of indicator values (1s or 0s) for when the expression is true. For example, the expression floor3 < 5 returns a record of indicator values of the input record for when the values are less than 5. floor2 > floor3 produces a record of indicator values for when the sensor data of floor2 is greater than the corresponding values of floor3.

Arithmetic Operators

Similarly, arithmetic operators allow for basic arithmetic on various data types, e.g. floor3 + floor2 will add the data from corresponding sensors in the operand records. 3 * floor3 will multiply all the values in the record.

Query Language Reference

PreviousCoordinate systemsNextQuery Language Reference

Last updated 8 days ago