Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions bli-guides/_developers-guides/driverDevelopmentGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,29 @@ A typical example of resource with state is a dimmer with feedback as shown in t
```


<a id="queries"></a>

#### queries

Queries define requests that BLI can make to the driver to retrieve dynamic data from the third party system for the corresponding resource.
Unlike commands (which trigger actions) or states (which are continuously synchronized), queries are executed on demand — typically when the user clicks **Synchronize** in the admin UI.

For each resource type, an optional table of queries may be provided in which keys are the query names (e.g. `LIST_INPUTS`) and values are tables with the following data:

- **`context_help`**: Context help describing what the query returns.

Example of queries for a RENDERER resource type:

```lua
queries = {
LIST_INPUTS = { context_help = "Lists the available input sources." },
LIST_APPLICATIONS = { context_help = "Lists the installed applications." }
}
```

The driver must implement a corresponding [query](#query) function to handle these queries and return the appropriate data. See the [RENDERER type](#RENDERER-type) section for the expected response formats.


<a id="driver_label"></a>

## driver\_label
Expand Down Expand Up @@ -1140,6 +1163,69 @@ Where `commandNumbers` is defined as:
["_MULTI TAP"] = 6, ["_HOLD RELEASE"] = 32, SET= 1 }
```

<a id="query"></a>

## query

This function is called whenever BLI needs to retrieve dynamic data from the third party system for a resource.
Queries are triggered when the user clicks **Synchronize** in the admin UI for a resource that has queries defined in its specification.

The function prototype must be:

```lua
function query(queryName, resource, queryArgs)
```

Where:

- **`queryName`** is the name of the query being executed, e.g. `"LIST_INPUTS"`.
- **`resource`** is the [resource](#resource-Lua-instance) for which the query is being executed.
- **`queryArgs`** is a table containing any arguments for the query (usually empty).

Like `executeCommand`, this function should return as soon as possible. If the data is already cached or can be computed immediately, return a table with the result directly.

#### Synchronous query

```lua
function query(queryName, resource, queryArgs)
if queryName == "LIST_INPUTS" then
return {
inputs = {
{ address = "HDMI1", name = "HDMI 1", type = "internal", capabilities = {} },
{ address = "HDMI2", name = "HDMI 2", type = "internal", capabilities = {} },
{ address = "TV", name = "TV Tuner", type = "internal", capabilities = {"CHANNEL"} }
}
}
end
end
```

#### Asynchronous query

If the driver needs to communicate with the device to gather the data and cannot return immediately, an optional fourth parameter `cont_fn` (continuation function) is provided. In this case the `query` function must **not** return a value — instead, it calls `cont_fn` when the data is ready.

```lua
function query(queryName, resource, queryArgs, cont_fn)
if queryName == "LIST_INPUTS" then
copas.addthread(function()
local inputs = fetchInputsFromDevice(resource.address)
if inputs then
cont_fn(true, { inputs = inputs })
else
cont_fn(false)
end
end)
end
end
```

The continuation function `cont_fn` takes two arguments:
- **`ok`** (boolean): `true` if the query succeeded, `false` otherwise.
- **`values`** (table, optional): the query result data (only when `ok` is `true`).

See the [RENDERER type](#RENDERER-type) section for the expected response formats for standard queries like `LIST_INPUTS`, `LIST_APPLICATIONS`, etc.


<a id="onResourceDelete"></a>

## onResourceDelete
Expand Down Expand Up @@ -4212,6 +4298,66 @@ All commands take no arguments.

(M) = mandatory if the CUSTOM_COMMAND capability is included.

### Query response formats

When the driver implements the [query](#query) function for a RENDERER or MATRIX resource, the returned data must follow these structures:

#### LIST\_INPUTS

Returns the available input sources for the resource. Each input entry has the following fields:

- **`address`** (string, required): The input identifier, used as the value for `SELECT_INPUT` commands.
- **`name`** (string, optional): Display name for the input. Defaults to the address if not provided.
- **`type`** (string, required): `"internal"` — the input is handled by the resource itself. This is currently the only supported value.
- **`capabilities`** (list of strings, optional): Capabilities available when this input is selected. Valid values correspond to capability names: `"POWER"`, `"INPUT"`, `"VOLUME"`, `"NAVIGATION"`, `"PLAYER"`, `"APPLICATION"`, `"CHANNEL"`, `"CUSTOM_COMMAND"`, `"CONTENT"`, `"PLAYQUEUE"`, `"MULTIROOM"`, `"KEYBOARD"`.

```json
{
"inputs": [
{ "address": "HDMI1", "name": "HDMI 1", "type": "internal", "capabilities": [] },
{ "address": "HDMI2", "name": "HDMI 2", "type": "internal", "capabilities": [] },
{ "address": "TV", "name": "TV Tuner", "type": "internal", "capabilities": ["CHANNEL"] },
{ "address": "NET", "name": "Network", "type": "internal", "capabilities": ["NAVIGATION", "CONTENT"] }
]
}
```

#### LIST\_APPLICATIONS

Returns the available applications.

```json
{
"applications": [
{ "name": "Netflix", "icon": "https://..." },
{ "name": "YouTube", "icon": "https://..." }
]
}
```

#### LIST\_CHANNELS

Returns the available channels.

```json
{
"channels": [
{ "name": "BBC One", "icon": "https://..." },
{ "name": "Channel 2", "icon": "https://..." }
]
}
```

#### LIST\_CUSTOM\_COMMANDS

Returns the available custom commands.

```json
{
"customCommands": ["PictureMode", "SoundMode", "AspectRatio"]
}
```

### Example specification

```lua
Expand Down Expand Up @@ -4240,6 +4386,10 @@ All commands take no arguments.
PLAY= {}, PAUSE= {}, STOP= {},
NEXT= {}, PREV= {}
},
queries= {
LIST_INPUTS = { context_help = "Lists the available input sources." },
LIST_APPLICATIONS = { context_help = "Lists the installed applications." }
},
states= {
enumArgument("ONLINE", {0, 1}, 0), -- global capability
stringArgument("INPUT", ""), -- INPUT capability (mandatory)
Expand Down