diff --git a/fhem/FHEM/98_MSwitch.pm b/fhem/FHEM/98_MSwitch.pm index 2455a3928..735528df5 100644 --- a/fhem/FHEM/98_MSwitch.pm +++ b/fhem/FHEM/98_MSwitch.pm @@ -4,7 +4,7 @@ # # copyright ##################################################### # -# 98_MSwitch.pm +# 98_MSwitch.pm # # written by Byte09 # Maintained by Byte09 @@ -23,19 +23,28 @@ # # You should have received a copy of the GNU General Public License # along with FHEM. If not, see . +# ################################################################# # Todo's: # -# info conf -# reading '.lock' wenn definiert -> device locked -# reading '.info' wenn definiert -> infotext für device -# reading '.change' wenn definiert -> angeforderte deviceänderung -# reading '.change_inf' wenn definiert -> info für angeforderte deviceänderung +#--------------------------------------------------------------- +# +# info sonderreadings +# +# reading '.info' wenn definiert -> infotext für device +# reading '.change' wenn definiert -> angeforderte deviceänderung +# reading '.change_inf' wenn definiert -> info für angeforderte deviceänderung +# reading '.lock' sperrt das Interface (1 - alles / 2 alles bis auf trigger) +# reading 'Sys_Extension' 'on' gibt Systemerweiterung frei +# +#--------------------------------------------------------------- # # info conffile - austausch eines/mehrerer devices -# I testinfo +# I Information zu Devicetausch # Q dummy1#zu schaltendes geraet#device # Q dummy2#zu schaltendes geraet2#device +# +##--------------------------------------------------------------- # ################################################################# @@ -46,8 +55,40 @@ use warnings; use POSIX; # Version ####################################################### -my $autoupdate = 'on'; #off/on -my $version = '2.02'; + + +my $preconf=""; +my $verzeichnis = "./FHEM/MSwitch"; +if(-d $verzeichnis) { + + opendir(DIR, $verzeichnis); + while (my $entry = readdir(DIR)) + { + my $dat = $entry; + $entry = $verzeichnis.'/'.$entry; + + next if $entry eq "."; + next if $entry eq ".."; + unless (-f $entry) + { + next; + } + $preconf.=$dat.","; + } + closedir(DIR); + chop ($preconf); + } + else { + $preconf=""; + } + if ($preconf && $preconf ne "") + { + $preconf="get_MSwitch_preconf:".$preconf; + } + + +my $autoupdate = 'off'; #off/on +my $version = '2.07'; my $vupdate = 'V2.00' ; # versionsnummer der datenstruktur . änderung der nummer löst MSwitch_VUpdate aus . my $savecount = 30 @@ -105,6 +146,7 @@ sub MSwitch_clearlog($); sub MSwitch_LOG($$$); sub MSwitch_Getsupport($); sub MSwitch_confchange($$); +sub MSwitch_setconfig($$); my %sets = ( "on" => "noArg", @@ -127,9 +169,8 @@ my %sets = ( "savesys" => "noArg", "sort_device" => "noArg", "fakeevent" => "noArg", - "exec_cmd1" => "noArg", - "exec_cmd2" => "noArg", - "exec_cmd1+2" => "noArg", + "exec_cmd_1" => "noArg", + "exec_cmd_2" => "noArg", "wait" => "noArg", "VUpdate" => "noArg", "confchange" => "noArg", @@ -137,6 +178,9 @@ my %sets = ( "set_trigger" => "noArg", "change_renamed" => "" ); + + +# "exec_cmd1+2" => "noArg", my %gets = ( "active_timer" => "noArg", "restore_MSwitch_Data" => "noArg", @@ -145,7 +189,9 @@ my %gets = ( #################### sub MSwitch_Initialize($) { + my ($hash) = @_; + $hash->{SetFn} = "MSwitch_Set"; $hash->{AsyncOutput} = "MSwitch_AsyncOutput"; $hash->{RenameFn} = "MSwitch_Rename"; @@ -175,17 +221,21 @@ sub MSwitch_Initialize($) { . " MSwitch_Include_MSwitchcmds:0,1" . " MSwitch_Activate_MSwitchcmds:0,1" . " MSwitch_Lock_Quickedit:0,1" - . " MSwitch_Ignore_Types" + . " MSwitch_Ignore_Types:textField-long " . " MSwitch_Trigger_Filter" . " MSwitch_Extensions:0,1" . " MSwitch_Inforoom" - . " MSwitch_Mode:Full,Notify,Toggle" + . " MSwitch_Mode:Full,Notify,Toggle,Dummy" . " MSwitch_Condition_Time:0,1" . " MSwitch_RandomTime" . " MSwitch_RandomNumber" . " MSwitch_Safemode:0,1" . " MSwitch_Startdelay:0,10,20,30,60,90,120" - . " MSwitch_Wait"; + . " MSwitch_Wait" + . " setList:textField-long " + . " readingList:textField-long " + . $readingFnAttributes; + $hash->{FW_addDetailToSummary} = 0; } #################### @@ -203,13 +253,15 @@ sub MSwitch_Copy ($) { my ( $old_name, $new_name ) = @_; my $hash = $defs{$new_name}; my @areadings = - qw(.Device_Affected .Device_Affected_Details .Device_Events .First_init .Trigger_Whitelist .Trigger_cmd_off .Trigger_cmd_on .Trigger_condition .Trigger_off .Trigger_on .Trigger_time .V_Check Exec_cmd Trigger_device Trigger_log last_event state .sysconf Sys_Extension) + qw(.Device_Affected .Device_Affected_Details .Device_Events .First_init .Trigger_Whitelist .Trigger_cmd_off .Trigger_cmd_on .Trigger_condition .Trigger_off .Trigger_on .Trigger_time .V_Check last_exec_cmd Trigger_device Trigger_log last_event state .sysconf Sys_Extension) ; #alle readings my $cs = "attr $new_name disable 1"; my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { Log3( $new_name, 1, "ERROR $cs" ); + + } foreach my $key (@areadings) { @@ -314,15 +366,26 @@ sub MSwitch_summary($) { . $info . "')\">"; } - if ( $trigger eq 'no_trigger' || $trigger eq 'undef' ) { + if ( $trigger eq 'no_trigger' || $trigger eq 'undef' || $trigger eq '') { $triggerc = 0; if ( $triggerc != 0 || $timer != 0 ) { $ret .= ""; } - else { + else + { + + if ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) ne "Dummy" ) { $affectedtime = ""; $ret .= "  Multiswitchmode (no trigger / no timer) "; + } + else + { + $affectedtime = ""; + $affected =""; + $ret .= "  Dummymode "; + } + } } else { @@ -420,6 +483,7 @@ sub MSwitch_LoadHelper($) { my $cdev = ''; my $ctrigg = ''; if ( defined $hash->{DEF} ) { + $devhash = $hash->{DEF}; my @dev = split( /#/, $devhash ); $devhash = $dev[0]; @@ -454,6 +518,7 @@ sub MSwitch_LoadHelper($) { $hash->{NOTIFYDEV} = $oldtrigger; readingsSingleUpdate( $hash, "Trigger_device", $oldtrigger, 0 ); } + ################# MSwitch_set_dev($hash); @@ -540,14 +605,14 @@ sub MSwitch_Define($$) { my $name = $a[0]; my $devpointer = $name; my $devhash = ''; - my $old = $hash->{OLDDEF}; - $old = '' if !defined $old; + $modules{MSwitch}{defptr}{$devpointer} = $hash; $hash->{Version_Modul} = $version; $hash->{Version_Datenstruktur} = $vupdate; $hash->{Version_autoupdate} = $autoupdate; - if ( $init_done && $old ne '' ) { + if($init_done && !defined($hash->{OLDDEF})) + { my $timecond = gettimeofday() + 5; InternalTimer( $timecond, "MSwitch_LoadHelper", $hash ); } @@ -570,6 +635,17 @@ sub MSwitch_Get($$@) { return $ret; } #################### + + + + if ( $opt eq 'get_MSwitch_preconf') { + + MSwitch_setconfig($hash,$args[0]); + + return "MSwitch_preconfig for $name has loaded.\nPlease refresh device."; + } + +######################## if ( $opt eq 'restore_MSwitch_Data' && $args[0] eq "all_Devices" ) { open( BACKUPDATEI, "{helper}{timer}; foreach my $a ( sort keys %{$timehash} ) { - my $time = FmtDateTime( $hash->{helper}{timer}{$a} ); + + + + my @string=split(/-/,$hash->{helper}{timer}{$a}); + my @string1=split(/ID/,$string[1]); + + my $number = $string1[0]; + my $id = $string1[1]; + + my $time = FmtDateTime( $string[0] ); my @timers = split( /,/, $a ); - if ( substr( $hash->{helper}{timer}{$a}, 11, 1 ) eq '1' ) { + + if ( $number eq '1' ) { $ret .= "
" . $time . " switch MSwitch on + execute 'on' cmds
"; } - if ( substr( $hash->{helper}{timer}{$a}, 11, 1 ) eq '2' ) { + if ( $number eq '2' ) { $ret .= "
" . $time . " switch MSwitch off + execute 'off' cmds
"; } - if ( substr( $hash->{helper}{timer}{$a}, 11, 1 ) eq '3' ) { + if ( $number eq '3' ) { $ret .= - "
" . $time . " execute 'on' commands only
"; + "
" . $time . " execute 'cmd1' commands only
"; } - if ( substr( $hash->{helper}{timer}{$a}, 11, 1 ) eq '4' ) { + if ( $number eq '4' ) { $ret .= - "
" . $time . " execute 'off' commands only
"; + "
" . $time . " execute 'cmd2' commands only
"; } - if ( substr( $hash->{helper}{timer}{$a}, 11, 1 ) eq '5' ) { + + if ( $number eq '9' ) { + $ret .= + "
" . $time . " execute 'cmd1+cmd2' commands only
"; + } + + if ( $number eq '10' ) { + + $ret .="
" . $time . " execute 'cmd1+cmd2' commands from ID ".$id." only
"; + } + + + + + + if ( $number eq '5' ) { $ret .= "
" . $time . " neuberechnung aller Schaltzeiten
"; } + + if ( $number eq '6' ) { + $ret .="
" . $time . " execute 'cmd1' commands from ID ".$id." only
"; + } + if ( $number eq '7' ) { + $ret .="
" . $time . " execute 'cmd2' commands from ID ".$id." only
"; + } + + } #delays @@ -758,13 +868,20 @@ sub MSwitch_Get($$@) { $extension = 'get_sysextension:noArg'; } + + if ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) eq "Dummy" ) { + return "Unknown argument $opt, choose one of get_support_info:noArg restore_MSwitch_Data:this_Device,all_Devices"; + } + + + if ( ReadingsVal( $name, '.lock', 'undef' ) ne "undef" ) { return -"Unknown argument $opt, choose one of active_timer:show,delete get_config:noArg restore_MSwitch_Data:this_Device,all_Devices"; +"Unknown argument $opt, choose one of active_timer:show,delete get_config:noArg restore_MSwitch_Data:this_Device,all_Devices $preconf"; } else { return -"Unknown argument $opt, choose one of get_support_info:noArg get_config:noArg active_timer:show,delete restore_MSwitch_Data:this_Device,all_Devices $extension"; +"Unknown argument $opt, choose one of get_support_info:noArg get_config:noArg active_timer:show,delete restore_MSwitch_Data:this_Device,all_Devices $preconf $extension"; } } @@ -778,33 +895,22 @@ sub MSwitch_AsyncOutput ($) { sub MSwitch_Set($@) { my ( $hash, $name, $cmd, @args ) = @_; + Log3( $name, 5, "$name Set $cmd, @args " . __LINE__ ); + + ############################## - - if ( $cmd eq 'inactive' ) { - - # setze device auf inaktiv - readingsSingleUpdate( $hash, "state", 'inactive', 1 ); - return; - } -############################## - if ( $cmd eq 'active' ) { - - # setze device auf aktiv - readingsSingleUpdate( $hash, "state", 'active', 1 ); - return; - } -############################## - return "" if ( IsDisabled($name) && ( $cmd eq 'on' || $cmd eq 'off' ) ) ; # Return without any further action if the module is disabled my $execids = "0"; $hash->{eventsave} = 'unsaved'; - # verry special commands readingactivated ( +############################## +# verry special commands readingactivated ( my $special = ''; my $cs = ReadingsVal( $name, '.sysconf', 'undef' ); if ( $cs ne "undef" ) { + $cs =~ s/#\[tr\]/[tr]/g; $cs =~ s/#\[wa\]/|/g; $cs =~ s/#\[sp\]/ /g; $cs =~ s/#\[nl\]/\n/g; @@ -816,50 +922,24 @@ sub MSwitch_Set($@) { $cs =~ s/#\[ko\]/,/g; $cs =~ s/#.*\n//g; $cs =~ s/\n//g; - - my $return = "no value"; + $cs =~ s/\[tr\]/#[tr]/g; + my $return = "no value"; $return = eval($cs); if ($@) { Log3( $name, 1, "$name MSwitch_repeat: ERROR $cs: $@ " . __LINE__ ); + } - return if $return eq "exit"; } - ############################ +############################ if ( !defined $args[0] ) { $args[0] = ''; } - if ( $cmd eq 'exec_cmd1' && $args[0] eq 'ID' ) { - Log3( $name, 5, "$name: execids werden gesetzt -> " . $args[1] ); - $execids = $args[1]; - $args[0] = 'ID'; - } - - if ( $cmd eq 'exec_cmd2' && $args[0] eq 'ID' ) { - Log3( $name, 5, "$name: execids werden gesetzt als -> " . $args[1] ); - $execids = $args[1]; - $args[0] = 'ID'; - } - my $ic = ''; - $ic = $hash->{IncommingHandle}; - ####################################### - if ( ( ( $cmd eq 'on' ) || ( $cmd eq 'off' ) ) - && ( $args[0] ne '' ) - && ( $ic ne 'fromnotify' ) ) - { - readingsSingleUpdate( $hash, "Parameter", $args[0], 1 ); - if ( $cmd eq 'on' ) { $args[0] = "$name:on_with_Parameter:$args[0]"; } - if ( $cmd eq 'off' ) { $args[0] = "$name:off_with_Parameter:$args[0]"; } - } - - delete( $hash->{IncommingHandle} ); - - ####################################### - if ( AttrVal( $name, 'MSwitch_Debug', "0" ) eq '4' ) - - #AUFRUF DEBUGFUNKTIONEN - { - MSwitch_Debug($hash); - } + + my $setList = AttrVal($name, "setList", " "); + $setList =~ s/\n/ /g; + + my $devicemode = AttrVal( $name, 'MSwitch_Mode', 'Full' ); + if ( !exists( $sets{$cmd} ) ) { my @cList; @@ -882,29 +962,108 @@ sub MSwitch_Set($@) { if ( ReadingsVal( $name, '.change', '' ) ne '' ) { return "Unknown argument $cmd, choose one of "; } + + +# bearbeite setlist und readinglist +############################## +if ($cmd ne "?") +{ + my @sl = split(" ", AttrVal($name, "setList", "")); + my $re = qr/$cmd/; + my @gefischt=grep(/$re/,@sl); + if(@sl && grep /$re/, @sl ) + { + my @rl = split(" ", AttrVal($name, "readingList", "")); + if(@rl && grep /$re/, @rl ) + { + readingsSingleUpdate( $hash, $cmd, "@args", 1 ); + } + else + { + readingsSingleUpdate( $hash, "state", $cmd." @args", 1 ); + } + return; + } +############################## +# dummy state setzen und exit + if ( $devicemode eq "Dummy" ) + { + readingsSingleUpdate( $hash, "state", $cmd." @args", 1 ); + return; + } +#AUFRUF DEBUGFUNKTIONEN + if ( AttrVal( $name, 'MSwitch_Debug', "0" ) eq '4' ) + { + MSwitch_Debug($hash); + } +####################################### - if ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) eq "Notify" ) { + my $ic = ''; + $ic = $hash->{IncommingHandle}; + if ( ( ( $cmd eq 'on' ) || ( $cmd eq 'off' ) ) + && ( $args[0] ne '' ) + && ( $ic ne 'fromnotify' ) ) + { + readingsSingleUpdate( $hash, "Parameter", $args[0], 1 ); + if ( $cmd eq 'on' ) { $args[0] = "$name:on_with_Parameter:$args[0]"; } + if ( $cmd eq 'off' ) { $args[0] = "$name:off_with_Parameter:$args[0]"; } + } + delete( $hash->{IncommingHandle} ); +####################################### + +} +############################################ + + + + if ( $devicemode eq "Notify" ) { return -"Unknown argument $cmd, choose one of active:noArg inactive:noArg del_delays:noArg backup_MSwitch:all_devices fakeevent exec_cmd1 exec_cmd2 exec_cmd1+2 wait reload_timer:noArg change_renamed $special"; +"Unknown argument $cmd, choose one of active:noArg inactive:noArg del_delays:noArg backup_MSwitch:all_devices fakeevent exec_cmd_1 exec_cmd_2 wait reload_timer:noArg change_renamed $setList $special"; } - elsif ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) eq "Toggle" ) { + elsif ( $devicemode eq "Toggle" ) { return -"Unknown argument $cmd, choose one of active:noArg inactive:noArg on offdel_delays:noArg backup_MSwitch:all_devices fakeevent wait reload_timer:noArg change_renamed $special"; +"Unknown argument $cmd, choose one of active:noArg inactive:noArg on off del_delays:noArg backup_MSwitch:all_devices fakeevent wait reload_timer:noArg change_renamed $setList $special"; } - else { + + + elsif ( $devicemode eq "Dummy" ) { return -"Unknown argument $cmd, choose one of active:noArg inactive:noArg on off del_delays:noArg backup_MSwitch:all_devices fakeevent exec_cmd1 exec_cmd2 exec_cmd1+2 wait reload_timer:noArg change_renamed $special"; +"Unknown argument $cmd, choose one of state $setList $special"; + } + + else { + #full + return +"Unknown argument $cmd, choose one of active:noArg inactive:noArg on off del_delays:noArg backup_MSwitch:all_devices fakeevent exec_cmd_1 exec_cmd_2 wait reload_timer:noArg change_renamed $setList $special"; } } + + if ( AttrVal( $name, 'MSwitch_RandomNumber', '' ) ne '' ) { # randomnunner erzeugen wenn attr an MSwitch_Createnumber1($hash); } - ####################################### + +############################## + + if ( $cmd eq 'inactive' ) { + + # setze device auf inaktiv + readingsSingleUpdate( $hash, "state", 'inactive', 1 ); + return; + } +############################## + if ( $cmd eq 'active' ) { + + # setze device auf aktiv + readingsSingleUpdate( $hash, "state", 'active', 1 ); + return; + } +############################## if ( $cmd eq 'change_renamed' ) { my $changestring = $args[0] . "#" . $args[1]; MSwitch_confchange( $hash, $changestring ); @@ -952,10 +1111,14 @@ sub MSwitch_Set($@) { MSwitch_Check_Event( $hash, $args[0] ); return; } - ############################## - if ( $cmd eq 'exec_cmd1' ) { + if ( $cmd eq 'exec_cmd_1' ) { + + if ( $args[0] eq 'ID' ) { + $execids = $args[1]; + $args[0] = 'ID'; + } # cmd1 abarbeiten MSwitch_Exec_Notif( $hash, 'on', 'nocheck', '', $execids ); @@ -964,9 +1127,14 @@ sub MSwitch_Set($@) { ############################## - if ( $cmd eq 'exec_cmd2' ) { + if ( $cmd eq 'exec_cmd_2' ) { - # cmd1 abarbeiten + if ( $args[0] eq 'ID' ) { + $execids = $args[1]; + $args[0] = 'ID'; + } + + # cmd2 abarbeiten MSwitch_Exec_Notif( $hash, 'off', 'nocheck', '', $execids ); return; } @@ -1010,8 +1178,13 @@ sub MSwitch_Set($@) { # event manuell zufügen my $devName = ReadingsVal( $name, 'Trigger_device', '' ); - $args[0] =~ s/~/ /g; - my @newevents = split( /,/, $args[0] ); + $args[0] =~ s/\[sp\]/ /g; + + # MSwitch_LOG( $name, 0, "args0 ".$args[0] ); + # TODO leerzeichen im perteil ersetzen + + my @newevents = split( / /, $args[0] ); + if ( ReadingsVal( $name, 'Trigger_device', '' ) eq "all_events" ) { foreach (@newevents) { $hash->{helper}{events}{all_events}{$_} = "on"; @@ -1066,25 +1239,26 @@ sub MSwitch_Set($@) { ############################## if ( $cmd eq "set_trigger" ) { - # setze trigger - chop( $args[1], $args[2], $args[3], $args[4], $args[5] ); + chop( $args[1], $args[2], $args[3], $args[4], $args[5], $args[6] ); my $triggertime = 'on' . $args[1] . '~off' . $args[2] . '~ononly' . $args[3] . '~offonly' - . $args[4]; + . $args[4] + . '~onoffonly' + . $args[5]; my $oldtrigger = ReadingsVal( $name, 'Trigger_device', '' ); readingsSingleUpdate( $hash, "Trigger_device", $args[0], '1' ); - readingsSingleUpdate( $hash, ".Trigger_condition", $args[5], 0 ); + readingsSingleUpdate( $hash, ".Trigger_condition", $args[6], 0 ); - if ( !defined $args[6] ) { + if ( !defined $args[7] ) { readingsDelete( $hash, '.Trigger_Whitelist' ); } else { - readingsSingleUpdate( $hash, ".Trigger_Whitelist", $args[6], 0 ); + readingsSingleUpdate( $hash, ".Trigger_Whitelist", $args[7], 0 ); } my $testtrig = ReadingsVal( $name, 'Trigger_device', '' ); @@ -1095,7 +1269,8 @@ sub MSwitch_Set($@) { if ( $args[1] ne '' || $args[2] ne '' || $args[3] ne '' - || $args[4] ne '' ) + || $args[4] ne '' + || $args[5] ne '' ) { readingsSingleUpdate( $hash, ".Trigger_time", $triggertime, 0 ); MSwitch_Createtimer($hash); @@ -1107,18 +1282,33 @@ sub MSwitch_Set($@) { $hash->{helper}{events}{ $args[0] }{'no_trigger'} = "on"; - if ( $args[0] ne 'no_trigger' ) { - if ( $args[0] eq "all_events" ) { + if ( $args[0] ne 'no_trigger' ) + { + if ( $args[0] eq "all_events" ) + { delete( $hash->{NOTIFYDEV} ); - if ( ReadingsVal( $name, '.Trigger_Whitelist', '' ) ne '' ) { + if ( ReadingsVal( $name, '.Trigger_Whitelist', '' ) ne '' ) + { $hash->{NOTIFYDEV} = ReadingsVal( $name, '.Trigger_Whitelist', '' ); } } - else { + else + { + + + if ( $args[0] ne "MSwitch_Self" ){ $hash->{NOTIFYDEV} = $args[0]; my $devices = MSwitch_makeAffected($hash); $hash->{DEF} = $args[0] . ' # ' . $devices; + } + else{ + $hash->{NOTIFYDEV} = $name; + my $devices = MSwitch_makeAffected($hash); + $hash->{DEF} = $name . ' # ' . $devices; + +} + } } else { @@ -1221,7 +1411,6 @@ sub MSwitch_Set($@) { split( /,/, ReadingsVal( $name, '.Device_Affected', '' ) ); my @inputcmds = split( /#\[ND\]/, $args[0] ); - #my $counter = 0; my $error = ''; my $key = ''; my $savedetails = ''; @@ -1378,10 +1567,15 @@ sub MSwitch_Set($@) { # liste anpassen ( reihenfolge ) wenn expert = 1 @devices = MSwitch_priority( $hash, $execids, @devices ); - LOOP1: foreach my $device (@devices) { + + my $expertmode = AttrVal( $name, 'MSwitch_Expert', "0" ); + my $randomtime = AttrVal( $name, 'MSwitch_RandomTime', ''); + + LOOP1: foreach my $device (@devices) + { $out = '0'; - if ( AttrVal( $name, 'MSwitch_Expert', "0" ) eq '1' ) { + if ( $expertmode eq '1' ) { $ekey = $device . "_exit" . $exittest; $out = $devicedetails{$ekey}; } @@ -1491,6 +1685,10 @@ sub MSwitch_Set($@) { MSwitch_LOG( $name, 6, "$name: ergebniss condition -> ergebniss " . $execute ); if ( $execute eq 'true' ) { + + + + $cs =~ s/\$NAME/$hash->{helper}{eventfrom}/; $cs =~ s/\$SELF/$name/; MSwitch_LOG( $name, 6, @@ -1502,6 +1700,7 @@ sub MSwitch_Set($@) { MSwitch_LOG( $name, 6, "$name: Abbruchbefehl erhalten von " . $device ); + last LOOP1; } @@ -1511,7 +1710,7 @@ sub MSwitch_Set($@) { MSwitch_LOG( $name, 6, "$name: teste auf condition -> keine vorhanden " ); - if ( AttrVal( $name, 'MSwitch_RandomTime', '' ) ne '' + if ( $randomtime ne '' && $devicedetails{$timerkey} eq '[random]' ) { MSwitch_LOG( $name, 6, @@ -1525,7 +1724,7 @@ sub MSwitch_Set($@) { "$name: timerd ersetzt-> " . $devicedetails{$timerkey} ); } - elsif ( AttrVal( $name, 'MSwitch_RandomTime', '' ) eq '' + elsif ( $randomtime eq '' && $devicedetails{$timerkey} eq '[random]' ) { MSwitch_LOG( $name, 6, @@ -1580,7 +1779,7 @@ sub MSwitch_Set($@) { "$name: delay wird ersetzt " ); $devicedetails{$timerkey} = MSwitch_replace_delay( $hash, $teststateorg ); - Log3( $name, 6, + MSwitch_LOG( $name, 6, "$name: delay ersetzt -> " . $devicedetails{$timerkey} ); } @@ -1620,6 +1819,7 @@ sub MSwitch_Set($@) { MSwitch_LOG( $name, 6, "$name: Abbruchbefehl erhalten von " . $device ); + last LOOP1; } @@ -1629,7 +1829,7 @@ sub MSwitch_Set($@) { } - if ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) ne "Notify" ) { + if ( $devicemode ne "Notify" ) { readingsSingleUpdate( $hash, "state", $cmd, 1 ); } else { @@ -1643,8 +1843,12 @@ sub MSwitch_Set($@) { MSwitch_LOG( $name, 6, "$name: uebergabe an sub execute " ) if $anzahl > 0; MSwitch_Cmd( $hash, @cmdpool ) if $anzahl > 0; + #$lastdevice = $device ; + + #readingsSingleUpdate( $hash, "last_cmd", $hash->{helper}{priorityids}{$lastdevice}, 1 ); return; } + return; } @@ -1654,17 +1858,21 @@ sub MSwitch_Cmd(@) { my ( $hash, @cmdpool ) = @_; my $Name = $hash->{NAME}; - +my $lastdevice ; my %devicedetails = MSwitch_makeCmdHash($Name); foreach my $cmds (@cmdpool) { MSwitch_LOG( $Name, 6, "$Name: execute -> " . $cmds ); my @cut = split( /\|/, $cmds ); $cmds = $cut[0]; - # ersetze platzhakter vor ausführung + #ersetze platzhakter vor ausführung #change # $cmds =~ s/#\[wa\]/|/g; #neu my $device = $cut[1]; + + $lastdevice = $device; + + my $toggle = ''; if ( $cmds =~ m/set (.*)(MSwitchtoggle)(.*)/ ) { MSwitch_LOG( $Name, 6, @@ -1764,6 +1972,7 @@ sub MSwitch_Cmd(@) { if ($@) { MSwitch_LOG( $Name, 1, "$Name MSwitch_Set: ERROR $cmds: $@ " . __LINE__ ); + } } @@ -1774,6 +1983,7 @@ sub MSwitch_Cmd(@) { if ( defined($errors) ) { MSwitch_LOG( $Name, 1, "$Name MSwitch_Set: ERROR $cmds: $errors " . __LINE__ ); + } } } @@ -1784,7 +1994,11 @@ sub MSwitch_Cmd(@) { if ( length($showpool) > 100 ) { $showpool = substr( $showpool, 0, 100 ) . '....'; } - readingsSingleUpdate( $hash, "Exec_cmd", $showpool, 1 ) if $showpool ne ''; + + readingsSingleUpdate( $hash, "last_exec_cmd", $showpool, 1 ) if $showpool ne ''; + if ( AttrVal( $Name, 'MSwitch_Expert', '0' ) eq "1" ) { + readingsSingleUpdate( $hash, "last_cmd", $hash->{helper}{priorityids}{$lastdevice}, 1 ); + } } #################### @@ -1900,9 +2114,22 @@ sub MSwitch_Attr(@) { if ( $aName eq 'MSwitch_Mode' && ( $aVal eq 'Full' || $aVal eq 'Toggle' ) ) { + my $cs = "setstate $name ???"; my $errors = AnalyzeCommandChain( undef, $cs ); } + + + + + if ( $aName eq 'MSwitch_Mode' && ( $aVal eq 'Dummy' ) ) + { + MSwitch_Delete_Delay( $hash, 'all' ); + MSwitch_Clear_timer($hash); + $hash->{NOTIFYDEV} = 'no_trigger'; + + } + if ( $aName eq 'MSwitch_Mode' && $aVal eq 'Notify' ) { readingsSingleUpdate( $hash, "state", 'active', 1 ); @@ -2000,9 +2227,25 @@ sub MSwitch_Notify($$) { if ( IsDisabled($ownName) ) ; # Return without any further action if the module is disabled + + + my $devicemode = AttrVal( $ownName, 'MSwitch_Mode', 'Full' ); + my $devicefilter = AttrVal( $ownName, 'MSwitch_Trigger_Filter', 'undef' ); + my $debugmode = AttrVal( $ownName, 'MSwitch_Debug', "0" ) ; + my $startdelay = AttrVal( $ownName, 'MSwitch_Startdelay', $standartstartdelay ); + my $attrrandomnumber= AttrVal( $ownName, 'MSwitch_RandomNumber', '' ); + + return if ( $devicemode eq 'Dummy' ); + return if ( ReadingsVal($ownName,"Trigger_device","no_trigger") eq 'no_trigger' ); + return if (!$own_hash->{NOTIFYDEV}); + + + + + + # startverzöferung abwarten - my $startdelay = - AttrVal( $ownName, 'MSwitch_Startdelay', $standartstartdelay ); + my $diff = int(time) - $fhem_started; if ( $diff < $startdelay ) { MSwitch_LOG( $ownName, 6, @@ -2032,7 +2275,7 @@ sub MSwitch_Notify($$) { return; } - if ( AttrVal( $ownName, 'MSwitch_RandomNumber', '' ) ne '' ) { + if ( $attrrandomnumber ne '' ) { # create randomnumber wenn attr an MSwitch_Createnumber1($own_hash); @@ -2079,14 +2322,14 @@ sub MSwitch_Notify($$) { my $triggercmdon = ReadingsVal( $ownName, '.Trigger_cmd_on', '' ); my $triggercmdoff = ReadingsVal( $ownName, '.Trigger_cmd_off', '' ); - if ( AttrVal( $ownName, 'MSwitch_Mode', 'Full' ) eq "Notify" ) { + if ( $devicemode eq "Notify" ) { # passt triggerfelder an attr an $triggeron = 'no_trigger'; $triggeroff = 'no_trigger'; } - if ( AttrVal( $ownName, 'MSwitch_Mode', 'Full' ) eq "Toggle" ) { + if ( $devicemode eq "Toggle" ) { # passt triggerfelder an attr an $triggeroff = 'no_trigger'; @@ -2162,13 +2405,9 @@ sub MSwitch_Notify($$) { } # wird nur ausgefüht wenn ankommende events gelogd werden - if ( AttrVal( $ownName, 'MSwitch_Trigger_Filter', 'undef' ) ne - 'undef' - && AttrVal( $ownName, 'MSwitch_Trigger_Filter', 'undef' ) ne - "" ) + if ( $devicefilter ne 'undef' && $devicefilter ne "" ) { my $eventcopy1 = $eventcopy; - if ( $triggerdevice eq "all_events" ) { # fügt dem event den devicenamen hinzu , wenn global getriggert wird @@ -2176,8 +2415,7 @@ sub MSwitch_Notify($$) { } my @filters = - split( /,/, - AttrVal( $ownName, 'MSwitch_Trigger_Filter', 'undef' ) ) + split( /,/, $devicefilter ) ; # beinhaltet filter durch komma getrennt MSwitch_LOG( $ownName, 5, "$ownName: Filtertest Event -> " . $eventcopy ); @@ -2206,7 +2444,7 @@ sub MSwitch_Notify($$) { } } -############################################################################################################## +############################################################################################################ #anzahl checken / ggf nicht mehr nötig #check checken / ggf nicht mehr nötig @@ -2223,7 +2461,7 @@ sub MSwitch_Notify($$) { } # Teste auf einhaltung Triggercondition ENDE -############################################################################################################### +############################################################################################################ my $eventcopy1 = $eventcopy; @@ -2293,7 +2531,6 @@ sub MSwitch_Notify($$) { push @cmdarray, $own_hash . ',off,check,' . $eventcopy1; $check = 1; - #readingsSingleUpdate( $own_hash, "incomming", $eventcopy, 0 ); } MSwitch_LOG( $ownName, 6, "$ownName: checktrigger ergebniss -> " . $testvar ); @@ -2309,8 +2546,6 @@ sub MSwitch_Notify($$) { if ( $testvar ne 'undef' ) { push @cmdarray, $own_hash . ',on,check,' . $eventcopy1; $check = 1; - - #readingsSingleUpdate( $own_hash, "incomming", $eventcopy, 0 ); } MSwitch_LOG( $ownName, 6, "$ownName: checktrigger ergebniss -> " . $testvar ); @@ -2324,10 +2559,8 @@ sub MSwitch_Notify($$) { MSwitch_LOG( $ownName, 6, "$ownName: inhalt gefundener Befehle -> @cmdarray" ); $own_hash->{IncommingHandle} = 'fromnotify'; - - #$event =~ s/ //ig; #? $event =~ s/~/ /g; #? - if ( AttrVal( $ownName, 'MSwitch_Mode', 'Full' ) eq "Notify" + if ( $devicemode eq "Notify" and $activecount == 0 ) { # reading activity aktualisieren @@ -2346,7 +2579,7 @@ sub MSwitch_Notify($$) { # abfrage und setzten von blocking ENDE - if ( AttrVal( $ownName, 'MSwitch_Mode', 'Full' ) eq "Toggle" + if ( $devicemode eq "Toggle" && $set eq 'on' ) { # umschalten des devices nur im togglemode @@ -2358,7 +2591,7 @@ sub MSwitch_Notify($$) { MSwitch_LOG( $ownName, 6, "$ownName: togglemode execute -> " . $cmd ); - if ( AttrVal( $ownName, 'MSwitch_Debug', "0" ) ne '2' ) { + if ($debugmode ne '2' ) { my $errors = AnalyzeCommandChain( undef, $cmd ); if ( defined($errors) ) { MSwitch_LOG( $ownName, 1, @@ -2374,7 +2607,9 @@ sub MSwitch_Notify($$) { #my @cmdarray1; #enthält auszuführende befehle nach conditiontest #schaltet zweig 3 und 4 - if ( $anzahl != 0 ) { + + # ACHTUNG + if ( $anzahl && $anzahl != 0 ) { MSwitch_LOG( $ownName, 6, "$ownName: abarbeiten aller befehle aus eventprüfung " ); @@ -2388,12 +2623,9 @@ sub MSwitch_Notify($$) { if ( !defined $ar2 ) { $ar2 = ''; } if ( $ar2 eq '' ) { next LOOP31; } my $returncmd = 'undef'; - - #MSwitch_LOG( $ownName, 0,"$ownName: aufruf execnotif $_ $ar2, $ar3, $ar4 "); $returncmd = MSwitch_Exec_Notif( $own_hash, $ar2, $ar3, $ar4, $execids ); - #MSwitch_LOG( $ownName, 0,"$ownName: ergebniss execnotif -> ".$returncmd); if ( defined $returncmd && $returncmd ne 'undef' ) { @@ -2411,14 +2643,14 @@ sub MSwitch_Notify($$) { foreach ( split( /,/, $befehlssatz ) ) { my $ecec = $_; if ( !$ecec =~ m/set (.*)(MSwitchtoggle)(.*)/ ) { - if ( AttrVal( $ownName, 'MSwitch_RandomNumber', '' ) ne '' ) + if ( $attrrandomnumber ne '' ) { MSwitch_Createnumber($own_hash); } MSwitch_LOG( $ownName, 6, "$ownName: Befehlsausfuehrung -> " . $ecec ); - if ( AttrVal( $ownName, 'MSwitch_Debug', "0" ) ne '2' ) { + if ( $debugmode ne '2' ) { my $errors = AnalyzeCommandChain( undef, $_ ); @@ -2431,7 +2663,7 @@ sub MSwitch_Notify($$) { if ( length($ecec) > 100 ) { $ecec = substr( $ecec, 0, 100 ) . '....'; } - readingsSingleUpdate( $own_hash, "Exec_cmd", $ecec, 1 ) + readingsSingleUpdate( $own_hash, "last_exec_cmd", $ecec, 1 ) if $ecec ne ''; } else { @@ -2485,11 +2717,11 @@ sub MSwitch_Notify($$) { # variabelersetzung $cs =~ s/\$NAME/$own_hash->{helper}{eventfrom}/; $cs =~ s/\$SELF/$ownName/; - if ( AttrVal( $ownName, 'MSwitch_RandomNumber', '' ) ne '' ) { + if ( $attrrandomnumber ne '' ) { MSwitch_Createnumber($own_hash); } MSwitch_LOG( $ownName, 6, "$ownName: Befehlsausführung -> " . $cs ); - if ( AttrVal( $ownName, 'MSwitch_Debug', "0" ) ne '2' ) { + if ( $debugmode ne '2' ) { my $errors = AnalyzeCommandChain( undef, $cs ); } @@ -2508,6 +2740,8 @@ sub MSwitch_fhemwebFn($$$$) { my $jsvarset = ''; my $j1 = ''; my $border = 0; + + return if ( AttrVal( $Name, 'MSwitch_Mode', "Full" ) eq 'Dummy' ); if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '4' ) { $border = 0; @@ -2718,6 +2952,7 @@ sub MSwitch_fhemwebFn($$$$) { my $cs = ""; my %cmdsatz; # ablage desbefehlssatzes jedes devices my $globalon = 'off'; + my $globalon1 = 'off'; if ( ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ) eq 'no_trigger' ) { @@ -2729,19 +2964,32 @@ sub MSwitch_fhemwebFn($$$$) { } if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' ) { - if ( ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ) eq - 'all_events' ) + + if ( ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ) eq 'all_events' ) { - $triggerdevices .= -""; + $triggerdevices .=""; $globalon = 'on'; } - else { + else + { $triggerdevices .= ""; } + + } - my @notype = split( / /, AttrVal( $Name, 'MSwitch_Ignore_Types', "" ) ); + + + if ( ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ) eq 'MSwitch_Self' ) + { + $triggerdevices .=""; + + } + else + { + $triggerdevices .= ""; + } + my $affecteddevices = ReadingsVal( $Name, '.Device_Affected', 'no_device' ); # affected devices to hash @@ -2762,11 +3010,6 @@ sub MSwitch_fhemwebFn($$$$) { my @testid = split( /#\[NF\]/, $_ ); my $x = 0; - #foreach (@testid) - #{ - #MSwitch_LOG( $Name, 0, "devfelder $x -> $testid[$x]"); - #$x++; - #} MSwitch_LOG( $Name, 5, "devfelder @testid" ); my $id = $testid[13]; MSwitch_LOG( $Name, 5, "id $id" ); @@ -2795,11 +3038,6 @@ sub MSwitch_fhemwebFn($$$$) { my @testid = split( /#\[NF\]/, $_ ); my $x = 0; - #foreach (@testid) - #{ - #MSwitch_LOG( $Name, 0, "devfelder $x -> $testid[$x]"); - #$x++; - #} MSwitch_LOG( $Name, 5, "devfelder @testid" ); my $id = $testid[18]; MSwitch_LOG( $Name, 5, "id $id" ); @@ -2833,7 +3071,101 @@ sub MSwitch_fhemwebFn($$$$) { $usedevices{$a} = 'on'; } - LOOP9: for my $name ( sort keys %defs ) { + + my $notype = AttrVal( $Name, 'MSwitch_Ignore_Types', "" ) ; + my @found_devices; + my $setpattern = ""; + my $setpattern1 = ""; + + + + ###### ersetzung ATTR oder READING + if ($notype =~ /(.*)\[(ATTR|READING):(.*):(.*)\](.*)/) + { + my $devname = $3; + my $firstpart = $1; + my $lastpart = $5; + my $readname = $4; + my $type = $2; + + $devname =~ s/\$SELF/$Name/; + + my $magic = ".*"; + $magic = AttrVal( $devname, $readname, ".*" ) if $type eq "ATTR"; + $magic = ReadingsVal( $devname, $readname, '.*' ) if $type eq "READING"; + + $notype =$firstpart.$magic.$lastpart; + + } + + if ($notype =~ /(")(.*)(")/) + { + + + my $reg =$2; + if ($reg =~ /(.*?)(s)(!=|=)([a-zA-Z]{1,10})(:?)(.*)/) + { + $reg = $1.$5.$6; + $setpattern1 = $4; + $setpattern = "=~" if ($3 eq "="); + $setpattern = "!=" if ($3 eq "!="); + + chop $reg if $6 eq ""; + $reg =~ s/::/:/g; + + + } + + @found_devices =devspec2array("$reg"); + } + else + { + $notype =~ s/ /|/g; + @found_devices =devspec2array("TYPE!=$notype"); + } + + if ($setpattern eq "=~" ) + { + my @found_devices_new; + my $re = qr/$setpattern1/; + for my $name (@found_devices) + { + my $cs = "set $name ?"; + my $errors = AnalyzeCommandChain( undef, $cs ); + if ($errors =~ /$re/) + { + push @found_devices_new, $name; + } + } + @found_devices = @found_devices_new; + } + + + if ($setpattern eq "!=" ) + { + my @found_devices_new; + my $re = qr/$setpattern1/; + for my $name (@found_devices) + { + my $cs = "set $name ?"; + my $errors = AnalyzeCommandChain( undef, $cs ); + if ($errors !~ /$re/) + { + push @found_devices_new, $name; + } + } + @found_devices = @found_devices_new; + } + + + if (!grep {$_ eq $Name} @found_devices) + { + MSwitch_LOG( $Name, 5, "grep Devicetest $Name nicht vorhanden -> wird ergänzt" ); + push @found_devices, $Name; + } + + + LOOP9: for my $name ( sort @found_devices) { my $selectedtrigger = ''; my $devicealias = AttrVal( $name, 'alias', "" ); my $devicewebcmd = @@ -2842,9 +3174,6 @@ sub MSwitch_fhemwebFn($$$$) { my $deviceTYPE = $devicehash->{TYPE}; # triggerfile erzeugen - foreach (@notype) { - if ( lc($_) eq lc($deviceTYPE) ) { next LOOP9; } - } if ( ReadingsVal( $Name, 'Trigger_device', '' ) eq $name ) { $selectedtrigger = 'selected=\"selected\"'; @@ -2867,14 +3196,14 @@ sub MSwitch_fhemwebFn($$$$) { else { $errors = ''; } - + + if ( !defined $errors ) { $errors = '' } my @tmparg = split( /of /, $errors ); if ( !defined $tmparg[1] ) { $tmparg[1] = "" } - #if ( defined $tmparg[1] && $tmparg[1] ne '' ) { $errors = $tmparg[1]; } if ( $tmparg[1] ne '' ) { $errors = $tmparg[1]; } @@ -3109,13 +3438,15 @@ sub MSwitch_fhemwebFn($$$$) { if ( !defined( $savedetails{ $aktdevice . '_timeon' } ) ) { my $key = ''; $key = $aktdevice . "_timeon"; - $savedetails{$key} = '000000'; + #$savedetails{$key} = '000000'; #change + $savedetails{$key} = '00:00:00'; } if ( !defined( $savedetails{ $aktdevice . '_timeoff' } ) ) { my $key = ''; $key = $aktdevice . "_timeoff"; - $savedetails{$key} = '000000'; + #$savedetails{$key} = '000000'; #change + $savedetails{$key} = '00:00:00'; } if ( !defined( $savedetails{ $aktdevice . '_conditionon' } ) ) { @@ -3884,12 +4215,14 @@ sub MSwitch_fhemwebFn($$$$) { my $timeoff = ''; my $timeononly = ''; my $timeoffonly = ''; + my $timeonoffonly = ''; if ( $lenght != 0 ) { $timeon = substr( $triggertimes[0], 2 ); $timeoff = substr( $triggertimes[1], 3 ); $timeononly = substr( $triggertimes[2], 6 ); $timeoffonly = substr( $triggertimes[3], 7 ); + $timeonoffonly = substr( $triggertimes[4], 9 ); } my $ret = ''; @@ -4058,7 +4391,6 @@ sub MSwitch_fhemwebFn($$$$) { return "$ret" . "$j1"; } - #readingsSingleUpdate( $hash, ".wrong_version", $1, 0 ); if ( ReadingsVal( $Name, '.wrong_version', 'undef' ) ne "undef" ) { $ret .= " @@ -4138,6 +4470,13 @@ sub MSwitch_fhemwebFn($$$$) { if ( $globalon ne 'on' ) { $visible = 'collapse'; } + + my $visible1 = 'visible'; + if ( $globalon1 ne 'on' ) { + $visible1 = 'collapse'; + } + + $ret = $ret . ""; $ret = $ret . ""; + my $inhalt = "execute 'cmd1' only at :"; my $inhalt1 = "execute 'cmd2' only at :"; + + my $inhalt6 = "execute 'cmd1+cmd2' only at :"; + my $inhalt2 = "execute 'cmd1' only"; my $inhalt3 = "execute 'cmd2' only"; my $inhalt4 = "switch MSwitch on + execute 'cmd1' at :"; @@ -4206,7 +4549,7 @@ sub MSwitch_fhemwebFn($$$$) { - + + + + + + + + + "; + + + my $triggerinhalt = "Trigger condition (events only): "; if ( AttrVal( $Name, 'MSwitch_Condition_Time', "0" ) eq '1' ) { @@ -4256,6 +4611,7 @@ sub MSwitch_fhemwebFn($$$$) { #################### # triggerdetails my $selectedcheck3 = ""; + my $SELF = $Name; my $testlog = ReadingsVal( $Name, 'Trigger_log', 'on' ); if ( $testlog eq 'on' ) { $selectedcheck3 = "checked=\"checked\""; @@ -4276,12 +4632,24 @@ sub MSwitch_fhemwebFn($$$$) { "; $ret .= " - + - + "; $ret .= " @@ -4303,8 +4682,18 @@ sub MSwitch_fhemwebFn($$$$) { Trigger " . $Triggerdevice . " : + "; + + ############## + my $fieldcmdon =""; + if ( $triggercmdon =~ m/{(.*)}/ ) + { + my $exec = "\$fieldcmdon = ".$1; + eval ($exec); + $ret .= "" ; + } + ##################### + $ret .= " @@ -4313,8 +4702,17 @@ sub MSwitch_fhemwebFn($$$$) { + . $optioncmdoff . ""; + ############## + my $fieldcmdoff =""; + if ( $triggercmdoff =~ m/{(.*)}/ ) + { + my $exec = "\$fieldcmdoff = ".$1; + eval ($exec); + $ret .= "" ; + } + ##################### + $ret .= " @@ -4654,7 +5052,16 @@ sub MSwitch_fhemwebFn($$$$) { globallock =' this device is locked !'; [ \"aw_dev\",\"aw_det\",\"aw_trig\",\"aw_md\",\"aw_md1\",\"aw_md2\",\"aw_addevent\"].forEach (lock,); randomdev.forEach (lock);" - if ( ReadingsVal( $Name, '.lock', 'undef' ) ne "undef" ); + if ( ReadingsVal( $Name, '.lock', 'undef' ) eq "1" ); + + + $j1 .= " + globallock =' only trigger is changeable'; + [ \"aw_dev\",\"aw_det\",\"aw_md\",\"aw_md1\",\"aw_md2\",\"aw_addevent\"].forEach (lock,); + randomdev.forEach (lock);" + if ( ReadingsVal( $Name, '.lock', 'undef' ) eq "2" ); + + $j1 .= " sel1.onchange = function() @@ -4783,7 +5190,7 @@ sub MSwitch_fhemwebFn($$$$) { if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { - $j1 .= " + my $j1raw .= " function info(from){ text='Help: ' + from +'

