akenza.io
WebsiteAPI DocumentationWhat's newLogin
  • Overview
  • Getting Started
    • Connect a Device
  • Changelog
  • General
    • Applications
    • Organization context
    • Workspace Context
    • Users
      • User Roles
  • Device Management
    • Managing an organization
      • API keys
      • Users (Organization)
        • Add & removing users from your organization
    • Managing a workspace
      • General Settings
        • Device Lifecycle Reports
        • Workspace properties
        • Occupancy settings
        • Device Setup Assistant
      • Custom fields
      • Tags
      • Users (Workspace)
    • Devices
      • Device
      • Device Simulator
      • Bulk actions
      • Bulk import CSV templates
    • Rules
      • Input
      • Logic blocks
        • Comparison
        • Custom Logic
          • Logic Block Scripting
      • Timed Rules
      • Rule Actions
        • Downlink
    • Data Flows
      • Device Connectors
        • Device Security
          • Using Device Credentials
            • Creating Public/Private Key Pairs
            • Using JSON Web Tokens (JWTs)
              • Python
              • Java
        • HTTP
        • MQTT
        • CoAP
        • LoRaWAN
          • Connectivity Management
          • Swisscom LoRaWAN
          • The Things Network
          • Loriot
          • Actility’s ThingPark Wireless
          • EWZ
          • Cibicom
          • Helium
          • ChirpStack
        • NB-IoT
        • mioty
        • Disruptive Technologies
        • VergeSense
        • Spaceti
        • Haltian
      • Device Types
        • Custom Device Types
          • Uplink
          • Downlink
          • Scripting
        • Library
      • Output Connectors
        • Databases
          • akenza DB
          • InfluxDB
          • SQL Databases
        • Streaming
          • Webhook
          • Azure IoT Hub
          • AWS Kinesis
          • Google Cloud Pub/Sub
          • Apache Kafka
        • Notifications
          • E-Mail
          • SMS
          • Microsoft Teams
          • Slack
    • Custom Components
    • Integrations
    • Reference
      • REST API
        • Filtering
        • Querying Device Data
      • WebSocket API
      • Scripting
        • Stateful Operations
        • Utility Functions
      • Payload Templating
  • Reference
  • Dashboard Builder
    • Managing Dashboards
      • Embedding dashboards
    • Components
      • Map
      • Floorplan
  • Device Setup Assistant
    • Device Setup Assistant - Overview
  • Tutorials
    • BI Tools
      • Grafana Data Source Plugin
      • How to build a dashboard with Retool
      • How to analyze data with AWS QuickSight
    • Devices
      • How to integrate the XDK device from Legic via MQTT on akenza
      • How to connect the Disruptive Technologies-cloud on akenza
      • How to send Downlinks to the Kuando Busylight device
      • How to integrate an Arduino device via MQTT on akenza
      • Integrate a MClimate Vicki LoRaWAN Radiator Thermostat on akenza
      • How to integrate an ERS Elsys device with Loriot on akenza
      • How to integrate the IAM Decentlab device with TTN on akenza
      • How to integrate the Seeed SenseCAP T1000 tracker on akenza
      • How to integrate a Swisscom Multisense device on akenza
    • Notifications
      • How to send SMS notifications
      • How to send notifications to Slack
      • How to send notifications to Microsoft Teams
    • Enterprise solutions
      • How to send data to Azure IoT Hub
      • How to send data to the Google Cloud Pub/Sub
      • How to send data to InfluxDB
      • How to send data to AWS Kinesis
      • How to send data to Azure Event Hubs with Apache Kafka
    • IoT Starter Kits
      • How to integrate the IAQ Kit with Actility on akenza
      • How to integrate the CoWork Kit with Actility on akenza
      • How to integrate the Smart Building Kit with Actility on akenza
      • How to integrate the Pepperl+Fuchs Kit with Actility on akenza
  • Support Center
    • FAQ
    • Status Page
    • Service Desk
    • Request a feature
  • Deprecated
    • SIM-Cards
    • Everynet
    • Sigfox
    • How to connect the Yanzi Lifecycle cloud on akenza
Powered by GitBook
On this page
  • Script Structure
  • Emit Function
  • sample
  • downlink
  • log
  • state
  • Module Imports
  • Available Modules
  • Disabled Functionality
  • One Time Script Running
  • Run Script

Was this helpful?

  1. Device Management
  2. Reference

Scripting

This page describes available functionalities and features for running scripts.

