more G-Labs products

Author Topic: How to make a program run only once (v496)  (Read 2456 times)

October 13, 2015, 06:54:13 AM
Read 2456 times

mvdarend

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

I have a number of programs running at set times to switch the lights on. In earlier versions of HomeGenie I could set the script to 'Run when switches to true' (something like that), but that option is no longer available in v496

Is it still possible to set this in some way? Now my new programs are behaving like 'Run when equals true' in earlier versions, ie. they are running every second while the scheduler value is true.

October 13, 2015, 08:10:08 AM
Reply #1

JerryR

  • *
  • Information
  • Newbie
  • Posts: 20
I have the same issue. Prior to upgrading to 1.1 I used the trigger mechanism.
Now with 1.1 I only have access to "Startup Code" and "Program Code".
I was thinking that Startup Code would only run once but in fact it seems to run over and over all the time.
So, that didn't help me solve this problem.

I tried the helper function When.ModuleParameterChanged but that didn't seem to work as expected.

So, I'min the same boat - trying to figure out how to script a program in C# that will send out a message ONCE when my window/door switch changes state to 'open'. I don't want it to send the message over and over while the window/door is open so I need it to run just once and then reset when the window/door closes.

I tried setting up a static variable to use for that purpose but the compiler doesn't seem to understand static variables.

I can't seem to find any documentation on the relationship between those two tabs "Startup Code" and "Program Code" but please let me know if you figure it out.

Hoping we can get some answers for how to do this soon.

Jerry


October 13, 2015, 11:39:31 AM
Reply #2

mvdarend

  • *****
  • Information
  • Hero Member
  • Posts: 431
Two possible workarounds:

- For switching lights/switches etc. I've modified the program to check the current value, if it's not what I want it to be switch, otherwise ignore.

- [ugly workaround] Do your thing in the program and then Pause(60);. Not pretty, but it might work for scheduler events. (or will it run in a new thread every second)

October 13, 2015, 05:08:26 PM
Reply #3

bkenobi

  • *****
  • Information
  • Global Moderator
  • Posts: 1525
Can't you check that the current time is the scheduled time?  If it is, then run your code.  Make sure there's a pause of 30-60 seconds so it won't run 60+ times in that scheduled minute.  I hadn't noticed the change but that's how the scheduled events APP is/was written.

October 13, 2015, 06:55:08 PM
Reply #4

JerryR

  • *
  • Information
  • Newbie
  • Posts: 20
Under the previous version of Home Genie there were triggers to cause your code to run but they seem to have been removed.
For window/door sensors, the goal is to execute some software (ONE time) when the sensor changes state.
I was hoping there was still a means to do that without resulting to timers and such.

I could do it with a static variable like "has_run" and set that to true the first time the code runs when the sensor is triggered and then not run again until it is false. Set it to false when the sensor is reset. However, the language in HG doesn't seem to support such a static variable. All variables I have been able to allocate either in the "Startup Code" or "Program Code" windows seem to be treated like local variables and they are created and initialized each time they are called. So that doesn't help the code to remember what state it was in the last time.

I'm guessing Gene has a way to do this - I can't imagine he or the other supporters who write HG code would take away such a feature but I'm guessing it's more that I just don't understand the new environment and how to work in it.

So, I am hoping someone more familiar with the new HG method of invoking our code can tell us how to do this relatively simple thing - run some code one time when an external switch changes state.

Jerry
p.s. thanks for the suggestions but I don't think they will work in my situation

October 13, 2015, 07:03:05 PM
Reply #5

mvdarend

  • *****
  • Information
  • Hero Member
  • Posts: 431
I've found a way to get it to work again I'm just not sure how long it will stay supported, this is what you need to do:

- Find the program you want to change and Export it.
- Open the downloaded .hgx file in your favorite text editor.
- Find the ConditionType node, it should look like this: <ConditionType>OnTrue</ConditionType>
- Change OnTrue to OnSwitchTrue
- Save, Import and then delete the old program

Not the greatest solution, but it works :)

* Edit: Another way is to directly edit the Programs.xml file in the HomeGenie root folder.
« Last Edit: October 13, 2015, 07:07:39 PM by mvdarend »

October 13, 2015, 07:10:59 PM
Reply #6