'; @@ -4794,17 +5201,50 @@ sub MSwitch_fhemwebFn($$$$) { if (from == 'timer'){ text = text + 'Hier kann entweder eine direkte Angabe einer Verzögerungszeit (delay with Cond_check) angegeben werden, oder es kann eine Ausführungszeit (at with Cond-check) für den Befehl angegeben werden
Bei der Angabe einer Ausführungszeit wird der Schaltbefehl beim nächsten erreichen der angegebenen Zeit ausgeführt. Ist die Zeit am aktuellen Tag bereits überschritten , wird der angegebene Zeitpunkt am Folgetag gesetzt.
Die Auswahl \"with Conf-check\" oder \"without Conf-check\" legt fest, ob unmittelbar vor Befehlsausführung nochmals die Condition für den Befehl geprüft wird oder nicht.

[NAME.reading] des Devices ->z.B. [dummy.state]
Das Reading muss in folgendem Format vorliegen: hh:mm:ss ';} - if (from == 'trigger'){ - text = text + 'Trigger ist das Gerät, oder die Zeit, auf die das Modul reagiert, um andere devices anzusprechen.
Das Gerät kann aus der angebotenen Liste ausgewählt werden, sobald dieses ausgewählt ist werden weitere Optionen angeboten.
Soll auf mehrereGerät gleichzeitig getriggert werden , so ist dieses ebenfalls möglich. Hierzu muss das Attribut \"MSwitch_Expert\" auf 1 gesetzt sein und als Auswahl \"GLOBAL\" erfolgen.

