Skip to main content

 

 

 

 

Electronic Theatre Controls Inc

Creating Syrcadia Function Blocks

This document describes how to use, modify or create your own Syrcadia Function blocks in ver 2.2 and above.

What are Syrcadia Function Blocks

Syrcadia function blocks are really scripts running in the background that can be easily configured by an definable User Interface dialog, embedded in Syrcadia.
These function blocks can be used to e.g. read sensors, make decisions on that data and control equipment based on the data received.

Static configuration parameters for these scripts can be entered by a normal user.
Dynamic input parameters can be received from settings in a day plan (set-points).
This data can be combined with data coming from other input sources such as sensors.
The function blocks can control items defined in devices.

More advanced scripting methodology allows to listen to data and send out control parameters to 3rd party equipment on the network or even in the cloud (e.g. 3rd party sensors, weather-report, 3rd party output devices).

The scripting technology (Python) provides a very powerful tool to extend and modify the functionality of the control system for e.g. highly custom features without needing to request a specific feature and waiting for it to make it into a released core code of Syrcadia.

The "API" or main communication methodology for data and control in and out of Syrcadia happens via the MQTT protocol, but a provided Syrcadia library handles the communication and subscription and encoding to this type of data.

How do I use an existing Function Block?

In Syrcadia go to setup/Function Block/ add a script template. It will ask you to name the Function Block, do not use Spaces use underscores.

once the script is saved. This puts it in the working file of the configuration and is saved with the configuration.  user/   /RAYN/  Configuration name/Scrips

Click on the edit pencil on the right.  This is were you will enter the user Data for the Function Block. common information is Zone names, set-points, Output device, ETC.

Then you can tap the start button next to name. If it turns Green then its running.  Red then there is an error. check the scrip log file.

What do I need to make my own?

in order to develop your own function blocks, you need a few items to get started

  • knowledge of the Python programming language
  • knowledge of MQTT is a bonus, especially if connection to 3rd party gear is required
  • A Rayn Touch controller or PC with a Syrcadia Dongle, running Syrcadia Software
  • A PC, MAC or Linux computer for development (can be the same as the PC running Syrcadia)
  • Python installed on the computer
  • PyCharm, Python Integrated Development Environment (IDE), download here: https://www.jetbrains.com/pycharm/download/

 

Where do I start?

The best place to start is to use an existing function block that is close to what your are trying to do and start to modify it.

Syradia Function Blocks consist of two files, a UI configuration  file  and a the script  itself.

How do I create/configure a Syrcadia function block configuration user interface?

The Function block configuration user interface allow a user to simply configure the parameters of the function block.

A user interface can look like this:

clipboard_e7866ff1fd71009aaf73e29cc282ab5c7.png

This UI is configured by a corresponding JSON file:

[
    {
        "displayName": "Zone",
        "hint": "<i>The zone name in the controller</i>",
        "type": "zone",
        "value": ""
    },
    {
        "displayName": "Sensor",
        "hint": "<i>The name of the sensor we are listening to</i>",
        "type": "sensor",
        "value": ""
    },
    {
        "displayName": "Setpoint",
        "hint": "<i>The name of the setpoint we are listening to</i>",
        "type": "input",
        "value": ""
    },
    {
        "displayName": "Upper deadband",
        "hint": "<i>The inactive range above the setpoint</i>",
        "type": "integer",
        "value": "0"
    },
    {
        "displayName": "Lower deadband",
        "hint": "<i>The inactive range below the setpoint</i>",
        "type": "integer",
        "value": "0"
    },
    {
        "displayName": "Lower Than Output",
        "hint": "<i>The name of the output going active, once the measured value is lower than the setpoint</i>",
        "type": "output",
        "value": ""
    },
    {
        "displayName": "Higher Than Output",
        "hint": "<i>The name of the output going active, once the measured value is higher than the setpoint</i>",
        "type": "output",
        "value": ""
    },
    {
        "displayName": "MQTT Broker",
        "hint": "<i>The IP address to the MQTT Broker</i>",
        "type": "ip",
        "value": "localhost"
    },
    {
        "displayName": "Controller",
        "hint": "<i>The name of the Syrcadia controller</i>",
        "type": "controller",
        "value": ""
    },
    {
        "displayName": "Version",
        "hint": "<i>1.0.5.3</i>",
        "type": "string",
        "value": "1.0.5.3"
    }
]
 

Description:

The "displayName" is the value used in the script itself to pull in the respective value entered by the user.

"hint" is a string that provides some guidance to the user about what this setting is

"type" is the data type of the value, supported types are:

  • Integer
  • String
  • IP (4 Bytes IP address or e.g. localhost)
  • zone (the name of the zone where the data is coming from, this will be converted by the Syrcadia library into a respective UUID)
  • sensor (the name of the sensor in that zone where the data is coming from, this will be converted by the Syrcadia library into a respective UUID)
  • input (the name of a setpoint input, coming from the day-plan in Syrcadia)
  • controller (the name of the controller the script should listen to, this will be converted by the Syrcadia library into a respective UUID)
  • output (the name of the output unit, defined in "devices", this will be converted by the Syrcadia library into a respective UUID)

