We have moved at community.getvera.com

Author Topic: Will it work?  (Read 1990 times)

Offline kwieto

  • Hero Member
  • *****
  • Posts: 624
  • Karma: +27/-15
Will it work?
« on: January 19, 2017, 04:22:21 pm »
I have to admit that I am completely new to scripting so I need an assistance at the beginning.

I have a scene which triggers a specific switch "ON" if a condition is met - this can be done in standard scene creator.
The problem I have is that this switch is a WiFi connected one and from time to time it fails to be switched after scene is executed, so the result is like nothing happened.

I thought about some kind of check mechanism and got an idea of creating a loop in which the status of the switch is checked after the change and, if the switch status remain unchanged, started once more. if status changed, then the process ends and the scene is finished.

The resulting code is as follow:


local device  = 63    --the switch ID

function switch_on()
    luup.call_action("urn:upnp-org:serviceId:SwitchPower1","SetTarget",{ newTargetValue="1" },device)   --turn on the switch
    luup.call_delay( 'check', 120) -- wait 2 minutes before checking the status
end

function check()
local dev_status = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Status", device)  --check status of the switch
  if (dev_status == "0") then  --if switch is still off then go back to the function switch_on, else do nothing and end the loop
    switch_on()
  else
end


Is this written correctly?

Offline kwieto

  • Hero Member
  • *****
  • Posts: 624
  • Karma: +27/-15
Re: Will it work?
« Reply #1 on: January 19, 2017, 06:02:01 pm »
I did try to enter this code to a scene and received an error. So I did modifications and some experiment and I am stucked - the code saves properly only when the "if... then" part is deleted.
Whenever I add the if... then condition after saving the scene I am getting the "error in lua for scenes and events" message.

Any help/idea?

function switch_on()
    luup.call_action("urn:upnp-org:serviceId:SwitchPower1","SetTarget",{ newTargetValue="1" }, 62)
    luup.call_delay( 'check', 120)
end

function check()
  local devStatus = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Status", 62)
  local devOff = "0"
  if devStatus = devOff then
     luup.call_delay( 'switch_on', 0)
  else
end

Offline jswim788

  • Hero Member
  • *****
  • Posts: 809
  • Karma: +58/-2
Re: Will it work?
« Reply #2 on: January 19, 2017, 06:16:12 pm »
Are you missing an 'end' to the if/then/else clause?  Both the function and the if need an end.  Also, you need '==' to compare, not the '='.  I'm sure others may be able to help further.

But what calls these functions?  This just defines the functions - is there other code that calls the functions?

Offline RichardTSchaefer

  • Community Beta
  • Master Member
  • ******
  • Posts: 10091
  • Karma: +764/-143
Re: Will it work?
« Reply #3 on: January 19, 2017, 09:51:39 pm »
Try:

Code: [Select]
if devStatus == devOff then

Offline kwieto

  • Hero Member
  • *****
  • Posts: 624
  • Karma: +27/-15
Re: Will it work?
« Reply #4 on: January 20, 2017, 04:27:00 am »
Quote
Are you missing an 'end' to the if/then/else clause?  Both the function and the if need an end