Zeitangaben können ebenso als Trigger genutzt werden, das Format muss wie folgt lauten:

[STUNDEN:MINUTEN|TAGE] - Tage werden von 1-7 gezählt, wobei 1 für Montag steht, 7 für Sonntag.

Die Variable \$we ist anstatt der Tagesangabe verwendbar
[STUNDEN:MINUTEN|\$we] - Schaltvorgang nur an Wochenenden.
[STUNDEN:MINUTEN|!\$we] - Schaltvorgang nur an Werktagen.

Mehrere Zeitvorgaben können aneinandergereiht werden.
[17:00|1][18:30|23] würde den Trigger Montags um 17 Uhr auslösen und Dienstags,Mittwochs um 18 Uhr 30.

Sunset - Zeitangaben können mit folgender Sytax eingebunden werden: z.B [{sunset()}] , [{sunrise(+1800)}].

Es ist eine gleichzeitige Nutzung für Trigger durch Zeitangaben und Trigger durch Deviceevents möglich.

Sonderformate:
[?20:00-21:00|5] - Zufälliger Schaltvorgang zwischen 20 Uhr und 21 Uhr am Freitag
[00:02*04:10-06:30] - Schaltvorgang alle 2 Minuten zwischen 4.10 Uhr und 6.30 Uhr';} +if (from == 'trigger') +{ + text = text + ' +Trigger ist das Gerät, oder die Zeit, auf die das Modul reagiert, um andere Devices anzusprechen.
Das Gerät kann aus der angebotenen Liste ausgewählt werden, sobald dieses ausgewählt ist werden weitere Optionen angeboten.
Soll auf mehrereGerät gleichzeitig getriggert werden , so ist dieses ebenfalls möglich. Hierzu muss das Attribut \"MSwitch_Expert\" auf 1 gesetzt sein und als Auswahl \"GLOBAL\" erfolgen.

