Block Controller
Use the Block Controller component to easily declare one or more controls and their connections, and then build the Lua script associated with those controls using a visual block interface.
After you configure your controls and connections in the elements configurator, you can then build your configuration using a visual programming tool that uses interlocking graphical blocks to represent common code programming concepts including logical expressions and loops. Rapid code creation and editing allows you to compose simple or sophisticated AV scripts while ensuring that the generated code is always syntactically correct.
The underlying script interacts with components through their control pins. You can write scripts to control elements entirely within the Q-SYS Designer file, or you can use it to interface Q-SYS with third-party hardware accessible via TCP, UDP, Serial, or SSH.
Note: This component uses the Q-SYS Scripting Engine, which is a licensed feature on certain Cores manufactured with Q-SYS 7.0 and later. For more information, see Licensing.
- In your schematic, double-click the Block Controller component to open the elements editor.
- In the Controls section, click to add a new control.
- In the Properties section, configure the new control, including its name, count, and type.
- In the Connections section, click to add a new connection.
- In the Properties section, configure the new connection, including its name, type, and control pins.
- Click Edit to edit and save the Lua script for your control configuration using a visual block interface.
Double-click the Block Controller component to open the elements editor, which is where you define controls for your block configuration. After defining your controls, click Edit to open the Blocks editor.
Controls and Connections
Control |
Function |
---|---|
Controls |
Click to add a new control to the list, and then configure its properties. See Controls Properties. |
Connections |
Click to add a new connection to the list, and then configure its properties. See Connections Properties. |
Controls Properties
Property |
Function |
Choices |
---|---|---|
General |
||
Name |
Specify a name for the input. |
Text input |
Count |
Specify the number of controls of the specified type to create. |
1 to 256 |
Control Type |
||
Category |
Button
Select a Push Action:
Knob
Specify a Max Value and Min Value for the specified Units:
Indicator
Specify a Type: LED, Meter, Text, Status. Text
Specify a Type: Text Box, Combo Box, List Box |
Button, Knob, Indicator, Text |
Control Pin |
Expose pins for these controls: None, Input (pins on the left), Output (pins on the right), or Both. |
None, Input, Output, Both |
Connections Properties
Property |
Function |
Choices |
---|---|---|
Name |
Specify a name for the connection and its controls. |
Text input |
Type |
Specify how to communicate with the external device: TCP
Expose IP Address, Port, and Status pins for these controls: None, Input (pins on the left), Output (pins on the right), or Both.
UDP
Expose IP Address, Port, and Status pins for these controls: None, Input (pins on the left), Output (pins on the right), or Both. Serial
Expose Baud Rate, Bits, Parity, and Status pins for these controls: None, Input (pins on the left), Output (pins on the right), or Both. Note that this will expose a serial control pin that needs to be wired to a matching pin on the component that represents the hardware. For an example of creating a serial connection, see Creating a Serial Connection. SSH
Expose IP Address, Port, Status, User Name, and Password pins for these controls: None, Input (pins on the left), Output (pins on the right), or Both.
|
TCP, UDP, Serial, SSH |
After configuring your controls and connections, click Edit to open the Blocks editor (Blocks tab). Controls and connections are presented as graphical blocks that you can drag into the script and configure with values and statements.
- In the Controls and Connections drop-downs, add and configure script components (blocks), as desired.
- If your design contains Named Controls or Named Components, use their drop-down menus to add blocks from those categories.
- Add and configure new blocks (Values, Strings, etc.) from the menu, as desired.
- Click Save changes to commit any changes to your script.
- Click the Lua tab to view your configuration in script form.
For examples of creating controls using the visual block interface, see Block Examples. To modify your script in a traditional script editor, see Using the Script Editor.
To edit the script using a text-based editor, click the button and select Convert to Script.
WARNING: When you switch to the text-based editor, the editor is initially populated with the Lua script generated from the Block editor. If you later switch back to the Block editor ( > Revert to Blocks), your text editor changes are lost. Any text-based script you enter is overwritten by text generated by the Block editor.
The script editor contains three areas:
- Text editor – Modify the script for your configuration. You can edit the script in the Design, Emulate, or Run modes, but any errors are only detected in the Run or Emulate modes.
- Information bar at the top of the script:
- Click the yellow "Save changes" bar to reload (not run) the script.
- Syntax errors are indicated in a red bar at top-right, as well as in the Debug Output area.
Tip: While in the Script area, press F1 for help on the Lua scripting language.
- Refer to the Q-SYS Lua Environment and the Lua 5.3 Reference Manual topics for information about writing scripts.
- Click the Search bar on the right side of the page to locate or replace text in your script. As a shortcut, press F3 to find the next item.
See Debug Output.
The available Control Pins depend on settings in Properties.
Pin Name |
Value |
String |
Position |
Pins Available |
---|---|---|---|---|
Code |
(text) |
Input / Output |
||
Script Start |
(trigger) |
Input / Output |
||
Script Status |
(text) |
Output |
||
Script Stop |
(trigger) |
Input / Output |
This section demonstrates how you can create controls using the visual block interface, which then generates the underlying Lua script. Refer to the Control Scripting topic for information on Lua scripting.
Serial port communication is supported via the RS-232 ports on some Q-SYS devices. To create a connection:
- In your schematic, double-click the Block Controller component to define the controls and connections using the elements editor.
- Click Edit to define the controller configuration in the Blocks editor.
- Drag the Q-SYS device's Serial Port component into your schematic and wire it to the Block Controller component.
In this example, a trigger button is used to send data (entered in a text box) through the serial port on a Core 110f. For more information on serial port connections, and to see an example of the Lua script used to create this example, see SerialPorts.
Defining controls and connections
Double-click the Block Controller component to open the elements editor. In this example, two controls and one connection are defined.
Tip: You can drag individual control and connection components into your schematic or copy them to the User Control Interface editor.
Controls
- Trigger button (Control Type = Button; Button Type = Trigger)
- Text box for sending data (Control Type = Text; Text Type = Text Box)
Connections
- Serial port (Connection Type = Serial)
Blocks and script equivalents
Click Edit to open the Blocks editor. Define the controller configuration using the available blocks in the left menu. The Controls and Connections categories contain the elements defined in the elements editor.
In this example, there are four groups of blocks that do the following:
- Establish the event handler for the trigger button.
- Print out baud rate, data bits, and parity once a connection has been established.
- Print disconnect messaging.
- Print any message received from the device.
Blocks | Script Equivalent |
---|---|
Controls['send'].EventHandler = function() local tx = Controls['data'].String tx = tostring(Controls['data'].String) .. tostring('\r') sp:Write(tx) print(tostring('sending data out to serial port ') .. tostring(Controls['data'].String)) end |
|
spStatusConnectedFunctions['W20|n-~B=8xbb@M)EUz]'] = function() print('serial port connected') print(tostring('baudrate ') .. tostring(Controls['sp.Baud_Rate'].String)) print(tostring('databits ') .. tostring(Controls['sp.Data_Bits'].String)) print(tostring('parity ') .. tostring(Controls['sp.Parity'].String)) end |
|
spStatusClosedFunctions['ik3z-W^jqC}cB9g*Vt!9'] = function(error_message) print('serial port disconnected') end |
|
sp.Data = function() message = sp:ReadLine(SerialPorts.EOL.Any) while (message ~= nil) do print(tostring('read line ') .. tostring(message)) message = sp:ReadLine(SerialPorts.EOL.Any) end end |
Setting baud rate, data bits, and parity
The Block Controller automatically produces script for handling the setting of baud rate, data bits, and parity. When you emulate or save and run your design to the Core, open the Block Controller control panel to set baud rate, data bits, and parity using the drop-down menus.
The TcpSocket object allows Q-SYS cores to make client TCP/IP connections to devices on the network. In this example, a trigger button is used to send data entered in a text box to a TCP device with a specified IP address and port number. For more information, and to see an example of the Lua script used to create this example, see TcpSocket.
Defining controls and connections
Double-click the Block Controller component to open the elements editor. In this example, two controls and one connection are defined.
Tip: You can drag individual control and connection components into your schematic or copy them to the User Control Interface editor.
Controls
- Trigger button (Control Type = Button; Button Type = Trigger)
- Text box for sending data (Control Type = Text; Text Type = Text Box)
Connections
- TCP socket (Connection Type = TCP)
Blocks and script equivalents
Click Edit to open the Blocks editor. Define the controller configuration using the available blocks in the left menu. The Controls and Connections categories contain the elements defined in the elements editor.
Blocks | Script Equivalent |
---|---|
sendData = 'Hello\x0d\x0a' |
|
sockStatusConnectedFunctions['rq{I?iu_o,WJQo?H:W2X'] = function() print('socket connected') end |
|
sockStatusClosedFunctions['jArNCFTp,o|3t(#/z?sc'] = function(error_message) print('TCP socket was closed by the remote end') end |
|
sock.Data = function() message = sock:ReadLine(TcpSocket.EOL.Any) while (message ~= nil) do print(tostring('TCP socket has data:\t') .. tostring(message)) message = sock:ReadLine(TcpSocket.EOL.Any) end end |
|
Controls['Trigger button'].EventHandler = function() -- A comment for this block sock:Write(sendData) print('sending data') end |
Use SSH to create secure client connections to devices on the network. It is very similar to creating a TCP socket, but requires additional connection arguments (host, port, user, password). For information about creating SSH connections in Lua, see Ssh.
In this example, an SSH connection is configured that:
- Automatically attempts to connect with the provided login host, port, and credentials.
- Writes the date to the connection.
- Prints any messages received from the device.
- Prints a login failure message if the wrong credentials are provided.
Defining controls and connections
Double-click the Block Controller component to open the elements editor. In this example, a new SSH connection is defined. Controls are available for IP Address, Port, UserName, Password, and Status, which can be dragged into your design.
Blocks and script equivalents
Click Edit to open the Blocks editor. Define the controller configuration using the available blocks in the left menu. The Connections category contains the elements for the SSH connection.
Blocks | Script Equivalent |
---|---|
timer0 = Timer.New() |
|
SSH_Connection.Connected = function() timer0:Start(10) end |
|
timer0.EventHandler = function() SSH_Connection:Write('date\n') end |
|
SSH_Connection.Data = function() message = SSH_Connection:ReadLine(TcpSocket.EOL.Any) while (message ~= nil) do print(message) message = SSH_Connection:ReadLine(TcpSocket.EOL.Any) end end |
|
SSH_Connection.LoginFailed = function() print("Wrong password!") end |
Setting connection parameters
Run or emulate your design. In the SSH connection controls, set the host/IP address, port, username, and password. Block Controller automatically attempts to connect with the provided parameters.
The Timer object is used to create delays or trigger events after a defined elapsed time. It should be used instead of Lua's native delay and time functions. For more information, and to see an example of the Lua script used to create this example, see System.
Blocks and script equivalents
Blocks | Script Equivalent |
---|---|
timer1 = Timer.New() timer2 = Timer.New() timer_1 = 'timer1!' timer_2 = 'timer2' timer = 'timer2' |
|
function timerFunc() if timer == timer_1 then print(timer_1) elseif timer == timer_2 then print(timer_2) end end |
|
timer1.EventHandler = function() timer = timer_1 timerFunc() end |
|
timer2.EventHandler = function() timer = timer_2 timerFunc() end |
|
timer1:Start(1) timer2:Start(2) |
Use the after time block to create a single event or a series of events that execute after a specified period of seconds. Unlike a standard timer, this block only fires once.
To add more events to execute, click the gear icon and drag the then after time block under the after time block.
Blocks and script equivalents
In this example, a series of debug print strings executes in three timed steps.
Blocks | Script Equivalent |
---|---|
Timer.CallAfter(function() print('This') Timer.CallAfter(function() print('is') Timer.CallAfter(function() print('Q-SYS') print(Qlib.version().Version) end,5) end,3) end,2) |
Debug Output
This is Q-SYS 7.1.0.27
This example shows how you can use the Block Controller component to create multiple controls (trigger buttons) and then use those controls in a user control interface with layer transitions.
Overview
This example UCI allows the user to push one of six buttons to either show a Q-SYS product category image or remove the current image and show the Q-SYS logo:
There are three overall steps to creating this UCI:
- Defining the control buttons in the Block Controller elements editor.
- Copying those controls from the Block Controller elements editor into the UCI editor and defining layers and button images.
- Defining the controller configuration in the Blocks editor to configure the UCI functionality, including transitions between controls.
Defining controls
Double-click the Block Controller component to open the elements editor. In this example, six controls are defined - each for displaying a different Q-SYS product image (Control Type = Button; Button Type = Trigger).
Configuring the UCI
Note: For information on creating UCIs, see UCI Design.
- Create a new user control interface and name it "Q-SYS".
- Select and copy each of the six controls (gray rectangles) from the Block Controller elements editor and paste into the UCI editor.
- Configure the properties for each control button in the UCI:
- Set Graphics Properties > Button Style to "Image".
- Set Button Images > On Image to an appropriate button graphic.
- Your UCI will now contain a single layer with six elements (buttons). Rename this layer "buttons".
- Create six new layers – named "cores", "network", "conference", "touchscreen", "amplifiers", and "logo" – each with a large graphic that will be placed in the middle of the display above the buttons layer.
Now, you will have a UCI with one page ("Page 1") containing seven layers:
Using the Blocks editor to define the controller configuration
Finally, use the Blocks editor to define the UCI functionality.
- In the Block Controller elements editor, click the Edit button to open the Blocks editor.
- In the Blocks menu, you will see categories for various types of statements, including a Controls category that contains available blocks for each of the control buttons you defined in the elements editor.
- Build the configuration by selecting individual blocks from the menu. This example uses blocks from the Variables and Functions, System, and Controls categories. See the next section for the configuration for this example.
Blocks and script equivalents
In this example, there are three groups of blocks that do the following:
- Define the "clear" function, which clears the display of all product images with a Fade transition, revealing only the Q-SYS logo.
- Run the "clear" function when starting the UCI.
- Define what occurs when each button is pressed.
Note: For information about the UCI Lua functions used behind the scenes in this example, see Uci.
Blocks | Script Equivalent |
---|---|
function clear() Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'cores', false, 'fade') Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'network', false, 'fade') Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'conference', false, 'fade') Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'touchscreen', false, 'fade') Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'amplifiers', false, 'fade') end |
|
clear() |
|
Controls['cores'].EventHandler = function() clear() Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'logo', false, 'fade') Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'cores', true, 'left') end Controls['network'].EventHandler = function() clear() Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'logo', false, 'fade') Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'network', true, 'right') end Controls['conference'].EventHandler = function() clear() Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'logo', false, 'fade') Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'conference', true, 'bottom') end Controls['touchscreens'].EventHandler = function() clear() Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'logo', false, 'fade') Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'touchscreen', true, 'top') end Controls['amplifiers'].EventHandler = function() clear() Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'logo', false, 'fade') Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'amplifiers', true, '') end Controls['logo'].EventHandler = function() clear() Uci.SetLayerVisibility('Q-SYS', 'Page 1', 'logo', true, 'fade') end |
In this example, a UCI contains two pages with distinct graphics. Two shared layers – one for a Toggle Time control and another for a time display – are used on each page. When the Toggle Time button is pushed, the time display is therefore shown or hidden on both pages.
Note: For information about adding a date/time text box to your UCI, see Date/Time.
Defining controls
In this example, one control is defined (Category = Button; Push Action = Toggle). The button is configured in the visual Blocks editor to turn on/off the shared layer containing the time display.
Configuring the UCI
This simple UCI (named "MyUCI") contains two pages, each with a different QSC graphic. Two shared layers - one for the Toggle Time control ("ToggleTime") and the other for the time display ("Time") - are also included on each page. For information about creating shared layers, see Working with Layers.
Define the controller configuration
Use the Blocks editor (accessible via the Edit button) to define what happens when the Toggle Time button is pushed: Show or hide the Time shared layer across any page that includes that shared layer, and with a specified transition type. This example uses blocks from the Flow Control, Operators, System, and Controls categories.
Note: For information about the UCI Lua functions used behind the scenes in this example, see Uci.
Blocks | Script Equivalent |
---|---|
Controls['Toggle Time'].EventHandler = function() if Controls['Toggle Time'].Boolean == true then Uci.SetSharedLayerVisibility('MyUCI', 'Time', true, 'fade') elseif Controls['Toggle Time'].Boolean == false then Uci.SetSharedLayerVisibility('MyUCI', 'Time', false, 'fade') end end |
In this example, whenever the Start_Loop button is pushed, two "for loop" blocks start a countdown - one to 10, and one from 10.
Blocks | Script Equivalent |
---|---|
Controls['Start_Loop'].EventHandler = function() local output = '' for index = 1, 10, 1 do output = tostring(output) .. tostring((tostring('-') .. tostring(index))) end print('Count to 10') print(output) output = '' for index = 10, 1, -1 do output = tostring(output) .. tostring((tostring('-') .. tostring(index))) end print('Count from 10') print(output) end |
Debug Output
Count to 10 -1-2-3-4-5-6-7-8-9-10 Count from 10 -10-9-8-7-6-5-4-3-2-1
In this example, a trigger button control (MyControl) changes color depending on whether a condition is met.
Blocks | Script Equivalent |
---|---|
if 5 * 2 == 10 then Controls['MyControl']:Trigger() Controls['MyControl'].Color = '#33ff33' else Controls['MyControl']:Trigger() Controls['MyControl'].Color = '#ff0000' end |
When your design contains Named Controls, blocks for these controls become available in the block editor from a Named Controls drop-down menu:
In the following example, a timeline (after time) block is configured to trigger playback and set control values in a timed sequence for four named controls from an Audio Player component.
Note: For more information about timelines, see Creating a Timeline. For information about referencing named controls in Lua script, see NamedControl.
Blocks | Script Equivalent |
---|---|
Timer.CallAfter(function() NamedControl.Trigger('AudioPlayerPlay') print('Playback started') Timer.CallAfter(function() NamedControl.SetPosition('AudioPlayerGain', 0.75) print('Gain reduced') Timer.CallAfter(function() NamedControl.SetValue('AudioPlayerMute', 1) print('Playback muted') Timer.CallAfter(function() NamedControl.SetValue('AudioPlayerMute', 0) print('Playback unmuted') Timer.CallAfter(function() NamedControl.Trigger('AudioPlayerStop') print('Playback stopped') end,5) end,5) end,5) end,15) end,5) |
When your design contains Named Components, blocks for these components become available in the block editor from a Named Components drop-down menu:
In the following example, an Audio Player component has been renamed "MyPlayer". In this simple script, blocks from the Named Components drop-down menu for this named component are configured to enable looped playback whenever the Play button is pressed.
Note: For information about renaming components to create named components, see Labeling Schematic Elements. For information about named components in Lua script, see Component.
Blocks | Script Equivalent |
---|---|
namedComponent_MyPlayer = Component.New('MyPlayer') namedComponent_MyPlayer['play_state_trigger'].EventHandler = function(ctl) namedComponent_MyPlayer['loop'].Boolean = true end |
For further explanation of the Block Controller component, see the following videos:
- Q-SYS Training - Control 101
Learn the basic Q-SYS third party control principles, including Lua scripting basics.
- Q-SYS Training - Block Controller Part A
Learn about the Block Controller component through a navigational overview. In this lesson, you'll learn how to manipulate a simple button control using blocks.
- Q-SYS Training - Block Controller Part B
Learn about sections of the Block Controller, including control change, flow control, if statements, operators, boolean values, and converting blocks to lua script.