Yes, seems that it was the main problem. Also it should be double equal sign in the condition (as it was in the first version, I've changed it trying to get it work).
Thanks!

Quote
But what calls these functions?

The main trigger is defined in step one of building a scene. There is a condition that if temperature reported by a sensor drops below certain level it starts the scene to run.
Step two (choosing device and action) is omitted and the code is put in the step three, section "also, execute the following luup code".
If I am correct, after the scene is triggered the actions defined by code will take place.

I will test it today.

Also I have one more question.
To go from the function "check" back to the "switch_on" I used the  luup.call_delay argument, simply because I know it should work.
But maybe I can do it in more simple way?
Will writing something like
Code: [Select]
if... then switch_on work?
« Last Edit: January 20, 2017, 04:29:26 am by kwieto »

Offline RichardTSchaefer

  • Community Beta
  • Master Member
  • ******
  • Posts: 10091
  • Karma: +764/-143
Re: Will it work?
« Reply #5 on: January 20, 2017, 06:46:00 am »
Quote
But what calls these functions?

You do!
Put a call to the function as the last line of your scene ... i.e.

Code: [Select]
switch_on()

I do not understand your logic ... why do you can a delay with a value of 0  ... you can just call the function switch_on() there as well.

 
« Last Edit: January 20, 2017, 06:50:31 am by RichardTSchaefer »

Offline cybrmage

  • Beta Testers
  • Hero Member
  • *****
  • Posts: 1104
  • Karma: +113/-43
Re: Will it work?
« Reply #6 on: January 20, 2017, 10:56:59 am »
Try this - it is modified to be a target follower - keeps sending the setTarget command until the switch changes to that state...

Code: [Select]
local SwitchID  = 63    --the switch ID

function switch_device(newValue)
    luup.call_action("urn:upnp-org:serviceId:SwitchPower1","SetTarget",{ newTargetValue=newValue },SwitchID)   --turn on/off the switch
    luup.call_delay( 'check', 120) -- wait 2 minutes before checking the status
end

function check()
  local dev_target = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Target", SwitchID)  --check commanded state of the switch
  local dev_status = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Status", SwitchID)  --check status of the switch
  if (dev_status ~= dev_target) then  --if switch is not in the commanded state then call the function switch_device, else do nothing and end the loop
    switch_device(dev_target)
  end
end



Your original error come from the if...then structure...

The stucture is:
   if (condition) then (condition is true action) end
  - or -
   if (condition) then (condition is true action) else (condition is false action) end
  - or -
   if (condition) then (condition is true action) elseif (new condition) then (new condition is true action) end
  - or -
   if (condition) then (condition is true action) elseif (new condition) then (new condition is true action) else (new condition is false action) end

Note: the else/elseif is optional.

Your original struction included the "else" but omitted the "end"... omitting the end causes the error.

« Last Edit: January 20, 2017, 10:58:59 am by cybrmage »

Offline kwieto

  • Hero Member
  • *****
  • Posts: 624
  • Karma: +27/-15
Re: Will it work?
« Reply #7 on: January 20, 2017, 03:53:29 pm »
I do not understand your logic ... why do you can a delay with a value of 0  ... you can just call the function switch_on() there as well.

Umm, because I am freshly learning the syntax and "grammar" of Lua and didn't know other possibilities?  :-[
Searching through this forum or wiki I didn't find example of code where function is called from other function except cases where it is done with delay.

But there is something interesting here:
I've found that if I put the code just as it is in my first post (of course after corrections), it isn't executed.
The scene is triggered, but the code is simply ignored. To make it working I have to point and call one of the functions at the beginning of the code.

And I've found that the command
Code: [Select]
switch_on() works only if I call the function from another one (like from the "check" function). If I put it at the beginning of the code, nothing happens, the code still is ignored.

But if I enter
Code: [Select]
luup.call_delay( 'switch_on', 0) the code is executed and works as it should.

The final (checked and working) code is then:
Code: [Select]
luup.call_delay( 'switch_on', 0) --run the function "switch_on"

function switch_on()
    luup.call_action("urn:upnp-org:serviceId:SwitchPower1","SetTarget",{ newTargetValue="1" }, 62)  -- turn on the switch
    luup.call_delay( 'check', 120)  --wait two minutes before executing the function "check"
end

function check()
  local devStatus = luup.variable_get("urn:upnp-org:serviceId:SwitchPower1", "Status", 62) --check status of the switch
  local devOff = "0" --undesired state of the switch (OFF)
    if devStatus == devOff then  --if the switch is off then
      switch_on() --execute function "switch_on"
    end
end

I don't know, maybe there is a better way to call the "switch_on()" function at the very beginning than using luup.call_delay syntax, but writing just function name doesn't work in this case.

Offline kwieto

  • Hero Member
  • *****
  • Posts: 624
  • Karma: +27/-15
Re: Will it work?
« Reply #8 on: January 20, 2017, 04:07:56 pm »
Your original error come from the if...then structure...

Thanks for explaining all operators and syntax which I can use.

Try this - it is modified to be a target follower - keeps sending the setTarget command until the switch changes to that state...


This is interesting and I'll keep it as it is much more elastic than my original code.
Unfortunately, the WiFi switches I have seems to not support the variable "Target". If I go to variables section of the switch I see only two variables: ModeSetting and Status.
I suppose your code won't be able to check commanded state of the switch as it isn't stored anywhere, then.

Offline aa6vh

  • Hero Member
  • *****
  • Posts: 642
  • Karma: +15/-0
Re: Will it work?
« Reply #9 on: January 23, 2017, 10:13:57 am »
Where are you placing your function code? Within the scene LUA code?

Even if the functions are contained within a scene, your functions are still global functions. If you have another scene that has a function with the same function name, then there may be a conflict.

Also, scene LUA code will only be compiled when the LUA scene is first executed (after a reboot or LUA reload). So if you are referencing a function that is declared in another scene, that function may not exist yet.

This is a long winded way of saying that it is a good idea to place your functions within the LUA start up code area. That way you can see that each function has a unique name, and the startup code is always compiled immediately after a reboot/LUA reload, so the functions will exist.

Offline kwieto

  • Hero Member
  • *****
  • Posts: 624
  • Karma: +27/-15
Re: Will it work?
« Reply #10 on: January 23, 2017, 10:31:59 am »
Yes, I am placing it within the scene LUA code.

Good to know that If I use some function name in one scene, it is available globally, I will avoid potential issues.

Offline kwieto

  • Hero Member
  • *****
  • Posts: 624
  • Karma: +27/-15
Re: Will it work?
« Reply #11 on: January 25, 2017, 08:54:08 am »
Also, scene LUA code will only be compiled when the LUA scene is first executed (after a reboot or LUA reload). So if you are referencing a function that is declared in another scene, that function may not exist yet.

And this probably explains why writing
Code: [Select]
function_name() doesn't work at at the beginning of the code (the function is defined later in the code so at the time it is called it "doesn't exist") and using
Code: [Select]
luup.call_delay( 'function_name', 0) is necessary.

Offline alexlui

  • Jr. Member
  • **
  • Posts: 58
  • Karma: +0/-0
Re: Will it work?
« Reply #12 on: January 27, 2017, 04:43:24 am »
Where are you placing your function code? Within the scene LUA code?

Even if the functions are contained within a scene, your functions are still global functions. If you have another scene that has a function with the same function name, then there may be a conflict.

Also, scene LUA code will only be compiled when the LUA scene is first executed (after a reboot or LUA reload). So if you are referencing a function that is declared in another scene, that function may not exist yet.

This is a long winded way of saying that it is a good idea to place your functions within the LUA start up code area. That way you can see that each function has a unique name, and the startup code is always compiled immediately after a reboot/LUA reload, so the functions will exist.

aa6vh, So where is the LUA start up code area located ? Thanks in advance.
Vera2 (UI5), Vera3 (UI5), Vera Edge, Vera Plus

Offline kwieto

  • Hero Member
  • *****
  • Posts: 624
  • Karma: +27/-15
Re: Will it work?
« Reply #13 on: January 27, 2017, 09:28:04 am »
Go to the Apps > Develop Apps section and choose "edit startup Lua"

Whatever you will write down there it will be executed each time vera restarts.