diff --git a/fhem/FHEM/95_Alarm.pm b/fhem/FHEM/95_Alarm.pm index 3ef9c0431..a32a5ce25 100644 --- a/fhem/FHEM/95_Alarm.pm +++ b/fhem/FHEM/95_Alarm.pm @@ -2,7 +2,7 @@ # # Alarm.pm # -# FHEM module for house alarm +# FHEM module to set up a house alarm system with 8 different alarm levels # # Prof. Dr. Peter A. Henning # @@ -40,7 +40,7 @@ my $alarmname = "Alarms"; # link text my $alarmhiddenroom = "AlarmRoom"; # hidden room my $alarmpublicroom = "Alarm"; # public room my $alarmno = 8; -my $alarmversion = "2.6"; +my $alarmversion = "2.8"; ######################################################################################### # @@ -58,7 +58,7 @@ sub Alarm_Initialize ($) { $hash->{GetFn} = "Alarm_Get"; $hash->{UndefFn} = "Alarm_Undef"; #$hash->{AttrFn} = "Alarm_Attr"; - my $attst = "lockstate:lock,unlock statedisplay:simple,color,table,graphics,none armdelay armwait armact disarmact cancelact"; + my $attst = "lockstate:lock,unlock statedisplay:simple,color,table,none armdelay armwait armact disarmact cancelact"; for( my $level=0;$level<$alarmno;$level++ ){ $attst .=" level".$level."start level".$level."end level".$level."msg level".$level."xec:0,1 level".$level."onact level".$level."offact "; } @@ -154,8 +154,21 @@ sub Alarm_CreateEntry($) { } } } + #-- recover state from stored readings + for( my $level=0;$level<$alarmno;$level++ ){ + my $val = $hash->{READINGS}{"level".$level}{VAL}; + if( $val eq "disarmed" ){# + CommandAttr (undef,$name.' level'.$level.'xec disarmed'); + }elsif( $val eq "armed" ){ + CommandAttr (undef,$name.' level'.$level.'xec armed'); + }else{ + Log3 $hash,1,"[Alarm $level] has undefined save data, disarming"; + CommandAttr (undef,$name.' level'.$level.'xec disarmed'); + } + } my $mga = Alarm_getstate($hash)." Keine Störung"; readingsSingleUpdate( $hash, "state", $mga, 1 ); + } ######################################################################################### @@ -228,10 +241,12 @@ sub Alarm_getstate($) { my ($hash) = @_; my $res = ''; my $type = AttrVal($hash->{NAME},"statedisplay",0); + my $val; #-------------------------- if( $type eq "simple" ){ for( my $level=0;$level<$alarmno;$level++ ){ - if( $hash->{READINGS}{"level".$level}{VAL} eq "off" ){ + $val = $hash->{READINGS}{"level".$level}{VAL}; + if( ($val eq "disarmed")||($val eq "armed") ){ $res.='O'; }else{ $res.='X'; @@ -241,7 +256,8 @@ sub Alarm_getstate($) { }elsif( $type eq "color" ){ $res = ''; for( my $level=0;$level<$alarmno;$level++ ){ - if( $hash->{READINGS}{"level".$level}{VAL} eq "off" ){ + $val = $hash->{READINGS}{"level".$level}{VAL}; + if( ($val eq "disarmed")||($val eq "armed") ){ $res.=' '.$level; }else{ $res.=' '.$level.''; @@ -252,7 +268,8 @@ sub Alarm_getstate($) { }elsif( $type eq "table" ){ $res = ''; for( my $level=0;$level<$alarmno;$level++ ){ - if( $hash->{READINGS}{"level".$level}{VAL} eq "off" ){ + $val = $hash->{READINGS}{"level".$level}{VAL}; + if( ($val eq "disarmed")||($val eq "armed") ){ $res.='"; $ret .= "". "\n"; @@ -752,7 +777,7 @@ sub Alarm_Html($) if( AttrVal($d, "alarmDevice","") eq "Sensor" ) { my @aval = split('\|',AttrVal($d, "alarmSettings","")); if( int(@aval) != 4){ - @aval=("","","",""); + Log3 $hash, 1, "[Alarm] Settings incomplete for alarmSensor $d"; } $row++; $ret .= sprintf("", ($row&1)?"odd":"even"); @@ -781,8 +806,9 @@ sub Alarm_Html($) foreach my $d (sort keys %defs ) { next if(IsIgnored($d)); if( AttrVal($d, "alarmDevice","") eq "Actor" ) { - my @aval = split('\|',AttrVal($d, "alarmSettings","")); + my @aval = split('\|',AttrVal($d, "alarmSettings","|||0:00")); if( int(@aval) != 4){ + Log3 $hash, 1, "[Alarm] Settings incomplete for alarmActor $d"; @aval=("","","",""); } $row++; @@ -807,11 +833,13 @@ sub Alarm_Html($) 1; =pod +=item helper +=item summary to set up a house alarm system with 8 different alarm levels =begin html

