Introduction
Integrate your KNX control system with your high-end Bang & Olufsen Mozart audio products for a unified smart home experience. This tutorial will walk you through setting up two BeoLiving Intelligence macros to create a robust, two-way binding between a KNX slider and a Mozart product’s volume. You’ll be able to adjust the volume from your KNX wall panel, and the slider will accurately reflect any volume changes made via a remote control or the BeoLiving app, keeping everything perfectly in sync.
Prerequisites
Before you begin, ensure you have a KNX “1 byte unsigned integer (DPT 5.001)” resource configured in your BeoLiving Intelligence that corresponds to your KNX slider. This resource will represent the volume level (0-255) on the KNX bus.
How to Set It Up
Creating a two-way synchronization requires two separate macros. One macro will listen for changes from the KNX slider and update the Mozart product’s volume. The second macro will do the reverse: listen for volume changes on the Mozart product and update the KNX slider.
Part 1: Macro from KNX Slider to Mozart Volume
- Navigate to the Macro tab and create a new Macro. Name it something descriptive, like “KNX to Mozart Volume”.
- As the event, add the
STATE_UPDATE
event from your KNX slider resource. It will look like:RndLab/LivingRoom/_KNX_GROUP_ADDRESS/knxSlider/STATE_UPDATE
. - Press the “Convert to code” button in the commands table.
- Copy the Lua code from the Macro 1 section below and paste it into the code text area.
- Customize the
targetProduct
variable in the SETTINGS section to match your Mozart device address. - Save the macro.
Part 2: Macro from Mozart Volume to KNX Slider
- Create another new Macro. Name it something descriptive, like “Mozart to KNX Volume”.
- As the event, add the
STATE_UPDATE
event from your Mozart RENDERER product. It will look like:RndLab/LivingRoom/RENDERER/Beovision Theatre-35554298/STATE_UPDATE
. - Press the “Convert to code” button.
- Copy the Lua code from the Macro 2 section below and paste it into the code text area.
- Customize the
knxSlider
andmacroAddress
variables in the SETTINGS section. ThemacroAddress
must be the full address of this macro itself. - Save the macro.
Now, when you adjust the KNX slider, the B&O product’s volume should change. When you change the volume using a Beoremote or the B&O App, the KNX slider should update its position after a short delay.
The Lua Code
Macro 1: KNX Slider → Mozart Product
This macro scales the KNX value (0-255) to the Mozart volume range (0-90) and updates the product, preventing command loops by checking the current volume first.
-- === KNX SLIDER TO MOZART VOLUME ===
-- This macro listens for changes on a KNX slider and updates the volume
-- of a target Mozart product. It includes volume scaling from KNX's 0-255
-- range to the Mozart's 0-90 range.
--
-- How to use it:
-- 1. Create a Macro triggered by the STATE_UPDATE of your
-- KNX "1 byte unsigned integer" resource.
-- e.g., RndLab/LivingRoom/_KNX_GROUP_ADDRESS/knxSlider/STATE_UPDATE
-- 2. Press "Convert to code" and paste this code.
-- 3. Update the SETTINGS section with your device address.
-- =======================================================================
function(event, engine)
-- --------------------------------------------------------
-- SETTINGS
-- --------------------------------------------------------
-- Replace this with the address of the target Mozart product:
local targetProduct = "RndLab/LivingRoom/RENDERER/Beovision Theatre-35554298"
-- --------------------------------------------------------
-- DO NOT EDIT BELOW HERE UNLESS YOU UNDERSTAND THE CODE!
-- --------------------------------------------------------
-- Check if the VALUE parameter of the KNX resource was updated
if event.updated("VALUE") then
-- Get the raw value (0-255) from the KNX slider
local knxValue = event.get_number("VALUE")
-- Scale the KNX value (0-255) to the B&O volume range (0-90)
local targetVolume = math.floor((knxValue / 255) * 90)
-- Query the current state of the target product to get its volume
local productState = engine.query(targetProduct)
if productState and productState[1] then
local currentVolume = productState[1].get_number("VOLUME")
-- To prevent loops, only send the command if the new volume is different
if currentVolume ~= targetVolume then
Debug("KNX->Mozart: Setting volume from " .. tostring(currentVolume) .. " to " .. tostring(targetVolume))
engine.fire(targetProduct .. "/SET_VOLUME?VOLUME=" .. targetVolume)
else
Debug("KNX->Mozart: Volume already at " .. tostring(targetVolume) .. ". Ignoring.")
end
end
end
end
Once added it should look like:
Macro 2: Mozart Product → KNX Slider (with Debounce)
This macro listens for volume changes on the Mozart product, debounces the events to avoid flooding the KNX bus, scales the volume (0-90) to the KNX range (0-255), and updates the slider.
-- === MOZART VOLUME TO KNX SLIDER (WITH DEBOUNCE) ===
-- This macro listens for volume changes on a Mozart product and updates
-- a KNX slider. It includes a debounce mechanism to prevent flooding the
-- KNX bus with rapid volume changes.
--
-- How to use it:
-- 1. Create a Macro triggered by the STATE_UPDATE of your Mozart RENDERER.
-- e.g., RndLab/LivingRoom/RENDERER/Beovision Theatre-35554298/STATE_UPDATE
-- 2. Press "Convert to code" and paste this code.
-- 3. Update the SETTINGS section with your device and macro addresses.
-- =======================================================================
function(event, engine)
-- --------------------------------------------------------
-- SETTINGS
-- --------------------------------------------------------
-- Replace this with the address of the KNX slider resource ("1 byte unsigned integer"):
local knxSlider = "RndLab/LivingRoom/_KNX_GROUP_ADDRESS/knxSlider"
-- Replace this with the address of this macro, required for the debouncer.
-- Find it in the BeoLiving Intelligence UI (e.g., Main/global/MACRO/Mozart to KNX Volume).
local macroAddress = "Main/global/MACRO/Mozart to KNX Volume"
-- Debounce delay in milliseconds to prevent flooding the KNX bus.
local debounce_ms = 500
-- --------------------------------------------------------
-- DO NOT EDIT BELOW HERE UNLESS YOU UNDERSTAND THE CODE!
-- --------------------------------------------------------
-- Check if the VOLUME parameter of the Mozart product was updated
if event.updated("VOLUME") then
-- 1. Debounce: Cancel any other instance of this macro that is waiting.
engine.fire(macroAddress .. "/CANCEL OTHER")
-- Wait for a short period to see if more volume changes come in.
engine.delay(0, debounce_ms)
-- Get the new volume (0-90) from the Mozart product.
-- We re-query the state in case it changed during the delay.
local productState = engine.query(event.area() .. "/" .. event.zone() .. "/" .. event.type() .. "/" .. event.name())
local mozartVolume = productState[1].get_number("VOLUME")
-- Scale the B&O volume (0-90) to the KNX slider range (0-255)
local targetKnxValue = math.floor((mozartVolume / 90) * 255)
-- Query the current state of the KNX slider
local knxState = engine.query(knxSlider)
if knxState and knxState[1] then
local currentKnxValue = knxState[1].get_number("VALUE")
-- To prevent loops, only send the command if the new value is different
if currentKnxValue ~= targetKnxValue then
Debug("Mozart->KNX: Setting slider from " .. tostring(currentKnxValue) .. " to " .. tostring(targetKnxValue))
engine.fire(knxSlider .. "/SET?VALUE=" .. targetKnxValue)
else
Debug("Mozart->KNX: Slider value already at " .. tostring(targetKnxValue) .. ". Ignoring.")
end
end
end
end
A Note on Volume Scaling
Bang & Olufsen Mozart products typically use a volume scale of 0 to 90. In contrast, a KNX “1 byte unsigned integer” (DPT 5.001) has a range of 0 to 255. The provided macros automatically handle the mathematical conversion between these two scales. This ensures that when your B&O volume is at its maximum (90), the KNX slider correctly shows its maximum value (255), and vice-versa, with proportional mapping for all values in between.