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

need help with scene while loop


Question

Posted (edited)

Hi All,

 

Desperately need your help with the following:

 

I'm trying to accomplish to send a pushmessage to my in-wall dashboards when motion is detected. After motion is detected the scene needs to check every 10 min if the motions lastBreached is lower then 30 min and send the pushmesssge again until lastBreached is more then 30 min

 

This is what i have so far:

 

--[[
%% properties
203 value
%% weather
%% events
%% globals
USBWKScreen
--]]

if (fibaro:countScenes() >1) 
then
fibaro:abort();
end

 

-- Local
local hc=fibaro;
local StartSource=hc:getSourceTrigger();
local iosDeviceID = {43}; -- inwall dashboards
local motionID = {203}; -- PIR sensors
local movement = 600; -- 10 min

local screen        = "USBWKScreen"; -- variabele
local screenMapping = {On="Aan", Off="Uit"};

 

-- Send notification to devices
function setScreenOn()
   if(#iosDeviceID > 0)
      then
      for i = 1, #iosDeviceID do
         hc:call(iosDeviceID, "sendPush", "ScreenOn");
     hc:debug("Message send to device - "..iosDeviceID);
      end
   else
      hc:debug(" No devices found");
   end 
end

 

-- Main
if(hc:getGlobalValue(screen)==screenMapping.On)
   then
   for i=1,#motionID do 
      if ( (tonumber(os.time()) - tonumber(fibaro:getValue(motionID, "lastBreached"))) < tonumber(movement) )
         then 
         setScreenOn();
      else
         hc:debug("Scene runned")
      end 
   end
else
   hc:debug("Scene runned"))
end

 

Thanks in advance!

 

 

Edited by rickydehaas

5 answers to this question

Recommended Posts

  • 0
Posted (edited)

Few question:

1. your variable screen defined as local and at the same time you're trying to get global value with the same name?

2. if(hc:getGlobalValue(screen)==screenMapping.On
and motion)

This statement becomes false after sensor back to safe (I believe it's not set to 30 minutes).  You are looking for lastBreached value not motion detected value.

3. Any specific reason why your device (motionID) defined as tables and you loop him?

 

Edited by cag014
  • 0
Posted (edited)

You need to use setTimeout() function to loop your scene every 10 minutes.

See details

 

Edited by cag014
  • 0
Posted
6 hours ago, cag014 said:

You need to use setTimeout() function to loop your scene every 10 minutes.

See details

 

 

Something that is almost a "best practice" Is how to write a setTimeout loop so it doesn't drift. I have seen many scenes that uses a setTimeout loop to do some work every minute or so and doesn't compensate for the time that work takes. That means that the loop is longer than the time the loop is setup for and it starts to "drift". The problem is that you may eventually miss an interval - if you check for them (ex. going from 10,999999 to 12,0000001)

 

The "Lua idiom" to setup a non-drift setTimeout loop is

Ex. a 60s loop

Please login or register to see this code.

In this case, if 'doWork()' takes a millisecond or 30s it doesn't matter. The loop will run every 60s.

However, when in the minute doWork is called depends on when the loop is started. If it is started 10:05:26 it will loop 

10:05:26, 10:06:26, 10:07:26, 10:08:26 ...

 

This is easy to extend to make it run starting on the minute (works for hour too)

E.g. looping 10:06:00, 10:07:00, 10:08:00, 10:09:00 ...

Please login or register to see this code.

and then the pattern can be captured in a function

Please login or register to see this code.

 

  • Like 1
  • Thanks 1
  • 0
  • Inquirer
  • Posted

    Thanks for the info @jgab @cag014

     

    This is what i have so far, but it's not working properly and i can't find out why. Also i'm not known with function timeOut. Can 1 off you help me with it. 

     

    --[[
    %% properties
    203 value
    %% weather
    %% events
    %% globals
    --]]

    if (fibaro:countScenes() >1) 
    then
    fibaro:abort();
    end

    -- Local
    local hc=fibaro;
    local StartSource=hc:getSourceTrigger();
    local iosDeviceID = {43};
    local motionID = {203};
    local movement = 1800; -- 30 min
    local wait = 600;  -- 10 min

     

    local screen        = "USBWKScreen";
    local screenMapping = {On="Aan", Off="Uit"};

     

    -- Send notification to devices
    function setScreenOn()
       if(#iosDeviceID > 0)
          then
          for i = 1, #iosDeviceID do
             hc:call(iosDeviceID, "sendPush", "ScreenOn");
          end
       else
          hc:debug("   Geen device gevonden");
       end 
    end

    -- Check Motion
    function checkMotion()
       if(StartSource['type']=='property')
          then
          for i=1,#motionID do 
             if ( tonumber(hc:getValue(motionID,'value'))>0 )
                then 
                motion=true 
             end 
          end
       end
    end

    -- Main
    checkMotion()
    if(hc:getGlobalValue(screen)==screenMapping.On
    and motion)
       then
       for i=1,#motionID do 
          while (tonumber(os.time()) - tonumber(hc:getValue(motionID, "lastBreached"))) < tonumber(movement) do 
             setScreenOn();
             hc:debug("<font color=blue> Message send</font>")
             hc:debug("<font color=blue> 10min for next check</font>")
             hc:sleep(wait*1000)
          end 
       end
    else
       hc:debug("Scene runned")
    end
     

    • 0
  • Inquirer
  • Posted
    9 minutes ago, cag014 said:

    Few question:

    1. your variable screen defined as local and at the same time you're trying to get global value with the same name?

    2. if(hc:getGlobalValue(screen)==screenMapping.On
    and motion)

    This statement becomes false after sensor back to safe (I believe it's not set to 30 minutes).  You are looking for lastBreached value not motion detected value.

    3. Any specific reason why your device (motionID) defined as tables and you loop him?

     

     

    Thanks for your time @cag014

     

    The scene is working properly now and indeed notices some incorrect coding in the scene. 

     

    Thanks for your time

    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...