akenza provides the possibility to run scripts as part of a data flow in order to decode data sent by devices and turn it into an actionable and human readable format (uplink decoder), encode data that is used to send commands to devices (downlink encoder), or run a script (custom logic block) as part of the rule engine to evaluate logic used to trigger actions (e.g. SMS notification or downlink).

The scripts support JavaScript using the ECMAScript 2020 (ES 11) standard in strict mode. The scripts are plain JavaScript and every JavaScript and ES 11 functionality can be used. However, there are certain restrictions which are listed below. Importantly, loading of node.js modules and other files is disabled.

When creating a Custom Device Type or Custom Logic Block, the script can be executed and debugged allowing for easy development of a script. The script can also be executed by calling the API directly (more information below).

Script Structure

An uplink decoder, downlink encoder or custom logic block script has to implement the function consume(object) which takes an event object as argument. An error will be returned if the script doesn't implement a consume(event) function.

function consume(event) {
    emit('<emitType>', { data: {}, topic: 'default' });
}

The consume(event) function is the entry point for the script and will be invoked upon execution. Each execution loads the script again, resetting any variable values which were set in previous runs.

Emit Function

The emit('string', object) function is used to publish data back to the system, e.g. the generated sample which should be stored in the database or forwarded to a 3rd party system using an output connector. If the emit function is never called in a script, the script just runs through without any effects and no error is thrown.

Any of the following emit types can be used multiple times throughout script.

  • sample (only for uplink decoders of a device type)

  • log

  • downlink (only for downlink encoders of a device type)

  • state (for uplink decoders and custom logic blocks)

A maximum of 50 emit function invocations is allowed per script run.

sample

If the emit function is invoked with sample as first argument, the second argument will be forwarded to the output connector

The object needs to contain the following structure:

{
    "data": {
        // the generated sample during the script run
    },
    "meta": {
        // optional, can contain meta info about value calculation or similar
    },
    "timestamp": new Date(), // optional, can contain a date object which overwrites the emited time 
    "topic": "string" // the topic of the sample
}

If the object does not follow the above structure, an error will be shown in the processing logs and the sample will not be used for further processing in the output connector.

Topic Validation

The topic of the sample has to adhere to a specified format:

  • it must start and end with an alphanumeric character

  • it must consist of at least two alphanumeric characters

  • it can contain an optional separator after at least two alphanumeric characters followed by at least one alpha numeric character

    • valid separators are . ,: ,- and _

    • separators cannot be consecutive and cannot be placed at the beginning or end

Some topic examples are listed below:

Valid Topics
Invalid Topics
  • default

  • temperature

  • temp.1

  • device-001_status

  • weather.report:01_01_2023T10:00:00

  • a1.b2-c3_d4:e5

  • a1:b2:c3:d4:e5:f6

  • .leadingSeparator

  • trailingSeparator_

  • consecutive--separator

  • special@chars!$

  • contains spaces

  • ümläuts

  • 1.temp

If a sample contains a topic which does not adhere to the required format, it will still be stored but using the topic default instead. In addition, the property akenzaTopicValidation is added to the meta field of the sample which contains the original invalid topic. Additionally, a warning will be shown in the processing logs, also indicating the invalid topic.

Example topic validation message in the meta object of the sample:

{
  ...
  "data": {
    ...
  },
  "meta": {
    "akenzaTopicValidation": {
      "message": "topic 'invalid topic' is not valid"
    },
    ...
  },
  ...
}

Data Key Validation

Similarly to topics, each individual data key of the data object has adhere to a specified format:

  • they must start with a character (lower- or uppercase, lower case is preferred), all following characters can be alpha numeric

  • they must consist of at least one character

  • it can contain an optional separator after at least one alphanumeric characters followed by at least one alpha numeric character

    • valid separators are . , _and -

    • separators cannot be consecutive and cannot be placed at the beginning or end

This also applies for nested objects, all the way down to the max allowed nesting depth of 100.

NOTE: A data key containing dots is not transformed to a nested object. If the data should be nested, it has to be structured accordingly. Dots in the data keys are only a separator and has no further effect on the data structure.

Some data key examples are listed below:

Valid Data Keys
Invalid Data Keys
  • temperature

  • humidity_percent

  • v.temp_ch-3

  • ANALOG_20

  • L3-Power_Consumption.kWh

  • a.1_b-2D4

  • i

  • N

  • .leadingSeparator

  • trailingSeparator_

  • consecutive--separator

  • special@chars!$

  • contains spaces

  • ümläuts

  • 1.leadingNumber

  • _

