Scenes allow automated actions to be conditionally processed when status change reports are received from sensors or on a pre-defined timer basis. Scenes can also be triggered manually to provide assistance in complex or multiple step processes e.g. turn on power to the TV, switch the TV on and dim the lights. Scene logic can be "Magic (simple)", "Graphic Block" or "Lua".
Lua as a full programming language enables complex conditional processing based on input from and interrogation of multiple sensors e.g. if first the garden sensor and then within 10 seconds the backdoor sensor are breached someone has just entered the house via the backdoor. This ability provides for better automation, in this example we have both direction (into the house) and we have a sensor double check (in case insects are triggering the garden sensor again!).
A Lua scene identifies to the Fibaro API exactly which triggers should cause it to be run using a %% trigger_name statement and if necessary on the following lines parameters (filters) for the trigger, all within Lua multi-line comments (--[[ and --]]), see the examples below.
--[[
%% autostart
%% globals
TimeOfDay
--]]
--[[
%% properties
39 power
--]]
Trigger names can be:
Use the buttons to the right for expanded descriptions of these statements.
Note that a scene will be invoked on each occaision that the trigger criteria are met. A wall plug for example may trigger a power dependent scene multiple times as an attached device is switched on and reaches normal operating power usage. You define how many concurrent copies of the scene may run, when this number is exceeded you will receive the too many instances error message. Testing is normally required to ensure that the trigger condition desired is the one being processed e.g.
if ( power < 100) then fibaro:abort(); end;
Will exit a scene if it was entered at some intermediate power usage level during device power up. The scene drops through the condition if it has been triggered for a power above 100W when presumably the attached device has completed power up. The number of times the scene is triggered will be dependent on the number of z-wave reports from the wall-plug and this number can be affected through the advanced wall-plug parameters in the device configuration.
if ( fibaro:countScenes() > 1) then fibaro:abort(); end; fibaro:sleep(10000);
If the above scene were long running e.g. it sleeps for some seconds, then we can check for concurrent trigger processing due to triggers at say 120W and again at 200W as shown in the example to the left.
A scene may be in one of three basic states as detailed by the "run scene" dropdown list on the scene detail panel, "General" tab, these are:
Run Scene | Description |
---|---|
Automatic | Scene is enabled to run when either the scene's defined trigger conditions have been met or when manually started via the play button (start in scene's advanced panel). |
Manual | Scene is enabled to run when manually started via the play button (start in scene's advanced panel). |
Disabled | Scene is disabled, it will not run when its trigger conditions are met nor when the play button is used. |
A scene's state can also be determined directly from the scenes panel. The examples below show both the "run scene" state, from the scene detail "General" tab and the equivalent SceneRunConfig value as used by setSceneRunConfig() and returned by getSceneRunConfig() functions.
Unlike with block scenes there is no option for a Lua scene to be scheduled at a particular time. To execute commands at a particular time a scene must be coded to start when the home center starts, using the %% autostart directive. The scene must then sleep until the desired time to execute the command is reached.
The example below illustrates how commands can be issued at a fixed time of day.
--[[
%% autostart
--]]
local runDailyAt = "18:00";
function waitUntilTime( runTime)
local sTime, rDay;
local rTime = tonumber(string.sub(runTime,1,2))*60*60
+ tonumber(string.sub(runTime,4)*60);
local dtab = os.date("*t");
local cTime = tonumber(dtab["hour"])*60*60
+ tonumber(dtab["min"]*60)
+ tonumber(dtab["sec"]);
if ( cTime < rTime) then
sTime = rTime-cTime;
rDay = "Today";
else
sTime = 24*60*60 - (cTime-rTime);
rDay = "Tomorrow";
end;
fibaro:debug("Sleeping until "..runTime.." "..rDay);
fibaro:sleep (sTime * 1000);
fibaro:debug( "Sleep finished");
end;
-- Mainline
while true do -- loop forever
waitUntilTime( runDailyAt);
fibaro:debug("Command executed"); -- commands go here
end;
Notes
Function | Description | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
fibaro:getSourceTrigger(); | Returns a table identifying the resource associated with the scene trigger. Values returned are as follows:
| |||||||||||||||
fibaro:getSourceTriggerType() | Returns only the type value (as listed above). May be used when
trigger has no associated parameters or when only a single
device or variable may trigger the scene, the device or variable name then being implicit to the trigger. Example: |
|||||||||||||||
fibaro:abort() | Terminates current scene processing. | |||||||||||||||
fibaro:countScenes() | Returns the number of copies of this scene that are active, including the current scene. Multiple simultaneous copies of a scene run when the scene takes longer to complete than the time between trigger events. | |||||||||||||||
fibaro:sleep( milli-seconds ); | Suspends the scene for the number of milli-seconds specified. |
In the following code snippet we test for being triggered due to a power change on the TV wall socket with id 77. In this case we record the actual power consumption in variable tvPower.
--[[
%% properties
77 power
--]]
local idTV = 77;
local tvPower;
local trigger = fibaro:getSourceTrigger();
if (( trigger['type'] == "property")
and ( trigger['deviceID'] == idTV )) then
tvPower = tonumber(fibaro:getValue( idTV, "power"));
end;
Note:
Now the more simple case when we only need to know why the scene was invoked. In this case, presumably, we have completed some initialization and will now exit if we were triggered by the home center booting.
if ( getSourceTriggerType() == "autostart") then fibaro:abort(); end;
Function | Description |
---|---|
fibaro:countScenes( sceneID ) | Returns the number of running copies of the specified scene. Multiple simultaneous copies of a scene run when the scene takes longer to complete than the time between trigger events. |
fibaro:startScene( sceneID < ,{ table } > ) | Starts the specified scene optionally passing parameters in a table (see Calling a Scene below for details). It is often useful to record the required sceneID in a global variable say myTestSceneID and then use the function fibaro:startScene( fibaro:getGlobalValue( 'myTestSceneID')); |
fibaro:killScenes( sceneID ) | Kills, terminates all running instances of the specified scene. |
fibaro:setSceneEnabled( sceneID, [ true | false ] ) | This binary scene switch seems unneccessary, being replaced with the tri-state switch setSceneRunConfig() that carries out granular function in the enabled state. setSceneEnabled enables or disables the specified scene. See scene states above. |
fibaro:isSceneEnabled( sceneID ) | Returns true if the specified scene is enabled, otherwise false. |
fibaro:setSceneRunConfig( sceneID, [ 'TRIGGER_AND_MANUAL' | 'MANUAL_ONLY' | 'DISABLED' ] ) | Sets whether the scene can be triggered, run on request or cannot run at all. This is equivalent to the "Run Scene" parameter on the Scene's General tab with options Automatic, Manual or Disabled. See scene states above. |
fibaro:getSceneRunConfig( sceneID ) | Returns a string containing one of the setRunConfig() parameter options. |
Using the fibaro:startScene() function it is possible to call another scene, this function will also work from a virtual device. The code snippet below illustrates how to use the startScene() function and pass data parameters across to the other scene.
fibaro:startScene(71, {"Charlie","Chaplin"});
Above is the call to scene 71 with a table containing two parameters for use by the scene. Note: the scene id is available on the general tab of the target scene.
--[[ --]] if (fibaro:args()) then local nameFirst, nameLast = fibaro:args()[1], fibaro:args()[2]; fibaro:debug("Welcome "..nameFirst.." "..nameLast); fibaro:debug( string.format("Welcome %s %s", nameFirst, nameLast)); end;
The called scene first checks for a passed table and then uses the supplied parameters. Note the two fibaro:debug functions write the exact same message to the log. The string.format() function will be familiar to C programmers (think printf) and this option is less overhead compared to concatenating the variables one at a time.
A list of scenes to be called is held in lua table subScenes. This example allows us to use the ON/OFF slidebar on the scenes panel to decide whether a particular scene should be run. This saves going to the scene detail and changing the "run scene" state to 'Disabled' i.e. we are treating 'TRIGGER_AND_MANUAL' state as enabled and 'MANUAL_ONLY' as a pseudo disabled.
--[[
--]]
local subScenes = { 38, 39, 41};
for i, sceneId in pairs (subScenes) do
if ( fibaro:getSceneRunConfig(sceneId) == 'TRIGGER_AND_MANUAL') then
fibaro:startScene(sceneID);
fibaro:debug( 'Scene '..sceneId..' scheduled');
end;
end;
Questions or comments, please e-mail us at info@snys.nl