Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
blocks:tasks [2019-04-16 18:58]
admin created
blocks:tasks [2025-02-24 19:48] (current)
admin [Tasks and Expressions]
Line 33: Line 33:
 While the //Trigger// is the mere occurrence of the specified event (such as the time being 8:00 in the morning), the //Trigger Condition// can apply arbitrarily complex conditions on top of this event in order to decide whether to actually start the task. For instance, in the case of a time-of-day trigger, you can specify that it should only start the task if it's Saturday and a certain Block is playing on a particular Spot. While the //Trigger// is the mere occurrence of the specified event (such as the time being 8:00 in the morning), the //Trigger Condition// can apply arbitrarily complex conditions on top of this event in order to decide whether to actually start the task. For instance, in the case of a time-of-day trigger, you can specify that it should only start the task if it's Saturday and a certain Block is playing on a particular Spot.
  
-A //Trigger Condition// often uses the predefined variable named //trigger//, as in the example shown above. This variable is further described below under //Predefined Variables//. You can, however, use any variable or system property in the condition.+A //Trigger Condition// often uses the predefined variable named //trigger//, as in the example shown above. This variable is further described below under "Predefined Variables". You can, however, use any system property in the condition.
  
 ===== JavaScript Expressions ===== ===== JavaScript Expressions =====
Line 39: Line 39:
 Expressions in Blocks use JavaScript syntax. There are numerous excellent sources of information on this subject, such as this one: Expressions in Blocks use JavaScript syntax. There are numerous excellent sources of information on this subject, such as this one:
  
-https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operator+[[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators]]
  
 Here we'll only provide a brief overview of the syntax, enough to get you started with programming of Tasks in Blocks. Here we'll only provide a brief overview of the syntax, enough to get you started with programming of Tasks in Blocks.
Line 80: Line 80:
   * **""** (empty string)   * **""** (empty string)
  
-While this well known behaviors may be used as convenient shortcuts, it's often better to write an explicitly boolean expression, as it more clearly expresses your intention.+While this behavior may be used as convenient shortcut, it's often better to write an explicitly boolean expression, as it more clearly expresses your intention.
  
 ==== Optional Parameters ==== ==== Optional Parameters ====
  
-Task statements may need multiple parameters. The //do/ statement shown above accepts up to three parameters:+Task statements may need multiple parameters. The //gotoControlCue// statement accepts up to three parameters:
  
   - The name of the cue to go to (String).   - The name of the cue to go to (String).
   - Whether to search forward and then backwards, or backwards in time only (Boolean).   - Whether to search forward and then backwards, or backwards in time only (Boolean).
   - Which timeline to control (String).   - Which timeline to control (String).
 +
 +{{ :blocks:task:wogotocontrolcue.png?nolink |}}
  
 Of these three parameters, only the first two are required. An Optional parameter is indicated by a question mark following its name, and is also marked as //optional// in the description in the right hand corner. In this case, leaving out the timeline name will target the Main Timeline, as stated in the description. Of these three parameters, only the first two are required. An Optional parameter is indicated by a question mark following its name, and is also marked as //optional// in the description in the right hand corner. In this case, leaving out the timeline name will target the Main Timeline, as stated in the description.
Line 116: Line 118:
 === Relational Operators === === Relational Operators ===
  
-Another type of operators allow you to compare things, such as numbers. As hey evaluate the //relation// of two values to each other, they are often called //relational operators//. They all result in a boolean value. Examples of relational operators include:+Another type of operators allow you to compare things, such as numbers. As they evaluate the //relation// of two values to each other, they are often called //relational operators//. They all result in a boolean value. Examples of relational operators include:
  
-  * **<** for "left is less than right"+  * < for "left is less than right"
-  * **>** for "left is greater than right"+  * > for "left is greater than right"
-  * **==** for "left is equal to right"+  * == for "left is equal to right"
-  * **!=** for "left is not equal to right".+  * != for "left is not equal to right".
  
 For example, in the trigger condition of a task triggered by time of day, you can write: For example, in the trigger condition of a task triggered by time of day, you can write:
Line 129: Line 131:
 </code> </code>
  
-This uses the fact that the //trigger// variable (more on that below under Predefined Variables) of a task triggered by time of day is a Date object, which provides a getDay() method, returning the number of the weekday represented, where 0 is Sunday. Thus this task will run any day except Sunday. That is, the day number returned by the getDay() method is not equal to 0. Learn more about the date object here:+This uses the fact that the //trigger// variable (more on that below under "Predefined Variables") of a task triggered by time of day is a Date object, which provides a getDay() method, returning the number of the weekday represented, where 0 is Sunday. Thus this task will run any day except Sunday. That is, the day number returned by the getDay() method is not equal to 0. Learn more about the date object here:
  
 https://www.w3schools.com/jsref/jsref_obj_date.asp https://www.w3schools.com/jsref/jsref_obj_date.asp
Line 145: Line 147:
 Here are some common boolean operators: Here are some common boolean operators:
  
-  * **&&** for //and//. +  * && for //and//. 
-  * **||** for //or//. +  * || for //or//. 
-  * **!** for //not//.+  * ! for //not//.
  
 The && and || operators take two values (one on each side of the operator). Thus, if you want to run a task //only// on weekends, you could write a condition like this: The && and || operators take two values (one on each side of the operator). Thus, if you want to run a task //only// on weekends, you could write a condition like this:
Line 157: Line 159:
 Which reads "day is equal to 0 //or// day is equal to 6". Which reads "day is equal to 0 //or// day is equal to 6".
  
-The last of the three boolean operators shown above is known as a //unary operator//, since it takes only a single value, which follows after it, and inverts its boolean value. Thus, if the value that follows it is //false//, the result will be //true// and vice versa.+The //not// (exclamation point) operators shown above is known as a //unary operator// as it takes a single value (also called //operand//), which follows after the operator. The //not// operator inverts the boolean value of its single operand. Thus, if the value that follows it is //falsey//, the result will be //true// and vice versa.
  
 For instance, assume you want to trigger a task only if an contact closure input is //not// activated, then you could write a condition like this For instance, assume you want to trigger a task only if an contact closure input is //not// activated, then you could write a condition like this
Line 202: Line 204:
 ===== Variables ===== ===== Variables =====
  
-The true power of expressions come from the use of variables. A variable essentially names a "mailbox" in which a value is stored. When you reference the name of that "mailbox", what you get is the value in it. In Blocks, you can use pretty much any state in the entire system as such a value source. For instance, if you have a contact closure input connected through a Modbus box, the state of that input can referenced. +The true power of expressions comes from the use of variables. A variable essentially names a "mailbox" in which a value is stored. When you reference the name of that "mailbox", what you get is the value in it. In Blocks, you can use pretty much any state in the entire system as such a value source. For instance, if you have a contact closure input connected through a Modbus box, the state of that input can referenced. 
  
 As an example, to trigger a task only if a certain input signal is present, simply refer to the value of that input in the trigger condition: As an example, to trigger a task only if a certain input signal is present, simply refer to the value of that input in the trigger condition:
Line 222: Line 224:
 ==== Predefined Variables ==== ==== Predefined Variables ====
  
-In addition to all system properties of you Blocks system, you also have access to the following predefined variables in tasks and their trigger condition field:+In addition to all system properties of your Blocks system, you also have access to the following predefined variables in tasks and their trigger condition field:
  
   * **trigger** contains the value of whatever triggered the task.   * **trigger** contains the value of whatever triggered the task.
Line 230: Line 232:
  
   * If the triggering mode is “Time of Day”; it's a JavaScript Date object.   * If the triggering mode is “Time of Day”; it's a JavaScript Date object.
-  * If the triggering mode is “Property Change” it's a number, boolean or string containing the property’s new value.+  * For “Property Change” it's a number, booleanstring or other object indicating the property’s new state. 
 +  * For "Server Startup", the value of //trigger// is undefined.
  
 If no trigger is assigned to the task, the value of //trigger// is undefined, and should not be used. Note that //trigger// will contain the current value of the tasks trigger even if the task was started by other means, such as manually clicking the //play// arrow next to the task's name, or by setting the task's //running// property to true. If no trigger is assigned to the task, the value of //trigger// is undefined, and should not be used. Note that //trigger// will contain the current value of the tasks trigger even if the task was started by other means, such as manually clicking the //play// arrow next to the task's name, or by setting the task's //running// property to true.