Alarm

-

FHEM module to set up a House Alarm System with 8 different alarm levels

+

FHEM module to set up a house alarm system with 8 different alarm levels

Define

@@ -863,12 +891,12 @@ sub Alarm_Html($) simple,color,table,none
defines how the state of all eight alarm levels is shown. Example for the case when only alarm no. 2 is raised:

  • attr <name> armdelay mm:ss diff --git a/fhem/www/pgm2/alarm.js b/fhem/www/pgm2/alarm.js index e97ba91d5..665b4846a 100644 --- a/fhem/www/pgm2/alarm.js +++ b/fhem/www/pgm2/alarm.js @@ -1,5 +1,7 @@ //######################################################################################## // alarm.js +// Version 2.8 +// See 95_Alarm for licensing //######################################################################################## //# Prof. Dr. Peter A. Henning @@ -42,6 +44,13 @@ function HashTable() { return typeof(this.items[in_key]) != 'undefined'; } } + +function encodeParm(oldval) { + var newval; + newval=oldval.replace('+', '%2B'); + newval=newval.replace('#', '%23'); + return newval; +} var ah = new HashTable('l0s','','l0e',''); @@ -53,6 +62,7 @@ function alarm_setAttribute(name, attr, val) {//set Alarm Attribute if (location.substr(location.length-1,1) == '/') {location = location.substr(0,location.length-1);} var url = document.location.protocol+"//"+document.location.host+location; attr = attr.replace('+', '%2B'); + val = val.replace('#', '%23'); FW_cmd(url+'?XHR=1&cmd.'+name+'=attr '+name+' '+attr+' '+val); } @@ -129,6 +139,7 @@ function alarm_set(name){ val += "|"+sarr[k].children[2].children[1].value; val += "|"+sarr[k].children[3].children[0].options[sarr[k].children[3].children[0].selectedIndex].value; val = val.replace('+', '%2B'); + val = val.replace('#', '%23'); FW_cmd(url+'?XHR=1&cmd.'+nam+'=attr '+nam+' alarmSettings ' + val); } @@ -147,6 +158,7 @@ function alarm_set(name){ val += "|"+aarr[k].children[2].children[1].value; val += "|"+aarr[k].children[3].children[0].value; val = val.replace('+', '%2B'); + val = val.replace('#', '%23'); FW_cmd(url+'?XHR=1&cmd.'+nam+'=attr '+nam+' alarmSettings ' + val); }
  • '; }else{ $res.=''; @@ -295,7 +312,7 @@ sub Alarm_Exec($$$$$){ #-- raising the alarm if( $act eq "on" ){ #-- only if this level is armed and not yet active - if( ($xec eq "armed") && ($xac eq "off") ){ + if( ($xec eq "armed") && ($xac eq "armed") ){ #-- check for time my $start = AttrVal($name, "level".$level."start", 0); if( index($start, '{') != -1){ @@ -325,7 +342,7 @@ sub Alarm_Exec($$$$$){ if( (($stp < $etp) && ($ntp <= $etp) && ($ntp >= $stp)) || (($stp > $etp) && (($ntp <= $etp) || ($ntp >= $stp))) ){ #-- raised by sensor (attribute values have been controlled in CreateNotifiers) - @sta = split('\|', AttrVal($dev, "alarmSettings", 0)); + @sta = split('\|', AttrVal($dev, "alarmSettings", "")); if( $sta[2] ){ $mga = $sta[2]." ".AttrVal($name, "level".$level."msg", 0); #-- replace some parts @@ -338,11 +355,17 @@ sub Alarm_Exec($$$$$){ #-- readings readingsSingleUpdate( $hash, "level".$level,$dev,0 ); readingsSingleUpdate( $hash, "short", $mga, 0); - $mga = Alarm_getstate($hash)." ".$mga; - readingsSingleUpdate( $hash, "state", $mga, 1 ); + $msg = Alarm_getstate($hash)." ".$mga; + readingsSingleUpdate( $hash, "state", $msg, 1 ); $msg = "[Alarm $level] raised from device $dev with event $evt"; #-- calling actors AFTER state update $cmd = AttrVal($name, "level".$level."onact", 0); + $cmd =~ s/\$NAME/$dev/g; + $cmd =~ s/\$EVENT/$evt/g; + $cmd =~ s/\$SHORT/$mga/g; + for( my $i=1;$i<= int(@evtpart);$i++){ + $cmd =~ s/\$EVTPART$i/$evtpart[$i-1]/g; + } fhem($cmd); Log3 $hash,3,$msg; }else{ @@ -359,7 +382,7 @@ sub Alarm_Exec($$$$$){ } }elsif( ($act eq "off")||($act eq "cancel") ){ #-- only if this level is active - if( $xac ne "off"){ + if( ($xac ne "armed")&&($xac ne "disarmed") ){ #-- deleting all running ats $dly = sprintf("alarm%1ddly",$level); foreach my $d (sort keys %intAt ) { @@ -375,8 +398,8 @@ sub Alarm_Exec($$$$$){ $cmd = AttrVal($name, "cancelact", 0); fhem($cmd) if( $cmd ); - #-- readings - readingsSingleUpdate( $hash, "level".$level,"off",0 ); + #-- readings - arm status does not change + readingsSingleUpdate( $hash, "level".$level,"armed",0 ); $mga = " Level $level canceled"; readingsSingleUpdate( $hash, "short", "", 0); $mga = Alarm_getstate($hash)." ".$mga; @@ -418,7 +441,7 @@ sub Alarm_Arm($$$$$){ my $cmdact = AttrVal($name, "armact", 0); if( ($xdl eq '')|($xdl eq '0:00')|($xdl eq '00:00') ){ CommandAttr(undef,$name.' level'.$level.'xec armed'); - $msg = "[Alarm $level] armed from device $dev with event $evt"; + $msg = "[Alarm $level] armed from alarmSensor $dev with event $evt"; Log3 $hash,3,$msg; } elsif( $xdl =~ /([0-9])?:([0-5][0-9])?/ ){ CommandAttr(undef,$name.' level'.$level.'xec armwait'); @@ -434,8 +457,9 @@ sub Alarm_Arm($$$$$){ } } #-- compose commands - $cmd = sprintf("define alarm%1d.arm.dly at +00:%02d:%02d {fhem(\"attr %s level%1dxec armed\");;%s}",$level,$1,$2,$name,$level,$cmdactf); - $msg = "[Alarm $level] will be armed from device $dev with event $evt, delay $xdl"; + $cmd = sprintf("define alarm%1d.arm.dly at +00:%02d:%02d {fhem(\"setreading %s level%1d armed\");;fhem(\"attr %s level%1dxec armed\");;%s}", + $level,$1,$2,$name,$level,$name,$level,$cmdactf); + $msg = "[Alarm $level] will be armed from alarmSensor $dev with event $evt, delay $xdl"; #-- delete old delayed arm fhem('delete alarm'.$level.'.arm.dly' ) if( defined $defs{'alarm'.$level.'.arm.dly'}); @@ -455,8 +479,9 @@ sub Alarm_Arm($$$$$){ if( defined $defs{'alarm'.$level.'.arm.dly'}); CommandAttr (undef,$name.' level'.$level.'xec disarmed'); Alarm_Exec($name,$level,"program","disarm","cancel"); + readingsSingleUpdate( $hash, "level".$level,"disarmed",0 ); #-- - $msg = "[Alarm $level] disarmed from device $dev with event $evt"; + $msg = "[Alarm $level] disarmed from alarmSensor $dev with event $evt"; $cmd = AttrVal($name, "disarmact", 0); fhem("define alarm".$level.".disarm.T at +00:00:03 ".$cmd) if( $cmd ); @@ -557,19 +582,19 @@ sub Alarm_CreateNotifiers($){ if( AttrVal($d, "alarmDevice","") eq "Sensor" ) { my @aval = split('\|',AttrVal($d, "alarmSettings","")); if( int(@aval) != 4){ - # Log3 $hash, 1, "[Alarm $level] Settings incomplete for sensor $d"; + Log3 $hash, 5, "[Alarm $level] Settings incomplete for alarmSensor $d"; next; } if( index($aval[0],"alarm".$level) != -1){ if( $aval[3] eq "on" ){ $cmd .= '('.$aval[1].')|'; - # Log3 $hash,1,"[Alarm $level] Adding sensor $d to raise notifier"; + Log3 $hash,5,"[Alarm $level] Adding alarmSensor $d to raise notifier"; }elsif( $aval[3] eq "arm" ){ $cmdarm .= '('.$aval[1].')|'; - #Log3 $hash,1,"[Alarm $level] Adding sensor $d to arm notifier"; + Log3 $hash,5,"[Alarm $level] Adding alarmSensor $d to arm notifier"; }elsif( $aval[3] eq "disarm" ){ $cmddisarm .= '('.$aval[1].')|'; - # Log3 $hash,1,"[Alarm $level] Adding sensor $d to disarm notifier"; + Log3 $hash,5,"[Alarm $level] Adding alarmSensor $d to disarm notifier"; } } } @@ -595,12 +620,12 @@ sub Alarm_CreateNotifiers($){ if( AttrVal($d, "alarmDevice","") eq "Actor" ) { my @aval = split('\|',AttrVal($d, "alarmSettings","")); if( int(@aval) != 4){ - Log3 $hash, 5, "[Alarm $level] Settings incomplete for actor $d"; + Log3 $hash, 5, "[Alarm $level] Settings incomplete for alarmActor $d"; next; } if( index($aval[0],"alarm".$level) != -1 ){ #-- activate without delay - if(( $aval[3] eq "0" )||($aval[3] eq "00:00")){ + if(( $aval[3] eq "0" )||($aval[3] eq "0:00")||($aval[3] eq "00:00")){ $cmd .= $aval[1].';'; #-- activate with delay } else { @@ -705,17 +730,17 @@ sub Alarm_Html($) $ret .= "
    \n"; $ret .= ""; $ret .= "\n"; $ret .= "\n"; $ret .="
    Arm Button ↠ Wait Action "; - $ret .= sprintf("",AttrVal($name, "armwait","")); + $ret .= sprintf("",(AttrVal($name, "armwait","") eq "1")?"":AttrVal($name, "armwait","")); $ret .= " ↴ Delay
    ↲"; - $ret .= sprintf("",AttrVal($name, "armdelay","")); + $ret .= sprintf("",(AttrVal($name, "armdelay","0:00") eq "1")?"":AttrVal($name, "armdelay","0:00")); $ret .= "
    Arm Action "; - $ret .= sprintf("",AttrVal($name, "armact","")); + $ret .= sprintf("",(AttrVal($name, "armact","") eq "1")?"":AttrVal($name, "armact","")); $ret .= "
    Disarm Button ↠Disarm Action "; - $ret .= sprintf("",AttrVal($name, "disarmact","")); + $ret .= sprintf("",(AttrVal($name, "disarmact","") eq "1")?"":AttrVal($name, "disarmact","")); $ret .= "
    Cancel Button ↠ Cancel Action "; - $ret .= sprintf("",AttrVal($name, "cancelact","")); + $ret .= sprintf("",(AttrVal($name, "cancelact","") eq "1")?"":AttrVal($name, "cancelact","")); $ret .= "
    LevelTime [hh:mm]Message Part IIArmed/Cancel