How to write LUA Macros

The Macro configuration page of the BeoLiving Intelligence has a simple user interface that displays available resources and commands on these resources, but aside from selecting the command to execute and setting a time delay between commands, the possibilities are limited.

A user may desire to use their system variable’s values to act in a different way depending on this.

E.g.: Lower the curtains after sunset only if the rooms lights are turned ON.

For this kind of control, the installer/advanced-user may press the Convert to code button and gain access to a very easy and complete tool: lua Macros

The following is an introduction to the main tools used in lua code programming for the BeoLiving Intelligence, including code snippets and practical examples.

Getting started

When the macro executes because any of the defined events has matched, the function defined in the “Lua code” text area will be executed.


The function should have the following signature: function(event, engine) Every lua Macro should start by stating the signature and end with end, as seen in the examples. The available parameters are those under event and under engine:


The event that originated the call will have many parameters with information related to this event and this information can be useful for setting conditions or values of variables.

E.g. Get the level of a dimmer who’s change has triggered the event, and set half the value to all the other lights.

  • tostring (function(): string): The full string representation of the event.

    event.tostring() = “Main/global/DIMMER/MyLamp/STATE_UPDATE?LEVEL=55!”

  • area (function(): string): The area name.

    event.area() = “Main”

  • zone (function(): string): The zone name. = “global”

  • type (function(): string): The type name.

    event.type() = “DIMMER”

  • name (function(): string): The originator name. = “MyLamp”

  • parameters (function(): table): The parameters, with full values, as a lua table.

    event.parameters() = {“LEVEL” = “55!”}

  • get (function(string): string): Gets the value of a parameter, excluding the updated mark.

    event.get(“LEVEL”) = “55”

  • updated (function(string): boolean): Checks whether a parameter was updated on the event.

    event.updated(“LEVEL”) = true

  • group (function(): string): The name of the group the zone is in. = “indoors”

  • group_zones (function(string) : table): The addresses of the zones contained in a group.

    event.group_zones(“indoors”) = {“Main/global”, “Downstairs/Kitchen”, “Upstairs/Main room”, “other/room”}


The BeoLiving Intelligence’s execution engine. The engine allows you te set values or query states of all your BLI’s devices.

  • fire (function(string, …)): Fires one or more commands on the engine.“other/room/DIMMER/*/SET?LEVEL = 75”)

  • fire_on_group (function(string, string)): Fires one commands every zone that belongs to a group.

    engine.fire_on_group(“indoors”, “DIMMER/*/SET?LEVEL = 75”)

  • query (function(string): table): Performs a state query on the engine. The returned table is an array of states, with the following members:
    • tostring (function(): string): The full string representation of the state.
    • area (function(): string): The area name.
    • zone (function(): string): The zone name.
    • type (function(): string): The type name.
    • name (function(): string): The state owner name.
    • get (function(string): string): Gets the value of a parameter.
    • group (function(): string): The name of the group the zone is in.
    • group_zones (function(string) : table): The addresses of the zones contained in a group.

      tab = engine.query(“other/room/DIMMER/*”)

      tab[1].tostring() = “other/room/DIMMER/OtherLamp/STATE_UPDATE?LEVEL=62” tab[1].area() = “other” tab[1].zone() = “room” tab[1].type() = “DIMMER” tab[1].name() = “OtherLamp” tab[1].get(“LEVEL”) = “62” tab[1].group() = “indoors” tab[1].group_zones(“indoors”) = {“Main/global”, “Downstairs/Kitchen”, “Upstairs/Main room”, “other/room”}

  • wait_until (function(string, int, int): bool, string): Blocks the execution of the macro for a certain amount of time or until a given condition is met. Returns whether the condition was held and the address that matched.

    success, address = engine.wait_until(“other/room/AV renderer/TV/STATE_UPDATE?state=Play”, 120, 0)

  • delay (function(int, int)): Blocks the execution for a certain amount of time.


No return value is expected or should be set from the lua function.


Any runtime error will be sent to the system log (Tools–>Log).

Example of what could be seen in log: Execution error on Main/global/MACRO/sample: Line 6: attempt to call field ‘wrong_delay’ (a nil value).

For debugging purposes, the macro code can call the Debug function, which receives a string that is sent to the system log. This can be used to print a variable’s value or to see if your macro is arriving to the end of the code or “crashing” before hand.

Example of what you can write in your Macro’s code: Debug(“Will debug: “ .. tostring(123)).

Two special commands, which cannot be added via normal macro edition, are available for group creation and group clear. These commands are provided by the system driver, which is located on the global zone.

Set the kitchen on the “indoors” group: Main/global/SYSTEM/BeoLiving Intelligence/SET GROUP?zone=Downstairs/Kitchen&group=indoors

Clear the kitchen group: Main/global/SYSTEM/BeoLiving Intelligence/CLEAR GROUP?zone=Downstairs/Kitchen

Only one execution of a macro is allowed to wait_until or delay at a time. If the macro is fired while the same macro is waiting or delaying, then the previous wait is canceled.

Canceling a macro immediately cancels any wait_until or delay.

Learn lua

All lua native functions are available for use in the lua Macros configuration.

A good place to start learning Lua is Tyler Neylon’s “Learn Lua in 15 Minutes”. This is a short and simple introduction

A more complete reference guide is the book Programming in Lua. The first edition is freely available online. And includes all available functiones.

Code examples

Improve this document: Edit on github!