Zeitangaben können ebenso als Trigger genutzt werden, das Format muss wie folgt lauten:
+Hierfür stehen folgende Optionen zur Verfügung:
+
+1. switch MSwitch on + execute \\'cmd1\\' at
+das komplette Device wird auf \"on\" geschaltet. Der Zweig \"cmd1\" wird in +allen \"device actions\" ausgeführt.
+
+2. switch MSwitch off + execute \\'cmd2\\' at
+das komplette Device wird auf \"off\" geschaltet. Der Zweig \"cmd2\" wird in +allen \"device actions\" ausgeführt.
+
+3. execute \\'cmd1\\' only at
+es werden alle \"cmd1\" Zweige aller \"device actions\" ausgeführt
+
+4. execute \\'cmd2\\' only at
+es werden alle \"cmd2\" Zweige aller \"device actions\" ausgeführt
+
+5. execute \\'cmd1+cmd2\\' only at
+es werden alle \"cmd1\" und \"cmd2\" Zweige aller \"device actions\" ausgeführt
+
+Die Syntax muss wie folgt lauten:
[STUNDEN:MINUTEN|TAGE|IDx,y]
+Tage werden von 1-7 gezählt, wobei 1 für Montag steht, 7 für Sonntag.
+Die Angabe der ID ist optional. Wenn eine ID angegeben ist , werden nur +\\'cmds\\' ausgeführt, denen eine ID zugewiesen ist. Ist keine ID angegeben , +werden nur alle \\'cmds\\' ausgeführt , denen keine ID zugewiesen ist .
+Diese Option ist nur in den Feldern \"execute cmd1 only at :\" , \"execute cmd2 only at :\" +und \"execute \\'cmd1+cmd2\\' only at:\" möglich.

Die Variable \$we ist anstatt der Tagesangabe verwendbar
[STUNDEN:MINUTEN|\$we] - Schaltvorgang nur an Wochenenden.
[STUNDEN:MINUTEN|!\$we] - Schaltvorgang nur an Werktagen.

Mehrere Zeitvorgaben können aneinandergereiht werden.
[17:00|1][18:30|23] würde den Trigger Montags um 17 Uhr auslösen und Dienstags,Mittwochs um 18 Uhr 30.

Sunset - Zeitangaben können mit folgender Sytax eingebunden werden: z.B:
+ [{sunset()}] , [{sunrise(+1800)}].

Es ist eine gleichzeitige Nutzung für Trigger durch Zeitangaben und Trigger durch Deviceevents möglich.

+Sonderformate:
[?20:00-21:00|5] - Zufälliger Schaltvorgang zwischen 20 Uhr und 21 Uhr am Freitag
[00:02*04:10-06:30] - Schaltvorgang alle 2 Minuten zwischen 4.10 Uhr und 6.30 Uhr


+ + ' +;} if (from == 'triggercondition'){ - text = text + 'Hier kann die Angabe von Bedingungen erfolgen, die zusätzlich zu dem triggernden Device erfuellt sein müssen.
Diese Bedingunge sind eng an DOIF- Bedingungen angelehnt .
Zeitabhängigkeit: [19.10-23:00] - Trigger des Devices erfolgt nur in angegebenem Zeitraum
Readingabhängige Trigger [Devicename:Reading] =/>/< X oder [Devicename:Reading] eq \"x\" - Trigger des Devicec erfolgt nur bei erfüllter Bedingung.
Achtung ! Bei der Abfrage von Readings nach Strings ( on,off,etc. ) ist statt \"=\" \"eq\" zu nutzen und der String muss in \"\" gesetzt werden!
Die Kombination mehrerer Bedingungen und Zeiten ist durch AND oder OR möglich.
[19.10-23:00] AND [Devicename:Reading] = 10 - beide Bedingungen müssen erfüllt sein
[19.10-23:00] OR [Devicename:Reading] = 10 - eine der Bedingungen muss erfüllt sein.
Es ist auf korrekte Eingabe der Leerzeichen zu achten.

sunset - Bedingungen werden mit zusätzlichen {} eingefügt z.B. : [{ sunset() }-23:00].

Variable \$we:
Die globlae Variable \$we ist nutzbar und muss in {} gesetzt werden .
{ !\$we } löst den Schaltvorgang nur Werktagen an aus
{ \$we } löst den Schaltvorgang nur an Wochenenden, Feiertagen aus

