Dear mvdarend,
Thank you very much for your solution. It did work and now have a scheduled security system. Thanks to you.
I hereby share my code for all who wish to do the same (existing security code with some minor changes of my own).
In the menu (trigger) I have created two additional options 'Hour Time when alarm should be armed' and 'Hour Time when alarm should be disarmed'.
The solution allows for human intervention at any time.
Program
//
// init program parameters
//
Program.RaiseEvent("HomeGenie.SecurityArmed", "0", "Security System");
Program.Parameter("HomeGenie.SecurityTriggered").Value = "0";
Program.Parameter("Status.Level").Value = "0";
var AlarmHourOn=(Program.InputField("Trigger.TimeAlarmOn").DecimalValue);
var AlarmHourOff=(Program.InputField("Trigger.TimeAlarmOff").DecimalValue);
var TimedAlarm=true;
//
Func<bool> _armdisarm = new Func<bool>(()=>{
Program.RunAsyncTask(()=>
{
if (Program.Parameter("Status.Level").Value == "0")
{
// disarming
Program.Parameter("HomeGenie.SecurityTriggered").Value = "0";
}
else
{
// arming
Pause( Program.InputField("System.ArmDelay").DecimalValue );
}
Program.RaiseEvent("HomeGenie.SecurityArmed", Program.Parameter("Status.Level").Value, "Security System");
// run armed/disarmed program
if (Program.Parameter("Status.Level").Value != "0")
{
var armedProgram = Program.InputField("Trigger.ArmedProgram").Value;
if (armedProgram != "")
{
Program.Run(armedProgram);
}
}
else
{
var disarmedProgram = Program.InputField("Trigger.DisarmedProgram").Value;
if (disarmedProgram != "")
{
Program.Run(disarmedProgram);
}
}
});
return true;
});
//
// module events handling
//
When.ModuleParameterChanged((module, parameter)=>
{
///vanaf hier
TimedAlarm=true;
if ((AlarmHourOff-AlarmHourOn)>=0)
{
if ((DateTime.Now.Hour<AlarmHourOn)||(DateTime.Now.Hour>=AlarmHourOff))
{
TimedAlarm=false;
}
}
else
{
if ((DateTime.Now.Hour>=AlarmHourOff)||(DateTime.Now.Hour<AlarmHourOn))
{
TimedAlarm=false;
}
}
///tot hier
if (Program.Parameter("HomeGenie.SecurityArmed").Value == "1")
{
if (module.HasFeature("HomeGenie.SecuritySensor")
&& Program.Parameter("HomeGenie.SecurityTriggered").Value != "1"
&& ( parameter.Name == "Status.Level"
|| parameter.Name == "Sensor.Generic"
|| parameter.Name == "Sensor.Tamper"
|| parameter.Name == "Sensor.MotionDetect"
|| parameter.Name == "Sensor.DoorWindow"
|| parameter.Name == "Sensor.Flood"
|| parameter.Name == "Sensor.Smoke"
|| parameter.Name == "Sensor.Heat"
|| parameter.Name == "Sensor.CarbonMonoxide"
|| parameter.Name == "Sensor.CarbonDioxide" )
&& parameter.DecimalValue > 0 && TimedAlarm)
{
Program.RaiseEvent("HomeGenie.SecurityTriggered", "1", "Security System");
Program.Parameter("HomeGenie.SecurityTriggerSource").Value =
module.Instance.Name + " " + parameter.Name + " (" +
module.Instance.Domain + "." +
module.Instance.Address + ")";
var triggeredProgram = Program.InputField("Trigger.TriggeredProgram").Value;
if (triggeredProgram != "")
{
Program.Run(triggeredProgram);
}
return false;
}
}
return true;
});
//
// web service calls handling
//
When.WebServiceCallReceived(Program.Module.Domain + "/" + Program.Module.Address, (args) => //"HomeGenie.SecuritySystem", ( args ) =>
{
string[] reqs = ((string)args).Split('/');
var res = "";
try
{
string command = reqs[2];
string pid = reqs[1];
if (pid == Program.Module.Address)
{
switch(command)
{
case "Control.On":
Program.RaiseEvent("Status.Level", "1", "Security System");
_armdisarm();
res = "{ 'ResponseValue' : 'ARMED' }";
break;
case "Control.Off":
Program.RaiseEvent("Status.Level", "0", "Security System");
_armdisarm();
res = "{ 'ResponseValue' : 'DISARMED' }";
break;
}
}
}
catch (Exception ex)
{
res = "{ 'ResponseValue' : 'ERROR: " + ex.Message + " " + ex.StackTrace + "' }";
}
// unable to process request
return res;
});
//
// main program loop
//
var sirenModules = Modules.WithFeature("HomeGenie.SecurityAlarm").OfDeviceType("Siren");
var alarmModules = Modules.WithFeature("HomeGenie.SecurityAlarm").OfDeviceType("Dimmer,Switch,Light");
while (Program.IsEnabled)
{
if (Program.Parameter("HomeGenie.SecurityTriggered").Value == "1")
{
sirenModules.On();
//
var alarmstart = DateTime.Now;
//
// send email
//
var subject = "HomeGenie Security System Alarmed";
var messagetext = "Security System Alarm triggered by " + Program.Parameter("HomeGenie.SecurityTriggerSource").Value;
var recipients = Program.InputField("Email.Recipients").Value;
if (recipients != "")
{
Program.RunAsyncTask(()=>{
Net.SendMessage(recipients, subject, messagetext);
});
}
//
var sirenstopped = false;
while (Program.Parameter("HomeGenie.SecurityTriggered").Value == "1")
{
// flashing SecurityAlarm lights
alarmModules.Toggle();
Pause(1);
alarmModules.Toggle();
Pause(1);
//
var elapsed = new TimeSpan(DateTime.Now.Ticks - alarmstart.Ticks);
if (!sirenstopped && Program.InputField("System.SirenMaxTime").DecimalValue > 0 && elapsed.TotalSeconds > Program.InputField("System.SirenMaxTime").DecimalValue)
{
sirenModules.Off();
sirenstopped = true;
}
}
//Pause(1);
alarmModules.Off();
sirenModules.Off();
}
Pause(1);
}
Trigger
Program.Setup( () => {
Program.AddControlWidget("homegenie/generic/securitysystem");
Program.AddFeature("Sensor,DoorWindow", "HomeGenie.SecuritySensor", "Use as Security Sensor");
Program.AddFeature("Siren,Light,Dimmer,Switch", "HomeGenie.SecurityAlarm", "Use as Security Alarm");
//
Program.AddInputField("System.ArmDelay", "10", "1. Arm Delay (seconds)");
Program.AddInputField("System.SirenMaxTime", "30", "2. Sirens Max Time (seconds, 0=infinite)");
Program.AddInputField("Email.Recipients", "", "3. Comma separated list of recipients e-mails for alarm notifications");
Program.AddInputField("Trigger.ArmedProgram", "", "4. Program to run when armed");
Program.AddInputField("Trigger.DisarmedProgram", "", "5. Program to run when disarmed");
Program.AddInputField("Trigger.TriggeredProgram", "", "6. Program to run when triggered");
Program.AddInputField("Trigger.TimeAlarmOn", "20", "7. Hour time to arm alarm");
Program.AddInputField("Trigger.TimeAlarmOff", "23", "8. Hour time to disarm alarm");
});
// this program will be running in background
return true;
As stated before, I am not real good in programming, so it could probably be done much cleaner. But I am already happy with the fact that is works.