more G-Labs products

Author Topic: Another wall switch question  (Read 6046 times)

September 23, 2014, 09:18:47 AM
Read 6046 times

mvdarend

  • *****
  • Information
  • Hero Member
  • Posts: 431
Hi there,

Another wall switch question from me, currently I'm using the following script to detect a change in a wall switch value (Trigger script):
Code: [Select]
var wallSwitch = Modules.WithName("Switch 1").Get();

return (wallSwitch.WasFound && wallSwitch.Parameter("Sensor.Generic").DecimalValue == 21);
This works fine, but it only works when the value of the switch has changed, not when it is pressed.

For example, I press the top right button on the switch (value 21) and the light goes on. Afterwards I press the bottom right button (value 41) and the light goes off, works perfectly.

But, when I press the top right button (value 21) and the light switches off for some other reason (time based event, switch off via app etc.) and I press the top right button again (value 21 again) the Trigger script does not return true because the value has not changed (switch value was, and still is 21)

(I hope you're still following me on this :) )

So I decided to try to catch the button pressed event with the following code in the trigger script:

Code: [Select]
When.ModuleParameterChanged( (module, parameter) =>
{
  if (module.Is("Switch 2") && parameter.DecimalValue == 21)
  {
    Program.Notify("Debug", "Top right button pressed");
    return true;
  }
  else
  {
    return false;
  }
}); 

This won't compile, I get the error ''Not all code paths return a value"

So I tried this:

Code: [Select]
bool retValue = false;
When.ModuleParameterChanged( (module, parameter) =>
{
  if (module.Is("Switch 2") && parameter.DecimalValue == 21)
  {
    Program.Notify("Debug", "Top right button pressed");
    retValue = true;
  }
  else
  {
    retValue = false;
  }
}); 
return retValue;

The Program.Notify fires, but the 'Code to Run' doesn't, retValue is always false. I realize that I'm misunderstanding how ModuleParameterChanged actually works, I'm hoping someone can point me in the right direction.

Tanks for any help.



October 18, 2014, 12:37:48 AM
Reply #1

MickEE

  • *
  • Information
  • Newbie
  • Posts: 17
    • MikaelStenstrand.com
Hard for me to test this without the hardware.
Some suggestions:

You could try to put the When.ModuleParameterChanged()-function in "Program Code" and have a simple
Code: [Select]
return true; in the "Trigger Code".

I have a IR-remote for playing/pausing music. I've used a different approach for catching these events.
First I have one program running the normal Wizard-mode. In the "Trigger Code" section, I Captured the event of a button press on the IR-remote. This program will only trigger another program, where the actual C# code is. You trigger the other program in the wizard by adding HomeAutomation.HomeGenie.Automation - Program.Run (Program ID) to the "Program Code"-section.

The other program, coded in C#, has a
Code: [Select]
return false;statement in the "Trigger Code". This is because it will be triggered by the other program. The actual code to be run is inside in the "Program Code".

Hope this helps

October 18, 2014, 07:36:40 AM
Reply #2

mvdarend

  • *****
  • Information
  • Hero Member
  • Posts: 431
Thanks for that MickEE! I'll play around with those options.

I think I'll go with the second approach (with the Wizard), as I'd like to keep the trigger and code to run separately.

I'll be away for a short vacation, but when I get back I'll give it a try and let you know how it goes.

Thanks again, Marcel.

October 20, 2014, 11:28:29 PM
Reply #3

bkenobi

  • *****
  • Information
  • Global Moderator
  • Posts: 1525
This may have to do with the LastValue code.  HG assumes that you only care when the value of an item is changed so it sometimes ignores a repeated command.  I had this issue with my Advanced Smart Lights code, so I came up with a work-around.  I added a Stuck Module Check code (when a module has been ON for more than a specified time out period, turn it off) and a Last Event code (record the LastON, LastOFF, and LastEvent as well as times of each).

You might be able to change the trigger type in order to get your code working, but if not take a look at what I put together.

October 23, 2014, 08:37:36 AM
Reply #4

mvdarend

  • *****
  • Information
  • Hero Member
  • Posts: 431
Thanks bkenobi,

I had a quick look at your Advanced Smart Lights code a while back but didn't read it completely through. (I assumed from the first couple of lines that it was mainly for sensors and such...)

Just got back from vacation late last night, so I'll try to have a look at it some time today.

thanks again

October 23, 2014, 04:30:36 PM
Reply #5

bkenobi

  • *****
  • Information
  • Global Moderator
  • Posts: 1525
Yes, the Advanced Smart Lights code is intended primarily for making a motion sensor turn on lights, but it also has more advanced switch based control as well.  It may not be directly useful for what you need to do, but snippets from the various codes might help you or someone else.

October 24, 2014, 08:28:45 AM
Reply #6

mvdarend

  • *****
  • Information
  • Hero Member
  • Posts: 431
I tried the Wizard approach mentioned by MickEE, but unfortunately that still gives the original problem. The wizard waits for a change in value before firing. (When a button is pressed on the wall switch, the wall switch value stays the same until another button is pressed, re-pressing the same button doesn't result in a 'value changed' event.)

I'm almost certain the second approach will work, but I'm not a fan of having the 'trigger' and 'code to run' all mixed up.

I'll try to look at bkenobis code today, hopefully a combination of that and MickEEs ideas will work out.

October 24, 2014, 04:52:46 PM
Reply #7

bkenobi

  • *****
  • Information
  • Global Moderator
  • Posts: 1525
The last event code is specifically intended to help with what you are experiencing.  However, since it's not built in to the main HG code, you will have to use a loop inside a C# (or similar) script to watch for commands.  It's not ideal, but Gene didn't want to modify the LastValue code to work the way I (and you) expected.  If you use the LastEvent in my script, it will give you what you are looking for.  I also included LastON and LastOff for convenience.

October 24, 2014, 05:46:37 PM
Reply #8

mvdarend

  • *****
  • Information
  • Hero Member
  • Posts: 431
Hi bkenobi,

I've just checked your code, but If I understand it correctly it is very focused on and 'on' and 'off' value. The wall switch I have is a dual paddle switch with lots of different values, for example:

Top left click 11, double click 12, hold 13, release 15
Top right click 21, double click 22, hold 23
Bottom left click 31, double click 32, hold 33
etc. etc.

So I think it will need a major rewrite to work in my situation (please correct me if I'm wrong.)

I'm going to try MickEEs first idea, let you know if it works.

Edit: MickEEs idea works perfectly!
« Last Edit: October 24, 2014, 06:02:38 PM by mvdarend »

October 24, 2014, 06:35:57 PM
Reply #9

MickEE

  • *
  • Information
  • Newbie
  • Posts: 17
    • MikaelStenstrand.com
Glad I could help  :)

October 24, 2014, 08:41:27 PM
Reply #10

bkenobi

  • *****
  • Information
  • Global Moderator
  • Posts: 1525
You are correct.  My code was written for on/off type switches that can transmit over PLC (or whatever other communication standard you use).  I don't have a multi-switch like you are looking at and the switches I have also can't transmit dim level.  You may be able to modify what I have written to your needs, but if MickEE's approach proves reliable, great!

October 24, 2014, 09:12:46 PM
Reply #11

mvdarend

  • *****
  • Information
  • Hero Member
  • Posts: 431
Thanks both of you again for your help, I really appreciate it.

October 25, 2014, 07:53:58 AM
Reply #12

MickEE

  • *
  • Information
  • Newbie
  • Posts: 17
    • MikaelStenstrand.com
Using the first mentioned approach, you can still separate the event listening from the actual code to be run. This can be done by just triggering the other module by
Code: [Select]
Program.Run("1011"); *the function takes the ID of the other module as parameter.

Or you can just separate the code by calling a function inside the same module

October 25, 2014, 09:23:36 AM
Reply #13

mvdarend

  • *****
  • Information
  • Hero Member
  • Posts: 431
Thanks MickEE, when I first tested your idea yesterday I did it with only one 'Action'. I found when adding more that the event wasn't captured for some reason. (Could it be that the first Program with a 'return true' is always 'getting in the way' of the other programs?)

I saw your new post when I was playing around with the switches this morning, I now have one program with a return true, and it catches all events from my three switches, and then calls the corresponding program. Works great!

Thanks again

Edit for others with a similar problem, here is a code example for one switch:

Trigger code C#:
Code: [Select]
return true;
Program code C#:
Code: [Select]
When.ModuleParameterChanged( (module, parameter) =>
{
  if (module.Is("Switch 1"))
  {
    // -----------------------------------------
    // Single clicks
    // -----------------------------------------
    if (parameter.DecimalValue == 11)
    {
      // Top Left, turn on Ceiling LED strip
      Program.Run("1039"); return false;
    }
    if (parameter.DecimalValue == 21)
    {
      // Top Right, turn on Dining table light
      Program.Run("1016"); return false;
    }
    if (parameter.DecimalValue == 31)
    {
      // Bottom Left, turn off Ceiling LED strip
      Program.Run("1040"); return false;
    }
    if (parameter.DecimalValue == 41)
    {
       // Bottom Right, turn off Dining table light
      Program.Run("1017"); return false;
    }
    // -----------------------------------------
    // Double Clicks
    // -----------------------------------------
    if (parameter.DecimalValue == 12)
    {
      // Top Left, Reading theme
      Program.Run("1037"); return false;
    }
    if (parameter.DecimalValue == 22)
    {
      // Top Right, All On
      Program.Run("1035"); return false;
    }
    if (parameter.DecimalValue == 32)
    {
      // Bottom Left, Concentrate
      Program.Run("1038"); return false;
    }
    if (parameter.DecimalValue == 42)
    {
      // Bottom Right, All Off
      Program.Run("1036"); return false;
    }
  }
  // if we get this far, no corresponding button has been pressed
  return true;
});

Edit: Switched true/false. See explanantion from MickEE below
« Last Edit: October 31, 2014, 08:44:02 PM by mvdarend »

October 25, 2014, 11:33:59 AM
Reply #14

MickEE

  • *
  • Information
  • Newbie
  • Posts: 17
    • MikaelStenstrand.com
If I remember correctly, the return statement of the ModuleParameterChanged-function will determine if the  thread should continue to find the trigger code for this ModuleParameterChange-event. Which means that when you have found the button presses, u should return false, and if your code didn't find the event it should return true. Ie, the opposite of what u have.