more G-Labs products

Author Topic: Generic Switch Widget - Simple (really simple) Example?  (Read 2738 times)

January 15, 2015, 05:26:38 PM
Read 2738 times

xefil

  • **
  • Information
  • Jr. Member
  • Posts: 31

Hello to all (again) :)
After having played a lot with generic thermometer sensors, it's time to make a step further and try to play with switches.
I was able to collect data from a web service and store a set of values. Then, I was able to get these values from other programs (always within HG). I would like to use a generic switch (widgets/homegenie/generic/switch) to control them.
To start deal with the switches, is there someone that could share a REALLY SIMPLE example of a switch that, when pressed ON, writes "Switch ON" in console, ans when pressed OFF, writes OFF to the console?
It should then interact, if possible, with the WEB API as well (http://xxx/api/yyy/1/Control.On)

When the switch does what above, I'll try then by myself put the rest of the code to interact with the web json.

Thanks a lot for the help!

Simon

PS: I've already seen a startup script for switches made by 'mvdarend' but cannot understood when to put the code that will be executed pressing the ON or OFF switch.

January 16, 2015, 04:47:34 PM
Reply #1

xefil

  • **
  • Information
  • Jr. Member
  • Posts: 31
Hello guys!

I'm there again but I need some help.
I was able to create a SIMPLE switch that writes in the console if pressed but have some issues.

Trigger Code:
Code: [Select]
Program.Setup(()=>{
Program.AddVirtualModules("HomeAutomation.XefilHomeArduinoSwitch", "Switch", "homegenie/generic/switch", 1, 1);
    Modules.InDomain("HomeAutomation.XefilHomeArduinoSwitch").Each((m)=>{
      return false;
    });

});

return true;

Program Code:
Code: [Select]
// CSharp Automation Program Plugin


var SettingSwitchModules = Modules.InDomain("HomeAutomation.XefilHomeArduinoSwitch");
// We want to do further processing whenever a module prop changes
When.ModuleParameterChanged( (module, property) => {
  Console.WriteLine("---");
  Console.WriteLine("Why this is matching often even if nothing is touched???");
  Console.WriteLine("---");
 
  if (module.Is("Prova Switch")) {
    Console.WriteLine("---");
    Console.WriteLine("This works, if the Switch has name 'Prova Switch' I get this line - GOOD!");
    Console.WriteLine("---");

   
    return true;
   
  }
 
  return false;
 

 
});



  // Get a value from outside this program
  var xefilSwitch = Program.WithName("xefil - XefilHomeArduino");
  var xefilSwitchStatus = xefilSwitch.Parameter("xefil.XefilHomeArduino.LeafNodeId03.Relay02").Value;
  Console.WriteLine("***********************");
  Console.WriteLine("*********************** xefil.XefilHomeArduino.LeafNodeId03.Relay02 -> " + xefilSwitchStatus);
  Console.WriteLine("***********************");

/* Often I get this error
ERROR: LogWriter could not flush log - Object reference not set to an instance of an object
  at HomeGenie.Service.Logging.SystemLogger.FlushLog () [0x00000] in <filename unknown>:0
*/

When.WebServiceCallReceived("HomeAutomation.XefilHomeArduinoSwitch", ( args ) =>
{
  string[] reqs = ((string)args).Split('/');
  string switchnumber = reqs[1];
  string command = reqs[2];

  var module = SettingSwitchModules.WithAddress(switchnumber).Get();
 
  //
  switch(command)
  {
    case "Control.On":
      Program.RaiseEvent(module, "Status.Level", "1", "SettingSwitch");
      break;
    case "Control.Off":
      Program.RaiseEvent(module, "Status.Level", "0", "SettingSwitch");
      break;
    case "Control.Toggle":
      if (module.Parameter("Status.Level").DecimalValue == 0)
      {
        Program.RaiseEvent(module, "Status.Level", "1", "SettingSwitch");
      }
      else
      {
        Program.RaiseEvent(module, "Status.Level", "0", "SettingSwitch");
      }
      break;
  }
  return "{ 'ResponseValue' : 'OK' }";   
});

Program.GoBackground();

The questions are:

1. Based on the code, how can I force every time the status of the switch to ON or OFF? I've tried in different ways but cannot :( Setting a
Code: [Select]
SettingSwitchModules.WithAddress("1").Command("Control.On").Set();
..in the 'When.WebServiceCallReceived' procedure, It creates a loop. Why? How to do that?

2. In the program code, when I call this part:
Code: [Select]
  var xefilSwitch = Program.WithName("xefil - XefilHomeArduino");
  var xefilSwitchStatus = xefilSwitch.Parameter("xefil.XefilHomeArduino.LeafNodeId03.Relay02").Value;
  Console.WriteLine("***********************");
  Console.WriteLine("*********************** xefil.XefilHomeArduino.LeafNodeId03.Relay02 -> " + xefilSwitchStatus);
  Console.WriteLine("***********************");
It's written in the Console Log only when I compile it, why??

3. I often get this error in the log, why?

ERROR: LogWriter could not flush log - Object reference not set to an instance of an object
  at HomeGenie.Service.Logging.SystemLogger.FlushLog () [0x00000] in <filename unknown>:0


4. In the program code, here:
Code: [Select]
When.ModuleParameterChanged( (module, property) => {
  Console.WriteLine("---");
  Console.WriteLine("Why this is matching often even if nothing is touched???");
  Console.WriteLine("---");
(...)
Well, why this is matching often even if nothing is touched?


Please help!

Thanks a lot!

Simon

January 16, 2015, 05:11:11 PM
Reply #2

bkenobi

  • *****
  • Information
  • Global Moderator
  • Posts: 1525
1) To turn a module on in code:
Code: [Select]
module.On();
2) You need to put your code you want run in some kind of a When statement.  If you have it sitting on it's own, it won't execute more than once.
  • When.Enabled
  • When.ModuleParameterChanged
  • etc

3) I don't use the Console.Write functions, so I can't say what the issue is.  I write to an external file for my code.  I do get sharing errors if I have that file open and HG tries to write to it.