Soll nur an bestimmten Wochentagen geschaltet werden, muss eine Zeitangsbe gemacht werden und durch z.B. |135 ergänzt werden.
[10:00-11:00|13] würde den Schaltvorgang z.B nur Montag und Mitwoch zwischen 10 uhr und 11 uhr auslösen. Hierbei zählen die Wochentage von 1-7 für Montag-Sonntag.
Achtung: Bei Anwendung der geschweiften Klammern zur einletung eines Perlasdrucks ist unbedingt auf die Leerzeichen hinter und vor der Klammer zu achten !
Überschreitet die Zeitangabe die Tagesgrenze (24.00 Uhr ), so gelten die angegebenen Tage noch bis zum ende der angegebenen Schaltzeit,
d.H. es würde auch am Mitwoch noch der schaltvorgang erfolgen, obwohl als Tagesvorgabe Dienstag gesetzt wurde.

Wird in diesem Feld keine Angabe gemacht , so erfolgt der Schaltvorgang nur durch das triggernde Device ohne weitere Bedingungen.

Achtung: Conditions gelten nur für auslösende Trigger eines Devices und habe keinen Einfluss auf zeitgesteuerte Auslöser. Um Zeitgesteuerte Auslösr ebenfalls an Bedingungen zu Knüpfen muss dieses in den Attributen aktiviert werden.';} + text = text + 'Hier kann die Angabe von Bedingungen erfolgen, die zusätzlich zu dem triggernden Device erfuellt sein müssen.
Diese Bedingunge sind eng an DOIF- Bedingungen angelehnt .
Zeitabhängigkeit: [19:10-23:00] - Trigger des Devices erfolgt nur in angegebenem Zeitraum
Readingabhängige Trigger [Devicename:Reading] =/>/< X oder [Devicename:Reading] eq \"x\" - Trigger des Devicec erfolgt nur bei erfüllter Bedingung.
Achtung ! Bei der Abfrage von Readings nach Strings ( on,off,etc. ) ist statt \"=\" \"eq\" zu nutzen und der String muss in \"\" gesetzt werden!
Die Kombination mehrerer Bedingungen und Zeiten ist durch AND oder OR möglich.
[19.10-23:00] AND [Devicename:Reading] = 10 - beide Bedingungen müssen erfüllt sein
[19.10-23:00] OR [Devicename:Reading] = 10 - eine der Bedingungen muss erfüllt sein.
Es ist auf korrekte Eingabe der Leerzeichen zu achten.

sunset - Bedingungen werden mit zusätzlichen {} eingefügt z.B. : [{ sunset() }-23:00].

Variable \$we:
Die globlae Variable \$we ist nutzbar und muss in {} gesetzt werden .
{ !\$we } löst den Schaltvorgang nur Werktagen an aus
{ \$we } löst den Schaltvorgang nur an Wochenenden, Feiertagen aus

Soll nur an bestimmten Wochentagen geschaltet werden, muss eine Zeitangsbe gemacht werden und durch z.B. |135 ergänzt werden.
[10:00-11:00|13] würde den Schaltvorgang z.B nur Montag und Mitwoch zwischen 10 uhr und 11 uhr auslösen. Hierbei zählen die Wochentage von 1-7 für Montag-Sonntag.
Achtung: Bei Anwendung der geschweiften Klammern zur einletung eines Perlasdrucks ist unbedingt auf die Leerzeichen hinter und vor der Klammer zu achten !
Überschreitet die Zeitangabe die Tagesgrenze (24.00 Uhr ), so gelten die angegebenen Tage noch bis zum ende der angegebenen Schaltzeit,
d.H. es würde auch am Mitwoch noch der schaltvorgang erfolgen, obwohl als Tagesvorgabe Dienstag gesetzt wurde.

Wird in diesem Feld keine Angabe gemacht , so erfolgt der Schaltvorgang nur durch das triggernde Device ohne weitere Bedingungen.

Achtung: Conditions gelten nur für auslösende Trigger eines Devices und habe keinen Einfluss auf zeitgesteuerte Auslöser. Um Zeitgesteuerte Auslösr ebenfalls an Bedingungen zu Knüpfen muss dieses in den Attributen aktiviert werden.';} if (from == 'whitelist'){ text = text + 'Bei der Auswahl \\\'GLOBAL\\\' als Triggerevent werde alle von Fhem erzeugten Events an dieses Device weitergeleitet. Dieses kann eine erhöhte Systemlast erzeugen.
In dem Feld \\\'Trigger Device Global Whitelist:\\\' kann dieses eingeschränkt werden , indem Devices oder Module benannt werden , deren Events Berücksichtigt werden. Sobald hier ein Eintrag erfolgt , werden nur noch Diese berücksichtigt , gibt es keinen Eintrag , werden alle berücksichtigt ( Whitelist ).
Format: Die einzelnen Angaben müssen durch Komma getrennt werden .

Mögliche Angaben :
Modultypen: TYPE=CUL_HM
Devicenamen: NAME

';} if (from == 'addevent'){ - text = text + 'Hier können manuell Events zugefügt werden , die in den Auswahllisten verfügbar sein sollen und auf die das Modul reagiert.
Grundsätzlich ist zu unterscheiden , ob das Device im Normal-, oder Globalmode betrieben wird
Im Normalmode bestehen die Events aus 2 Teilen , dem Reading und dem Wert \"state:on\"
Wenn sich das Device im GLOBAL Mode befindet müssen die Events aus 3 Teilen bestehen , dem Devicename, dem Reading und dem Wert \"device:state:on\".
Wird hier nur ein \"*\" angegeben , reagiert der entsprechende Zweig auf alle eingehenden Events.
Weitherhin sind folgende Syntaxmöglichkeiten vorgesehen :
device:state:*, device:*:*, *:state:* , etc.
Der Wert kann mehrere Auswahlmöglichkeiten haben , durch folgende Syntax: \"device:state:(on/off)\". In diesem Fal reagiert der Zweig sowohl auf den Wert on, als auch auf off.

Es können mehrere Evebts gleichzeitig angelegt werden . Diese sind durch Komma zu trennen .

Seit V1.7 kann hier die gängige RegEx-Formulierung erfolgen.';} + text = text + 'Hier können manuell Events zugefügt werden , die in den Auswahllisten verfügbar sein sollen und auf die das Modul reagiert.
Grundsätzlich ist zu unterscheiden , ob das Device im Normal-, oder Globalmode betrieben wird
Im Normalmode bestehen die Events aus 2 Teilen , dem Reading und dem Wert \"state:on\"
Wenn sich das Device im GLOBAL Mode befindet müssen die Events aus 3 Teilen bestehen , dem Devicename, dem Reading und dem Wert \"device:state:on\".
Wird hier nur ein \"*\" angegeben , reagiert der entsprechende Zweig auf alle eingehenden Events.
Weitherhin sind folgende Syntaxmöglichkeiten vorgesehen :
device:state:*, device:*:*, *:state:* , etc.
Der Wert kann mehrere Auswahlmöglichkeiten haben , durch folgende Syntax: \"device:state:(on/off)\". In diesem Fal reagiert der Zweig sowohl auf den Wert on, als auch auf off.

Es können mehrere Evebts gleichzeitig angelegt werden . Diese sind durch Leerzeichen zu trennen .

Seit V1.7 kann hier die gängige RegEx-Formulierung erfolgen.';} if (from == 'condition'){ text = text + 'Hier kann die Angabe von Bedingungen erfolgen, die erfüllt sein müssen um den Schaltbefehl auszuführen.
Diese Bedingunge sind eng an DOIF- Bedingungen angelehnt.

Zeitabhängiges schalten: [19.10-23:00] - Schaltbefehl erfolgt nur in angegebenem Zeitraum
Readingabhängiges schalten [Devicename:Reading] =/>/< X oder [Devicename:Reading] eq \"x\" - Schaltbefehl erfolgt nur bei erfüllter Bedingung.
Achtung! Bei der Abfrage von Readings nach Strings ( on,off,etc. ) ist statt \"=\" \"eq\" zu nutzen und der String muss in \"x\" gesetzt werden!
Die Kombination mehrerer Bedingungen und Zeiten ist durch AND oder OR möglich:
[19.10-23:00] AND [Devicename:Reading] = 10 - beide Bedingungen müssen erfüllt sein
[19.10-23:00] OR [Devicename:Reading] = 10 - eine der Bedingungen muss erfüllt sein.
Es ist auf korrekte Eingabe der Leerzeichen zu achten.

sunset - Bedingungen werden mit zusätzlichen {} eingefügt z.B. : [{ sunset() }-23:00].

Variable \$we:
Die globlae Variable \$we ist nutzbar und muss {} gesetzt werden .
{ !\$we } löst den Schaltvorgang nur Werktagen aus
{ \$we } löst den Schaltvorgang nur Wochenenden, Feiertagen aus

Soll nur an bestimmten Wochentagen geschaltet werden, muss eine Zeitangsbe gemacht werden und durch z.B. |135 ergänzt werden.
[10:00-11:00|13] würde den Schaltvorgang z.B nur Montag und Mitwoch zwischen 10 uhr und 11 uhr auslösen. Hierbei zählen die Wochentage von 1-7 für Montag-Sonntag.
Achtung: Bei Anwendung der geschweiften Klammern zur einletung eines Perlasdrucks ist unbedingt auf die Leerzeichen hinter und vor der Klammer zu achten !
Überschreitet die Zeitangabe die Tagesgrenze (24.00 Uhr ), so gelten die angegebenen Tage noch bis zum ende der angegebenen Schaltzeit , d.H. es würde auch am Mitwoch noch der schaltvorgang erfolgen, obwohl als Tagesvorgabe Dienstag gesetzt wurde.

\$EVENT Variable: Die Variable EVENT enthält den auslösenden Trigger, d.H. es kann eine Reaktion in direkter Abhängigkeit zum auslösenden Trigger erfolgen.
[\$EVENT] eq \"state:on\" würde den Kommandozweig nur dann ausführen, wenn der auslösende Trigger \"state:on\" war.
Wichtig ist dieses, wenn bei den Triggerdetails nicht schon auf ein bestimmtes Event getriggert wird, sondern hier durch die Nutzung eines wildcards (*) auf alle Events getriggert wird, oder auf alle Events eines Readings z.B. (state:*)

Bei eingestellter Delayfunktion werden die Bedingungen je nach Einstellung sofort,verzögert oder sowohl-als-auch überprüft, d.H hiermit sind verzögerte Ein-, und Ausschaltbefehle möglich die z.B Nachlauffunktionen oder verzögerte Einschaltfunktionen ermöglichen, die sich selbst überprüfen. z.B. [wenn Licht im Bad an -> schalte Lüfter 2 Min später an -> nur wenn Licht im Bad noch an ist]

