HomeGenie Forum
Automation Program Plugins and Wizard Scripting => Help => Topic started by: Boeky on May 28, 2014, 10:40:36 AM
-
Hi,
Now that I've managed to get the MCP23017 working correctly, I started writing a SmartControl module to use the inputs of the MCP23017 as control buttons :
1 button mode :
short press (<2seconds) -> Toggle On and Off
long press (>2seconds) -> change the level by +5 or -5, changing bright and dim every time i release the button
(sensors are working inversed for now : so they are at 1 all the time and a key press sets them to 0)
The program I made so far work without errors but when it is entering the long press loop it changes the module level by 5 every 10 seconds or more instead of the pause of 1 second.
Am I doing it right or do i loch up some other triggers by programming this way?
var SMART_CONTROL_ENABLE = "HomeGenie.SmartControl.Enable";
var SENSOR_NAME = "HomeGenie.SmartControl.PushSensor";
var smart_devices = Modules.WithFeature(SMART_CONTROL_ENABLE);
//
When.ModuleParameterIsChanging((module, parameter) => {
if (module.IsOfDeviceType("Sensor"))
{
if (parameter.Name == "Status.Level")
{
var motionlevel = parameter.DecimalValue;
if (motionlevel < 1)
{
smart_devices.Each((mod)=>
{
if (mod.Parameter(SENSOR_NAME).Value == module.Instance.Name)
{
Pause(1);
if (module.Level == 0)
{
while(module.Level == 0)
{
mod.Level = (mod.Level - 5);
// If i set a pause of 1 second it somhow takes 10 seconds
//Pause(1);
}
}
else {
mod.Toggle();
}
//if (mod.Level == 0)
//{
//Program.Notify("Smart Control", module.Instance.Name + "<br> Toggled " + mod.Instance.Address + " " + mod.Instance.Name);
//}
}
//
return false;
});
}
else
{
// timeout before turning it off
}
}
}
return true;
});
Program.GoBackground();
Thanks,
Christophe
-
When the button is released (Status.Level == 1 in your case) you can measure the press duration by simply diffing these two dates:
var endTime = parameter.UpdateTime; // this is the timestamp of button release
var startTime = parameter.LastUpdateTime; // this is the timestamp of button press
var pressDuration = endTime - startTime;
if (pressDuration.TotalSeconds > 2)
{
// is a long press
}
else
{
// is a short press
}
So you don't need to use a loop. In general it's best to avoid long time tasks inside the event handler.
Hope this helps.
g.
-
Hi,
I tried implementing the code but nothing works. Not even a switch on or off.
It also seems that your code invokes only once after the button is released,
What I need is something that works like this :
Short press : Toggle command
Long press : dimming or brightning by 5 command in a loop of each second as long as i hold the key. After releasing the loop should stop.
The problem is that the code works fine but it is executing the commands of the loop only once every 10 - 20 seconds instead of 1 second...
I already tried running an asynctask but the problem remains...
Thanks,
Christophe
-
Try this:
var SMART_CONTROL_ENABLE = "HomeGenie.SmartControl.Enable";
var SENSOR_NAME = "HomeGenie.SmartControl.PushSensor";
int LEVEL_ON = 0;
int LONG_PRESS_SECONDS = 2;
var smart_devices = Modules.WithFeature(SMART_CONTROL_ENABLE);
//
When.ModuleParameterIsChanging((module, parameter) =>
{
// TODO: the sensor buttons should also be marked with a specific feature
if (module.IsOfDeviceType("Sensor"))
{
if (parameter.Name == "Status.Level")
{
var sensorLevel = parameter.DecimalValue;
// store the initial timestamp
var levelTimestamp = parameter.UpdateTime.Ticks;
if (sensorLevel == LEVEL_ON)
{
Program.RunAsyncTask(() =>
{
// wait for the long press delay
Pause(LONG_PRESS_SECONDS);
// while the button is kept pressed...
while (levelTimestamp == parameter.UpdateTime.Ticks)
{
// Dim all SmartControl enabled dimmers by 5%
smart_devices.Each((mod) =>
{
if (mod.Parameter(SENSOR_NAME).Value == module.Instance.Name)
{
mod.Level -= 5;
}
return false;
});
}
});
}
else
{
// timeout before turning it off
var endTime = parameter.UpdateTime;
var startTime = parameter.LastUpdateTime;
var pressDuration = new TimeSpan(endTime.Ticks - startTime.Ticks);
// short press
if (pressDuration.TotalSeconds < LONG_PRESS_SECONDS)
{
smart_devices.Each((mod) =>
{
if (mod.Parameter(SENSOR_NAME).Value == module.Instance.Name)
{
mod.Toggle();
}
return false;
});
}
}
}
}
return true;
});
Program.GoBackground();
I cannot test it right now because my only develop raspi is into the Touch Panel.
But this is the way the code should work.
Cheers,
g.
-
Hi Christophe,
did you succeed in getting this to work?
Cheers,
g.
-
Hi Gene,
I didn't had the time to try your code for now.
I'll let you know if it works as soon as I can continu this week.
Thanks for the great support.
-
Hi gene,
I tested your code but it gives exact the same problem as my code :
On and Off works great but when I dim (holding button down for more then 2 seconds) it starts dimming by 5 but it lowers the value with 5 every 10 or more seconds... The pauses between lowering are getting longer and longer each time it lowers by 5. Actually there is not any fixed time between them The time is random it is just getting longer and longer as long as you keep holding the button...
The program itself works but I dont know why it takes more then 10 seconds ...
Overview Logfile
14:00:37.896 Status.Level 0 5 Components.MCP23017 (RELEASE BUTTON)
14:00:35.845 Status.Level 0.74 B1 HomeAutomation.X10
14:00:25.785 Status.Level 0.78 B1 HomeAutomation.X10
14:00:25.785 Status.Level 0.78 B1 HomeAutomation.X10
14:00:15.845 Status.Level 0.82 B1 HomeAutomation.X10
14:00:05.819 Status.Level 0.86 B1 HomeAutomation.X10
13:59:55.750 Status.Level 0.9 B1 HomeAutomation.X10
13:59:55.750 Status.Level 0.9 B1 HomeAutomation.X10
13:59:47.725 Status.Level 0.95 B1 HomeAutomation.X10
13:59:45.698 Status.Level 1 5 Components.MCP23017 (PRESS AND HOLD BUTTON)
13:59:43.17 Status.Level 1 B1 HomeAutomation.X10 (MODULE ON TO START DIMMING)
13:59:42.979 Status.Level 0 5 Components.MCP23017
13:59:42.707 Status.Level 1 5 Components.MCP23017 (SHORT PRESS BUTTON)
13:59:38.113 Status.Level 0 B1 HomeAutomation.X10 (MODULE OFF)
13:59:38.100 Status.Level 0 5 Components.MCP23017
13:59:37.874 Status.Level 1 5 Components.MCP23017 (SHORT PRESS BUTTON)
13:59:33.921 Status.Level 1 B1 HomeAutomation.X10 (MODULE ON)
13:59:33.905 Status.Level 0 5 Components.MCP23017
13:59:33.677 Status.Level 1 5 Components.MCP23017 (SHORT PRESS BUTTON)
Thanks,
Christophe
-
Let's do some tests.
Change this piece of code
// while the button is kept pressed...
while (levelTimestamp == parameter.UpdateTime.Ticks)
{
// Dim all SmartControl enabled dimmers by 5%
smart_devices.Each((mod) =>
{
if (mod.Parameter(SENSOR_NAME).Value == module.Instance.Name)
{
mod.Level -= 5;
}
return false;
});
}
to this:
// while the button is kept pressed...
while (levelTimestamp == parameter.UpdateTime.Ticks)
{
// Dim all SmartControl enabled dimmers by 5%
Program.Notify("SmartControl", "Dimming by 5%");
}
Then try it and see the log.
This is just to understand where is the cause of the excessive delay.
Probably the Each or the mod.Parameter(SENSOR_NAME) is taking lot of time.
So we can either optimize these functions, or selecting the modules before entering the loop, so that no other time-consuming operations are made inside the loop.
Cheers,
g.
-
Hi Gene,
The first attempt of your code resulted in a script lock because there was no pause and the Notify was executed too much so Internet Explorer forced te script to stop and reloaded the webpage.
So I added a Pause of 1 second and this looks better :
14:58:06.966 Status.Level 0 5 Components.MCP23017 (WHY 3 TIMES ?)
14:58:06.966 Status.Level 0 5 Components.MCP23017
14:58:06.966 Status.Level 0 5 Components.MCP23017 (BUTTON RELEASE)
14:58:06.606 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:58:05.605 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:58:04.604 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:58:03.603 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:58:02.603 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:58:01.602 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:58:00.601 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:59.600 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:58.600 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:57.599 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:56.598 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:55.598 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:54.597 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:53.596 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:52.595 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:51.595 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:50.594 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:49.559 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:48.559 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:48.559 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:47.558 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:46.557 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:45.556 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:44.556 SmartControl Dimming by 5% 1001 HomeAutomation.HomeGenie.Automation
14:57:42.543 Status.Level 1 5 Components.MCP23017 (START PRESS AND HOLD)
14:57:38.999 Status.Level 1 B1 HomeAutomation.X10 (MODULE ON TO START DIMMING)
14:57:38.986 Status.Level 0 5 Components.MCP23017
14:57:38.761 Status.Level 1 5 Components.MCP23017 (SHORT PRESS)
14:57:36.998 Status.Level 0 B1 HomeAutomation.X10 (MODULE OFF)
14:57:36.981 Status.Level 0 5 Components.MCP23017
14:57:36.761 Status.Level 1 5 Components.MCP23017 (SHORT PRESS)
14:57:32.911 Status.Level 1 B1 HomeAutomation.X10 (MODULE ON)
14:57:32.894 Status.Level 0 5 Components.MCP23017
14:57:32.663 Status.Level 1 5 Components.MCP23017 (SHORT PRESS)
SO I'm trying to declare a targetModule out of the RunAsyncTask Scope now but it is still inside the 'smart_devices.Each((mod) =>' scope so I cannot acces is from the AsyncTask Scope. How do I declare the variable outside the Scope so I can acces it within the asynctask Scope?
Thanks
-
Wait a minute =)
Since the cause seems to be the "Each" function I suggest the following:
// After the 2 seconds delay let's buid the modules list
if (levelTimestamp == parameter.UpdateTime.Ticks)
{
var smartModules = new List<ModuleHelper>();
smart_devices.Each((mod) =>
{
if (mod.Parameter(SENSOR_NAME).Value == module.Instance.Name)
{
smartModules.Add(mod);
}
return false;
});
// while the button is kept pressed...
while (levelTimestamp == parameter.UpdateTime.Ticks)
{
// Dim all SmartControl enabled dimmers by 5%
foreach(var mod in smartModules)
{
mod.Level -= 5;
}
}
}
That way the Each function will be called just once. You don't need to use RunAsyncTask.
The Each function seem to be slow on raspberry since it's not just iterating modules, but also filtering agaist all the filters applied to the selection.
So it's best to call it just once, before doing the dim job.
Cheers,
g.
-
Gene,
Do you think this could be part of why the X10 speed is slow for me? I'm using the Each command there as well. I know you optimized X10 quite a bit, but it seemed like there was a little variation that could be either very quick or a little bit slow (not 10 seconds any more, but 1-2 maybe).
-
Hi Ben,
yes it could.
-
Interesting. I'll have to look at moving the code out of the Each loops then.
-
But again, the problem remains...
LOGBOOK
20:17:14.742 Status.Level 0 5 Components.MCP23017 (RELEASE BUTTON)
20:17:13.162 Status.Level 0.78 B1 HomeAutomation.X10
20:17:03.116 Status.Level 0.82 B1 HomeAutomation.X10
20:16:53.100 Status.Level 0.86 B1 HomeAutomation.X10
20:16:43.83 Status.Level 0.9 B1 HomeAutomation.X10
20:16:38.775 Status.Level 0.95 B1 HomeAutomation.X10
20:16:36.751 Status.Level 1 5 Components.MCP23017 (PRESS EN HOLD)
20:16:34.457 Status.Level 1 B1 HomeAutomation.X10 (MODULE ON)
20:16:34.435 Status.Level 0 5 Components.MCP23017
20:16:34.209 Status.Level 1 5 Components.MCP23017 (SHORT PRESS)
SOURCE CODE
var SMART_CONTROL_ENABLE = "HomeGenie.SmartControl.Enable";
var DIGITAL_INPUT_MODULE_NAME = "HomeGenie.SmartControl.DigitalInputModule";
//var DIGITAL_OUTPUT_MODULE_NAME = "HomeGenie.SmartControl.DigitalOutputModule";
int LEVEL_ON = 1;
int LONG_PRESS_SECONDS = 2;
//
var smart_devices = Modules.WithFeature(SMART_CONTROL_ENABLE);
//
When.ModuleParameterIsChanging((module, parameter) => {
// Adding a confirmation LED for Niko buttons with LED
// The feature works but is currently disabled for testing the press an hold function
//if (module.HasFeature(SMART_CONTROL_ENABLE) && module.Parameter(DIGITAL_OUTPUT_MODULE_NAME).Value != "" && parameter.Name == "Status.Level")
//{
//if(parameter.DecimalValue > 0)
//{
// Modules.WithName(module.Parameter(DIGITAL_OUTPUT_MODULE_NAME).Value).On();
//}
//else
//{
// Modules.WithName(module.Parameter(DIGITAL_OUTPUT_MODULE_NAME).Value).Off();
// }
//}
// PRESS EN HOLD FUNCTION
// TODO: the sensor buttons should also be marked with a specific feature
if (module.IsOfDeviceType("Sensor"))
{
if (parameter.Name == "Status.Level")
{
var sensorLevel = parameter.DecimalValue;
var levelTimestamp = parameter.UpdateTime.Ticks;
if (sensorLevel == LEVEL_ON)
{
Pause(LONG_PRESS_SECONDS);
if (levelTimestamp == parameter.UpdateTime.Ticks)
{
var smartModules = new List<ModuleHelper>();
smart_devices.Each((mod) =>
{
if (mod.Parameter(DIGITAL_INPUT_MODULE_NAME).Value == module.Instance.Name)
{
smartModules.Add(mod);
}
return false;
});
// while the button is kept pressed...
while (levelTimestamp == parameter.UpdateTime.Ticks)
{
// Dim all SmartControl enabled dimmers by 5%
foreach(var mod in smartModules)
{
mod.Level -= 5;
}
}
}
}
else
{
// SHORT PRESS FUNCTION -> Works
// timeout before turning it off
var endTime = parameter.UpdateTime;
var startTime = parameter.LastUpdateTime;
var pressDuration = new TimeSpan(endTime.Ticks - startTime.Ticks);
// short press
if (pressDuration.TotalSeconds < LONG_PRESS_SECONDS)
{
smart_devices.Each((mod) =>
{
if (mod.Parameter(DIGITAL_INPUT_MODULE_NAME).Value == module.Instance.Name)
{
mod.Toggle();
}
return false;
});
}
}
}
}
return true;
});
Program.GoBackground();
-
MMmm.... so that was not the Each function! =/
Can you try a new script with just these instructions:
var dimmer = Modules.WithAddress("B1").Get();
dimmer.On();
Pause(1);
dimmer.Level -= 5;
dimmer.Level -= 5;
dimmer.Level -= 5;
dimmer.Level -= 5;
dimmer.Level -= 5;
dimmer.Level -= 5;
dimmer.Level -= 5;
Pause(1);
dimmer.Off();
Cheers,
g.
-
Hi Gene,
Ok the problem seems to be the Level function itself...
Does it wait for a response of the X10 USB module? Because it is not connected at the time...
LOGBOOK
22:12:33.483 Program.Status Idle 1002 HomeAutomation.HomeGenie.Automation
22:12:13.448 Status.Level 0.7 B1 HomeAutomation.X10
22:12:03.332 Status.Level 0.74 B1 HomeAutomation.X10
22:11:53.315 Status.Level 0.78 B1 HomeAutomation.X10
22:11:43.357 Status.Level 0.82 B1 HomeAutomation.X10
22:11:43.357 Status.Level 0.82 B1 HomeAutomation.X10
22:11:33.340 Status.Level 0.86 B1 HomeAutomation.X10
22:11:23.324 Status.Level 0.9 B1 HomeAutomation.X10
22:11:14.305 Status.Level 0.95 B1 HomeAutomation.X10
22:11:11.499 Status.Level 1 B1 HomeAutomation.X10
22:11:11.475 Program.Status Running 1002 HomeAutomation.HomeGenie.Automation
-
Hi Gene,
I connected the CM15PRO USB Module and now it seems to work much much faster.
So I guess the Level function waits for a response somehow?
Why exactly is there 1 second between the the comands as there is no Pause(1) programmed?
LOGBOOK / Testcode Dimmer
22:28:07.141 Program.Status Idle 1002 HomeAutomation.HomeGenie.Automation
22:28:05.637 Status.Level 0 B1 HomeAutomation.X10
22:28:03.623 Status.Level 0.7 B1 HomeAutomation.X10
22:28:02.718 Status.Level 0.74 B1 HomeAutomation.X10
22:28:01.712 Status.Level 0.78 B1 HomeAutomation.X10
22:28:00.707 Status.Level 0.82 B1 HomeAutomation.X10
22:27:59.802 Status.Level 0.86 B1 HomeAutomation.X10
22:27:58.777 Status.Level 0.9 B1 HomeAutomation.X10
22:27:57.271 Status.Level 0.95 B1 HomeAutomation.X10 (7 seconds ? Not Always there)
22:27:50.431 Status.Level 1 B1 HomeAutomation.X10
22:27:50.191 Program.Status Running 1002 HomeAutomation.HomeGenie.Automation
LOGBOOK / Press & hold function
22:42:00.392 Status.Level 0 5 Components.MCP23017 (RELEASE)
22:41:59.788 Status.Level 0.38 B1 HomeAutomation.X10
22:41:58.783 Status.Level 0.42 B1 HomeAutomation.X10
22:41:57.778 Status.Level 0.46 B1 HomeAutomation.X10
22:41:56.873 Status.Level 0.5 B1 HomeAutomation.X10
22:41:55.868 Status.Level 0.54 B1 HomeAutomation.X10
22:41:54.863 Status.Level 0.58 B1 HomeAutomation.X10
22:41:53.943 Status.Level 0.62 B1 HomeAutomation.X10
22:41:52.938 Status.Level 0.66 B1 HomeAutomation.X10
22:41:52.30 Status.Level 0.7 B1 HomeAutomation.X10
22:41:51.25 Status.Level 0.74 B1 HomeAutomation.X10
22:41:50.20 Status.Level 0.78 B1 HomeAutomation.X10
22:41:49.115 Status.Level 0.82 B1 HomeAutomation.X10
22:41:48.110 Status.Level 0.86 B1 HomeAutomation.X10
22:41:47.105 Status.Level 0.9 B1 HomeAutomation.X10
22:41:46.400 Status.Level 0.95 B1 HomeAutomation.X10
22:41:44.320 Status.Level 1 5 Components.MCP23017 (PRESS &HOLD)
Thanks again for the great support,
Christophe
-
Hi Boeky,
yes HG waits for acknowledge message from the interface after sending a command.
It will wait for a maximum time of 5 seconds.
You and bkenobi are making me think that another approach could be to ignore the acknowledge message and just wait 500ms before sending the next command, regardless of the ack (I already tested that CM15 can do this, while CM11 cannot ignore acks).
If you want, I can post a modified version of XTenLib for you to test.
Cheers,
g.
-
Hi Gene,
Yes i'm interested in a modified XTenLib dll file as long as you can provide me with some installation instructions on a raspbian pi 2 as my linux skills are far from good :-)
The pause of 1 second (altough it is not programmed) between the dim steps are making the dimming not fluent... so changing to burst commands will definately fasten up things.
As I already told in http://www.homegenie.it/forum/index.php?topic=222.0 (http://www.homegenie.it/forum/index.php?topic=222.0) I am using twm4 x10 modules behind my buttons. They are sending Dim(5) or Bright (5) commands way faster then 500ms on the 230V net and ActiveHome (software for the CM15pro) is handling this very fast...
Also the LW12 x10 dimmers store the last dim level. When you turn on an x10 dimmer with homegenie, homegene resets the level to 100 with only sending the on command. The lw12 receives the on command and turns on to the last level dim level so they are out of sync (except if you use the always bright to 100 option of course)
It is possible to ask the current level status with extended x10 codes (but not all x10 modules support this, only the expensive ones)
Is there any way homegenie can sync the level when turning on a dimmer module?
Thanks already for all your help,
Kind Regards,
Christophe.
-
Swapping the library is easy once you get the file on the Raspberry Pi. I installed Samba to do this, but it requires some steps. If there's a way to use wget from Raspi, things would be much simpler.
-
Hi Gene,
Any news for the modified XTenLib already?
Thanks,
Christophe.
-
Hi Christope,
it will take some time since right now I'm taking care of some other tasks.
Let you know.
Cheers,
g.