4) The "When.ModuleParameterChanged" runs whenever any module (including programs) changes.  I'd ad an if...then statement to only look at the module(s) you care about.

January 17, 2015, 10:10:53 AM
Reply #3

xefil

  • **
  • Information
  • Jr. Member
  • Posts: 31
Hello,

There are still some issues:

1) To turn a module on in code:
Code: [Select]
module.On();

If I put
Code: [Select]
module.On(); exactly here
Code: [Select]
  var module = SettingSwitchModules.WithAddress(switchnumber).Get();
 
  module.On();  //////////////// HERE
 
  switch(command)
then the HomeGenie crashes with: 'Segmentation fault'.

2) You need to put your code you want run in some kind of a When statement.  If you have it sitting on it's own, it won't execute more than once.
  • When.Enabled
  • When.ModuleParameterChanged
  • etc
Ok, I'll look documentation for that.

3) I don't use the Console.Write functions, so I can't say what the issue is.  I write to an external file for my code.  I do get sharing errors if I have that file open and HG tries to write to it.
Ok, meanwhile I'll skip this error not considering it as caused by my program. :)

4) The "When.ModuleParameterChanged" runs whenever any module (including programs) changes.  I'd ad an if...then statement to only look at the module(s) you care about.
Ok, that's make sense. I've understood this part.

If you (or someone else) could helo me with the first question :)

Thanks!

Simon
« Last Edit: January 17, 2015, 10:13:02 AM by xefil »

January 19, 2015, 03:03:14 PM
Reply #4

xefil

  • **
  • Information
  • Jr. Member
  • Posts: 31

Hello,

After trying what suggested in this thread for my tests: http://www.homegenie.it/forum/index.php?topic=644.msg3776#msg3776
now I get 'Segmentation fault' and the program crashes.
The issue is now that I've tried to add the 'module.On()' parameter ad the beginning of a program. Now every time HG starts, after some minutes it hangs because it executes the program at startup.

What can I do for:

1. Sove the module.On() segment fault?

2. Start HG in mantenance mode to prevent start the program with the part of code, because otherwise or it crashes.

Thanks for support.

Simon