Line 236: Line 239:
 ==== Realm Variables ==== ==== Realm Variables ====
  
-You can add externally visible variables to a Realm. When doing o, you specify the data type used by that variable (number, boolean or string). Such a variable can be set frmo the outside, for example using a button on a panel, or by another task (using a //set realm variable// statement).+You can add externally visible variables to a Realm. When doing so, you specify the data type used by that variable (number, boolean or string). Such a variable can be set frmo the outside, for example using a button on a panel, or by another task (using a //set realm variable// statement).
  
 The value of such a realm variable can be used as a trigger, just like any other system property. You can also directly reference the value of a realm variable in any task within the same realm using the name of the variable followed by a period and the work //value//. Assuming you have a realm variable named //Brightness//, you can use its value in an expression like this: The value of such a realm variable can be used as a trigger, just like any other system property. You can also directly reference the value of a realm variable in any task within the same realm using the name of the variable followed by a period and the work //value//. Assuming you have a realm variable named //Brightness//, you can use its value in an expression like this:
Line 246: Line 249:
 ==== Local Variables ==== ==== Local Variables ====
  
-A local variable is often useful to hold intermediate results, or other values you want to use multiple times in a task. For example, to create a simple lighting chaser effect, you can use a //while// loop with the sequence of statements needed to control the lights, interspersed with /7wait// statements to control the speed of the effect. If you're unsure of what speed will work best, you can assign the value to a local variable called //speed//, and then use that variable in the wait statements:+A local variable is often useful to hold intermediate results, or other values you want to use multiple times in a task. For example, to create a simple lighting chaser effect, you can use a //while// loop with the sequence of statements needed to control the lights, interspersed with //wait// statements to control the speed of the effect. If you're unsure of what speed will work best, you can assign the value to a local variable called //speed//, and then use that variable in the wait statements:
  
 {{ :blocks:task:localvar.png?nolink |}} {{ :blocks:task:localvar.png?nolink |}}
Line 257: Line 260:
 ==== Property References ==== ==== Property References ====
  
-As seen in some of the example above, you can set the value of any property in your Blocks system using a //do// statement. You can pick the target of the //do// statement using the dropdown menus to the right. Alternatively, if you know the full path to the desired property, you can type this into the //do// statement's target field.+As seen in some of the examples above, you can set the value of any property in your Blocks system using a //do// statement. You can pick the target of the //do// statement using the dropdown menus to the right. Alternatively, if you know the full path to the desired property, you can type this into the //do// statement's target field.
  
-Some properties are //read only//. An example of such a read only property is the //connected// state of a Display Spot. There's nothing you can do from within Blocks to force a Spot to connect. Thus, this property can only be read, not set. Read only properties are shown in //italics// on dropdown menus. They can not be used as the target property of a //do//statement. They can, however, be used in expressions and task triggers.+Some properties are //read only//. An example of such a read only property is the //connected// state of a Display Spot. There's nothing you can do from within Blocks to force a Spot to connect. Thus, this property can only be read, not set. Read only properties are shown in //italics// on dropdown menus. They can not be used as the target property of a //do// statement. They can, however, be used in expressions and task triggers.
  
 The value of a system property can also be directly used in expressions. Since such an expression typically consists of more than just a single property reference, you need to enter the full path to the property manually here.  The value of a system property can also be directly used in expressions. Since such an expression typically consists of more than just a single property reference, you need to enter the full path to the property manually here. 
Line 289: Line 292:
 </code> </code>
  
-The expression inside the brackets performa string concatenation, so that if the /7channel// realm variable contains 2, the resulting string will be "c2", thus controlling the channel with that name.+The expression inside the brackets performa string concatenation, so that if the //channel// realm variable contains 2, the resulting string will be "c2", thus controlling the channel with that name.