JerryR

  • *
  • Information
  • Newbie
  • Posts: 20
I just found this page and it looks helpful. I thought I would pass it along in case it helps you. At least it defines some of the new things in terms of C# programming.

http://genielabs.github.io/HomeGenie/programs.html

October 13, 2015, 07:15:56 PM
Reply #7

mvdarend

  • *****
  • Information
  • Hero Member
  • Posts: 431
Thanks, that's great. I hadn't seen that page yet it must be new.

Code: [Select]
// Run the program every day at 7 am
if (Scheduler.IsScheduling("0 7 * * *"))
    Program.Run();

Is the new way of doing things, I just hope that the program will only run once...:)
« Last Edit: October 13, 2015, 07:26:51 PM by mvdarend »

October 14, 2015, 06:31:51 AM
Reply #8

JerryR

  • *
  • Information
  • Newbie
  • Posts: 20
I found this approach worked but I am putting all of my operational code in the Startup Code section.
It seems like I should be putting some of this in the Program Code section.

However, I guess if it works, it works.
I originally had the email sending portion of the code below in the Program Code section but I couldn't get it to run - ever.
I even added the Program.Run() command to the Startup Code but it would not seem to invoke the Program Code section.
So, anyway, for what it's worth, here you go and I hope it is helpful to you.
You can just replace the email section with whatever it is you want to do.
In my case it was email me when a switch changed status to "1" (open).
Good luck!

When.ModuleParameterChanged( (module, parameter) =>
{
    if (module.Is("Test Sensor") && parameter.Is("Status.Level")) // If my Test Sensor had a status change...
    {
      if( module.Parameter("Status.Level").Value == "1" ) // and if it changed to a "1" meaning it opened...
      {
       Program.Notify("Test Sensor", "Triggered");            // then do all this stuff.... pop up a msg and send an email
       string smtpserver = "smtp.your_email_server.com";   
       Net.MailService(smtpserver,587,false).WithCredentials("your_email@your_site.com", "your_email_password")
       .SendMessage("your_email_address",           //from
        "email_recipient_address",   // recipients
        "Your_subject_for_the_msg",                          // subject
        "Message_text");        // message text
       Program.Run(); // I tried to use this to run the Program Code section of this program - but it didn't seem to work - a notification I had there never ran
       return false; // I'm not sure what returning false vs. true does for you. It didn't seem to make any difference in this code.
      }
      return true;
    }
    return true;
});

October 14, 2015, 07:06:33 AM
Reply #9

mvdarend

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

I think I was misunderstanding what your problem was. With the code example you've given I usually do it like this:

Startup Code:
Code: [Select]
return true; // Tell HG to run the 'Program Code'
// In version 1.1 it should no be Program.Run(); apparently, but return true still works

Program Code:
Code: [Select]
When.ModuleParameterChanged( (module, parameter) =>
                            {                             
                              if (module.Is("Front door sensor"))
                              {   
                                if(parameter.Name == "Sensor.MotionDetect" && parameter.Value == "1")
                                {     
                                  // Do your stuff

                                  return false; // return False to tell HG to stop searching
                                }
                              }
                              return true; // return True to tell HG to keep searching.
                            });

Basically the returning false or true tells the HomeGenie engine whether or not to keep searching for another ModuleParameterChanged for this module. If you've found and processed what you need, returen false, otherwise return true.

It's possible that ModuleParameterChanged should now be contained in the Startup code from version 1.1 on, but I'm not sure if that's how Gene envisioned how it should now work.
« Last Edit: October 14, 2015, 07:14:03 AM by mvdarend »

October 15, 2015, 06:07:20 AM
Reply #10

JerryR

  • *
  • Information
  • Newbie
  • Posts: 20
mvdarend,

Thank you very much! I appreciate your sharing this with me. I will give it a try.
My solution is working and does not appear to have any problems but I would like to learn how to more properly use HG.

Thanks again and I will try it.

Jerry

October 19, 2015, 12:00:17 AM
Reply #11

JerryR

  • *
  • Information
  • Newbie
  • Posts: 20
I have been running this code and it works great (when my CM15 is working ;) ) but I have found that I get two triggers of the operational code each time the remote sensor changes state. I'm not quite sure why that is happening. Any ideas?

Thanks!
Jerry