January 19, 2015, 05:37:18 PM
Reply #5

bkenobi

  • *****
  • Information
  • Global Moderator
  • Posts: 1525
I've never used ".Get()" in my code.  When I change the state of a module, I simply do:
Code: [Select]
Modules.WithAddress("A1").On();or for something more advanced:
Code: [Select]
Modules.WithFeature(SMART_LIGHT_ENABLE).WithParameter(SWITCH_NAME).Each((switch_mod)=>
{
  switch_mod.On();
});

The documentation for Get indicates that the following should work:
Code: [Select]
var strobeAlarm = Modules.WithName("Strobe Alarm").Get();
strobeAlarm.On();
I have not tried that, so I can't say.  But, your code does look right to me (assuming SettingSwitchModules is a Module type).  You might try one of the other methods to test.
« Last Edit: January 19, 2015, 05:41:58 PM by bkenobi »

January 19, 2015, 08:00:07 PM
Reply #6

xefil

  • **
  • Information
  • Jr. Member
  • Posts: 31
Hello bkneobi,

First of all, I was able to start HG again. I post the solution in case someone coud have the same issue.
Looking into programs.xml I've found the block of my program code which was causing a segment fault. This is not normale that it causes a crash, btw... then I've taken a look to the ID HG has associated to my program. Moving than in the programs folder I've deleted the <id>.dll file. The result is the program needs to be compiled again. Starting HG I was able to login, go to my program, correct the code and compile it again. All went well :)

Back to the switch issue. Now I've tried the following to turn off a switch (only the display status):

Code: [Select]
Modules.InDomain("HomeAutomation.XefilHomeArduino").WithAddress("100").Off();

This refers to:
Code: [Select]
{
   "Name": "TEST123",
   "Description": "",
   "DeviceType": "Switch",
   "Domain": "HomeAutomation.XefilHomeArduino",
   "Address": "100",
   "Properties": [
       {
           "Name": "HomeGenie.ScheduleControl",
           "Description": "",
           "Value": "",
           "UpdateTime": "2015-01-19 18:46:16Z"
       },
       {
           "Name": "HomeGenie.ScheduleOff",
           "Description": "",
           "Value": "",
           "UpdateTime": "2015-01-19 18:46:16Z"
       },
       {
           "Name": "HomeGenie.ScheduleOn",
           "Description": "",
           "Value": "",
           "UpdateTime": "2015-01-19 18:46:16Z"
       },
       {
           "Name": "HomeGenie.SecurityAlarm",
           "Description": "",
           "Value": "",
           "UpdateTime": "2015-01-19 18:46:16Z"
       },
       {
           "Name": "HomeGenie.SmartLights.CheckLuminosity",
           "Description": "",
           "Value": "",
           "UpdateTime": "2015-01-19 18:46:16Z"
       },
       {
           "Name": "HomeGenie.SmartLights.Enable",
           "Description": "",
           "Value": "",
           "UpdateTime": "2015-01-19 18:46:16Z"
       },
       {
           "Name": "HomeGenie.SmartLights.OnMotionDetect",
           "Description": "",
           "Value": "",
           "UpdateTime": "2015-01-19 18:46:16Z"
       },
       {
           "Name": "HomeGenie.SmartLights.SwitchOffTimeout",
           "Description": "",
           "Value": "",
           "UpdateTime": "2015-01-19 18:46:16Z"
       },
       {
           "Name": "HomeGenie.TurnOffDelay",
           "Description": "",
           "Value": "",
           "UpdateTime": "2015-01-19 18:46:16Z"
       },
       {
           "Name": "MobileNotification.SendChanges",
           "Description": "",
           "Value": "",
           "UpdateTime": "2015-01-19 18:46:16Z"
       },
       {
           "Name": "VirtualMeter.Watts",
           "Description": "",
           "Value": "0",
           "UpdateTime": "2015-01-19 18:46:16Z"
       },
       {
           "Name": "VirtualModule.ParentId",
           "Description": "",
           "Value": "1007",
           "UpdateTime": "2015-01-19 18:49:03Z"
       },
       {
           "Name": "Widget.DisplayModule",
           "Description": "",
           "Value": "homegenie/generic/switch",
           "UpdateTime": "2015-01-19 18:44:38Z"
       }   ],
   "RoutingNode": ""
},

