Welcome to Smart Home Forum by FIBARO
Dear Guest,
as you can notice parts of Smart Home Forum by FIBARO is not available for you. You have to register in order to view all content and post in our community. Don't worry! Registration is a simple free process that requires minimal information for you to sign up. Become a part of of Smart Home Forum by FIBARO by creating an account.
As a member you can:
- Start new topics and reply to others
- Follow topics and users to get email updates
- Get your own profile page and make new friends
- Send personal messages
- ... and learn a lot about our system!
Regards,
Smart Home Forum by FIBARO Team
Question
Ace02 2
Hi,
I'm using the SmartLight code from Stevenvd, but I need to have an additional motionsensor added to the code (My livingroom is too big for only one motion sensor)..
I'm still pretty novice with regards to LUA and the things I have tried didn't work..
Could anybody please help me to add another motionsensor to the below code:
--[[
%% properties
69 value
71 value
%% globals
TimeOfDay
--]]
--[[ Change - XXX value - above. One for motion sensor, one for Light sensor.
TimeOfDay global variable and lux make sure that the scene
will be triggered when you are already in the room and something changes.
Set your settings below, lights and add extra functions
This code is developed by Control Living. You can use this free of charge.
Feel free to suggest changes or contact when having problems.
Version 1.4.3
--]]
--------------------------------------------------------------------
-----------------------YOUR LIGHT SETTINGS--------------------------
--TODO: make possible for multiple motion sensors in one room
motionSensorID = 69; -- change id for your motion sensor.
LuxSensorID = 71; -- change id for your light sensor.
AutoLightsVdId = 555; -- The virtual device ID for the automatic lights timer.
--Enter the name of your Global variable. WITHOUT IT, THE SCENE DOES NOT WORK. Capital sensitive!
sleepState = "SleepState"; --Sleep globalstate variable.
timeOfDay = "TimeOfDay"; --Time of Day Global variable.
presentState = "PresentState"; --Present state Global variable.
--Enter the values of your global variables stated above. If not using, copy the name in front of the "YourValueName"
sleepStateMapping = {Sleeping="Sleeping", Awake="Awake"};
timeOfDayMapping = {Morning="Morning", Day="Day", Evening="Evening", Night="Night"};
presentStateMapping = {Home="Home", Away="Away", Holiday="Holiday"};
-- Set the lux value for which the lights have to be turned on.
-- If you don't want to use the MinLux then just set it to: 65535
minLuxMorning = 20;
minLuxDay = 20;
minLuxEvening = 20;
minLuxNight = 20;
--[[
Now the most important part:
Here you can enter what light, for how long and at what value has to be turned on.
Leave empty brackets for no lights.
To set the light value without timer use 2 parameters: {LightID, "VALUE"}
To set the light value with timer use 3 parameters: {LightID, "VALUE", timeInSeconds }
To set the light value with the
automatic lights virtual device. use 4 parameters: {LightID, "VALUE", "timeInSeconds", VirtualDeviceSliderID} --]]
lightsSleeping = {}; --lights that are triggered when Sleepstate is sleeping.
lightsMorning = {{11, "30", 600}};
lightsDay = {{7, "99", 300},{11, "99", 300}};
lightsEvening = {{7, "99", 900},{11, "90", 900}};
lightsNight = {};
--Manual Override, the time that lights will not be turned ON again after manually turning them off.
OverrideFor = 30;
--------------------------------------------------------------------
-------------------------EXTRA FEATURES-----------------------------
extraMorningFunc = function()
-- Add your extra code here. If you want some checks or maybe run a virtual device button.
--This code is always triggered if there is motion.
-- movieLights = {{180, "10"},{181, "10"} };
--if (xbmc == "playing" ) then CallLightArray(movieLights);
ExtraDebug("Extra morning function called");
end
extraDayFunc = function()
-- Add your extra code here. If you want some checks or maybe run a virtual device button.
--This code is always triggered if there is motion.
ExtraDebug("Extra day function called");
end
extraEveningFunc = function()
-- Add your extra code here. If you want some checks or maybe run a virtual device button.
--This code is always triggered if there is motion.
ExtraDebug("Extra evening function called");
end
extraNightFunc = function()
-- Add your extra code here. If you want some checks or maybe run a virtual device button.
--This code is always triggered if there is motion.
ExtraDebug("Extra night function called");
end
extraLightTriggerChecks = function()
--add extra checks here. and return the total true or false value.
--if returning false the lights will not be triggered.
-- for instance: return ( (pcTurnedOff == true ) and (xbmc ~= "Empty") );
return ( true );
end
--------------------------------------------------------------------
----------------------ADVANCES SETTINGS-----------------------------
local showStandardDebugInfo = true; -- Debug shown in white
local showExtraDebugInfo = true; -- Debug shown in orange
--------------------------------------------------------------------
--------------------------------------------------------------------
-- DO NOT CHANGE THE CODE BELOW --
--------------------------------------------------------------------
--UPDATE FROM HERE
local startSource = fibaro:getSourceTrigger();
local motionSensorStatus = tonumber(fibaro:getValue(motionSensorID, "value"));
local motionSensorArmed = tonumber(fibaro:getValue(motionSensorID, "armed"));
local lux = tonumber(fibaro:getValue(LuxSensorID, "value"));
local keepLightsOn = false;
local timerRunning = false;
version = "1.4.4";
SavedState = {
homeStatus = "",
timeOfDay = "",
lux = 0,
motion = 0,
startTime = 0,
sleepState = 0
}
Debug = function ( color, message )
fibaro:debug(string.format('<%s style="color:%s;">%s%s>', "span", color, message, "span"));
end
--Making sure that only one instance of the scene is running.
fibaro:sleep(50); --sleep to prevent all instances being killed.
if (fibaro:countScenes() > 1) then
if (showExtraDebugInfo) then
Debug( "grey", "Abort, Scene count = " .. fibaro:countScenes());
end
fibaro:abort();
end
--------------------------EXECUTION----------------------------------
SetCurrentStatus = function ()
ExtraDebug("Saving current variable statusses");
SavedState.homeStatus = GetPresentState();
SavedState.timeOfDay = GetTimeOfDay();
SavedState.sleepState = GetSleepState();
SavedState.lux = tonumber(fibaro:getValue(LuxSensorID, "value"));
SavedState.motion = tonumber(fibaro:getValue(motionSensorID, "value"));
end
CheckStatusChanges = function ()
ExtraDebug("Status change check");
if (GetPresentState() ~= SavedState.homeStatus ) or (GetTimeOfDay() ~= SavedState.timeOfDay ) then
SceneTriggered();
end
SetCurrentStatus();
-- we still have a motion so reset timer.
if (SavedState.motion ~= 0 ) then
ExtraDebug( "Resetting time" );
SavedState.startTime = os.time();
end
--any other case, we are not resetting the timer.
end
ManualOverRideCheck = function ( lightArray )
ExtraDebug("Manual override check");
for i = 1, #lightArray do
if ( #lightArray == 3) then
tmpId = lightArray[1];
if (tonumber(fibaro:getValue(tmpId, "value")) == 0 and lightArray["OffMode"] ~= "ByScene" ) then
ExtraDebug( "Manual override for light: " .. tmpId .. "active" );
lightArray["OffMode"] = "ManualOverride";
end
end
end
end
LightsOff = function ( lightArray )
local stillLightsOn = 0;
for i = 1,#lightArray do
if ( #lightArray == 3) then
tmpId = lightArray[1];
--On till:
timeL = SavedState.startTime + (lightArray[3]);
currentTime = os.time();
timeLeft = timeL - currentTime;
ExtraDebug("TimeLeft: " .. timeLeft .. " seconds" );
if ( timeLeft <= 0 ) then
fibaro:call(tmpId, "turnOff");
if ( lightArray["OffMode"] ~= "ManualOverride" ) then
lightArray["OffMode"] = "ByScene";
end
ExtraDebug("Switch off light: " .. tmpId);
elseif (tonumber(fibaro:getValue(tmpId, "value")) == 0 ) then
if ( lightArray["OffMode"] == "ManualOverride" ) then
ExtraDebug("Manual override for light: " .. tmpId .. "active, not turning on");
else
ExtraDebug("Turn light: " .. tmpId .. " back on");
fibaro:call(tmpId, "setValue", lightArray[2] );
end
else
lightArray["OffMode"] = "NoOverride";
stillLightsOn = stillLightsOn + 1;
end
end
end
return stillLightsOn;
end
KeepLightsOn = function ()
ExtraDebug("starting with while loop, to keep lights on");
SavedState.startTime = os.time();
SetCurrentStatus();
while ( keepLightsOn ) do
currentLightArray = GetTimeOfDayLightArray();
ManualOverRideCheck( currentLightArray );
CheckStatusChanges();
local stillLightsOn = 0;
stillLightsOn = LightsOff( currentLightArray );
if (stillLightsOn == 0 ) then
keepLightsOn = false;
RunManualOverrideMode( currentLightArray );
end
fibaro:sleep(1000);
ExtraDebug("--------------- next timer run ---------------");
end
end
RunManualOverrideMode = function ( currentLightArray )
ExtraDebug("-----------------Override Mode-------------");
OverrideForAll = 0;
for i = 1,#currentLightArray do
if ( currentLightArray["OffMode"] == "ManualOverride" ) then
OverrideForAll = OverrideForAll +1;
end
end
if ( OverrideForAll ~= 0 and OverrideForAll == #currentLightArray ) then
OverrideTimer = os.time();
while ( (OverrideTimer + OverrideFor ) - os.time() > 0 ) do
ExtraDebug("Still in override for: " .. (OverrideTimer + OverrideFor ) - os.time() .. " seconds" );
fibaro:sleep(1000);
end
end
end
----------------------Turn lights on functions------------------------
CallLightArray = function( lightArray )
debugVariable = "Lights: " .. GetTimeOfDay();
if (#lightArray == 0 ) then
debugVariable = "No lights set for " .. GetTimeOfDay();
return;
end
-- StandardDebug(type(lightArray));
-- if type(lightArray) ~= "table" then
-- ErrorDebug("Missing brackets for: lights" .. GetTimeOfDay() .. ", place extra brackts: { } around.");
-- else
for i = 1,#lightArray do
tmpId = lightArray[1];
tmpValue = lightArray[2];
--TODO: check if values not nill
if ( #lightArray == 2 ) then
fibaro:call(tmpId, "setValue", tmpValue);
StandardDebug( "Set id: " .. tmpId .. " to Value: " .. tmpValue );
elseif ( #lightArray == 3 ) then
fibaro:call(tmpId, "setValue", tmpValue);
StandardDebug( "Set id: " .. tmpId .. " to Value: " .. tmpValue );
keepLightsOn = true;
elseif ( #lightArray == 4 ) then
tmpVdTime = lightArray[3];
tmpBtnId = lightArray[4];
--TODO: set light value first. then time slider.
--check if off... else just set time.
fibaro:call(tmpId, "setValue", tmpValue);
fibaro:sleep(300);
fibaro:call(AutoLightsVdId, "setSlider", tmpBtnId, tmpVdTime );
StandardDebug( "Set id: " .. tmpId .. " to Value: " .. tmpValue .. " for: " .. tmpVdTime .. " sec." );
end
-- end
end
if ( keepLightsOn and not timerRunning ) then
ExtraDebug("Starting timer, not yet running");
timerRunning = true;
KeepLightsOn();
else
ExtraDebug("Timer already running, returning");
end
end
LightperDayPart = function( minLux, lightArray )
if ( (GetPresentState() == presentStateMapping.Home ) and
(extraLightTriggerChecks() ) ) then
-- add check for current light state. (because of changed lux value)
-- if lights on and use of virtual device. then extend time. else nothing.
if ( lux > minLux ) then
StandardDebug( "Sensor lux: " .. lux .. " higher then minValue: " .. minLux .. " : no action");
else
StandardDebug("Sensor lux: " .. lux .. " is lower then minValue: " .. minLux);
CallLightArray( lightArray );
end
else
ExtraDebug("ExtraLightTriggerChecks or PresentState is false, so not lights");
end
end
SceneTriggered = function()
debugVariable = "No lights: " .. GetTimeOfDay();
if ( GetSleepState() == sleepStateMapping.Sleeping ) then
LightperDayPart( 65535, lightsSleeping );
elseif ( GetTimeOfDay() == timeOfDayMapping.Morning ) then
extraMorningFunc();
LightperDayPart( minLuxMorning, lightsMorning );
elseif ( GetTimeOfDay() == timeOfDayMapping.Day ) then
extraDayFunc();
LightperDayPart( minLuxDay, lightsDay );
elseif ( GetTimeOfDay() == timeOfDayMapping.Evening ) then
extraEveningFunc();
LightperDayPart( minLuxEvening, lightsEvening );
elseif ( GetTimeOfDay() == timeOfDayMapping.Night ) then
extraNightFunc();
LightperDayPart( minLuxNight, lightsNight );
end
StandardDebug(debugVariable);
end
------------------------STATUS functions------------------------------
GetTimeOfDay = function ()
return LookupGlobal( timeOfDay, "TimeOfDay", "Day");
end
GetSleepState = function ()
return LookupGlobal( sleepState, "sleepState", "Awake");
end
GetPresentState = function ()
return LookupGlobal( presentState, "presentState", "Home");
end
LookupGlobal = function ( name, stateName, default )
local ps = fibaro:getGlobalValue( name );
if ( (ps ~= "") and (ps ~= nil ) ) then
ExtraDebug("returned " .. stateName .. ": " .. ps );
return ps;
else
ErrorDebug( stateName .. " variable not found");
return default;
end
end
lightsStatus = function ( id )
--check if lights are already on.
allLights = {lightsSleeping, lightsMorning, lightsDay, lightsEvening, lightsNight };
for i = 1,#allLights do
for iL = 1, #allLights do
if ( allLights[iL][1] == tonumber(id) ) then
if ( fibaro:getValue(allLights[iL][1], "value") == "0" ) then
return "off";
else
return "on";
end
end
end
end
ErrorDebug("Light status unknown");
return "unknown";
end
GetTimeOfDayLightArray = function ()
if ( SavedState.sleepState == sleepStateMapping.Sleeping ) then
return lightsSleeping;
elseif ( SavedState.timeOfDay == timeOfDayMapping.Morning ) then
return lightsMorning;
elseif ( SavedState.timeOfDay == timeOfDayMapping.Day ) then
return lightsDay;
elseif ( SavedState.timeOfDay == timeOfDayMapping.Evening ) then
return lightsEvening;
elseif ( SavedState.timeOfDay == timeOfDayMapping.Night ) then
return lightsNight;
end
end
--------------------Debugging Functions-----------------------------
StandardDebug = function ( debugMessage )
if ( showStandardDebugInfo ) then
Debug( "white", debugMessage);
end
end
ExtraDebug = function ( debugMessage )
if ( showExtraDebugInfo ) then
Debug( "orange", debugMessage);
end
end
ErrorDebug = function ( debugMessage )
Debug( "red", "Error: " .. debugMessage);
end
TestDebug = function (debugMessage )
Debug( "blue", "Testing: " .. debugMessage );
end
----------------------START OF THE SCENE----------------------------
StandardDebug("Home status: " .. GetPresentState() );
StandardDebug("Motion status: " .. ( motionSensorStatus == 0 and "No movement" or "movement"));
if (startSource["type"] == "property") then
startSourceID = tonumber(startSource['deviceID']);
triggerDebug = "Triggered by: " .. startSourceID;
if ( startSourceID == motionSensorID ) then
StandardDebug( triggerDebug .. " Motion sensor" );
if ( motionSensorStatus > 0 ) then
SceneTriggered();
end
elseif ( startSourceID == LuxSensorID ) then
StandardDebug( triggerDebug .. " Lux sensor" );
ExtraDebug( "Lux value changed to: " .. lux );
if ( motionSensorStatus > 0 ) then
SceneTriggered();
end
elseif ( IsWalkDirection( startSourceID ) ) then
StandardDebug( triggerDebug .. " Walk Direction sensor" );
--walkDirection( startSourceID );
else
st = lightsStatus( startSourceID );
StandardDebug( triggerDebug .. " Light switch" );
if (st == "off") then
ExtraDebug( "light turned off, sleep 4 sec" );
--TODO: Call manual override.
fibaro:sleep(4000);
elseif (st == "on") then
ExtraDebug( "light turned on, sleep 4 sec" );
--TODO: call manual override, make time available to user.
fibaro:sleep(4000);
else
ErrorDebug( "Unknown light trigger" );
end
-- Maybe we can change the light preset to make it more intelligent.
-- maybe we can change the Lux preset to make it more intelligent.
end
elseif ( startSource["type"] == "global" ) then
StandardDebug( "Triggered by: " .. "global variable" );
if ( motionSensorStatus > 0 ) then
SceneTriggered();
end
else
StandardDebug( "Triggered by: " .. startSource["type"] );
--Just run the Light Code, not checking for motion. Probably triggered manually.
if ( startSource["type"] == "other" ) then
SceneTriggered();
end
end
Debug( "green", "Smart Lights V" .. version .. " | by Control Living, Finished" );
Debug( "green", "--------------------------------------------------" );
fibaro:abort(); --otherwise scene will stay alive to long.
--UPDATE TILL HERE
Thanks a lot in advance.
1 answer to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.