Jump to content

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


  • 0

Lights automation [LUA][3.562+]


Question

Posted

Polska wersja:

Please login or register to see this link.

My idea for automation lights in the house. Example of usage...

The enter-room with dimmer. Every move event turn on the lights for 3 minutes and every open door event turn on the lights for 5 minutes. In the last counting minute the lights will dimm down to zero - softly.

Every move or opening the door event will restart counter to 3 or 5 minutes. Manualy turning on the lights will set counter to half hour and then any other event will not be able to set counter for lower time - manual control is a priority.

Summary:

- Automatic switching off lights after counting time.

- Extension of light time based on events (eg move, doors, etc.).

- Without interfering with the manual control.

- Each light has its own timer.

- Dimming light for a defined time.

- Easy access to functions from the scene.

and...

- Everything is based on one single virtual device,

- For presentation timer and counting using slider - one for each device.

- Switching the light in the scenes you can make in the traditional way, or...

- Or simply by setting the slider value (setting the timer) - nothing more!

- You can adjust the slider (timer) in many scenes together.

The whole is fully automated and is simple to implement!

And here's the recipe in a few steps:

1. Define a new virtual device with the following code as Main loop. Change only login and password for your HC2:

Please login or register to see this link.

2. Define the sliders for each device in your home that you want to control by timer. To do this, add a slider in the virtual device with content as below:

Please login or register to see this code.

Fields:

action must be always autoOff;

deviceId id of controlled device;

defaultTime (optionaly) - default timer when the switch is controling manualy;

defaultValue (optionaly) - default maximum dimmer value;

dimmTime (optionaly) - time of dimming on the switching off event;

NEW! wakeTime (optionaly) - wake up period in seconds if devcie is dead.

3. (Optionaly) For presentation on the home screen you can define two elements in that virtual device. One more slider witch id globalSlider and one label id globalLabel with title eg. Turning off:.

That's all.

Just a way to use this functionality in scenes:

Instead of selecting the turn on action, just select the action changes the slider to the virtual device to any value (in seconds). The light will turn on automaticly.

Good luck;)

And one more thing...

Please login or register to see this link.

to have new futures!

Update 1.3:

- added possibilites to set timer (slider) from scenes to any value (even lower than actual) by minused value (eg. -600).

Update 1.2:

- fixed slider values preview,

- added new parameter "wakeTime"

- few others.

Update 1.05:

- possibility to turn off by slider,

- possibility to controll time in any "direction" by main slider

- icons - with animation

Please login or register to see this image.

/emoticons/default_smile.png" alt=":)" srcset="https://forum.fibaro.com/uploads/emoticons/[email protected] 2x" width="20" height="20" />

- bug fixes

Please login or register to see this attachment.

Please login or register to see this attachment.

Please login or register to see this attachment.

Please login or register to see this attachment.

Please login or register to see this attachment.

Please login or register to see this attachment.

Recommended Posts

  • 0
Posted

I have this in my toilett and it works when its daytime.

For nighttime i want the light to turn on at 30%

But it will be on 30% for only 1 sekund and right after up to 100%

I have removed dimlevel in the slider but it doesent work.

Any tip to make this work?

  • 0
Posted

Is the light suppose to turn on during initial motion?

Id like that and then a timer based on additional motion.

 

Now the light is not turned on or off... just a running timer. What did i do wrong?

I got the deviceid right for my dimmer

 

It would be helpful if the device timmer is set by room.

Entering a room defined lights are turned on and then all turned of by running timer.

  • 0
Posted

Is this the latest version or does you guys running another script for movement lightning?

  • 0
Posted

I have done some alterations on the coding just recently to allow for having different Dim values set at different times for lights (use a global variable, and set the global variable to the dim value you want with scenes).

 

Your Slider code should look like this:

 

{
  "action": "autoOff",
  "deviceId": 14,
  "defaultTime": 600,
  "defaultValue": 100,
  "dimmTime": 60,
  "globalVariableName": "GlobalDimValue"
}
 
You will then need to create a global variable called 'GlobalDimValue', which should be set to 100 for the default value. You then create a scene which sets the GlobalDimValue to be a value based on the time of day, another scene, or whatever. Personally I set it so my toilet light comes on at 20% between 12 at night and an hour after sunrise in the morning. The rest of the time it is set to 100.
 
If you have multiple lights being controlled by this code, then each one can have a separate dim value that changes based on your preference. Just create another Global Variable, and set the "globalVariableName" to whatever the name of the global variable is called.
 
note that "globalVariableName" is optional. If you don't put it in, it will just work as it did previously.
 
I have also set up my scenes for when a switch is double-clicked, it sets the slider value to be about 5 days, and the dim value to be 100%. Basically, it turns the lights on full, and they won't go off automatically for a really long time. I don't have code to reset the dim value back, so you will need to do that in your scene. Works very nicely for me.
 