Why the switch doesn't change status?
The widget is created in another program (domain: HomeAutomation.XefilHomeArduino) and I'm trying to change that value from this program (domain: HomeAutomation.XefilHomeArduinoSwitch).
I've noticed It's missing this attribute:

Code: [Select]
       {
           "Name": "Status.Level",
           "Description": "",
           "Value": "0",
           "UpdateTime": "2015-01-19 16:36:40Z"
       },

Does it have someting to do?

Is it possible I'm missing this parameter because I'm creating two types of VirtualModules from the same program?

Code: [Select]
  // create 9 virtual modules in the domain HomeAutomation.Arduino with address from 1 to 10
  Program.AddVirtualModules("HomeAutomation.XefilHomeArduino", "Sensor", "homegenie/generic/sensor", 1, 10);
 
  // create virtual modules in the domain HomeAutomation.Arduino with address from 100 to 112
  Program.AddVirtualModules("HomeAutomation.XefilHomeArduino", "Switch", "homegenie/generic/switch", 100, 112);


To be more precise, on program 1 (domain: HomeAutomation.XefilHomeArduino) I'm collecting informations via json parser and creating virtualmodules of type sensor and switch. This program runs every 500secs to update these values.
Then, program 2 (domain: HomeAutomation.XefilHomeArduinoSwitch) should take care about the switches. It should load the values of the switch from program 1 (domain: HomeAutomation.XefilHomeArduino) and, if pressed, change the status.
For now I would be happy only to change in program 2 the status from the switch statically and I should see in the dashboard On or Off (statically) up on what I've written in the code of program 2:

OFF:
Code: [Select]
Modules.InDomain("HomeAutomation.XefilHomeArduino").WithAddress("100").Off();

OR ON:
Code: [Select]
Modules.InDomain("HomeAutomation.XefilHomeArduino").WithAddress("100").On();

BTW changing the values I cannot obtain any result.

Ideas?

Thank's a lot!

Whole code:
Code: [Select]
// CSharp Automation Program Plugin
// Example for using Helper Classes:
// Modules.WithName("Light 1").On();

// Initialise parameters (Status Off)


var SettingSwitchModules = Modules.InDomain("HomeAutomation.XefilHomeArduinoSwitch");

Modules.InDomain("HomeAutomation.XefilHomeArduino").WithAddress("100").Off();   ///////////// HERE!!!

// We want to do further processing whenever a module prop changes
When.ModuleParameterChanged( (module, property) => {
  Console.WriteLine("---");
  Console.WriteLine("Why this is matching often even if nothing is touched???");
  Console.WriteLine("---");
 
  if (module.Is("Prova Switch")) {
    Console.WriteLine("---");
    Console.WriteLine("This works, if the Switch has name 'Prova Switch' I get this line");
    Console.WriteLine("---");
   
    return true;
   
  }
 
  return false;
 

 
});



When.WebServiceCallReceived("HomeAutomation.XefilHomeArduinoSwitch", ( args ) =>
{
  string[] reqs = ((string)args).Split('/');
  string switchnumber = reqs[1];
  string command = reqs[2];

  var module = SettingSwitchModules.WithAddress(switchnumber).Get();
 
 
  //
  switch(command)
  {
    case "Control.On":
      Program.RaiseEvent(module, "Status.Level", "1", "SettingSwitch");
      break;
    case "Control.Off":
      Program.RaiseEvent(module, "Status.Level", "0", "SettingSwitch");
      break;
    case "Control.Toggle":
      if (module.Parameter("Status.Level").DecimalValue == 0)
      {
        Program.RaiseEvent(module, "Status.Level", "1", "SettingSwitch");
      }
      else
      {
        Program.RaiseEvent(module, "Status.Level", "0", "SettingSwitch");
      }
      break;
  }
  return "{ 'ResponseValue' : 'OK' }";   
});

Program.GoBackground();


« Last Edit: January 19, 2015, 10:21:11 PM by xefil »