# Merged - Custom Logic Blocks

{% hint style="warning" %}
Merged into [Custom Logic](/akenza.io/get-started/rule-engine/logic-blocks/custom-logic.md)
{% endhint %}

**Custom Logic Blocks** allow the implementation of more complex business logic with the akenza **Rule Engine**. They enable simple stateless and stateful operations upon rule trigger using custom scripts in **Javascript**. Custom Logic Blocks are created on organization-level and are therefore available in all workspaces and can be selected when creating a rule.&#x20;

This webinar explains how to create **Custom Rules**:

{% embed url="<https://www.youtube.com/watch?v=weoSqm7Ugao&t=4s>" %}
Webinar about how to create Custom Rules
{% endembed %}

A set of examples for logic blocks can be found here:

{% embed url="<https://github.com/akenza-io/akenza-logic-block-examples>" %}

A Custom Logic Block consists of a definition of:

* **Inputs**: the dynamic data that is evaluated during script execution (sensor data)
* **Parameters**: constant values like thresholds
* A **script** used to run the logic

{% hint style="info" %}
In order to keep its usage consistent, it is not possible to edit custom logic inputs and parameters if the Custom Logic Block is assigned to an **active** rule.
{% endhint %}

### Inputs

Inputs specify the **input data sources** for a Custom Logic Block and contain the dynamic data of a device. At least one input needs to be defined in order to create a Custom Logic Block.

| Field                     | Description                                                                 |
| ------------------------- | --------------------------------------------------------------------------- |
| Input display/ label name | The input name                                                              |
| Input description         | An optional description                                                     |
| Input variable name       | A variable name used to access the value inside the script                  |
| Default topic             | An optional default topic that is preselected when using the logic block    |
| Default data key          | An optional default data key that is preselected when using the logic block |

### Parameters

Parameters represent **static properties** that are available during script runtime.

| Field                        | Description                                                    |
| ---------------------------- | -------------------------------------------------------------- |
| Parameter display/label name | The parameter name                                             |
| Parameter variable name      | A variable name used to access the parameter inside the script |
| Parameter Type               | The data type of the parameter; Numerical, String, or Boolean  |
| Default value                | A default value for the parameter                              |

### Rule logic script

The Rule logic script defines the custom logic that is evaluated during rule runs.

```javascript
function consume(event) {
  var temperature = event.inputs.temperature;
  var threshold = event.properties.tempThreshold;

  if (temperature < threshold) {
    emit("action", {
      message: `it is too cold: the temperature is ${temperature}°C`,
    });
  }
}
```

Once a Custom Logic Block is saved, it can be selected as a logic block when creating a rule. Inputs need to be linked to an input device or tag and parameters need to be set.&#x20;

Further, one or more actions need to be defined. The templating syntax can be used to access the results of a Custom Logic Block {{result.\*}}. For example, {{result.message}} for the script shown above.

#### Custom logic timer

There is also the possibility to emit a timer inside the custom logic block.

When emitting the timer event, two params can be specified

* `runAt` required, a date which needs to be at least 15 seconds in the future
* `meta` optional, object which can contain any values

The meta object will be available when the rule is triggered by that timer and can be accessed at `timer.meta` during script run. This can provide useful information for the next timed run or help uniquely identify timers when running them.

```javascript
function consume(event) { 
  let time = new Date();
  time = new Date(time.setDate(time.getDate() + 1));
  time = time.setHours(0,0,0,0);
  emit("timer", {runAt: new Date(time), meta: {"foo": "bar"}});
}
```

{% hint style="info" %}
Refer to Stateful Operations for more information on how to share data between runs of a rule.
{% endhint %}

## Event Object

The Custom Logic Block script is invoked with the event object as param. It contains the following properties & strucutre:

* `inputs` object, contains the values of the specified variables
* `state` object, contains the user defined rule state
* `type` string, indicates how the rule was invoked (either `timer` or `uplink`)
* `dataSources` object, see data source properties
* `device` object, see device properties
* `properties` object, contains the user defined properties of the custom logic block

**Note:** if `type` has the value of `timer`  certain properties will behave differently:

* the variable values of the `inputs` object will be null
* `dataSources` will be an empty object
* `device` will be undefined

#### Device Properties

The following properties of a device can be accessed when using template syntax.

**Note**: The prefix `device.` is always required in order to access sub properties.

* `name` the device name
* `description` the device description
* `integrationId` the integrationId of the device (only for LoRaWAN devices)
* `workspaceId` the workspaceId of the device
* `dataFlowId` the data flow id of the device
* `connectivity` the connectivity of the device
* `id` the akenza device id
* `deviceId` the unique device id

#### Data Source Properties

The following properties of a data source can be accessed when using template syntax.

To access a specific data source, use `dataSources.X` where `X` is the number of the data source as specified in the rule (starting at 1).

Some properties can be null in certain circumstances (e.g. the `correlationId` or the `device`) if e.g. the rule was triggered by a timer event or the data source is set to access the last sample.

**Note**: The prefix `dataSources.X.` is always required in order to access sub properties.

* `correlationId` the correlation id of the data source (only available if the data source was triggering the flow)
* `device` the complete device object. See Device Properties for sub properties
* `deviceId` the unique device id
* `akenzaDeviceId` the akenza device id
* `topic` the topic of the sample
* `timestamp` the timestamp of the sample
* `data.*` access any values of the sample.
* `meta.*` access any values of the meta object
* `uplinkMeta` the complete uplink meta object
* `trigger` boolean, indicates whether the data source has triggered the uplink
* `deviceInput` boolean, indicates if the data source is a device
* `tagInput` boolean, indicates if the data source is a tag

The values related to the sample (namely `correlationId`, `topic`, `timestamp`, `data`, `meta` and `uplinkMeta`) are resolved based on which data source triggered the rule evalution. If the data source is triggering (`trigger = true`) the rule, the values will be the one from the triggering uplink. Otherwise the values will correlate the most recent stored sample.

#### Uplink Meta Properties

The following properties of uplink meta data can be accessed when using template syntax

**Note**: The prefix `uplinkMeta.` is always required in order to access sub properties.

* `dataReceived` the ISO-8601 timestamp when the data was recieved
* `bytesReceived` the number of bytes received in the uplink request
* `processingStart` the ISO-8601 timestamp when the processing was started
* `scriptRunUplinkStart` the ISO-8601 timestamp when script run was started
* `scriptRunUplinkEnd` the ISO-8601 timestamp when script run ended
* `processingEnd` the ISO-8601 timestamp when the processing ended
* `outputProduced` the ISO-8601 timestamp when all output were produced
* `uplinkDuration` the ISO-8601 duration of the whole uplink flow
* `processingDuration` the IOS-8601 duration of the processing
* `scriptRunningDuration` the ISO-8601 duration of the script run


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.akenza.io/akenza.io/deprecated/custom-logic-blocks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
