> For the complete documentation index, see [llms.txt](https://docs.buildings.ability.abb/collection/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.buildings.ability.abb/collection/english-v14/documentation/engineering/script-engine/write-python-scripts.md).

# Write Python scripts

{% hint style="warning" %}
With the introduction of Eliona Version 12.2, important changes were made that require scripts to be adapted in order to use the new API design.
{% endhint %}

## Script definition

When a new script is created in the Eliona system, a function header is generated automatically. This header contains two parameters:

* **`id`**: The unique ID of the script.
* **`eliona`**: An object through which the user can interact with the Eliona system.

The function header looks as follows:

```python
# you may add imports only inside the function
# don't change or delete the function definition
def UserFunction(id, eliona):
	# add your code here
```

### Importing modules

All necessary modules must be imported within the function. It is important that modules are imported only within the function and that no global imports are used.

Example:

```python
def UserFunction(id, eliona):
    import random
    # More lines of code follow
```

***

## Methods of the Eliona object

The **`eliona`**-object provides a range of methods that enable users to interact with the Eliona system. Here are the most important methods together with their parameters and descriptions:

<table data-full-width="true"><thead><tr><th width="173">Method</th><th>Parameters</th><th>Description</th></tr></thead><tbody><tr><td><strong>GetHeap</strong></td><td><code>gai: str</code>, <code>subtype: str</code>, <code>attribute: str</code></td><td>Retrieves the current value of an attribute or the entire data JSON of an asset from the heap.</td></tr><tr><td><strong>SetHeap</strong></td><td><code>gai: str</code>, <code>subtype: str</code>, <code>data: dict</code>, <code>source: str</code></td><td>Sends data to the Calculator to process it and store it in the heap.</td></tr><tr><td><strong>GetAssetIDByGAI</strong></td><td><code>gai: str</code></td><td>Returns the numeric asset ID for the specified GAI.</td></tr><tr><td><strong>GetAll</strong></td><td><code>ids: list[intstr], subtype: str</code></td><td>Retrieves all data for a list of assets identified by their IDs and a subtype.</td></tr><tr><td><strong>SQLQuery</strong></td><td><code>query: str</code></td><td>Executes any SQL query and returns the results as a list of tuples.</td></tr><tr><td><strong>MakeSource</strong></td><td><code>id: int</code></td><td>Creates a source string for heap operations based on the function ID.</td></tr><tr><td><strong>OpenFile</strong></td><td><code>name: str</code>, <code>mode: str</code></td><td>Opens a file in the Eliona working directory (analogous to Python’s <code>open()</code>).</td></tr><tr><td><strong>AddAssetTag</strong></td><td><code>gai: str</code>, <code>tag: str</code></td><td>Adds a tag to an asset (if not already present).</td></tr><tr><td><strong>RemoveAssetTag</strong></td><td><code>gai: str</code>, <code>tag: str</code></td><td>Removes a tag from an asset (if present).</td></tr><tr><td><strong>GetTrendRecords</strong></td><td><code>asset_id: int</code>, <code>subtype: str</code>, <code>attr: str</code>, <code>begin: datetime</code></td><td>Retrieves historical measured values as a list of <code>TrendRecord(ts, value)</code> from the specified time onward.</td></tr><tr><td><strong>WriteTrendRecords</strong></td><td><code>asset_id: int</code>, <code>subtype: str</code>, <code>attr: str</code>, <code>`recs: TrendRecord</code></td><td>Writes one or more <code>TrendRecord</code>-records into the system.</td></tr><tr><td><strong>GetAggregate</strong></td><td><code>agg: Aggregate</code>, <code>asset_id: int</code>, <code>subtype: str</code>, <code>attr: str</code>,<code>raster: str</code>, <code>start: datetime</code>,<code>end: datetime = now()</code></td><td>Calculates aggregated values (Avg, Sum, Cusum) in a fixed raster over a period of time.</td></tr><tr><td><strong>GetLastAggregate</strong></td><td><code>agg: Aggregate</code>, <code>asset_id: int</code>, <code>subtype: str</code>, <code>attr: str</code>, <code>raster: str</code></td><td>Returns the most recent cumulative aggregate in the selected raster (incl. <code>last_ts</code>).</td></tr></tbody></table>

***

## Example scripts

### GetHeap

**Description:**\
Retrieves the current value of an attribute or the entire JSON of an asset from the heap.

**Parameters:**

* `gai: str` (required) – GAI of the asset, e.g. `"K86_WP01"`
* `subtype: str` (required) – data subtype, e.g. `"input"`
* `attribute: str` (required) – attribute name, e.g. `"Aussentemperatur"`

**Code example:**

```python
value = eliona.GetHeap("K86_WP01", "input", "Aussentemperatur")
```

**Example output:**

```
23.5
```

***

### SetHeap

**Description:**\
Sends a dictionary of values to the Calculator to process them and store them in the heap.

**Parameters:**

* `gai: str` (required)
* `subtype: str` (required)
* `data: dict` (required) – e.g. `{"Aussentemperatur": 23.5}`
* `source: str` (required) – typically `eliona.MakeSource(id)`

**Code example:**

```python
data   = {"Aussentemperatur": 23.5}
source = eliona.MakeSource(id)
eliona.SetHeap("K86_WP01", "input", data, source)
```

***

### GetAssetIDByGAI

**Description:**\
Returns the numeric asset ID for the specified GAI.

**Parameters:**

* `gai: str` (required)

**Code example:**

```python
asset_id = eliona.GetAssetIDByGAI("K86_WP01")
```

***

### GetAll

**Description:**\
Retrieves all data points of a specific subtype for a list of assets and returns them as a dictionary (GAI → data).

**Parameters:**

* `ids: list[int|str]` (required) – e.g. `["K86_WP01", 1073]`
* `subtype: str` (required)

**Code example:**

```python
all_data = eliona.GetAll(["K86_WP01"], "input")
```

***

### SQLQuery

**Description:**\
Executes any SQL query and returns the results as a list of tuples.

**Parameters:**

* `query: str` (required)

**Code example:**

```python
res = eliona.SQLQuery(
    "SELECT data->>'Aussentemperatur' "
    "FROM public.heap "
    "WHERE gai='K86_WP01' AND subtype='input' "
    "ORDER BY timestamp DESC LIMIT 1;"
)
```

**Example output:**

```css
[('23.5',)]
```

***

### MakeSource

**Description:**\
Creates a source string (e.g. `"ssr:123"`) for heap operations based on the function ID.

**Parameters:**

* `id: int` (required)

**Code example:**

```python
pythonKopierenBearbeitensrc = eliona.MakeSource(id)
```

***

### OpenFile

**Description:**\
Opens a file in the Eliona working directory (analogous to Python’s `open()`).

**Parameters:**

* `name: str` (required) – file name, e.g. `"log.txt"`
* `mode: str` (required) – e.g. `"w"`, `"r"`

**Code example:**

```python
pythonKopierenBearbeitenf = eliona.OpenFile("aussentemp_log.txt", "w")
f.write("Temperature: 23.5\n")
f.close()
```

***

### AddAssetTag

**Description:**\
Adds a tag to an asset if it has not already been assigned.

**Parameters:**

* `gai: str` (required)
* `tag: str` (required)

**Code example:**

```python
eliona.AddAssetTag("K86_WP01", "has-aussentemp")
```

***

### RemoveAssetTag

**Description:**\
Removes a tag from an asset, if present.

**Parameters:**

* `gai: str` (required)
* `tag: str` (required)

**Code example:**

```python
eliona.RemoveAssetTag("K86_WP01", "has-aussentemp")
```

***

### GetTrendRecords

**Description:**\
Loads a list of historical measured values (`TrendRecord(ts, value)`) from the specified start time.

**Parameters:**

* `asset_id: int` (required)
* `subtype: str` (required)
* `attr: str` (required)
* `begin: datetime` (required)

**Code example:**

```python
from datetime import datetime, timedelta

aid   = eliona.GetAssetIDByGAI("K86_WP01")
begin = datetime.now() - timedelta(hours=1)
records = eliona.GetTrendRecords(aid, "input", "Aussentemperatur", begin)
```

***

### WriteTrendRecords

**Description:**\
Writes one or more `TrendRecord`-records into the system.

**Parameters:**

* `asset_id: int` (required)
* `subtype: str` (required)
* `attr: str` (required)
* `recs: TrendRecord | list[TrendRecord]` (required)

**Code example:**

```python
from datetime import datetime, timedelta
import eliona_types

aid = eliona.GetAssetIDByGAI("K86_WP01")
now = datetime.now()
r1  = eliona_types.TrendRecord(now, 18.7)
r2  = eliona_types.TrendRecord(now + timedelta(minutes=30), 19.2)
eliona.WriteTrendRecords(aid, "input", "Aussentemperatur", [r1, r2])
```

***

### GetAggregate

**Description:**\
Calculates aggregated values (average, sum, cumulative sum) in a fixed raster over a period of time.

**Parameters:**

* `agg: Aggregate` (required) – e.g. `eliona_types.Aggregate.Avg`
* `asset_id: int` (required)
* `subtype: str` (required)
* `attr: str` (required)
* `raster: str` (required) – ISO 8601 duration, e.g. `"PT1H"` for hourly
* `start: datetime` (required)
* `end: datetime` (optional, default: `now()`)

**Code example:**

```python
from datetime import datetime, timedelta
import eliona_types

aid   = eliona.GetAssetIDByGAI("K86_WP01")
end   = datetime.now()
start = end - timedelta(days=1)
aggs  = eliona.GetAggregate(
    eliona_types.Aggregate.Avg,
    aid, "input", "Aussentemperatur",
    "PT1H", start, end
)
```

**Example output structure:**

```python
[
  TrendAggregate(ts=<datetime>, cnt=<int>, avg=<float>,
                 sum=<float>, first=<float>,
                 min=<float>, max=<float>, last=<float>),
  ...
]
```

***

### GetLastAggregate

**Description:**\
Returns the most recent cumulative aggregate in the selected raster (including `last_ts`).

**Parameters:**

* `agg: Aggregate` (required)
* `asset_id: int` (required)
* `subtype: str` (required)
* `attr: str` (required)
* `raster: str` (required)

**Code example:**

```python
import eliona_types

aid  = eliona.GetAssetIDByGAI("K86_WP01")
last = eliona.GetLastAggregate(
    eliona_types.Aggregate.Cusum,
    aid, "input", "Aussentemperatur", "P1D"
)
```

**Example output structure:**

```python
RunningAggregate(
  ts=<datetime>, cnt=<int>, avg=<float>,
  sum=<float>, first=<float>,
  min=<float>, max=<float>, last=<float>,
  last_ts=<datetime>
)
```

***

### Simple script for manipulating data

This example shows how a script generates a random value and writes it to the heap of an asset:

```python
def UserFunction(id, eliona):
    import random

    data = {
        "power_val": random.randint(10, 100)
    }

    eliona.SetHeap("TestInactIn", "input", data, eliona.MakeSource(id))
```

**Description:**

* The script imports the module `random`.
* A dictionary `data` is created, containing a key `power_val` to which a random value between 10 and 100 is assigned.
* The generated value is written to the asset heap with the method `SetHeap` in the heap of the asset `TestInactIn` written.

***

### Retrieve and modify data

In this example, the value of an attribute is retrieved from one asset, modified, and stored in another asset:

```python
def UserFunction(id, eliona):
    from datetime import datetime

    heap = eliona.GetHeap("TestInactIn", "input")

    data = {
        "energy_val": heap["power_val"] * 3
    }

    eliona.SetHeap("TestInactIn", "input", data, eliona.MakeSource(id))
```

**Description:**

* The script imports the module `datetime`.
* The current value of the attribute `power_val` is retrieved from the heap of the asset `TestInactIn` is retrieved.
* This value is tripled and written as `energy_val` to the same asset.

***

### Advanced functions and SQL queries

With the method `SQLQuery` any SQL queries can be executed directly from the script:

```python
def UserFunction(id, eliona):
    result = eliona.SQLQuery("SELECT * FROM public.asset WHERE gai = 'TestInactIn';")
    # Further processing of the result
```

**Description:**

* The SQL query retrieves all information about the asset with the GAI `TestInactIn` .
* The result can then be processed further.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.buildings.ability.abb/collection/english-v14/documentation/engineering/script-engine/write-python-scripts.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