Anstatt einer Verzögerung kann hier auch eine festgelegte Schaltzeit erfolgen.';} @@ -4832,6 +5272,10 @@ sub MSwitch_fhemwebFn($$$$) { FW_okDialog(textfinal); return; }"; + + $j1raw =~ s/\n//g; + #$j1raw =~ s/\'/\\'/g; + $j1 .= $j1raw; } $j1 .= " @@ -5044,8 +5488,11 @@ sub MSwitch_fhemwebFn($$$$) { timeoff = \$(\"[name=timeoff]\").val(); timeononly = \$(\"[name=timeononly]\").val(); timeoffonly = \$(\"[name=timeoffonly]\").val(); - + timeonoffonly = \$(\"[name=timeonoffonly]\").val(); + //alert(timeonoffonly); + + trigdevcond = \$(\"[name=triggercondition]\").val(); //trigdevcond = trigdevcond.replace(/:/g,'#[dp]'); @@ -5062,31 +5509,42 @@ sub MSwitch_fhemwebFn($$$$) { timeoff = timeoff.replace(/ /g, ''); timeononly = timeononly.replace(/ /g, ''); timeoffonly = timeoffonly.replace(/ /g, ''); + timeonoffonly = timeonoffonly.replace(/ /g, ''); timeon = timeon.replace(/:/g, '#[dp]'); timeoff = timeoff.replace(/:/g, '#[dp]'); timeononly = timeononly.replace(/:/g, '#[dp]'); timeoffonly = timeoffonly.replace(/:/g, '#[dp]'); + timeonoffonly = timeonoffonly.replace(/:/g, '#[dp]'); timeon = timeon+':'; timeoff = timeoff+':'; timeononly = timeononly+':'; timeoffonly = timeoffonly+':'; + timeonoffonly = timeonoffonly+':'; + trigwhite = \$(\"[name=triggerwhitelist]\").val(); - var def = nm+\" set_trigger \"+trigdev+\" \"+timeon+\" \"+timeoff+\" \"+timeononly+\" \"+timeoffonly+\" \"+trigdevcond+\" \"+trigwhite+\" \" ; + var def = nm+\" set_trigger \"+trigdev+\" \"+timeon+\" \"+timeoff+\" \"+timeononly+\" \"+timeoffonly+\" \"+timeonoffonly+\" \"+trigdevcond+\" \"+trigwhite+\" \" ; def = encodeURIComponent(def); location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def); }); + \$(\"#aw_addevent\").click(function(){ var nm = \$(t).attr(\"nm\"); + event = \$(\"[name=add_event]\").val(); - event= event.replace(/ /g,'~'); + + event= event.replace(/ /g,'[sp]'); event= event.replace(/\\|/g,'[bs]'); + + if (event == ''){ //alert('no event specified'); return; } + + var def = nm+\" addevent \"+event+\" \"; location = location.pathname+\"?detail=" . $Name . "&cmd=set \"+addcsrf(def); }); @@ -5194,6 +5652,9 @@ sub MSwitch_makeCmdHash($) { my %savedetails; foreach (@devicedatails) { + + + # ersetzung $_ =~ s/#\[sp\]/ /g; $_ =~ s/#\[nl\]/\n/g; @@ -5206,6 +5667,19 @@ sub MSwitch_makeCmdHash($) { my @detailarray = split( /#\[NF\]/, $_ ) ; #enthält daten 0-5 0 - name 1-5 daten 7 und9 sind zeitangaben + + + #MSwitch_LOG( $Name, 0, "$Name: device " .$_ ); + #MSwitch_LOG( $Name, 0, "$Name: detailarray8 " .$detailarray[8] ); + + + + + + + + + my $key = ''; my $testtimestroff = $detailarray[7]; $key = $detailarray[0] . "_delayatonorg"; @@ -5221,6 +5695,11 @@ sub MSwitch_makeCmdHash($) { } } + + + + + my $testtimestron = $detailarray[8]; $key = $detailarray[0] . "_delayatofforg"; $savedetails{$key} = $detailarray[8]; @@ -5229,6 +5708,13 @@ sub MSwitch_makeCmdHash($) { $testtimestron =~ s/[A-Za-z0-9#\.\-_]//g; if ( $testtimestron ne "[:]" && $testtimestroff ne "[\$:]" ) { + + if ($detailarray[8] ne "00:00:00") + { + #MSwitch_LOG( $Name, 0, "$Name: detailarray8 " .$detailarray[8] ); + } + + my $hdel = substr( $detailarray[8], 0, 2 ) * 3600; my $mdel = substr( $detailarray[8], 3, 2 ) * 60; my $sdel = substr( $detailarray[8], 6, 2 ) * 1; @@ -5254,7 +5740,7 @@ sub MSwitch_makeCmdHash($) { $savedetails{$key} = $detailarray[8]; $key = $detailarray[0] . "_repeatcount"; - if ( defined $detailarray[11] ) { + if ( defined $detailarray[11] && $detailarray[11] ne "") { $savedetails{$key} = $detailarray[11]; } @@ -5263,7 +5749,7 @@ sub MSwitch_makeCmdHash($) { } $key = $detailarray[0] . "_repeattime"; - if ( defined $detailarray[12] ) { + if ( defined $detailarray[12] && $detailarray[12] ne "" ) { $savedetails{$key} = $detailarray[12]; } else { @@ -5391,8 +5877,18 @@ sub MSwitch_Exec_Notif($$$$$) { my $name = $hash->{NAME}; my $protokoll = ''; my $satz; - $execids = "0"; + + MSwitch_LOG( $name, 5, + "$name: execnotif -> $execids " ); + + if (!$execids){$execids = "0"}; + + my $debugmode=AttrVal( $name, 'MSwitch_Debug', "0" ); + my $expertmode = AttrVal( $name, 'MSwitch_Expert', "0" ); + my $delaymode=AttrVal( $name, 'MSwitch_Delete_Delays', '0' ); + my $attrrandomtime = AttrVal( $name, 'MSwitch_RandomTime', '' ); + my $exittest = ''; $exittest = "1" if $comand eq "on"; $exittest = "2" if $comand eq "off"; @@ -5400,7 +5896,7 @@ sub MSwitch_Exec_Notif($$$$$) { my $ekey = ''; my $out = '0'; - MSwitch_LOG( $name, 6, + MSwitch_LOG( $name, 5, "$name: execnotif -> $hash, $comand, $check, $event,$execids " ); return "" @@ -5420,16 +5916,21 @@ sub MSwitch_Exec_Notif($$$$$) { # liste nach priorität ändern , falls expert @devices = MSwitch_priority( $hash, $execids, @devices ); + + my $lastdevice ; + + LOOP45: foreach my $device (@devices) { $out = '0'; - if ( AttrVal( $name, 'MSwitch_Expert', "0" ) eq '1' ) { + + if ( $expertmode eq '1' ) { $ekey = $device . "_exit" . $exittest; $out = $devicedetails{$ekey}; } - if ( AttrVal( $name, 'MSwitch_Delete_Delays', '0' ) eq '1' ) { + if ( $delaymode eq '1' ) { MSwitch_Delete_Delay( $hash, $device ); } @@ -5496,6 +5997,7 @@ sub MSwitch_Exec_Notif($$$$$) { $name, $event ); $testtoggle = 'undef'; if ( $execute eq 'true' ) { + $lastdevice = $device ; $testtoggle = $cs; ############# Log3( $name, 3, @@ -5550,7 +6052,7 @@ sub MSwitch_Exec_Notif($$$$$) { "$name: delay repeats -> " . $devicedetails{ $device . '_repeattime' } ); - if ( AttrVal( $name, 'MSwitch_Expert', "0" ) eq '1' + if ( $expertmode eq '1' && $devicedetails{ $device . '_repeatcount' } > 0 && $devicedetails{ $device . '_repeattime' } > 0 ) { @@ -5582,6 +6084,8 @@ sub MSwitch_Exec_Notif($$$$$) { MSwitch_LOG( $name, 6, "$name: Abbruchbefehl erhalten von " . $device ); + + $lastdevice = $device ; last LOOP45; } @@ -5592,7 +6096,7 @@ sub MSwitch_Exec_Notif($$$$$) { $cs = MSwitch_dec( $hash, $todec ); ############################ - if ( AttrVal( $name, 'MSwitch_Debug', "0" ) eq '2' ) { + if ( $debugmode eq '2' ) { MSwitch_LOG( $name, 6, "$name: execute -> " . $cs ); } else { @@ -5603,12 +6107,16 @@ sub MSwitch_Exec_Notif($$$$$) { MSwitch_LOG( $name, 1, "$name MSwitch_Set: ERROR $cs: $@ " . __LINE__ ); + + } if ( $out eq '1' ) { MSwitch_LOG( $name, 6, "$name: Abbruchbefehl erhalten von " . $device ); + + $lastdevice = $device ; last LOOP45; } @@ -5617,15 +6125,17 @@ sub MSwitch_Exec_Notif($$$$$) { my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { - MSwitch_LOG( $name, 1, -"$name Absent_Exec_Notif $comand: ERROR $device: $errors -> Comand: $cs" - ); + MSwitch_LOG( $name, 1, "$name Absent_Exec_Notif $comand: ERROR $device: $errors -> Comand: $cs"); + + + } if ( $out eq '1' ) { MSwitch_LOG( $name, 6, "$name: Abbruchbefehl erhalten von " . $device ); + $lastdevice = $device ; last LOOP45; } } @@ -5635,13 +6145,13 @@ sub MSwitch_Exec_Notif($$$$$) { if ( length($msg) > 100 ) { $msg = substr( $msg, 0, 100 ) . '....'; } - readingsSingleUpdate( $hash, "Exec_cmd", $msg, 1 ) + readingsSingleUpdate( $hash, "last_exec_cmd", $msg, 1 ) if $msg ne ''; } } else { - if ( AttrVal( $name, 'MSwitch_RandomTime', '' ) ne '' + if ($attrrandomtime ne '' && $devicedetails{$timerkey} eq '[random]' ) { $devicedetails{$timerkey} = @@ -5649,7 +6159,7 @@ sub MSwitch_Exec_Notif($$$$$) { # ersetzt $devicedetails{$timerkey} gegen randomtimer } - elsif ( AttrVal( $name, 'MSwitch_RandomTime', '' ) eq '' + elsif ( $attrrandomtime eq '' && $devicedetails{$timerkey} eq '[random]' ) { $devicedetails{$timerkey} = 0; @@ -5708,6 +6218,7 @@ sub MSwitch_Exec_Notif($$$$$) { if ( $out eq '1' ) { MSwitch_LOG( $name, 6, "$name: Abbruchbefehl erhalten von " . $device ); + $lastdevice = $device ; last LOOP45; } @@ -5719,7 +6230,12 @@ sub MSwitch_Exec_Notif($$$$$) { } } - MSwitch_LOG( $name, 6, "$name: return aus execnotif -> " . $satz ); + + if ( $expertmode eq "1" && $lastdevice) { + readingsSingleUpdate( $hash, "last_cmd", $hash->{helper}{priorityids}{$lastdevice}, 1 ); + } + + MSwitch_LOG( $name, 6, "$name: return aus execnotif -> " . $satz ) if $satz; return $satz; } #################### @@ -5788,11 +6304,11 @@ sub MSwitch_Restartcmd($) { my $name = $msgarray[1]; my $hash = $modules{MSwitch}{defptr}{$name}; return "" if ( IsDisabled($name) ); - + return if ( AttrVal( $name, 'MSwitch_Mode', "Full" ) eq 'Dummy' ); $hash->{eventsave} = 'unsaved'; - MSwitch_LOG( $name, 5, "----------------------------------------" ); - MSwitch_LOG( $name, 5, "$name: aufruf restartcmd -> " . $incomming ); - MSwitch_LOG( $name, 5, "----------------------------------------" ); + MSwitch_LOG( $name, 6, "----------------------------------------" ); + MSwitch_LOG( $name, 6, "$name: aufruf restartcmd -> " . $incomming ); + MSwitch_LOG( $name, 6, "----------------------------------------" ); # checke versionskonflikt der datenstruktur if ( ReadingsVal( $name, '.V_Check', $vupdate ) ne $vupdate ) { @@ -5807,9 +6323,14 @@ sub MSwitch_Restartcmd($) { my $event = $msgarray[2]; my $device = $msgarray[5]; + #MSwitch_LOG( $name, 0, "$name: conditionkey -> " . $conditionkey ); + MSwitch_LOG( $name, 5, "$name: erstelle cmdhash -> " . $name ); my %devicedetails = MSwitch_makeCmdHash($name); + + + if ( AttrVal( $name, 'MSwitch_RandomNumber', '' ) ne '' ) { MSwitch_Createnumber1($hash); } @@ -5818,25 +6339,23 @@ sub MSwitch_Restartcmd($) { ### antwort $execute 1 oder 0 ; my $execute = "true"; - MSwitch_LOG( $name, 5, - "$name: kein aufruf checkcondition - nicht gesetzt ->" . $execute ) - if $devicedetails{$conditionkey} eq '' - || $devicedetails{$conditionkey} eq 'nocheck'; + + $devicedetails{$conditionkey} = "nocheck" if $conditionkey eq "nocheck"; + MSwitch_LOG( $name, 5,"$name: kein aufruf checkcondition - nicht gesetzt ->".$execute ) if $conditionkey eq "nocheck" || $devicedetails{$conditionkey} eq '' || $devicedetails{$conditionkey} eq 'nocheck'; + + + if ( $msgarray[2] ne 'nocheck' ) { - MSwitch_LOG( $name, 5, - "$name: aufruf checkcondition mit -> " - . $devicedetails{$conditionkey} ); + MSwitch_LOG( $name, 5, "$name: aufruf checkcondition mit -> " . $devicedetails{$conditionkey} ); $execute = MSwitch_checkcondition( $devicedetails{$conditionkey}, $name, $event ); - MSwitch_LOG( $name, 5, - "$name: ergebniss checkcondition -> " . $execute ); + MSwitch_LOG( $name, 5,"$name: ergebniss checkcondition -> " . $execute ); } my $toggle = ''; if ( $execute eq 'true' ) { - Log3( $name, 3, - "$name MSwitch_Restartcm: Befehlsausfuehrung -> $cs " . __LINE__ ); + Log3( $name, 3, "$name MSwitch_Restartcm: Befehlsausfuehrung -> $cs " . __LINE__ ); if ( $cs =~ m/set (.*)(MSwitchtoggle)(.*)/ ) { $toggle = $cs; @@ -5872,6 +6391,11 @@ sub MSwitch_Restartcmd($) { "$name: repeattime nach test -> " . $devicedetails{ $device . '_repeattime' } ); + + #MSwitch_LOG( $name, 0, "$name repeattime ".$devicedetails{ $device . '_repeattime' } ); + #MSwitch_LOG( $name, 0, "$name repeatcount ".$devicedetails{ $device . '_repeatcount' }); + + ###################################### if ( AttrVal( $name, 'MSwitch_Expert', "0" ) eq '1' && $devicedetails{ $device . '_repeatcount' } > 0 @@ -5915,6 +6439,8 @@ sub MSwitch_Restartcmd($) { if ($@) { MSwitch_LOG( $name, 1, "$name MSwitch_Set: ERROR $cs: $@ " . __LINE__ ); + + } } else { @@ -5925,6 +6451,7 @@ sub MSwitch_Restartcmd($) { MSwitch_LOG( $name, 1, "$name MSwitch_Restartcmd :Fehler bei Befehlsausfuehrung ERROR $errors " . __LINE__ ); + } } } @@ -5933,7 +6460,7 @@ sub MSwitch_Restartcmd($) { { $cs = substr( $cs, 0, 100 ) . '....'; } - readingsSingleUpdate( $hash, "Exec_cmd", $cs, 1 ) if $cs ne ''; + readingsSingleUpdate( $hash, "last_exec_cmd", $cs, 1 ) if $cs ne ''; } RemoveInternalTimer($incomming); delete( $hash->{helper}{delays}{$incomming} ); @@ -5946,6 +6473,9 @@ sub MSwitch_checkcondition($$$) { my ( $condition, $name, $event ) = @_; my $hash = $modules{MSwitch}{defptr}{$name}; + + my $attrrandomnumber = AttrVal( $name, 'MSwitch_RandomNumber', '' ); + #### kompatibilität v < 2.01 $condition =~ s/\[\$EVENT\]/"\$EVENT"/g; $condition =~ s/\[\$EVTFULL\]/"\$EVTFULL"/g; @@ -5958,44 +6488,68 @@ sub MSwitch_checkcondition($$$) { MSwitch_LOG( $name, 6, "$name: Checkcondition - Parameter event -> " . $event ); + + + if ( !defined($condition) ) { return 'true'; } if ( $condition eq '' ) { return 'true'; } - + #MSwitch_LOG( $name, 0,"$name: searchstring erreicht -> " .$condition ); ###### perlersetzung ############## - # my $x = 0; - # while ( $condition =~ m/(.*?){(.*)}(.*)?/ ) { - # my $firstpart = $1; - # my $secondpart = $2; - # my $lastpart = $3; - # $condition = $firstpart . "test" . $lastpart; - # $x++; - # last if $x > 10; #notausstieg - # } - ##################################### + my $x = 0; + my $field =""; + my $SELF = $name; + while ( $condition =~ m/(.*){(.+)}(.*)/ ) { + my $firstpart = $1; + my $secondpart = $2; + my $lastpart = $3; + my $exec = "\$field = ".$2; + + # MSwitch_LOG( $name, 0,"$name: secondpart -> " .$secondpart ); + + if ($secondpart =~ m/(!\$.*|\$.*)/) + { + + #MSwitch_LOG( $name, 0,"$name: found var exec -> " .$field ); + $field = $secondpart; + } + else{ + eval ($exec); + } + #MSwitch_LOG( $name, 0,"$name: exec -> " .$exec ); + + + + # + + #if ($field eq "!\$we" || $field eq "\$we" ) + + + if ($field =~ m/([0-9]{2}):([0-9]{2}):([0-9]{2})/) + { + my $hh =$1; + if ($hh > 23){$hh= $hh -24}; + if ($hh < 10){$hh= "0".$hh}; + $field = $hh.":".$2; + } + + $condition = $firstpart . $field . $lastpart; + + $x++; + last if $x > 10; #notausstieg + } + + + #MSwitch_LOG( $name, 0,"$name: searchstring erreicht -> " .$condition ); + - - - - - - - - - - - - - - - - if ( AttrVal( $name, 'MSwitch_RandomNumber', '' ) ne '' ) { + if ( $attrrandomnumber ne '' ) { MSwitch_Createnumber($hash); } my $anzahlk1 = $condition =~ tr/{//; @@ -6041,8 +6595,21 @@ sub MSwitch_checkcondition($$$) { ### perlteile trennen ####################### - my @evtparts = split( /:/, $event ); + my @evtparts; + + + if ($event){ + + @evtparts = split( /:/, $event ) ; +} +else +{ +$event =""; +$evtparts[0]=""; +$evtparts[1]=""; +$evtparts[2]=""; +} my $evtsanzahl = @evtparts; if ( $evtsanzahl < 3 ) { my $eventfrom = $hash->{helper}{eventfrom}; @@ -6065,7 +6632,7 @@ sub MSwitch_checkcondition($$$) { $condition =~ s/{sunset\(\)}/{ sunset\(\) }/ig; $condition =~ s/{sunrise\(\)}/{ sunrise\(\) }/ig; - my $x = 0; + $x = 0; while ( $condition =~ m/(.*?)(\$NAME)(.*)?/ ) { my $firstpart = $1; my $secondpart = $2; @@ -6085,6 +6652,10 @@ sub MSwitch_checkcondition($$$) { last if $x > 10; #notausstieg } + + + + my $searchstring; $x = 0; while ( $condition =~ @@ -6102,6 +6673,12 @@ m/(.*?)(\[\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\]-\[[a-zA-Z][a-zA-Z0-9 while ( $searchstring =~ m/(.*?)(\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\])(.*)?/ ) { + + + + + + my $read1 = ''; my $firstpart = $1; my $secsearchstring = $2; @@ -6128,6 +6705,9 @@ m/(.*?)(\[\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\]-\[[a-zA-Z][a-zA-Z0-9 while ( $condition =~ m/(.*)({ )(sunset\([^}]*\)|sunrise\([^}]*\))( })(.*)/ ) { + + + $x++; # notausstieg last if $x > 20; # notausstieg if ( defined $2 ) { @@ -6135,12 +6715,23 @@ m/(.*?)(\[\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\]-\[[a-zA-Z][a-zA-Z0-9 chop($part2); chop($part2); chop($part2); + my ( $testhour, $testmin ) = split( /:/, $part2 ); if ( $testhour > 23 ) { $testhour = $testhour - 24; $testhour = '0' . $testhour if $testhour < 10; $part2 = $testhour . ':' . $testmin; } + # else{ + + #$testhour = '0' . $testhour if $testhour < 10; + # $part2 = $testhour . ':' . $testmin; + #} + + + #MSwitch_LOG( $name, 0,"$name: Checkcondition - Parameter part2 -> " . $part2 ); + + $condition = $part2; $condition = $1 . $condition if ( defined $1 ); $condition = $condition . $5 if ( defined $5 ); @@ -6157,7 +6748,7 @@ m/(.*?)(\[\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\]-\[[a-zA-Z][a-zA-Z0-9 $part3 = ''; $lenght = ''; - ## verursacht fehlerkennung bei angabe von regex [a-zA-Z] + ## verursacht fehlerkennung bei angabe von regex [a-zA-Z] ARGUMENT: for ( $i = 0 ; $i <= 10 ; $i++ ) { $pos = index( $condition, "[", 0 ); my $x = $pos; @@ -6193,6 +6784,11 @@ m/(.*?)(\[\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\]-\[[a-zA-Z][a-zA-Z0-9 # timerformatierung erkannt - auswerten über sub # my $param = $argarray[$count]; + + # MSwitch_LOG( $name, 0, + # "$name: Checkcondition - Parameter args -> " . $args ); + + $newargarray[$count] = MSwitch_Checkcond_time( $args, $name ); } elsif ( $testarg =~ '[.*:.*]' ) { @@ -6229,6 +6825,7 @@ m/(.*?)(\[\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\]-\[[a-zA-Z][a-zA-Z0-9 MSwitch_LOG( $name, 1, "ERROR: $@ " . __LINE__ ); MSwitch_LOG( $name, 1, "$finalstring " . __LINE__ ); $hash->{helper}{conditionerror} = $@; + return 'false'; } @@ -6282,6 +6879,15 @@ sub MSwitch_Checkcond_time($$) { my $hour2 = substr( $condition, 6, 2 ); my $min2 = substr( $condition, 9, 2 ); + + #MSwitch_LOG( $name, 0, "$name: timer-> " . $condition ); + #MSwitch_LOG( $name, 0, "$name: hour1-> " . $hour1 ); + #MSwitch_LOG( $name, 0, "$name: hour2-> " . $hour2 ); + + #MSwitch_LOG( $name, 0, "$name: min1-> " . $min1 ); + #MSwitch_LOG( $name, 0, "$name: min2-> " . $min2 ); + + if ( $hour1 eq "24" ) # test auf 24 zeitangabe { $hour1 = "00"; @@ -6300,6 +6906,10 @@ sub MSwitch_Checkcond_time($$) { my $timecondtest; my $timecond1; + + #MSwitch_LOG( $name, 0, "$name: hour1-> " . $hour1 ); + #MSwitch_LOG( $name, 0, "$name: hour2-> " . $hour2 ); + #my $time1; my ( $tday, $tmonth, $tdate, $tn ); #my ($tday,$tmonth,$tdate,$tn,$time1); if ( ( $akthour < $hour1 && $akthour < $hour2 ) && $hour2 < $hour1 ) # und @@ -6391,16 +7001,16 @@ sub MSwitch_Createtimer($) { my $Name = $hash->{NAME}; # keine timer vorhenden + my $condition = ReadingsVal( $Name, '.Trigger_time', '' ); $condition =~ s/#\[dp\]/:/g; + my $x = 0; while ( $condition =~ m/(.*)(\[)([0-9]?[a-zA-Z]{1}.*)\:(.*)(\])(.*)/ ) { $x++; # notausstieg notausstieg last if $x > 20; # notausstieg notausstieg my $setmagic = ReadingsVal( $3, $4, 0 ); $condition = $1 . '[' . $setmagic . ']' . $6; - - #MSwitch_LOG( $Name, 0,"create timer: ".$condition); } my $lenght = length($condition); @@ -6415,8 +7025,10 @@ sub MSwitch_Createtimer($) { # trenne timerfile my $key = 'on'; $condition =~ s/$key//ig; + $key = 'off'; $condition =~ s/$key//ig; + $key = 'ly'; $condition =~ s/$key//ig; @@ -6431,7 +7043,9 @@ sub MSwitch_Createtimer($) { my $part2 = eval $2 ; if ($part2 !~ m/^[0-9]{2}:[0-9]{2}$|^[0-9]{2}:[0-9]{2}:[0-9]{2}$/) { - MSwitch_LOG( $Name, 1, "$Name: ERROR wrong format in set timer. There are no timers running. Format must be HH:MM. Format is: $part2 " ); + MSwitch_LOG( $Name, 1, "$Name: ERROR wrong format in set timer. There are no timers running. Format must be HH:MM. Format is: $part2 " ); + + return; } $part2 = substr( $part2, 0, 5 ); @@ -6443,10 +7057,11 @@ sub MSwitch_Createtimer($) { my @timer = split /~/, $condition; - $timer[0] = '' if ( !defined $timer[0] ); - $timer[1] = '' if ( !defined $timer[1] ); - $timer[2] = '' if ( !defined $timer[2] ); - $timer[3] = '' if ( !defined $timer[3] ); + $timer[0] = '' if ( !defined $timer[0] ); #on + $timer[1] = '' if ( !defined $timer[1] ); #off + $timer[2] = '' if ( !defined $timer[2] ); #cmd1 + $timer[3] = '' if ( !defined $timer[3] ); #cmd2 + $timer[4] = '' if ( !defined $timer[4] ); #cmd1+2 # lösche bei notify und toggle if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Notify" ) { @@ -6458,6 +7073,7 @@ sub MSwitch_Createtimer($) { $timer[1] = ''; $timer[2] = ''; $timer[3] = ''; + $timer[4] = ''; } my $akttimestamp = TimeNow(); @@ -6491,8 +7107,13 @@ sub MSwitch_Createtimer($) { ## für jeden Timerfile ( 0 -4 ) my $i = 0; + my $id = ""; LOOP2: foreach my $option (@timer) { $i++; + $id =""; + + + #### inhalt array für eine option on , off ... $key = '\]\['; $option =~ s/$key/ /ig; @@ -6550,7 +7171,15 @@ m/(.*?)([0-9]{2}):([0-9]{2})\*([0-9]{2}:[0-9]{2})-([0-9]{2}:[0-9]{2})\|?([0-9]{0 # für jede angabe eines files LOOP3: foreach my $option1 (@optionarray) { - + $id =""; + + if ( $option1 =~ m/(.*)\|(ID.*)$/) + { + $id = $2; + + $option1 =$1; + } + if ( $option1 =~ m/\?(.*)(-)([0-9]{2}:[0-9]{2})(\|[0-9]{0,7})?(.*)?/ ) { @@ -6599,10 +7228,17 @@ m/(.*?)([0-9]{2}):([0-9]{2})\*([0-9]{2}:[0-9]{2})-([0-9]{2}:[0-9]{2})\|?([0-9]{0 my $test = FmtDateTime($timecond); my $sectowait = $timecond - $jetzt; if ( $timecond > $jetzt ) { - my $inhalt = $timecond . "-" . $i; + + + my $number = $i; + if ($id ne "" && $i == 3 || $i ==4){ $number =$number +3;} + if ($i == 5 ){ $number = 9;} + if ($id ne "" && $number == 9){ $number = 10;} + + + my $inhalt = $timecond . "-" . $number.$id; $hash->{helper}{timer}{$inhalt} = "$inhalt"; - my $msg = $Name . " " . $timecond . " " . $i; - my $gettime = gettimeofday(); + my $msg = $Name . " " . $timecond . " " . $number.$id; InternalTimer( $timecond, "MSwitch_Execute_Timer", $msg ); } } @@ -6615,6 +7251,7 @@ m/(.*?)([0-9]{2}):([0-9]{2})\*([0-9]{2}:[0-9]{2})-([0-9]{2}:[0-9]{2})\|?([0-9]{0 my $msg = $Name . " " . $newask . " " . 5; my $inhalt = $newask . "-" . 5; $hash->{helper}{timer}{$newask} = "$inhalt"; + InternalTimer( $newask, "MSwitch_Execute_Timer", $msg ); } @@ -6657,6 +7294,14 @@ sub MSwitch_Execute_Timer($) { my ( $Name, $timecond, $param ) = split( / /, $input ); my $hash = $defs{$Name}; return "" if ( IsDisabled($Name) ); + my @string=split(/ID/,$param ); + + + $param = $string[0]; + + my $execid =0; + $execid = $string[1] if ($string[1]); + $hash->{eventsave} = 'unsaved'; if ( ReadingsVal( $Name, '.V_Check', $vupdate ) ne $vupdate ) { my $ver = ReadingsVal( $Name, '.V_Check', '' ); @@ -6673,7 +7318,7 @@ sub MSwitch_Execute_Timer($) { MSwitch_Createnumber1($hash); } if ( $param eq '5' ) { - MSwitch_Createtimer($hash); + MSwitch_Createtimer($hash); return; } @@ -6716,6 +7361,7 @@ sub MSwitch_Execute_Timer($) { Log3( $Name, 1, "$Name MSwitch_Execute_Timer: Fehler bei Befehlsausfuehrung ERROR $Name: $errors " . __LINE__ ); + } return; } @@ -6730,6 +7376,8 @@ sub MSwitch_Execute_Timer($) { Log3( $Name, 1, "$Name MSwitch_Execute_Timer: Fehler bei Befehlsausfuehrung ERROR $Name: $errors " . __LINE__ ); + + } return; } @@ -6743,6 +7391,32 @@ sub MSwitch_Execute_Timer($) { MSwitch_Exec_Notif( $hash, 'off', 'nocheck', '', 0 ); return; } + + + if ( $param eq '6' ) { + MSwitch_Exec_Notif( $hash, 'on', 'nocheck', '', $execid ); + return; + } + + if ( $param eq '7' ) { + MSwitch_Exec_Notif( $hash, 'off', 'nocheck', '', $execid ); + return; + } + + + if ( $param eq '9' ) { + MSwitch_Exec_Notif( $hash, 'on', 'nocheck', '', 0); + MSwitch_Exec_Notif( $hash, 'off', 'nocheck', '', 0 ); + return; + } + + if ( $param eq '10' ) { + MSwitch_Exec_Notif( $hash, 'on', 'nocheck', '', $execid ); + MSwitch_Exec_Notif( $hash, 'off', 'nocheck', '', $execid ); + return; + } + + return; } @@ -6753,8 +7427,6 @@ sub MSwitch_ChangeCode($$) { my $x = 0; # exit secure #achtung perl5.30 while ( $option =~ m/(.*)\{(sunset|sunrise)(.*)\}(.*)/ ) - - #while ( $option =~ m/(.*){(sunset|sunrise)(.*)}(.*)/ ) { $x++; # exit secure last if $x > 20; # exit secure @@ -6983,8 +7655,15 @@ sub MSwitch_checktrigger(@) { my $triggercmdoff = ReadingsVal( $ownName, '.Trigger_cmd_off', '' ); my $answer = ""; - #$triggerfield =~ s/\(//g; - #$triggerfield =~ s/\)//g; + + if ( $triggerfield =~ m/{(.*)}/ ) + { + + my $SELF = $ownName; + my $exec = "\$triggerfield = ".$1; + eval ($exec); + } + unshift( @eventsplit, $device ) if ReadingsVal( $ownName, 'Trigger_device', '' ) eq "all_events"; @@ -7040,41 +7719,47 @@ sub MSwitch_VUpdate($) { my $Name = $hash->{NAME}; readingsSingleUpdate( $hash, ".V_Check", $vupdate, 0 ); - my $devs = ReadingsVal( $Name, '.Device_Affected_Details', '' ); + # my $devs = ReadingsVal( $Name, '.Device_Affected_Details', '' ); - # encode from old format + # # encode from old format - $devs =~ s/,/#[NF]/g; - $devs =~ s/\|/#[ND]/g; - $devs =~ s/~/ /g; - $devs =~ s/\[cnl\]/\n/g; - $devs =~ s/\[se\]/;/g; - $devs =~ s/#\[ko\]/,/g; - $devs =~ s/#\[sp\]/ /g; + # $devs =~ s/,/#[NF]/g; + # $devs =~ s/\|/#[ND]/g; + # $devs =~ s/~/ /g; + # $devs =~ s/\[cnl\]/\n/g; + # $devs =~ s/\[se\]/;/g; + # $devs =~ s/#\[ko\]/,/g; + # $devs =~ s/#\[sp\]/ /g; - # decode to new format + # # decode to new format - $devs =~ s/#\[wa\]/|/g; - $devs =~ s/\n/#[nl]/g; - $devs =~ s/;/#[se]/g; - $devs =~ s/\:/#[dp]/g; - $devs =~ s/\t/ /g; - $devs =~ s/ /#[sp]/g; - $devs =~ s/\\/#[bs]/g; - $devs =~ s/,/#[ko]/g; - $devs =~ s/^#\[/#[eo]/g; - $devs =~ s/^#\]/#[ec]/g; - $devs =~ s/\|/#[wa]/g; + # $devs =~ s/#\[wa\]/|/g; + # $devs =~ s/\n/#[nl]/g; + # $devs =~ s/;/#[se]/g; + # $devs =~ s/\:/#[dp]/g; + # $devs =~ s/\t/ /g; + # $devs =~ s/ /#[sp]/g; + # $devs =~ s/\\/#[bs]/g; + # $devs =~ s/,/#[ko]/g; + # $devs =~ s/^#\[/#[eo]/g; + # $devs =~ s/^#\]/#[ec]/g; + # $devs =~ s/\|/#[wa]/g; - # change timerkey to new format + # # change timerkey to new format - my $x = 0; - while ( $devs =~ m/(.*#\[NF\])([0-9]{2})([0-9]{2})([0-9]{2})(#\[NF\].*)/ ) { - $x++; # exit - last if $x > 20; # exit - $devs = $1 . $2 . "#[dp]" . $3 . "#[dp]" . $4 . $5; - } - readingsSingleUpdate( $hash, ".Device_Affected_Details", $devs, 0 ); + # my $x = 0; + # while ( $devs =~ m/(.*#\[NF\])([0-9]{2})([0-9]{2})([0-9]{2})(#\[NF\].*)/ ) { + # $x++; # exit + # last if $x > 20; # exit + # $devs = $1 . $2 . "#[dp]" . $3 . "#[dp]" . $4 . $5; + # } + # readingsSingleUpdate( $hash, ".Device_Affected_Details", $devs, 0 ); + + + #fhem("deletereading $Name Exec_cmd"); + + + return; } ################################ @@ -7082,9 +7767,12 @@ sub MSwitch_backup($) { my ($hash) = @_; my $Name = $hash->{NAME}; - my @areadings = - qw(.Device_Affected .Device_Affected_Details .Device_Events .First_init .Trigger_Whitelist .Trigger_cmd_off .Trigger_cmd_on .Trigger_condition .Trigger_off .Trigger_on .Trigger_time .V_Check Exec_cmd Trigger_device Trigger_log last_event state .sysconf Sys_Extension .sortby) - ; #alle readings + + my $testreading = $hash->{READINGS} ; + + + +my @areadings = ( keys %{ $testreading }); my %keys; open( BACKUPDATEI, ">MSwitch_backup_$vupdate.cfg" ) @@ -7140,8 +7828,6 @@ sub MSwitch_backup_this($) { foreach (@found) { if ( $_ =~ m/#S (.*) -> (.*)/ ) # setreading { - # Log3( $Name, 0, "s1 $1" ); - # Log3( $Name, 0, "s2 $2" ); if ( $2 eq 'undef' || $2 eq '' || $2 eq ' ' ) { } @@ -7156,6 +7842,7 @@ sub MSwitch_backup_this($) { my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { Log3( $Name, 1, "ERROR $cs" ); + } } } @@ -7267,14 +7954,14 @@ sub MSwitch_Getsupport($) { sub MSwitch_Getconfig($) { my ($hash) = @_; my $Name = $hash->{NAME}; - my @areadings = - qw(.Device_Affected .Device_Affected_Details .Device_Events .First_init .Trigger_Whitelist .Trigger_cmd_off .Trigger_cmd_on .Trigger_condition .Trigger_off .Trigger_on .Trigger_time .V_Check Trigger_device Trigger_log last_event .sysconf state Sys_Extension .sortby); - + my $testreading = $hash->{READINGS} ; + my @areadings = ( keys %{ $testreading }); my $count = 0; my $out = "#V $version\\n"; $out .= "#VS $vupdate\\n"; my $testdevice = $Name; foreach my $key (@areadings) { + my $tmp = ReadingsVal( $testdevice, $key, 'undef' ); if ( $key eq ".Device_Affected_Details" ) { $tmp =~ s/#\[nl\]/;;/g; @@ -7288,8 +7975,22 @@ sub MSwitch_Getconfig($) { $tmp =~ s/#\[st\]/\\'/g; $tmp =~ s/'/\\'/g; $tmp =~ s/#\[bs\]/\\\\/g; + } + if ( + $key eq ".Device_Events" || + $key eq ".info" || + $key eq ".Trigger_cmd_on" || + $key eq ".Trigger_cmd_off" || + $key eq ".Trigger_on" || + $key eq ".Trigger_off" + + ) + { + $tmp =~ s/'/\\'/g; + } + if ( $key eq ".sysconf" ) { } @@ -7308,9 +8009,6 @@ sub MSwitch_Getconfig($) { $tmp =~ s//\\>/g; $tmp =~ s/'/\\'/g; - -# $out .= "#A $attrdevice -> ". AttrVal( $testdevice, $attrdevice, '' ) . "\\n"; - $out .= "#A $attrdevice -> " . $tmp . "\\n"; $count++; } @@ -7318,13 +8016,14 @@ sub MSwitch_Getconfig($) { $count++; my $client_hash = $hash->{CL}; - Log3( $Name, 0, "MSWITCH-CONFIG: " . $out ); - asyncOutput( $hash->{CL}, + my $ret = asyncOutput( $hash->{CL}, "Änderungen sollten hier nur von erfahrenen Usern durchgeführt werden.
" + . "
" + ."" + ."" ); return; @@ -7374,7 +8073,7 @@ sub MSwitch_backup_all($) { foreach my $testdevice ( keys %{ $modules{MSwitch}{defptr} } ) # { - Log3( $testdevice, 0, "MSWITCH-RESTORE: " . $testdevice ); + my $devhash = $defs{$testdevice}; $Zeilen =~ s/\n/[NL]/g; @@ -7398,6 +8097,7 @@ sub MSwitch_backup_all($) { my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { Log3( $testdevice, 1, "ERROR $cs" ); + } } } @@ -7406,10 +8106,10 @@ sub MSwitch_backup_all($) { my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { Log3( $testdevice, 1, "ERROR $cs" ); + } MSwitch_LoadHelper($devhash); - Log3( $testdevice, 0, "MSWITCH-RESTORE ready -> " . $testdevice ); $answer = $answer . "MSwitch $testdevice restored.\n"; } return $answer; @@ -7420,6 +8120,9 @@ sub MSwitch_savesys($$) { my ( $hash, $cont ) = @_; my $name = $hash->{NAME}; $cont = urlDecode($cont); + + #$cont =~ s/#\[tr]/#[nl]/g; + $cont =~ s/\n/#[nl]/g; $cont =~ s/\t/ /g; $cont =~ s/ /#[sp]/g; @@ -7452,6 +8155,7 @@ sub MSwitch_saveconf($$) { my @changes; my $info = ""; + my @found = split( /#\[EOL\]/, $cont ); foreach (@found) { @@ -7477,6 +8181,8 @@ sub MSwitch_saveconf($$) { if ( $_ =~ m/#S (.*) -> (.*)/ ) # setreading { if ( $2 eq 'undef' || $2 eq '' || $2 eq ' ' ) { + + delete( $hash->{READINGS}{$1} ); } else { my $newstring = $2; @@ -7522,6 +8228,8 @@ sub MSwitch_saveconf($$) { readingsSingleUpdate( $hash, ".change_info", $info, 0 ); } + + return; } @@ -7618,6 +8326,7 @@ sub MSwitch_repeat($) { if ($@) { MSwitch_LOG( $name, 1, "$name MSwitch_repeat: ERROR $cs: $@ " . __LINE__ ); + } } else { @@ -7625,6 +8334,7 @@ sub MSwitch_repeat($) { if ( defined($errors) ) { MSwitch_LOG( $name, 1, "$name Absent_repeat $cs: ERROR : $errors -> Comand: $cs" ); + } } } @@ -7721,14 +8431,9 @@ sub MSwitch_EventBulk($$$$) { && $event ne '' && $hash->{eventsave} ne 'saved' ) { - #$hash-Bulkfrom} ="saved"; $hash->{eventsave} = "saved"; readingsBeginUpdate($hash); - # if ( AttrVal( $name, 'MSwitch_Debug', "0" ) eq '4' ) - # { - # readingsBulkUpdate( $hash, "Bulkfrom", "von:".$from ) ; - # } readingsBulkUpdate( $hash, "EVENT", $event ) if $event ne ''; readingsBulkUpdate( $hash, "EVTFULL", $evtfull ) if $evtfull ne ''; readingsBulkUpdate( $hash, "EVTPART1", $evtparts[0] ) @@ -7748,6 +8453,8 @@ sub MSwitch_EventBulk($$$$) { sub MSwitch_priority(@) { my ( $hash, $execids, @devices ) = @_; my $name = $hash->{NAME}; + + my @execids = split(/,/,$execids); MSwitch_LOG( $name, 5, "$name: zuweisung der reihenfolge und der id" ); if ( AttrVal( $name, 'MSwitch_Expert', "0" ) ne '1' ) { return @devices; @@ -7755,22 +8462,28 @@ sub MSwitch_priority(@) { my %devicedetails = MSwitch_makeCmdHash($name); - # my $execids = "0" if !defined $execids; - my %new; foreach my $device (@devices) { # $execids beinhaltet auszuführende ids gesetzt bei init my $key1 = $device . "_id"; - Log3( $name, 5, + Log3( $name, 6, "$name: device hat die ID $device - $devicedetails{$key1}" ); - next if $devicedetails{$key1} ne $execids; + + Log3( $name, 6, + "$name: zulässige IDS - @execids " ); + + + next if !(grep {$_ eq $devicedetails{$key1}} @execids); + my $key = $device . "_priority"; my $prio = $devicedetails{$key}; - MSwitch_LOG( $name, 5, - "$name: device hat die priority $device - $devicedetails{$key1}" + MSwitch_LOG( $name, 6, + "$name: device hat die priority $device - $prio" ); $new{$device} = $prio; + + $hash->{helper}{priorityids}{$device} = $prio; } my @new = %new; @@ -7778,6 +8491,9 @@ sub MSwitch_priority(@) { for my $key ( sort { $new{$a} <=> $new{$b} } keys %new ) { if ( $key ne "" && $key ne " " ) { push( @newlist, $key ); + my $key = $key . "_priority"; + + } } @@ -7999,8 +8715,11 @@ sub MSwitch_makefreecmd($$) { my $ersetzung = ""; # entferne kommntarzeilen - $cs =~ s/#.*\n//g; + $cs =~ s/\\#/comment/g; + $cs =~ s/#.*\n//g; + + $cs =~ s/comment/#/g; # entferne zeilenumbruch $cs =~ s/\n//g; @@ -8044,6 +8763,47 @@ sub MSwitch_makefreecmd($$) { ################################# +sub MSwitch_setconfig($$) +{ + my ( $hash, $aVal ) = @_; + my $name = $hash->{NAME}; + + + my %keys; + foreach my $attrdevice ( keys %{ $attr{$name} } ) #geht + { + + delete $attr{$name}{$attrdevice}; + + } + my $testreading = $hash->{READINGS} ; + my @areadings = ( keys %{ $testreading }); + # + foreach my $key (@areadings) + { + fhem("deletereading $name $key "); + } + + my $Zeilen =''; + open( BACKUPDATEI, "<./FHEM/MSwitch/$aVal" ) + || return "$name|no Backupfile ./MSwitch_Extensions/$aVal found\n"; + while () { + + + + $Zeilen = $Zeilen . $_; + } + close(BACKUPDATEI); + + $Zeilen =~ s/\n/#[EOL]/g; + + MSwitch_saveconf($hash,$Zeilen); + + +} + + +################################# 1; =pod
switch MSwitch off + execute 'cmd2' at :
" . $inhalt1 . "
" . $inhalt6 . "
"; - $ret .= $inhalt5 . " - Trigger " . $Triggerdevice . " : - - + $ret .= $inhalt5 . ""; + + $ret .= "Trigger " . $Triggerdevice . " : "; + $ret .= ""; + + ############## + my $fieldon =""; + if ( $triggeron =~ m/{(.*)}/ ) + { + my $exec = "\$fieldon = ".$1; + eval ($exec); + $ret .= "" ; + } + ##################### + + $ret .= "
@@ -4289,9 +4657,20 @@ sub MSwitch_fhemwebFn($$$$) { Trigger " . $Triggerdevice . " : - - "; + $ret .= ""; + + ############## + my $fieldoff =""; + if ( $triggeroff =~ m/{(.*)}/ ) + { + my $exec = "\$fieldoff = ".$1; + eval ($exec); + $ret .= "" ; + } + ##################### + + $ret .= "
- -
" . $inhalt3 . " -