How To's and Manuals

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 deppending 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.

Parameters

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:

Event

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.

Members
  • 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.

    event.zone() = “global”

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

    event.type() = “DIMMER”

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

    event.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.

    event.group() = “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”}

Engine

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

Members
  • fire (function(string, …)): Fires one or more commands on the engine.

    engine.fire(“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.

Return

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

Notes

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

How to connect B&O TVs to a BLI

Introduction

The connection between a Bang & Olufsen TV and a BeoLiving Intelligence enables the user to access the Home Control Panel (similar to web interface) on the TV’s screen. It will also enable scene execution with a BeoRemote as explained in the How to control Your BLI with the One Controller.

This document gives connection instrucctions to the BeoVision Eclipse, the BeoVision Horizon and the BeoPlay V1.

All these B&O products can be added as NetworkLink Resources to your BeoLiving Intelligence or BeoLink Gateway through the setup page, enabling you to set sources for the TV but not necesarilly uncovering its full potential.

Adding your TV as a resource enables the possibility of controlling it through the BeoLiving App by selecting & controlling sources (Audio & video sources). But by setting up the connection through the TV, access to the HOME CONTROL panel is enabled along with the posibility to trigger macros through shortcuts on your control.

BeoVision Eclipse

Part 1: Connect your B&O smart TV to a BLI

  1. With the TV on any source, press MENU to access the main menu.
  2. Go to Settings and open by pressing the center button.
  3. Go down to Sound & BeoLink
  4. Go to the BeoLink option and enter the menu by pressing the right arrow.
  5. Select the BeoLink Gateway option and choose the BeoLiving Intelligence or BeoLink Gateway you wish to connect to from the available options.

Part 2: Access your BLI

  1. Press the LIST button on the BeoRemote.
  2. Go to HOME CONTROL and press the center circle.
  3. Input your BeoLiving Intelligence User and Password in the window that appears on your B&O TV’s screen.
  4. The BLI’s control panel will appear on your TV screen, from which you will be able to trigger macros, control individual equipment (lights, shades, etc) or watch your home’s cameras.

BeoVision Horizon

Part 1: Connect your B&O smart TV to a BLI

  1. With the TV on any source, press MENU to access the main menu.
  2. Go to Settings and open by pressing the center button.
  3. Go down to the Service Menu and before pressing the center button, press red, thus accessing a special menu where the Customer Service Menu option is available.
  4. In the Customer Service Menu go to Settings and press the centre button
  5. Select the BeoLink Gateway option and choose the BeoLiving Intelligence or BeoLink Gateway you wish to connect to from the available options.

Part 2: Access your BLI

  1. Press the LIST button on the BeoRemote.
  2. Go to HOME CONTROL and press the center circle.
  3. Input your BeoLiving Intelligence User and Password in the window that appears on your B&O TV’s screen.
  4. The BLI’s control panel will appear on your TV screen, from which you will be able to trigger macros, control individual equipment (lights, shades, etc) or watch your home’s cameras.

BeoPlay V1

Part 1: Connect your B&O smart TV to a BLI

  1. With the TV on any source, press MENU to access the main menu.
  2. Go down to SETUP and open by pressing the center button.
  3. As soon as you access the setup menu, before pressing anything else, keep the red button pressed for 3 seconds and then press the center button.
  4. Once in the customer service menu, go to SETTINGS and press the center button.
  5. Go to REROUTE LIGHT/CONTROL and access the menu by pressing the right arrow on your remote.
  6. This menu shows you B&O systems available (BeoLiving Intelligences, BeoLink Gateways, Music players, etc.). Select your BLI by pressing the center button and once back in the settings menu, press the center circle to save your new settings.
  7. Restart your TV (turn OFF and ON).

Part 2: Access your BLI

  1. Press the LIST button on the BeoRemote.
  2. Go to HOME CONTROL and press the center circle.

    If HOME CONTROL doesn’t appear on the LIST menu:

    • Go down the menu to Settings and press the center circle.
    • Select LIST for TV and then SHOW.
    • Find HOME CONTROL and select it by pressing the center circle, so that the option is ticked. You will now find the HOME CONTROL option in your LIST on the BeoRemote.
  3. Input your BeoLiving Intelligence User and Password in the window that appears on your B&O TV’s screen.
  4. The BLI’s control panel will appear on your TV screen, from which you will be able to trigger macros, control individual equipment (lights, shades, etc) or watch your home’s cameras.

How to Fire IFTTT applets through BLI commands

BeoLiving Intelligence is now capable of firing IFTTT applets in a really simple way through its own driver. The driver can be found in the external drivers list (Tools–> Advanced–>Install External Drivers).

Basically, BeoLiving Intelligence will trigger your Applet by sending a POST HTTP request to an specific URL. Depending on the selected trigger, a body message will be needed or not.

Creating your IFTTT applet with Webhooks as a service

To create your Applet follow the next instructions:

  1. Choose Webhooks as a service (the one that will trigger your Applet).
  2. Select “Receive a web request” as a trigger.
  3. Set an “Event name” that will identify your trigger.
  4. Select the action of your Applet. Depending on the action selected, a body on the POST can be sent by BeoLiving Intelligence.
  5. To know the Key needed to fire your Applets its necessary to visit the IFTTT Webhook documentation and go to “Documentation”.

Configuring IFTTT - Webhooks driver on BeoLiving Intelligence

Enter to the web-interface of BeoLiving Intelligence and follow the next steps:

  1. Add the IFTTT - Webhooks system.
  2. At “Connection settings” of the driver insert your Key.
  3. Go to Resources and add a “FIRE” resource with the Event name at the resource address.
  4. Create a Macro setting a SEND (or SEND WITH VALUES to send a message with a body of three values) command on the resource created at 3. Add the Event you prefer. For example, this could be any physical button of your configuration. After pressing this button, the request will be fired and your phone will start ringing.

How to control Your BLI with the BeoRemote One

Introduction

Using your BeoRemote One, you may gain access to a BeoLiving Intelligence (BLI) through a Bang & Olufsen Smart TV.

The connection process between a BLI and a B&O TV is detailed in this tutorial.

You will be able to access the BLI’s webpanel to control all your home’s equipment (i.e. lights, shades, cameras, etc.) as well as trigger any macros you may have previously set up.

You will also be able to configure shortcuts to trigger Macros by pressing only a couple of buttons.

Adding your TV as a resource enables the possibility of controlling it through the BeoLiving App by selecting & controlling sources (Audio & video sources). But by setting up the connection through the TV, access to the HOME CONTROL panel is enabled along with the posibility to trigger macros through shortcuts on your control.

Configure and trigger shortcuts

As with the HOME CONTROL option on your BeoRemote’s LIST, you can find other options on the list: LIGHT and CONTROL.

To access any of these options menus, you have to enter the option (e.g. LIGHT) by pressing the right arrow so that the command functions are displayed (e.g. Morning, Home, Cinema, etc.).

By pressing any of these options (called Functions by the BLI), you are now able to fire events to the BLI that you can use to trigger Macros.

One may also fire events through LIGHT by simply highlighting LIGHT on the BeoRemote’s LIST and pressing numbers on the keypad which have been previously assigned to trigger macros.

By going to the Monitor tool on the web setup page, it is possible to view exactly the name of the events triggered with the functions.

Example

Select Light->Home function to turn on all lights on

  1. In the setup web page go to: Tools –> Monitor
  2. On the BeoRemote, press LIST, go to LIGHT, enter the menu by pressing the right arrow and select the HOME function.
  3. The monitor will show a message like: yy-mm-dd hh:mm:ss Event fired Test/local/AV renderer/BeoPlay-V1/Light?Action=Press&Command=FUNCTION_11 you now know that the HOME function is recieved by the BLI as FUNCTION_11.
  4. Go to Macros and create a Macro whos commands turn on all lights
  5. Add an event to trigger the macro
  6. Configure the event as follows:
    • Zone: Zone where the TV is located
    • Resource: TV
    • Event: Light
    • Action: Press
    • Command: FUNCTION_11

Press Light->0 to turn off all lights

  1. Repeat step 4 to 6 of the first example with two changes:
    1. Macro’s commands must turn off all lights
    2. Select Command: CIFFER_0_Digit_0

Business reception setup for TVs and doorbell

This guide shows an interesting Macro setup, inspired by a client who had various B&O TVs in the reception room of their business.

The client wanted the BLI to respond to somebody ringing the doorbell by turning on (if on standby) the TVs and showing the doorbell’s camera. After the receptionist has opened the door through any of the TVs, these should return to their previous state (before anybody rang).

This is easily set up through a LuaMacros code and implemented with the functions shown in the help section of the Macro writing page.

Installation configuration

Let us explain our fictitious installation, we have configured an Area called “Reception” and a Zone where all the television resources will be (which we called “TVs”).

The amount and name of the TVs are not relevant but the idea would be that no other B&O Audio equipment be assigned to this Zone.

We will also work with a DoorBird smart door station, these stations don’t send an Event notification when the OPEN_DOOR command is sent through a gateway, this event is needed to know when to close the Home Control panel again.

The workaround is to Hide the direct access to the OPEN_DOOR button on the Interfaces panel, add a Virtual Device button and create a Macro that does PRESS on both the OPEN_DOOR button and the virtual “StateButton” which will send an Event when saying that it has been pressed.

Our Lua code waits for this PRESS on the code line:

engine.wait_until("Reception/TVs/BUTTON/DoorState/PRESS", 80, 0)

If nobody opens or the door is opened phisically, after 80 seconds the programe advances to the next line.

DoorBird open door macro

The Macro for the DoorBird should simply execute two commands. One should send the command to the doorbell to open the door, the other should select PRESS on a virtual resource BUTTON.

DoorBird Macro

Lua Macro code

As well as the Lua code that goes in the commands section, an event has to be added that executes the Macro when the DoorBird’s button is pressed.

Event to execute the Macro

Next, we will explain the main three block that form our Lua code:

A query is done on AV renderers in TVs and the televisions that are turned off are set to a source to turn them on (we choose the source to be TV):

  init_tvs = engine.query("Reception/TVs/AV renderer/*")
  for i=1,#init_tvs do
    init_state=tostring(init_tvs[i].get("state"))
    if init_state=="Stop" or init_state=="None" then
      offname=tostring(init_tvs[i].name())
      Error(offname)
      engine.fire("Reception/TVs/AV renderer/"..tostring(init_tvs[i].name()).."/Select source?Connector=&Origin=local&Source Type=TV")
    end
  end

Once all the televisions are on, a HOME CONTROL command is sent. The door camera will now appear on the TVs alongside a button to fire the Open Door Macro:

  if tostring(init_tvs[1].get("state"))~="Play" then
    engine.wait_until("Main/Home Theater/AV renderer/"..tostring(init_tvs[1].name()).."/STATE_UPDATE?state=Play",15,0)
  end
 
  engine.fire("Reception/TVs/AV renderer/*/Send command?Command=HOME CONTROL&Continue type=short_press")
  engine.wait_until("Reception/TVs/BUTTON/DoorState/PRESS", 80, 0)

Once the door is open we leave the camera on for five seconds to see the visitor come in and then return all the televisions to their initial state:

  engine.delay(5,0)
  engine.fire("Reception/TVs/AV renderer/*/Send command?Command=BACK&Continue type=short_press")
 
  for i=1,#init_tvs do
    init_state=tostring(init_tvs[i].get("state"))
    if init_state=="Stop" or init_state=="None" then
      engine.fire("Reception/TVs/AV renderer/"..tostring(init_tvs[i].name()).."/Standby")
    end
  end
 
end