Updated code as follows (sorry I haven't made it perfectly clean yet):
 
-- LIGHTS AUTOMATION
-- LUA script by fibaro.rafikel.pl
-- version 1.5, 2015-02-19, license GPL
 
-- Documentations available on Fibaro forum at this topics:
--

Please login or register to see this link.

(EN)
--

Please login or register to see this link.

(PL)
 
-- Access to HC2 admin account is neccessary for control 
-- virtual device in non standard way. Enter user/password:
USER = "username"
PASSWORD = "password"
 
-- FUTURES:
-- Automatic switching off lights after counting time.
-- Extension of light time based on events (eg move, doors, etc.). 
-- Without interfering with the manual control.
-- Each light has its own timer. 
-- Dimming light for a defined time. 
-- Easy access to functions from the scenes. 
-- Everything is based on one single virtual device, 
-- For presentation timer and counting using slider - one for each device. 
-- Switching the light in the scenes you can make in the traditional way, or... 
-- ... simply by setting the slider value (setting the timer) - nothing more! 
-- You can adjust the slider (timer) in many scenes together.
-- If you want to set timer (slider) from scene to any value...
-- ... even if it is lower than actual, use minused value (eg. -600).
 
-- TODO:
-- Possibilites to separate setting dimm level in manual steering.
 
-- Donate this project:

Please login or register to see this link.

-- Any qestions? Need help? Go to forum.fibaro.com.
 
 
--[[AUTOLIGHTS
  pl.rafikel.fibaro.autolights
]]--
 
-- show status on debug window 
fibaro:debug("Getting list of virtual devices..."); 
-- connect to HC2 
HC2 = Net.FHttp("localhost", 80); 
-- with authentication 
HC2:setBasicAuthentication(USER, PASSWORD);
-- grab virtual devices list from api 
response, status, errorCode = HC2:GET("/api/virtualDevices"); 
-- show status on debug window 
fibaro:debug("Status of reqest: " .. status .. '.');
 
-- if answer is wrong 
if (tonumber(status)~=200) then
  fibaro:debug("Error " .. errorCode .. ".");
end
 
-- prepare places for previous values 
oldValues = {};
oldTimers = {};
manualControl = {};
lastWakeTime = {};
 
-- icons 
iconOn = 0; 
iconOff = 0; 
iconVId = 0; 
 
-- variables for summary 
globalValue = 0; 
globalSliderId = 0; 
globalSliderVId = 0; 
globalLabelId = 0; 
globalLabelVId = 0;
 
-- function to prepare value for sliders
function clockValue(val)
  clock = "";
  if (not tonumber(val)) then val = 0 end
  if (val<0) then val = 0 end
  m = math.floor( val/60 );
  s = math.floor( val - (m*60) );
  if (m<10) then clock = clock .. "0" end
  if (m) then clock = clock .. m .. "." end
  if (s<10) then clock = clock .. "0" end
  if (s) then clock = clock .. s end
  return clock;
end
 
-- main loop if answer is ok 
while (tonumber(status)==200) do 
  -- reset data of fastest device to switch off 
  fastestDevice = ""; 
  fastestTimer = 0; 
  fastestDeviceId = 0; 
  fastestSlider = 0;
  iconOn = 0;
  iconOff = 0;
  iconVId = 0; 
  -- decode text to json object 
  jsonTable = json.decode(response); 
  -- roll over all virtual devices 
  for virtualIndex, virtualData in pairs(jsonTable) do 
    -- fibaro:debug('Virtual Device Id [' .. virtualData.id .. ']'); 
    -- roll over all rows in virtual device 
    for rowIndex, rowData in pairs(virtualData.properties.rows) do 
      -- fibaro:debug('  Row [' .. rowIndex .. '][' .. rowData.type .. ']'); 
      -- if row type is label 
      if (rowData.type=='label') then 
        -- rool over all buttons in row 
        for labelIndex, labelData in pairs(rowData.elements) do 
          -- check if that is main label 
          if (globalLabelId==0 and labelData.name=='globalLabel') then 
            globalLabelVId = tonumber(virtualData.id); 
            globalLabelId = tonumber(labelData.id); 
            fibaro:debug('Label ' .. globalLabelId .. ' / ' .. globalLabelVId .. '.'); 
          end 
        end 
      end 
      -- if row type is slider 
      if (rowData.type=='slider') then 
        -- rool over all buttons in row 
        for sliderIndex, sliderData in pairs(rowData.elements) do 
          -- check if that is main slider 
          if (sliderData.name=='globalSlider') then 
            -- if not defined yet? 
            if (globalSliderId==0) then 
              globalSliderVId = virtualData.id; 
              globalSliderId = sliderData.id; 
              fibaro:debug('Global slider ' .. globalSliderId .. ' / ' .. globalSliderVId .. '.'); 
            end 
          end 
          -- check if button (slider) has right defined code? 
          if (string.find(sliderData.msg, "{")==1) then 
            -- decode defined code for button (slider) 
            sliderParams = json.decode(sliderData.msg); 
            -- if autoOff parameter is present? 
            if (sliderParams.action=="autoOff") then 
              
              -- grab device information from definition 
              deviceId = sliderParams.deviceId; 
              deviceType = fibaro:getType(deviceId); 
              deviceName = fibaro:getName(deviceId); 
              deviceValue, deviceTS = fibaro:get(deviceId, 'value'); 
              deviceSeconds = os.time() - deviceTS; 
              deviceValue = tonumber(deviceValue); 
              deviceDead =  tonumber(fibaro:getValue(deviceId, "dead")); 
              
              -- grab slider information 
              sliderId = sliderData.id;
              sliderName = "ui." .. sliderData.name .. ".value";
              sliderValue, sliderTS = fibaro:get(virtualData.id, sliderName);
              sliderSeconds = os.time() - sliderTS;
              sliderValue = tonumber(sliderValue);
              
              -- make old values if necessary 
              if (not oldValues[deviceId]) then 
                --fibaro:log('New device [' .. deviceName .. '][' .. deviceId .. ']!'); 
                fibaro:debug('New device [' .. deviceName .. '][' .. deviceId .. '] Type [' .. deviceType .. '] Value [' .. deviceValue .. '].'); 
                oldValues[deviceId] = 0; 
                oldTimers[deviceId] = 0; 
              end
              
              -- value from slider is not number?
              if (not sliderValue or (sliderValue % 1)>0 ) then
                --fibaro:debug(sliderData.caption .. " Set... [" .. sliderValue .. "]");
                sliderValue = oldTimers[deviceId];
              end
 
              -- set timer to lower value 
              -- if slider below zero (minused)
              -- and not manual turned before
              if (sliderValue<0 and not manualControl[deviceId]) then 
                sliderValue = math.abs(sliderValue);
                fibaro:debug(sliderData.caption .. " Without checking... [" .. sliderValue .. "]");
 
              -- slider value is smaller than prev value
              elseif ( (oldTimers[deviceId]-sliderValue) > 2 ) then
                sliderValue = oldTimers[deviceId];
              end
 
              -- slider value to number
              sliderValue = tonumber(sliderValue);
              
              -- checking if its dead?
              if (deviceDead>0) then
                wakePeriod = sliderParams.wakeTime;
                if (wakePeriod) then wakePeriod = tonumber(wakePeriod) end
                if (not wakePeriod) then wakePeriod = 3600 end
                if (not lastWakeTime[deviceId] or lastWakeTime[deviceId]>wakePeriod) then
                  lastWakeTime[deviceId] = 0;
                  fibaro:wakeUpDeadDevice(deviceId);
                  fibaro:debug('WAKE UP [' .. deviceId .. ']...');
                else
                  --fibaro:debug('Device [' .. deviceId .. '] dead  [' .. lastWakeTime[deviceId] .. ']!');
                  lastWakeTime[deviceId] = lastWakeTime[deviceId] + 1;
                end
                sliderValue = 0;
              --end 
 
              -- turn on by slider 
              -- detecting if device has to be switched on 
              -- if slider changes eg. from scenes 
              elseif (sliderValue>0 and ((deviceValue==0 and deviceSeconds>2) or sliderValue>oldTimers[deviceId])) then 
                -- if device type is dimmer 
                if (deviceType=="com.fibaro.multilevelSwitch") then 
                  -- if default value for dimmer is defined 
                  if (sliderParams.defaultValue) then 
 
 -- New Code ***********************
 -- If globalVariableName has a value then get the value of the global variable and put in the maximum dimmer value 
 if (sliderParams.globalVariableName) then
  local gDimmerVal2=tonumber(fibaro:getGlobalValue(sliderParams.globalVariableName));
  
  fibaro:call(deviceId, 'setValue', gDimmerVal2);
  deviceValue = gDimmerVal2; 
  else
  
  fibaro:call(deviceId, 'setValue', tonumber(sliderParams.defaultValue));
  deviceValue = tonumber(sliderParams.defaultValue); 
 end 
--fibaro:debug(deviceValue)
                    -- set dimmer value to that 
                    -- fibaro:call(deviceId, 'setValue', tonumber(sliderParams.defaultValue)); 
                    -- remember new value as actual 
                    --deviceValue = tonumber(sliderParams.defaultValue); 
                  -- if dimmer has not defined starting value 
                  else 
                    -- set maximum 
                    fibaro:call(deviceId, 'setValue', 100);
                    -- and remember as actual
                    deviceValue = 100;
                  end
                  -- log to home screen 
                  fibaro:log(sliderData.caption .. ' ON [' .. deviceValue .. '] by Slider [' .. sliderValue .. ']!'); 
                -- if device is binary switch or another 
                else 
                  -- remember as actual 
                  deviceValue = 1; 
                  -- basic switch on 
                  fibaro:call(deviceId, 'turnOn'); 
                  -- log to home screen 
                  fibaro:log(sliderData.caption .. ' ON by Slider [' .. sliderValue .. ']!'); 
                end 
              -- end 
 
              -- manualy on          
              -- if default value for timer is defined 
              -- and device was manualy switched on 
              -- and new status (value) is biggest than previously 
              -- and sliderValue==0? 
              elseif (sliderParams.defaultTime and deviceValue>oldValues[deviceId]) then 
 -- fibaro:log('Manual On')
 -- if deviceID ~= nil then
-- fibaro:log('Device ID=' .. deviceID)
 -- end
 -- if deviceValue ~= nil then
-- fibaro:log('Device Value=' .. deviceValue)
 -- end 
                -- remember is manual
                manualControl[deviceId] = 1;
                -- set slider value to defined time 
                sliderValue = sliderParams.defaultTime;
                -- if default starting value for dimmer device is defined? 
                if (sliderParams.defaultValue) then 
                  -- use maximum of defined dimmer value
 -- If globalVariableName has a value then get the value of the global variable and put in the maximum dimmer value 
 if (sliderParams.globalVariableName) then
  local gDimmerVal=tonumber(fibaro:getGlobalValue(sliderParams.globalVariableName));
  deviceValue = gDimmerVal;
  else
  deviceValue = tonumber(sliderParams.defaultValue);
 end 
                  deviceValue = tonumber(sliderParams.defaultValue);
                  fibaro:call(deviceId, 'setValue', deviceValue);
                end 
                -- log to home screen 
                fibaro:log(sliderData.caption .. ' Manual ON [' .. deviceValue .. ']!');
              -- end 
              
              -- manual off 
              elseif (sliderValue>0 and deviceValue==0 and deviceSeconds<2) then 
                -- clear is manual 
                manualControl[deviceId] = nil;
                -- default value
                sliderValue = 0; 
                -- show log on home screen 
                fibaro:log(sliderData.caption .. ' Aborting!'); 
                -- update slider value to show left time - zero 
                -- fibaro:call(virtualData.id, "setSlider", sliderData.id, sliderValue);
                fibaro:call(virtualData.id, "setProperty", sliderName,  sliderValue); 
              --end 
              
              -- switch off by slider 
              elseif (sliderValue==0 and oldTimers[deviceId]>0) then 
                -- clear is manual 
                manualControl[deviceId] = nil;
                -- log on home screen 
                fibaro:log(sliderData.caption .. ' OFF by slider!'); 
                -- switch off device 
                fibaro:call(deviceId, 'turnOff'); 
              --end 
                  
              -- counting to down 
              elseif (sliderValue>0) then 
 
                -- decresing slider value 
                sliderValue = sliderValue - 1; 
 
                -- debug on window
                if (manualControl[deviceId]) then
                  t = "Manual";
                else
                  t = "Auto";
                end
                fibaro:debug('Device [' .. deviceId .. '][' .. t .. ']: Value [' .. deviceValue .. '][' .. deviceSeconds .. ' s.]; Slider [' .. sliderValue .. '][' .. sliderSeconds .. ' s.];'); 
 
                -- time to switch off 
                if (sliderValue==0) then 
                  -- clear is manual 
                  manualControl[deviceId] = nil;
                  -- log on home screen 
                  fibaro:log(sliderData.caption .. ' Auto OFF!'); 
                  -- switch off device 
                  fibaro:call(deviceId, 'turnOff'); 
                --end 
              
                -- update dimmer level 
                -- if defined "dimming time" parameter? 
                elseif (sliderParams.dimmTime and deviceType=="com.fibaro.multilevelSwitch") then 
                  dimmTime = tonumber(sliderParams.dimmTime); 
                  -- if default starting value for dimmer device is defined? 
                  if (sliderParams.defaultValue) then 
                    -- calculate dimmer step for one second 
                    -- use starting default value for dimmer device 
-- New Code ***********************
-- If globalVariableName has a value then get the value of the global variable and put in the maximum dimmer value 
 if (sliderParams.globalVariableName) then
  local gDimmerVal1=tonumber(fibaro:getGlobalValue(sliderParams.globalVariableName));
   
  dimmStep = tonumber(gDimmerVal1) / dimmTime;
  
  else
  
  dimmStep = tonumber(sliderParams.defaultValue) / dimmTime;
 end 
 -- fibaro:debug(dimmStep);
                    --dimmStep = tonumber(sliderParams.defaultValue) / dimmTime; 
                    --dimmStep = deviceValue / dimmTime; 
                  else 
                    -- calculate dimmer step for one second 
                    -- use 100% value for dimmer device 
                    dimmStep = 100 / dimmTime; 
                  end 
                  -- if time to start dimming 
                  if (sliderValue<dimmTime) then 
                    -- calculate dimmer value 
                    newVal = sliderValue * dimmStep; 
                    -- in other case use maximum value 
                  else 
                    -- if default starting value for dimmer device is defined? 
                    if (sliderParams.defaultValue) then 
-- New Code ***********************
-- If globalVariableName has a value then get the value of the global variable and put in the maximum dimmer value 
 if (sliderParams.globalVariableName) then
  local gDimmerVal3=tonumber(fibaro:getGlobalValue(sliderParams.globalVariableName));
 
  newVal=gDimmerVal3;
  
  else
  -- use maximum of defined dimmer value 
  newVal = tonumber(sliderParams.defaultValue);
 end 
 
                      
                       
                    else 
                      -- use 100% 
                      newVal = 100; 
                    end 
                  end 
                  -- if calculated value is lower then 1 
                  if (newVal<1) then 
                    newVal = 1; 
                  end 
                  -- if calculated value is grater then 100 
                  if (newVal>100) then 
                    newVal = 100; 
                  end 
                  -- set the new dimmer value if calculated value is lower then actual 
                  -- or new value is bigger but depending of slider (time) changes 
                  if (newVal<deviceValue or sliderValue>oldTimers[deviceId]) then 
                    fibaro:call(deviceId, 'setValue', newVal+1); 
                  end 
                end 
              
              end 
 
              -- update fastest timer and device name and icons 
              if ((sliderValue>0 or oldValues[deviceId]>1)
              and (sliderValue<fastestTimer or fastestTimer==0))
              then
                fastestTimer = sliderValue;
                fastestDevice = sliderData.caption;
                fastestDeviceId = deviceId; 
                fastestSlider = sliderData.id; 
                iconVId = virtualData.id; 
                iconOff = virtualData.properties.deviceIcon; 
                iconOn = sliderData.buttonIcon; 
              end 
 
              -- remeber old values and timers (sliders) 
              oldValues[deviceId] = deviceValue; 
              oldTimers[deviceId] = sliderValue; 
              
              -- select new value on the slider
              new = tonumber(sliderValue);
              --clockValue(sliderValue);
              old = tonumber(fibaro:getValue(virtualData.id, sliderName));
              if (new ~= old) then
                fibaro:call(virtualData.id, "setProperty", sliderName, new);
              end
              
            end 
          end 
        end 
      end 
    end 
  end 
 
  --fibaro:debug(fastestDevice .. '... [' .. fastestTimer .. ']...');
  
  -- update main slider
  if (globalSliderId and globalSliderVId) then
    old = tonumber(fibaro:getValue(globalSliderVId, "ui.globalSlider.value"));
    new = tonumber(fastestTimer);
    --clockValue(fastestTimer);
    if (new ~= old) then
      fibaro:call(globalSliderVId, "setProperty", "ui.globalSlider.value", new);
    end
  end
  
  -- update main label 
  if (globalLabelId and globalLabelVId) then 
    new = "---";
    if (fastestTimer>0) then
      new = "";
      h = math.floor( fastestTimer/3600 );
      m = math.floor( ( fastestTimer - (h*3600) )/60 );
      s = math.floor( fastestTimer - (h*3600) - (m*60) );
      if (h>0) then new = new .. h .. ":" end
      if (m<10) then new = new .. "0" end
      new = new .. m .. ":";
      if (s<10) then new = new .. "0" end
      new = new .. s;
      new = new .. " " .. fastestDevice;
    end
    old = fibaro:getValue(globalSliderVId, "ui.globalLabel.value");
    if (new ~= old) then
      fibaro:call(globalLabelVId, "setProperty", "ui.globalLabel.value", new);
    end
  end 
    
  -- update icon to ON
  if (iconVId and iconOn) then 
    fibaro:call(iconVId, "setProperty", "currentIcon", iconOn); 
  end 
 
  -- WAIT
  fibaro:sleep(500); 
 
  -- update icon to OFF 
  if (iconVId and iconOff) then 
    fibaro:call(iconVId, "setProperty", "currentIcon", iconOff); 
  end 
  
  -- WAIT
  fibaro:sleep(500);
  
end 
-- if everything is ok, the main loop will never end 
 
-- wait after API error 
fibaro:sleep(10000); 
  • 0
Posted

Ok! Thx Will try this one, the old one didnt reset the timer on movment as it should.

  • 0
Posted

 

I have done some alterations on the coding just recently to allow for having different Dim values set at different times for lights (use a global variable, and set the global variable to the dim value you want with scenes).

 

Your Slider code should look like this:

 

{
  "action": "autoOff",
  "deviceId": 14,
  "defaultTime": 600,
  "defaultValue": 100,
  "dimmTime": 60,
  "globalVariableName": "GlobalDimValue"
}
 
You will then need to create a global variable called 'GlobalDimValue', which should be set to 100 for the default value. You then create a scene which sets the GlobalDimValue to be a value based on the time of day, another scene, or whatever. Personally I set it so my toilet light comes on at 20% between 12 at night and an hour after sunrise in the morning. The rest of the time it is set to 100.
 
If you have multiple lights being controlled by this code, then each one can have a separate dim value that changes based on your preference. Just create another Global Variable, and set the "globalVariableName" to whatever the name of the global variable is called.
 
note that "globalVariableName" is optional. If you don't put it in, it will just work as it did previously.
 
I have also set up my scenes for when a switch is double-clicked, it sets the slider value to be about 5 days, and the dim value to be 100%. Basically, it turns the lights on full, and they won't go off automatically for a really long time. I don't have code to reset the dim value back, so you will need to do that in your scene. Works very nicely for me.
 
Updated code as follows (sorry I haven't made it perfectly clean yet):
 
-- LIGHTS AUTOMATION
-- LUA script by fibaro.rafikel.pl
-- version 1.5, 2015-02-19, license GPL
 
-- Documentations available on Fibaro forum at this topics:
--

Please login or register to see this link.

(EN)
--

Please login or register to see this link.

(PL)
 
-- Access to HC2 admin account is neccessary for control 
-- virtual device in non standard way. Enter user/password:
USER = "username"
PASSWORD = "password"
 
-- FUTURES:
-- Automatic switching off lights after counting time.
-- Extension of light time based on events (eg move, doors, etc.). 
-- Without interfering with the manual control.
-- Each light has its own timer. 
-- Dimming light for a defined time. 
-- Easy access to functions from the scenes. 
-- Everything is based on one single virtual device, 
-- For presentation timer and counting using slider - one for each device. 
-- Switching the light in the scenes you can make in the traditional way, or... 
-- ... simply by setting the slider value (setting the timer) - nothing more! 
-- You can adjust the slider (timer) in many scenes together.
-- If you want to set timer (slider) from scene to any value...
-- ... even if it is lower than actual, use minused value (eg. -600).
 
-- TODO:
-- Possibilites to separate setting dimm level in manual steering.
 
-- Donate this project:

Please login or register to see this link.

-- Any qestions? Need help? Go to forum.fibaro.com.
 
 
--[[AUTOLIGHTS
  pl.rafikel.fibaro.autolights
]]--
 
-- show status on debug window 
fibaro:debug("Getting list of virtual devices..."); 
-- connect to HC2 
HC2 = Net.FHttp("localhost", 80); 
-- with authentication 
HC2:setBasicAuthentication(USER, PASSWORD);
-- grab virtual devices list from api 
response, status, errorCode = HC2:GET("/api/virtualDevices"); 
-- show status on debug window 
fibaro:debug("Status of reqest: " .. status .. '.');
 
-- if answer is wrong 
if (tonumber(status)~=200) then
  fibaro:debug("Error " .. errorCode .. ".");
end
 
-- prepare places for previous values 
oldValues = {};
oldTimers = {};
manualControl = {};
lastWakeTime = {};
 
-- icons 
iconOn = 0; 
iconOff = 0; 
iconVId = 0; 
 
-- variables for summary 
globalValue = 0; 
globalSliderId = 0; 
globalSliderVId = 0; 
globalLabelId = 0; 
globalLabelVId = 0;
 
-- function to prepare value for sliders
function clockValue(val)
  clock = "";
  if (not tonumber(val)) then val = 0 end
  if (val<0) then val = 0 end
  m = math.floor( val/60 );
  s = math.floor( val - (m*60) );
  if (m<10) then clock = clock .. "0" end
  if (m) then clock = clock .. m .. "." end
  if (s<10) then clock = clock .. "0" end
  if (s) then clock = clock .. s end
  return clock;
end
 
-- main loop if answer is ok 
while (tonumber(status)==200) do 
  -- reset data of fastest device to switch off 
  fastestDevice = ""; 
  fastestTimer = 0; 
  fastestDeviceId = 0; 
  fastestSlider = 0;
  iconOn = 0;
  iconOff = 0;
  iconVId = 0; 
  -- decode text to json object 
  jsonTable = json.decode(response); 
  -- roll over all virtual devices 
  for virtualIndex, virtualData in pairs(jsonTable) do 
    -- fibaro:debug('Virtual Device Id [' .. virtualData.id .. ']'); 
    -- roll over all rows in virtual device 
    for rowIndex, rowData in pairs(virtualData.properties.rows) do 
      -- fibaro:debug('  Row [' .. rowIndex .. '][' .. rowData.type .. ']'); 
      -- if row type is label 
      if (rowData.type=='label') then 
        -- rool over all buttons in row 
        for labelIndex, labelData in pairs(rowData.elements) do 
          -- check if that is main label 
          if (globalLabelId==0 and labelData.name=='globalLabel') then 
            globalLabelVId = tonumber(virtualData.id); 
            globalLabelId = tonumber(labelData.id); 
            fibaro:debug('Label ' .. globalLabelId .. ' / ' .. globalLabelVId .. '.'); 
          end 
        end 
      end 
      -- if row type is slider 
      if (rowData.type=='slider') then 
        -- rool over all buttons in row 
        for sliderIndex, sliderData in pairs(rowData.elements) do 
          -- check if that is main slider 
          if (sliderData.name=='globalSlider') then 
            -- if not defined yet? 
            if (globalSliderId==0) then 
              globalSliderVId = virtualData.id; 
              globalSliderId = sliderData.id; 
              fibaro:debug('Global slider ' .. globalSliderId .. ' / ' .. globalSliderVId .. '.'); 
            end 
          end 
          -- check if button (slider) has right defined code? 
          if (string.find(sliderData.msg, "{")==1) then 
            -- decode defined code for button (slider) 
            sliderParams = json.decode(sliderData.msg); 
            -- if autoOff parameter is present? 
            if (sliderParams.action=="autoOff") then 
              
              -- grab device information from definition 
              deviceId = sliderParams.deviceId; 
              deviceType = fibaro:getType(deviceId); 
              deviceName = fibaro:getName(deviceId); 
              deviceValue, deviceTS = fibaro:get(deviceId, 'value'); 
              deviceSeconds = os.time() - deviceTS; 
              deviceValue = tonumber(deviceValue); 
              deviceDead =  tonumber(fibaro:getValue(deviceId, "dead")); 
              
              -- grab slider information 
              sliderId = sliderData.id;
              sliderName = "ui." .. sliderData.name .. ".value";
              sliderValue, sliderTS = fibaro:get(virtualData.id, sliderName);
              sliderSeconds = os.time() - sliderTS;
              sliderValue = tonumber(sliderValue);
              
              -- make old values if necessary 
              if (not oldValues[deviceId]) then 
                --fibaro:log('New device [' .. deviceName .. '][' .. deviceId .. ']!'); 
                fibaro:debug('New device [' .. deviceName .. '][' .. deviceId .. '] Type [' .. deviceType .. '] Value [' .. deviceValue .. '].'); 
                oldValues[deviceId] = 0; 
                oldTimers[deviceId] = 0; 
              end
              
              -- value from slider is not number?
              if (not sliderValue or (sliderValue % 1)>0 ) then
                --fibaro:debug(sliderData.caption .. " Set... [" .. sliderValue .. "]");
                sliderValue = oldTimers[deviceId];
              end
 
              -- set timer to lower value 
              -- if slider below zero (minused)
              -- and not manual turned before
              if (sliderValue<0 and not manualControl[deviceId]) then 
                sliderValue = math.abs(sliderValue);
                fibaro:debug(sliderData.caption .. " Without checking... [" .. sliderValue .. "]");
 
              -- slider value is smaller than prev value
              elseif ( (oldTimers[deviceId]-sliderValue) > 2 ) then
                sliderValue = oldTimers[deviceId];
              end
 
              -- slider value to number
              sliderValue = tonumber(sliderValue);
              
              -- checking if its dead?
              if (deviceDead>0) then
                wakePeriod = sliderParams.wakeTime;
                if (wakePeriod) then wakePeriod = tonumber(wakePeriod) end
                if (not wakePeriod) then wakePeriod = 3600 end
                if (not lastWakeTime[deviceId] or lastWakeTime[deviceId]>wakePeriod) then
                  lastWakeTime[deviceId] = 0;
                  fibaro:wakeUpDeadDevice(deviceId);
                  fibaro:debug('WAKE UP [' .. deviceId .. ']...');
                else
                  --fibaro:debug('Device [' .. deviceId .. '] dead  [' .. lastWakeTime[deviceId] .. ']!');
                  lastWakeTime[deviceId] = lastWakeTime[deviceId] + 1;
                end
                sliderValue = 0;
              --end 
 
              -- turn on by slider 
              -- detecting if device has to be switched on 
              -- if slider changes eg. from scenes 
              elseif (sliderValue>0 and ((deviceValue==0 and deviceSeconds>2) or sliderValue>oldTimers[deviceId])) then 
                -- if device type is dimmer 
                if (deviceType=="com.fibaro.multilevelSwitch") then 
                  -- if default value for dimmer is defined 
                  if (sliderParams.defaultValue) then 
 
 -- New Code ***********************
 -- If globalVariableName has a value then get the value of the global variable and put in the maximum dimmer value 
 if (sliderParams.globalVariableName) then
  local gDimmerVal2=tonumber(fibaro:getGlobalValue(sliderParams.globalVariableName));
  
  fibaro:call(deviceId, 'setValue', gDimmerVal2);
  deviceValue = gDimmerVal2; 
  else
  
  fibaro:call(deviceId, 'setValue', tonumber(sliderParams.defaultValue));
  deviceValue = tonumber(sliderParams.defaultValue); 
 end 
--fibaro:debug(deviceValue)
                    -- set dimmer value to that 
                    -- fibaro:call(deviceId, 'setValue', tonumber(sliderParams.defaultValue)); 
                    -- remember new value as actual 
                    --deviceValue = tonumber(sliderParams.defaultValue); 
                  -- if dimmer has not defined starting value 
                  else 
                    -- set maximum 
                    fibaro:call(deviceId, 'setValue', 100);
                    -- and remember as actual
                    deviceValue = 100;
                  end
                  -- log to home screen 
                  fibaro:log(sliderData.caption .. ' ON [' .. deviceValue .. '] by Slider [' .. sliderValue .. ']!'); 
                -- if device is binary switch or another 
                else 
                  -- remember as actual 
                  deviceValue = 1; 
                  -- basic switch on 
                  fibaro:call(deviceId, 'turnOn'); 
                  -- log to home screen 
                  fibaro:log(sliderData.caption .. ' ON by Slider [' .. sliderValue .. ']!'); 
                end 
              -- end 
 
              -- manualy on          
              -- if default value for timer is defined 
              -- and device was manualy switched on 
              -- and new status (value) is biggest than previously 
              -- and sliderValue==0? 
              elseif (sliderParams.defaultTime and deviceValue>oldValues[deviceId]) then 
 -- fibaro:log('Manual On')
 -- if deviceID ~= nil then
-- fibaro:log('Device ID=' .. deviceID)
 -- end
 -- if deviceValue ~= nil then
-- fibaro:log('Device Value=' .. deviceValue)
 -- end 
                -- remember is manual
                manualControl[deviceId] = 1;
                -- set slider value to defined time 
                sliderValue = sliderParams.defaultTime;
                -- if default starting value for dimmer device is defined? 
                if (sliderParams.defaultValue) then 
                  -- use maximum of defined dimmer value
 -- If globalVariableName has a value then get the value of the global variable and put in the maximum dimmer value 
 if (sliderParams.globalVariableName) then
  local gDimmerVal=tonumber(fibaro:getGlobalValue(sliderParams.globalVariableName));
  deviceValue = gDimmerVal;
  else
  deviceValue = tonumber(sliderParams.defaultValue);
 end 
                  deviceValue = tonumber(sliderParams.defaultValue);
                  fibaro:call(deviceId, 'setValue', deviceValue);
                end 
                -- log to home screen 
                fibaro:log(sliderData.caption .. ' Manual ON [' .. deviceValue .. ']!');
              -- end 
              
              -- manual off 
              elseif (sliderValue>0 and deviceValue==0 and deviceSeconds<2) then 
                -- clear is manual 
                manualControl[deviceId] = nil;
                -- default value
                sliderValue = 0; 
                -- show log on home screen 
                fibaro:log(sliderData.caption .. ' Aborting!'); 
                -- update slider value to show left time - zero 
                -- fibaro:call(virtualData.id, "setSlider", sliderData.id, sliderValue);
                fibaro:call(virtualData.id, "setProperty", sliderName,  sliderValue); 
              --end 
              
              -- switch off by slider 
              elseif (sliderValue==0 and oldTimers[deviceId]>0) then 
                -- clear is manual 
                manualControl[deviceId] = nil;
                -- log on home screen 
                fibaro:log(sliderData.caption .. ' OFF by slider!'); 
                -- switch off device 
                fibaro:call(deviceId, 'turnOff'); 
              --end 
                  
              -- counting to down 
              elseif (sliderValue>0) then 
 
                -- decresing slider value 
                sliderValue = sliderValue - 1; 
 
                -- debug on window
                if (manualControl[deviceId]) then
                  t = "Manual";
                else
                  t = "Auto";
                end
                fibaro:debug('Device [' .. deviceId .. '][' .. t .. ']: Value [' .. deviceValue .. '][' .. deviceSeconds .. ' s.]; Slider [' .. sliderValue .. '][' .. sliderSeconds .. ' s.];'); 
 
                -- time to switch off 
                if (sliderValue==0) then 
                  -- clear is manual 
                  manualControl[deviceId] = nil;
                  -- log on home screen 
                  fibaro:log(sliderData.caption .. ' Auto OFF!'); 
                  -- switch off device 
                  fibaro:call(deviceId, 'turnOff'); 
                --end 
              
                -- update dimmer level 
                -- if defined "dimming time" parameter? 
                elseif (sliderParams.dimmTime and deviceType=="com.fibaro.multilevelSwitch") then 
                  dimmTime = tonumber(sliderParams.dimmTime); 
                  -- if default starting value for dimmer device is defined? 
                  if (sliderParams.defaultValue) then 
                    -- calculate dimmer step for one second 
                    -- use starting default value for dimmer device 
-- New Code ***********************
-- If globalVariableName has a value then get the value of the global variable and put in the maximum dimmer value 
 if (sliderParams.globalVariableName) then
  local gDimmerVal1=tonumber(fibaro:getGlobalValue(sliderParams.globalVariableName));
   
  dimmStep = tonumber(gDimmerVal1) / dimmTime;
  
  else
  
  dimmStep = tonumber(sliderParams.defaultValue) / dimmTime;
 end 
 -- fibaro:debug(dimmStep);
                    --dimmStep = tonumber(sliderParams.defaultValue) / dimmTime; 
                    --dimmStep = deviceValue / dimmTime; 
                  else 
                    -- calculate dimmer step for one second 
                    -- use 100% value for dimmer device 
                    dimmStep = 100 / dimmTime; 
                  end 
                  -- if time to start dimming 
                  if (sliderValue<dimmTime) then 
                    -- calculate dimmer value 
                    newVal = sliderValue * dimmStep; 
                    -- in other case use maximum value 
                  else 
                    -- if default starting value for dimmer device is defined? 
                    if (sliderParams.defaultValue) then 
-- New Code ***********************
-- If globalVariableName has a value then get the value of the global variable and put in the maximum dimmer value 
 if (sliderParams.globalVariableName) then
  local gDimmerVal3=tonumber(fibaro:getGlobalValue(sliderParams.globalVariableName));
 
  newVal=gDimmerVal3;
  
  else
  -- use maximum of defined dimmer value 
  newVal = tonumber(sliderParams.defaultValue);
 end 
 
                      
                       
                    else 
                      -- use 100% 
                      newVal = 100; 
                    end 
                  end 
                  -- if calculated value is lower then 1 
                  if (newVal<1) then 
                    newVal = 1; 
                  end 
                  -- if calculated value is grater then 100 
                  if (newVal>100) then 
                    newVal = 100; 
                  end 
                  -- set the new dimmer value if calculated value is lower then actual 
                  -- or new value is bigger but depending of slider (time) changes 
                  if (newVal<deviceValue or sliderValue>oldTimers[deviceId]) then 
                    fibaro:call(deviceId, 'setValue', newVal+1); 
                  end 
                end 
              
              end 
 
              -- update fastest timer and device name and icons 
              if ((sliderValue>0 or oldValues[deviceId]>1)
              and (sliderValue<fastestTimer or fastestTimer==0))
              then
                fastestTimer = sliderValue;
                fastestDevice = sliderData.caption;
                fastestDeviceId = deviceId; 
                fastestSlider = sliderData.id; 
                iconVId = virtualData.id; 
                iconOff = virtualData.properties.deviceIcon; 
                iconOn = sliderData.buttonIcon; 
              end 
 
              -- remeber old values and timers (sliders) 
              oldValues[deviceId] = deviceValue; 
              oldTimers[deviceId] = sliderValue; 
              
              -- select new value on the slider
              new = tonumber(sliderValue);
              --clockValue(sliderValue);
              old = tonumber(fibaro:getValue(virtualData.id, sliderName));
              if (new ~= old) then
                fibaro:call(virtualData.id, "setProperty", sliderName, new);
              end
              
            end 
          end 
        end 
      end 
    end 
  end 
 
  --fibaro:debug(fastestDevice .. '... [' .. fastestTimer .. ']...');
  
  -- update main slider
  if (globalSliderId and globalSliderVId) then
    old = tonumber(fibaro:getValue(globalSliderVId, "ui.globalSlider.value"));
    new = tonumber(fastestTimer);
    --clockValue(fastestTimer);
    if (new ~= old) then
      fibaro:call(globalSliderVId, "setProperty", "ui.globalSlider.value", new);
    end
  end
  
  -- update main label 
  if (globalLabelId and globalLabelVId) then 
    new = "---";
    if (fastestTimer>0) then
      new = "";
      h = math.floor( fastestTimer/3600 );
      m = math.floor( ( fastestTimer - (h*3600) )/60 );
      s = math.floor( fastestTimer - (h*3600) - (m*60) );
      if (h>0) then new = new .. h .. ":" end
      if (m<10) then new = new .. "0" end
      new = new .. m .. ":";
      if (s<10) then new = new .. "0" end
      new = new .. s;
      new = new .. " " .. fastestDevice;
    end
    old = fibaro:getValue(globalSliderVId, "ui.globalLabel.value");
    if (new ~= old) then
      fibaro:call(globalLabelVId, "setProperty", "ui.globalLabel.value", new);
    end
  end 
    
  -- update icon to ON
  if (iconVId and iconOn) then 
    fibaro:call(iconVId, "setProperty", "currentIcon", iconOn); 
  end 
 
  -- WAIT
  fibaro:sleep(500); 
 
  -- update icon to OFF 
  if (iconVId and iconOff) then 
    fibaro:call(iconVId, "setProperty", "currentIcon", iconOff); 
  end 
  
  -- WAIT
  fibaro:sleep(500);
  
end 
-- if everything is ok, the main loop will never end 
 
-- wait after API error 
fibaro:sleep(10000); 

 

 

Hi

Tried your code but got this in the debug

[DEBUG] 09:47:43: Getting list of virtual devices...

[DEBUG] 09:47:43: Status of reqest: 200.

[ERROR] 09:47:43: line 158: attempt to concatenate global 'deviceValue' (a nil value)

 
 
 
Line 158 is the second row oldValues
 
 fibaro:debug('New device [' .. deviceName .. '][' .. deviceId .. '] Type [' .. deviceType .. '] Value [' .. deviceValue .. '].'); 
               
oldValues[deviceId] = 0; 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...