> 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/platform/platform-core/script-engine/writing-python-scripts.md).

# Writing Python Scripts

## Writing Python Scripts

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

## Script Definition

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

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

The function header looks like this:

```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 only imported within the function and no global imports are used.

Example:

```python
def UserFunction(id, eliona):
    import random
    # Weitere Codezeilen folgen
```

***

## Methods of the BuildingPro Suites Object

The **`eliona`** object provides a set of methods that allow users to interact with the BuildingPro Suites system. Here are the most important methods along with their parameters and descriptions:

<table data-full-width="true"><thead><tr><th width="173">Methode</th><th>Parameter</th><th>Beschreibung</th><th></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><td></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><td></td></tr><tr><td><strong>GetAssetIDByGAI</strong></td><td><code>gai: str</code></td><td>Returns the numerical asset ID for the specified GAI.</td><td></td></tr><tr><td><strong>GetAll</strong></td><td>`ids: list[int</td><td>str]<code>,</code> subtype: str`</td><td>Retrieves all data points of a specific subtype for a list of assets and returns them as a dictionary (GAI → data).</td></tr><tr><td><strong>SQLQuery</strong></td><td><code>query: str</code></td><td>Executes an arbitrary SQL query and returns the results as a list of tuples.</td><td></td></tr><tr><td><strong>MakeSource</strong></td><td><code>id: int</code></td><td>Generates a source string for heap operations based on the function ID.</td><td></td></tr><tr><td><strong>OpenFile</strong></td><td><code>name: str</code>, <code>mode: str</code></td><td>Opens a file in the BuildingPro Suites working directory (analogous to Python’s <code>open()</code>).</td><td></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><td></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><td></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.</td><td></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> data sets to the system.</td><td></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.</td><td></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 latest cumulative aggregate in the selected raster (incl. <code>last_ts</code>).</td><td></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.

**Parameter:**

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

#### Example-Code:

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

**Example-Output:**

```python
23.5
```

***

### SetHeap

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

**Parameter:**

* `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 numerical asset ID for the specified GAI.

**Parameter:**

* `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).

**Parameter:**

* `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 an arbitrary SQL query and returns the results as a list of tuples.

**Parameter:**

* `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:**

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

***

### MakeSource

**Description:** Generates a source string (z. B. `"ssr:123"`) for heap operations based on the function ID.

**Parameter:**

* `id: int` (required)

**Code-Example:**

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

***

### OpenFile

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

**Parameter:**

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

**Code-Example:**

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

***

### AddAssetTag

**Description:** Adds a tag to an asset if it is not yet assigned.

**Parameter:**

* `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.

**Parameter:**

* `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.

**Parameter:**

* `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` data sets to the system.

**Parameter:**

* `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.

**Parameter:**

* `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()`)
* `recs: TrendRecord | list[TrendRecord]` (required)

**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-Struktur:**

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

***

### GetLastAggregate

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

**Parameter:**

* `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-Struktur:**

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

***

### Simple Script for Data Manipulation

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 `random` module.
* A dictionary `data` is created that contains a key `power_val`, to which a random value between 10 and 100 is assigned.
* The generated value is written to the heap of the `TestInactIn` asset using the `SetHeap` method.

***

## Get and Modify Data

In this example, the value of an attribute is retrieved from one asset, modified, and saved 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 `datetime` module.
* The current value of the `power_val` attribute is retrieved from the heap of the `TestInactIn` asset.
* This value is tripled and written to the same asset as `energy_val`.

***

## Advanced Functions and SQL Queries

With the `SQLQuery` method, 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';")
    # Weitere Verarbeitung des Ergebnisses
```

**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/platform/platform-core/script-engine/writing-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.