"value" is a sensible default value presented to the user and will eventually contain the data entered by the user.

 

This configuration file needs to be stored under "my-awesome-function-block-name.config"

Note: Both the .config file .py need to be named the same way.

 

Creating the Function Block script

This file now is responsible for doing the actual "hard work" and processing.

The script is written in Python and requires a number of blocks to function correctly:

Example

import syrcadia

flush = True

sensorValue = None
targetValue = None

# Define callbacks
def onSensorChanged(controllerName, zoneName, parameter, value):
    if controllerName == controller and zoneName == zone:
        print("onSensorChanged: " + controllerName + " " + zoneName + " " + parameter + " " + str(f"{value:.0f}"))
        if parameter == sensor:
            global sensorValue
            sensorValue = value
            print("New sensor value: " + str(f"{sensorValue:.0f}"))
        
def onTargetChanged(controllerName, zoneName, parameter, value):
    if controllerName == controller and zoneName == zone:
        print("onTargetChanged: " + controllerName + " " + zoneName + " " + parameter + " " + str(f"{value:.0f}"))
        if parameter == setpoint:
            global targetValue
            targetValue = value
            print("New target value: " + str(f"{targetValue:.0f}"))
    
def onTick():
    # print("Tick")
    global sensorValue
    global targetValue
    global invertOutput

    if sensorValue != None and targetValue != None:
            if sensorValue > targetValue + upperDeadband:
                syrcadia.setOutputValue(controller, zone, htoutput, "on")
                syrcadia.setOutputValue(controller, zone, ltoutput, "off")
                print("Status: Higher Than")
            elif sensorValue < targetValue - lowerDeadband:
                syrcadia.setOutputValue(controller, zone, htoutput, "off")
                syrcadia.setOutputValue(controller, zone, ltoutput, "on")
                print("Status: Lower Than")

        # TODO Handle invert setting

# Read settings from .config file
settings = syrcadia.settings(__file__)

# Set-up local variables for all settiings
ip = syrcadia.settingValue(settings, "MQTT Broker")
controller = syrcadia.settingValue(settings, "Controller")
zone = syrcadia.settingValue(settings, "Zone")
setpoint = syrcadia.settingValue(settings, "Setpoint")
upperDeadband = float(syrcadia.settingValue(settings, "Upper deadband"))
lowerDeadband = float(syrcadia.settingValue(settings, "Lower deadband"))
sensor = syrcadia.settingValue(settings, "Sensor")
# invertOutput = syrcadia.settingValue(settings, "Invert output")
ltoutput = syrcadia.settingValue(settings, "Lower Than Output")
htoutput = syrcadia.settingValue(settings, "Higher Than Output")

print("Controller: " + controller)
print("Zone: " + zone)

# Set callbacks for sensor and target changes
syrcadia.setSensorCallback(onSensorChanged)
syrcadia.setTargetCallback(onTargetChanged)

# Main script
print("Starting Python switch script...")

# Start Mqtt handler
syrcadia.initMqtt(ip, 1883)

# Define tick callback
syrcadia.setTickCallback(onTick)

# Start execution
syrcadia.execute(5)
 

This script needs to be stored under "my-awesome-function-block-name.py", together with the .config file.

 

The script is structured in several sections / building blocks:

The first thing to do is to include the Syrcadia library [ import syrcadia ]. This Library will take care of mapping human readable sensor and zone names into low-level UUID references and will take care of delivering the right values from the correct sources back to the script.
It also triggers callbacks to the script if certain values have changed.

The onTargetChanged and onSensorChanged functions allow to extract the right and target sensor data and store them in local variables.

the onTick function is where the entire processing of data happens and where output data is created.
this function is called every number of seconds defined in the syrcadia.execute(5) call.

The section following the settings = syrcadia.settings(__file__) takes care of reading the user configuration and translating those values into local variables.
It is important that the names here match the displayName in the config file.

 

 

Happy scripting !

Related Links/References 

Current Default Function blocks:

Switch.py

Watches a setpoint that is set to a level in Day Plan from a sensor. When above and below + deadband the output state changes.

Setpoint defined in Setting/setpoints. The rest if the setting are in the Function block settings under pencil.

Invert Off (default)  If sensorValue is > targetvalue + upperdeadband  then output is "off"

                             If sensorValue is < targetvalue - lowerdeadband  then output is "on"

Invert On: If sensorValue is > targetvalue + upperdeadband  then output is "on"

                If sensorValue is < targetvalue - lowerdeadband  then output is "off"

  • Was this article helpful?