The regex used to validate the topic is ^[a-zA-Z]+((|.|_|-)?[a-zA-Z0-9])*$ . Similarly as with topics, if there are any uncertainties whether a specific data key conforms to the required format it can be validated with a 3rd party regex tool.

If the data object contains a data key (at any nesting depth) which does not adhere to the required format, it will be removed and will not be contained in the resulting sample. The property akenzaDataKeyValidation is added to the meta field of the sample which contains the invalid data key and it's value. If a data key of a nested object is invalid, the key will be added to the meta field with the dot-notation (i.e. foo.bar.invalid key) to indicate the nesting depth. All other valid data keys of the nested object remain in place. Additionally, a warning will be shown in the processing logs indicating the invalid data key.

Example data key validation message in the meta object of the sample:

{
  ...
  "data": {
   ...
  },
  "meta": {
    "akenzaDataKeyValidation": {
      "invalid key_": {
        "message": "data key 'invalid key_' is not valid",
        "value": 1.615
      },
      ...
    }
  },
  ...
}

downlink

log

If the emit function is invoked with log as first argument, the second argument will be emitted as a log object. Log objects are only displayed when developing the script in the Akenza UI. They are otherwise omitted and won't be processed any further.

state

In order to pass state to the next execution of the script (see Stateful Operations), the new state has to be emitted using the state emit type.

Module Imports

The imported functions, objects, constants, etc... can be used throughout the script.

Timestamp manipulation example with luxon:

import { DateTime } from 'luxon'; 

function consume(event) {
	let data = {};
	// ...
	let timestamp = DateTime.fromJSDate(new Date(), {zone: 'America/Denver'})
		.minus({minutes: 10});
	// ...
	emit('sample', {data: data, timestamp: timestamp.toISO()});
}

Available Modules

Currently, the following modules are provided:

    • NOTE: it is required to invoke .toISO() or .toJSDate() when emitting the timestamp, otherwise the whole luxon date object will be emitted which can't be converted to a valid timestamp by akenza.

For additional modules to be made available, contact our customer support team.

Disabled Functionality

There are certain restrictions when it comes to Scripting and not every JavaScript functionality is available during script running:

  • invoking any of the console or print functions, use emit('log', object) instead

  • javascript syntax extensions

  • any file loading functionality

Uplink Metrics are extracted automatically based on type, as described in the respective page.

One Time Script Running

Run Script

POST https://api.akenza.io/v3/run-script

Scripts can be executed once without any further processing by calling an endpoint of the akenza API. Invocations of the emit('string', object) function have no further impact and are instead returned in the response body.

Headers

Name
Type
Description

x-api-key

string

api key required for authentication

Request Body

Name
Type
Description

script

string

the script to be processed

event

string

the event to process

[
    {
        "type": "SAMPLE",
        "event": {
            "data": {
                "tmp": 24.5
            }
        }
    },
    {
        "type": "ERROR",
        "event": {
            "message": "invalid emit type foo"
        }
    },
    {
        "type": "LOG",
        "event": {
            "data": {
                "tmp": 24.5
            }
        }
    }
]

In the above request the following script is used

function consume(event) { 
    emit('sample', {data: {tmp: event.data.temperature}});
    emit('foo', {data: event.foo});
    emit('log', {tmp: event.data.temperature});
}

And the following event

{
    "data": {
	"temperature": 24.5
    },
    "timestamp": "2020-09-07T18:20:05.199Z"
}

Which produces the output as seen in the response of the example. The type reflects the emit type used to invoke the emit('string', object) function. The resulting event contains whatever was passed as second argument. In case of errors during runtime of the script, the event contains a message property detailing the error.

PreviousWebSocket APINextStateful Operations

Last updated 3 days ago

Was this helpful?

The regex used to validate the topic is ^[a-zA-Z0-9]([a-zA-Z0-9]+(|\.|:|-|_)?)*[a-zA-Z0-9]+$ . If there are any uncertainties whether a specific topic conforms to the required format, it can be tested and verified with 3rd party tools, like .

If the emit function is invoked with downlink as first argument, the second argument will be sent back to the device. The resulting object needs to follow a strict convention and is explained in more detail in the page.

Certain ES6 Modules can be imported during script runtime using the following syntax (more info on imports can be found ).

luxon ^2.4.0 -> date and time manipulation, see for more details

regex101
Downlink
here
their docs