# $Id$ # 98_MSwitch.pm # # copyright ##################################################### # # 98_MSwitch.pm # # written by Byte09 # Maintained by Byte09 # # This file is part of FHEM. # # FHEM is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # FHEM is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with FHEM. If not, see . # ################################################################# # Todo's: # reading las_cmd fehlerhaft bei befehlen mit delay # del delays kontrollieren #--------------------------------------------------------------- # # 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 Information zu Devicetausch # Q dummy1#zu schaltendes geraet#device # Q dummy2#zu schaltendes geraet2#device # ##--------------------------------------------------------------- # ################################################################# package main; use Time::Local; use strict; use warnings; use POSIX; # Version ####################################################### 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.09'; my $vupdate = 'V2.00' ; # versionsnummer der datenstruktur . änderung der nummer löst MSwitch_VUpdate aus . my $savecount = 30 ; # anzahl der zugriff im zeitraum zur auslösung des safemodes. kann durch attribut überschrieben werden . my $standartstartdelay = 60 ; # zeitraum nach fhemstart , in dem alle aktionen geblockt werden. kann durch attribut überschrieben werden . my $eventset = '0'; # standartlist ignorierter Devices . kann durch attribut überschrieben werden . my @doignore = qw(notify allowed at watchdog doif fhem2fhem telnet FileLog readingsGroup FHEMWEB autocreate eventtypes readingsproxy svg cul); my $startmode = "Notify"; # Startmodus des Devices nach Define ##################### ############################################ sub MSwitch_Checkcond_time($$); sub MSwitch_Checkcond_state($$); sub MSwitch_Checkcond_day($$$$); sub MSwitch_Createtimer($); sub MSwitch_Execute_Timer($); sub MSwitch_LoadHelper($); sub MSwitch_debug2($$); sub MSwitch_ChangeCode($$); sub MSwitch_Add_Device($$); sub MSwitch_Del_Device($$); sub MSwitch_Debug($); sub MSwitch_Exec_Notif($$$$$); sub MSwitch_checkcondition($$$); sub MSwitch_Delete_Delay($$); sub MSwitch_Check_Event($$); sub MSwitch_makeAffected($); sub MSwitch_backup($); sub MSwitch_backup_this($); sub MSwitch_backup_all($); sub MSwitch_backup_done($); sub MSwitch_checktrigger(@); sub MSwitch_Cmd(@); sub MSwitch_toggle($$); sub MSwitch_Getconfig($); sub MSwitch_saveconf($$); sub MSwitch_replace_delay($$); sub MSwitch_repeat($); sub MSwitch_Createrandom($$$); sub MSwitch_Execute_randomtimer($); sub MSwitch_Clear_timer($); sub MSwitch_Createnumber($); sub MSwitch_Createnumber1($); sub MSwitch_Savemode($); sub MSwitch_set_dev($); sub MSwitch_EventBulk($$$$); sub MSwitch_priority; sub MSwitch_sort; sub MSwitch_dec($$); sub MSwitch_makefreecmd($$); sub MSwitch_clearlog($); sub MSwitch_LOG($$$); sub MSwitch_Getsupport($); sub MSwitch_confchange($$); sub MSwitch_setconfig($$); my %sets = ( "on" => "noArg", "off" => "noArg", "reload_timer" => "noArg", "active" => "noArg", "inactive" => "noArg", "devices" => "noArg", "details" => "noArg", "del_trigger" => "noArg", "del_delays" => "noArg", "trigger" => "noArg", "filter_trigger" => "noArg", "add_device" => "noArg", "del_device" => "noArg", "addevent" => "noArg", "backup_MSwitch" => "noArg", "import_config" => "noArg", "saveconfig" => "noArg", "savesys" => "noArg", "sort_device" => "noArg", "fakeevent" => "noArg", "exec_cmd_1" => "noArg", "exec_cmd_2" => "noArg", "wait" => "noArg", "VUpdate" => "noArg", "confchange" => "noArg", "clearlog" => "noArg", "set_trigger" => "noArg", "reset_cmd_count" => "", "change_renamed" => "" ); my %gets = ( "active_timer" => "noArg", "restore_MSwitch_Data" => "noArg", "get_config" => "noArg" ); #################### sub MSwitch_Initialize($) { my ($hash) = @_; $hash->{SetFn} = "MSwitch_Set"; $hash->{AsyncOutput} = "MSwitch_AsyncOutput"; $hash->{RenameFn} = "MSwitch_Rename"; $hash->{CopyFn} = "MSwitch_Copy"; $hash->{GetFn} = "MSwitch_Get"; $hash->{DefFn} = "MSwitch_Define"; $hash->{UndefFn} = "MSwitch_Undef"; $hash->{DeleteFn} = "MSwitch_Delete"; $hash->{ParseFn} = "MSwitch_Parse"; $hash->{AttrFn} = "MSwitch_Attr"; $hash->{NotifyFn} = "MSwitch_Notify"; $hash->{FW_detailFn} = "MSwitch_fhemwebFn"; $hash->{FW_deviceOverview} = 1; $hash->{FW_summaryFn} = "MSwitch_summary"; $hash->{NotifyOrderPrefix} = "45-"; $hash->{AttrList} = " disable:0,1" . " disabledForIntervals" . " stateFormat" . " MSwitch_Comments:0,1" . " MSwitch_Read_Log:0,1" . " MSwitch_Help:0,1" . " MSwitch_Debug:0,1,2,3,4" . " MSwitch_Expert:0,1" . " MSwitch_Delete_Delays:0,1" . " MSwitch_Include_Devicecmds:0,1" . " MSwitch_generate_Events:0,1" . " MSwitch_Include_Webcmds:0,1" . " MSwitch_Include_MSwitchcmds:0,1" . " MSwitch_Activate_MSwitchcmds:0,1" . " MSwitch_Lock_Quickedit:0,1" . " MSwitch_Ignore_Types:textField-long " . " MSwitch_Reset_EVT_CMD1_COUNT" . " MSwitch_Reset_EVT_CMD2_COUNT" . " MSwitch_Trigger_Filter" . " MSwitch_Extensions:0,1" . " MSwitch_Inforoom" . " 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" . " setList:textField-long " . " readingList:textField-long " . $readingFnAttributes; $hash->{FW_addDetailToSummary} = 0; } #################### sub MSwitch_Rename($) { # routine nicht in funktion my ( $new_name, $old_name ) = @_; my $hash_new = $defs{$new_name}; $modules{MSwitch}{defptr}{$new_name} = $hash_new; } #################### 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 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) ) { MSwitch_LOG( $new_name, 1, "ERROR $cs" ); } foreach my $key (@areadings) { my $tmp = ReadingsVal( $old_name, $key, 'undef' ); fhem( "setreading " . $new_name . " " . $key . " " . $tmp ); } MSwitch_LoadHelper($hash); } #################### sub MSwitch_summary($) { my ( $wname, $name, $room ) = @_; my $hash = $defs{$name}; my $testroom = AttrVal( $name, 'MSwitch_Inforoom', 'undef' ); if ( $testroom ne $room ) { return; } my $test = AttrVal( $name, 'comment', '0' ); my $info = AttrVal( $name, 'comment', 'No Info saved at ATTR omment' ); my $image = ReadingsVal( $name, 'state', 'undef' ); my $ret = ''; my $devtitle = ''; my $option = ''; my $html = ''; my $triggerc = 1; my $timer = 1; my $trigger = ReadingsVal( $name, 'Trigger_device', 'undef' ); my @devaff = split( / /, MSwitch_makeAffected($hash) ); $option .= ""; foreach (@devaff) { $devtitle .= $_ . ", "; $option .= ""; } chop($devtitle); chop($devtitle); my $affected = ""; ### time my $optiontime; my $devtitletime = ''; my $triggertime = ReadingsVal( $name, 'Trigger_device', 'not defined' ); my $devtime = ReadingsVal( $name, '.Trigger_time', '' ); $devtime =~ s/\[//g; $devtime =~ s/\]/ /g; my @devtime = split( /~/, $devtime ); $optiontime .= ""; my $count = @devtime; $devtime[0] =~ s/on/on+cmd1: /g if defined $devtime[0]; $devtime[1] =~ s/off/off+cmd2: /g if defined $devtime[1]; $devtime[2] =~ s/ononly/only cmd1: /g if defined $devtime[2]; $devtime[3] =~ s/offonly/only cmd2: /g if defined $devtime[3]; if ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) ne "Notify" ) { $optiontime .= "" if defined $devtime[0]; $optiontime .= "" if defined $devtime[1]; } $optiontime .= "" if defined $devtime[2]; $optiontime .= "" if defined $devtime[3]; my $affectedtime = ''; if ( $count == 0 ) { $timer = 0; $affectedtime = ""; } else { chop($devtitletime); chop($devtitletime); $affectedtime = ""; } if ( $info eq 'No Info saved at ATTR omment' ) { $ret .= ""; } else { $ret .= ""; } $ret .= " "; if ( $trigger eq 'no_trigger' || $trigger eq 'undef' || $trigger eq '' ) { $triggerc = 0; if ( $triggerc != 0 || $timer != 0 ) { $ret .= ""; } else { if ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) ne "Dummy" ) { $affectedtime = ""; $ret .= "  Multiswitchmode (no trigger / no timer) "; } else { $affectedtime = ""; $affected = ""; $ret .= "  Dummymode "; } } } else { $ret .= ""; } $ret .= $affectedtime; $ret .= $affected; if ( ReadingsVal( $name, '.V_Check', 'not defined' ) ne $vupdate ) { $ret .= " Versionskonflikt !
(please help)
"; } else { if ( AttrVal( $name, 'disable', "0" ) eq '1' ) { $ret .= " State:
disabled
"; } else { $ret .= " State:
" . ReadingsVal( $name, 'state', '' ) . "
"; if ( AttrVal( $name, 'MSwitch_Mode', 'Full' ) ne "Notify" ) { $ret .= "
" . ReadingsTimestamp( $name, 'state', '' ) . "
"; } else { $ret .= "
" . ReadingsTimestamp( $name, 'state', '' ) . "
"; } } } $ret .= ""; $ret =~ s/#dp /:/g; return $ret; } #################### sub MSwitch_LoadHelper($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $oldtrigger = ReadingsVal( $Name, 'Trigger_device', 'undef' ); my $devhash = undef; my $cdev = ''; my $ctrigg = ''; if ( defined $hash->{DEF} ) { $devhash = $hash->{DEF}; my @dev = split( /#/, $devhash ); $devhash = $dev[0]; ( $cdev, $ctrigg ) = split( / /, $devhash ); if ( defined $ctrigg ) { $ctrigg =~ s/\.//g; } else { $ctrigg = ''; } if ( defined $devhash ) { $hash->{NOTIFYDEV} = $cdev; # stand aug global ... änderung auf ... #readingsSingleUpdate( $hash, "Trigger_device", $cdev, 0 ); if ( defined $cdev && $cdev ne '' ) { #MSwitch_LOG( $Name, 0, "$Name Triggerdevice cdev - $cdev " . __LINE__ ); readingsSingleUpdate( $hash, "Trigger_device", $cdev, 0 ); } } else { $hash->{NOTIFYDEV} = 'no_trigger'; #MSwitch_LOG( $Name, 0, "$Name update Triggerdevice " . __LINE__ ); readingsSingleUpdate( $hash, "Trigger_device", 'no_trigger', 0 ); } } if ( !defined $hash->{NOTIFYDEV} || $hash->{NOTIFYDEV} eq 'undef' || $hash->{NOTIFYDEV} eq '' ) { $hash->{NOTIFYDEV} = 'no_trigger'; } if ( $oldtrigger ne 'undef' ) { $hash->{NOTIFYDEV} = $oldtrigger; #MSwitch_LOG( $Name, 0, "$Name update oldtrigger - $oldtrigger " . __LINE__ ); readingsSingleUpdate( $hash, "Trigger_device", $oldtrigger, 0 ); } ################# MSwitch_set_dev($hash); ################# if ( AttrVal( $Name, 'MSwitch_Activate_MSwitchcmds', "0" ) eq '1' ) { addToAttrList('MSwitchcmd'); } ################erste initialisierung eines devices if ( ReadingsVal( $Name, '.V_Check', 'undef' ) ne $vupdate && $autoupdate eq "on" ) { MSwitch_VUpdate($hash); } ################ if ( ReadingsVal( $Name, '.First_init', 'undef' ) ne 'done' ) { readingsBeginUpdate($hash); readingsBulkUpdate( $hash, ".V_Check", $vupdate ); readingsBulkUpdate( $hash, "state", 'off' ); if ( defined $ctrigg && $ctrigg ne '' ) { readingsBulkUpdate( $hash, ".Device_Events", $ctrigg ); $hash->{DEF} = $cdev; } else { readingsBulkUpdate( $hash, ".Device_Events", 'no_trigger' ); } readingsBulkUpdate( $hash, ".Trigger_on", 'no_trigger' ); readingsBulkUpdate( $hash, ".Trigger_off", 'no_trigger' ); readingsBulkUpdate( $hash, ".Trigger_cmd_on", 'no_trigger' ); readingsBulkUpdate( $hash, ".Trigger_cmd_off", 'no_trigger' ); readingsBulkUpdate( $hash, "Trigger_log", 'off' ); readingsBulkUpdate( $hash, ".Device_Affected", 'no_device' ); readingsBulkUpdate( $hash, ".First_init", 'done' ); readingsEndUpdate( $hash, 0 ); # setze ignoreliste $attr{$Name}{MSwitch_Ignore_Types} = join( " ", @doignore ); # setze attr inforoom my $testdev = ''; LOOP22: foreach my $testdevices ( keys %{ $modules{MSwitch}{defptr} } ) # { if ( $Name eq $testdevices ) { next LOOP22; } $testdev = AttrVal( $testdevices, 'MSwitch_Inforoom', '' ); } if ( $testdev ne '' ) { $attr{$Name}{MSwitch_Inforoom} = $testdev,; } #setze alle attrs $attr{$Name}{MSwitch_Help} = '0'; $attr{$Name}{MSwitch_Debug} = '0'; $attr{$Name}{MSwitch_Expert} = '0'; $attr{$Name}{MSwitch_Delete_Delays} = '1'; $attr{$Name}{MSwitch_Include_Devicecmds} = '1'; $attr{$Name}{MSwitch_Include_Webcmds} = '0'; $attr{$Name}{MSwitch_Include_MSwitchcmds} = '0'; $attr{$Name}{MSwitch_Include_MSwitchcmds} = '0'; $attr{$Name}{MSwitch_Lock_Quickedit} = '1'; $attr{$Name}{MSwitch_Extensions} = '0'; $attr{$Name}{MSwitch_Mode} = $startmode; } # NEU; ZUVOR IN SET my $testnew = ReadingsVal( $Name, '.Trigger_on', 'undef' ); if ( $testnew eq 'undef' ) { readingsBeginUpdate($hash); readingsBulkUpdate( $hash, ".Device_Events", 'no_trigger' ); readingsBulkUpdate( $hash, ".Trigger_on", 'no_trigger' ); readingsBulkUpdate( $hash, ".Trigger_off", 'no_trigger' ); readingsBulkUpdate( $hash, "Trigger_log", 'on' ); readingsBulkUpdate( $hash, ".Device_Affected", 'no_device' ); readingsEndUpdate( $hash, 0 ); } MSwitch_Createtimer($hash); #Neustart aller timer } #################### sub MSwitch_Define($$) { my $loglevel = 0; my ( $hash, $def ) = @_; my @a = split( "[ \t][ \t]*", $def ); my $name = $a[0]; my $devpointer = $name; my $devhash = ''; $modules{MSwitch}{defptr}{$devpointer} = $hash; $hash->{Version_Modul} = $version; $hash->{Version_Datenstruktur} = $vupdate; $hash->{Version_autoupdate} = $autoupdate; $hash->{MODEL} = $startmode; if ( $init_done && !defined( $hash->{OLDDEF} ) ) { my $timecond = gettimeofday() + 5; InternalTimer( $timecond, "MSwitch_LoadHelper", $hash ); } return; } #################### sub MSwitch_Get($$@) { my ( $hash, $name, $opt, @args ) = @_; my $ret; if ( ReadingsVal( $name, '.change', '' ) ne '' ) { return "Unknown argument, choose one of "; } return "\"get $name\" needs at least one argument" unless ( defined($opt) ); #################### if ( $opt eq 'restore_MSwitch_Data' && $args[0] eq "this_Device" ) { $ret = MSwitch_backup_this($hash); 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}{RESTORE_ANSWER} = $hash->{CL}; my $ret = MSwitch_backup_all($hash); return $ret; } #################### if ( $opt eq 'checkevent' ) { $ret = MSwitch_Check_Event( $hash, $args[0] ); return $ret; } #################### if ( $opt eq 'get_config' ) { $ret = MSwitch_Getconfig($hash); return $ret; } #################### if ( $opt eq 'get_support_info' ) { $ret = MSwitch_Getsupport($hash); return $ret; } #################### if ( $opt eq 'get_sysextension' ) { $ret = MSwitch_Sysextension($hash); return $ret; } #################### if ( $opt eq 'checkcondition' ) { my ( $condstring, $eventstring ) = split( /\|/, $args[0] ); $condstring =~ s/#\[dp\]/:/g; $condstring =~ s/#\[pt\]/./g; $condstring =~ s/#\[ti\]/~/g; $condstring =~ s/#\[sp\]/ /g; $eventstring =~ s/#\[dp\]/:/g; $eventstring =~ s/#\[pt\]/./g; $eventstring =~ s/#\[ti\]/~/g; $eventstring =~ s/#\[sp\]/ /g; $condstring =~ s/\(DAYS\)/|/g; my $ret1 = MSwitch_checkcondition( $condstring, $name, $eventstring ); my $condstring1 = $hash->{helper}{conditioncheck}; my $errorstring = $hash->{helper}{conditionerror}; if ( !defined $errorstring ) { $errorstring = '' } $condstring1 =~ s//\>\;/g; $errorstring =~ s//\>\;/g; if ( $errorstring ne '' && $condstring1 ne 'Klammerfehler' ) { $ret1 = '
Syntaxfehler:
' . $errorstring . '

'; } elsif ( $condstring1 eq 'Klammerfehler' ) { $ret1 = '
Syntaxfehler:
Fehler in der Klammersetzung, die Anzahl öffnender und schliessender Klammern stimmt nicht überein .

'; } else { if ( $ret1 eq 'true' ) { $ret1 = 'Bedingung ist Wahr und wird ausgeführt'; } if ( $ret1 eq 'false' ) { $ret1 = 'Bedingung ist nicht Wahr und wird nicht ausgeführt'; } } $condstring =~ s/~/ /g; my $condmarker = $condstring1; my $x = 0; # exit while ( $condmarker =~ m/(.*)(\d{10})(.*)/ ) { $x++; # exit last if $x > 20; # exit my $timestamp = FmtDateTime($2); chop $timestamp; chop $timestamp; chop $timestamp; my ( $st1, $st2 ) = split( / /, $timestamp ); $condmarker = $1 . $st2 . $3; } $ret = "eingehender String:
$condstring

If Anweisung Perl:
$condstring1

"; $ret .= "If Anweisung Perl Klarzeiten:
$condmarker

" if $x > 0; $ret .= $ret1; my $condsplit = $condmarker; my $reads = '

States der geprüften Readings:
'; $x = 0; # exit while ( $condsplit =~ m/(.*')(.*)',\s'(.*)',\s(.*)/ ) { $x++; # exit last if $x > 20; # exit $reads .= "Reading: [$2:$3] - Inhalt: " . ReadingsVal( $2, $3, 'undef' ); $reads .= "
Reading nicht vorhanden !
" if ( ReadingsVal( $2, $3, 'undef' ) ) eq "undef"; $reads .= "
"; $condsplit = $1 . $4; } $ret .= $reads if $x > 0; my $err1; my $err2; if ( $errorstring ne '' ) { ( $err1, $err2 ) = split( /near /, $errorstring ); chop $err2; chop $err2; $err2 = substr( $err2, 1 ); $ret =~ s/$err2/$err2<\/span>/ig; } $hash->{helper}{conditioncheck} = ''; $hash->{helper}{conditionerror} = ''; return "" . $ret . "<\/span>"; } ################################################# if ( $opt eq 'active_timer' && $args[0] eq 'delete' ) { MSwitch_Clear_timer($hash); MSwitch_Createtimer($hash); MSwitch_Delete_Delay( $hash, 'all' ); $ret .= "
INFO: Alle anstehenden Timer wurden neu berechnet, alle Delays wurden gelöscht
"; return $ret; } ################################################# if ( $opt eq 'active_timer' && $args[0] eq 'show' ) { $ret .= "
Systemzeit: " . localtime() . "

"; $ret .= "
Schaltzeiten (at - kommandos).

"; #timer my $timehash = $hash->{helper}{timer}; foreach my $a ( sort keys %{$timehash} ) { 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 ( $number eq '1' ) { $ret .= "
" . $time . " switch MSwitch on + execute 'on' cmds
"; } if ( $number eq '2' ) { $ret .= "
" . $time . " switch MSwitch off + execute 'off' cmds
"; } if ( $number eq '3' ) { $ret .= "
" . $time . " execute 'cmd1' commands only
"; } if ( $number eq '4' ) { $ret .= "
" . $time . " execute 'cmd2' commands only
"; } if ( $number eq '9' ) { $ret .= "
" . $time . " execute 'cmd1+cmd2' commands only
"; } if ( $number eq '10' ) { $ret .= "
" . $time . " execute 'cmd1+cmd2' commands with ID " . $id . " only
"; } if ( $number eq '5' ) { $ret .= "
" . $time . " neuberechnung aller Schaltzeiten
"; } if ( $number eq '6' ) { $ret .= "
" . $time . " execute 'cmd1' commands with ID " . $id . " only
"; } if ( $number eq '7' ) { $ret .= "
" . $time . " execute 'cmd2' commands from ID " . $id . " only
"; } } #delays $ret .= "
 
aktive Delays:

"; $timehash = $hash->{helper}{delays}; foreach my $a ( sort keys %{$timehash} ) { my $b = substr( $hash->{helper}{delays}{$a}, 0, 10 ); my $time = FmtDateTime($b); my @timers = split( /#\[tr\]/, $a ); $ret .= "
" . $time . " " . $timers[0] . "
"; } if ( $ret ne "
Schaltzeiten (at - kommandos).

aktive Delays:

" ) { return $ret; } return "Keine aktiven Delays/Ats gefunden <\/span>"; } my $extension = ''; if ( ReadingsVal( $name, 'Sys_Extension', '' ) eq 'on' ) { $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 $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 $preconf $extension"; } } #################### sub MSwitch_AsyncOutput ($) { my ( $client_hash, $text ) = @_; return $text; } #################### sub MSwitch_Set($@) { my ( $hash, $name, $cmd, @args ) = @_; MSwitch_LOG( $name, 5, "$name Set $cmd, @args " . __LINE__ ); ############################## 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'; ############################## my $showevents = AttrVal( $name, "MSwitch_generate_Events", 1 ); ############################## # 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; $cs =~ s/#\[se\]/;/g; $cs =~ s/#\[dp\]/:/g; $cs =~ s/#\[st\]/'/g; $cs =~ s/#\[dst\]/\"/g; $cs =~ s/#\[tab\]/ /g; $cs =~ s/#\[ko\]/,/g; $cs =~ s/#.*\n//g; $cs =~ s/\n//g; $cs =~ s/\[tr\]/#[tr]/g; my $return = "no value"; $return = eval($cs); if ($@) { MSwitch_LOG( $name, 1, "$name MSwitch_repeat: ERROR $cs: $@ " . __LINE__ ); } return if $return eq "exit"; } ############################ if ( !defined $args[0] ) { $args[0] = ''; } my $setList = AttrVal( $name, "setList", " " ); $setList =~ s/\n/ /g; my $devicemode = AttrVal( $name, 'MSwitch_Mode', 'Full' ); my $delaymode = AttrVal( $name, 'MSwitch_Delete_Delays', '0' ); if ( !exists( $sets{$cmd} ) ) { my @cList; # Overwrite %sets with setList my $atts = AttrVal( $name, 'setList', "" ); #Log3( $name, 0, $name." ".$atts ); my %setlist = split( "[: ][ ]*", $atts ); foreach my $k ( sort keys %sets ) { my $opts = undef; $opts = $sets{$k}; $opts = $setlist{$k} if ( exists( $setlist{$k} ) ); if ( defined($opts) ) { push( @cList, $k . ':' . $opts ); } else { push( @cList, $k ); } } # end foreach 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); } ####################################### 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_cmd_1 exec_cmd_2 wait reload_timer:noArg change_renamed reset_cmd_count:1,2 $setList $special"; } elsif ( $devicemode eq "Toggle" ) { return "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"; } elsif ( $devicemode eq "Dummy" ) { return "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 reset_cmd_count:1,2 $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 ); return; } ################################## if ( $cmd eq 'reset_cmd_count' ) { if ( $args[0] eq "1" ) { delete( $hash->{READINGS}{EVT_CMD1_COUNT} ); } if ( $args[0] eq "2" ) { delete( $hash->{READINGS}{EVT_CMD2_COUNT} ); } return; } ####################################### if ( $cmd eq 'reload_timer' ) { MSwitch_Clear_timer($hash); MSwitch_Createtimer($hash); return; } ####################################### if ( $cmd eq 'VUpdate' ) { MSwitch_VUpdate($hash); return; } ####################################### if ( $cmd eq 'confchange' ) { MSwitch_confchange( $hash, $args[0] ); return; } ################################### if ( $cmd eq 'clearlog' ) { MSwitch_clearlog($hash); return; } ############################## if ( $cmd eq 'wait' ) { readingsSingleUpdate( $hash, "waiting", ( time + $args[0] ), $showevents ); return; } ############################### if ( $cmd eq 'sort_device' ) { readingsSingleUpdate( $hash, ".sortby", $args[0], 0 ); return; } if ( $cmd eq 'fakeevent' ) { # fakeevent abarbeiten MSwitch_Check_Event( $hash, $args[0] ); return; } ############################## 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 ); return; } ############################## if ( $cmd eq 'exec_cmd_2' ) { if ( $args[0] eq 'ID' ) { $execids = $args[1]; $args[0] = 'ID'; } # cmd2 abarbeiten MSwitch_Exec_Notif( $hash, 'off', 'nocheck', '', $execids ); return; } ############################## if ( $cmd eq 'backup_MSwitch' ) { # backup erstellen MSwitch_backup($hash); return; } ############################## if ( $cmd eq 'del_delays' ) { # löschen aller delays MSwitch_Delete_Delay( $hash, $name ); MSwitch_Createtimer($hash); return; } ############################## if ( $cmd eq 'saveconfig' ) { # configfile speichern $args[0] =~ s/\[s\]/ /g; MSwitch_saveconf( $hash, $args[0] ); return; } ############################## if ( $cmd eq 'savesys' ) { # sysfile speichern MSwitch_savesys( $hash, $args[0] ); return; } ############################## if ( $cmd eq "addevent" ) { # event manuell zufügen my $devName = ReadingsVal( $name, 'Trigger_device', '' ); $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"; } } else { foreach (@newevents) { $hash->{helper}{events}{$devName}{$_} = "on"; } } my $events = ''; my $eventhash = $hash->{helper}{events}{$devName}; foreach my $name ( keys %{$eventhash} ) { $events = $events . $name . '#[tr]'; } chop($events); chop($events); chop($events); chop($events); chop($events); readingsSingleUpdate( $hash, ".Device_Events", $events, 0 ); return; } ############################## if ( $cmd eq "add_device" ) { #add device MSwitch_Add_Device( $hash, $args[0] ); return; } ############################## if ( $cmd eq "del_device" ) { #del device MSwitch_Del_Device( $hash, $args[0] ); return; } ############################## if ( $cmd eq "del_trigger" ) { #lösche trigger MSwitch_Delete_Triggermemory($hash); return; } ############################## if ( $cmd eq "filter_trigger" ) { #filter to trigger MSwitch_Filter_Trigger($hash); return; } ############################## if ( $cmd eq "set_trigger" ) { 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] . '~onoffonly' . $args[5]; my $oldtrigger = ReadingsVal( $name, 'Trigger_device', '' ); readingsSingleUpdate( $hash, "Trigger_device", $args[0], '1' ); readingsSingleUpdate( $hash, ".Trigger_condition", $args[6], 0 ); if ( !defined $args[7] ) { readingsDelete( $hash, '.Trigger_Whitelist' ); } else { readingsSingleUpdate( $hash, ".Trigger_Whitelist", $args[7], 0 ); } my $testtrig = ReadingsVal( $name, 'Trigger_device', '' ); if ( $oldtrigger ne $args[0] ) { MSwitch_Delete_Triggermemory($hash); # lösche alle events } if ( $args[1] ne '' || $args[2] ne '' || $args[3] ne '' || $args[4] ne '' || $args[5] ne '' ) { readingsSingleUpdate( $hash, ".Trigger_time", $triggertime, 0 ); MSwitch_Createtimer($hash); } else { readingsSingleUpdate( $hash, ".Trigger_time", '', 0 ); MSwitch_Clear_timer($hash); } $hash->{helper}{events}{ $args[0] }{'no_trigger'} = "on"; if ( $args[0] ne 'no_trigger' ) { if ( $args[0] eq "all_events" ) { delete( $hash->{NOTIFYDEV} ); if ( ReadingsVal( $name, '.Trigger_Whitelist', '' ) ne '' ) { $hash->{NOTIFYDEV} = ReadingsVal( $name, '.Trigger_Whitelist', '' ); } } 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 { $hash->{NOTIFYDEV} = 'no_trigger'; delete $hash->{DEF}; } return; } ############################## if ( $cmd eq "trigger" ) { # setze trigger events my $triggeron = ''; my $triggeroff = ''; my $triggercmdon = ''; my $triggercmdoff = ''; $args[0] =~ s/~/ /g; $args[1] =~ s/~/ /g; $args[2] =~ s/~/ /g; $args[3] =~ s/~/ /g; $args[4] =~ s/~/ /g; if ( !defined $args[1] ) { $args[1] = "" } if ( !defined $args[3] ) { $args[3] = "" } $triggeron = $args[0]; $triggeroff = $args[1]; if ( !defined $args[3] ) { $args[3] = "" } if ( !defined $args[4] ) { $args[4] = "" } $triggercmdon = $args[3]; $triggercmdoff = $args[4]; readingsBeginUpdate($hash); readingsBulkUpdate( $hash, ".Trigger_on", $triggeron ); readingsBulkUpdate( $hash, ".Trigger_off", $triggeroff ); if ( $args[2] eq 'nein' ) { readingsBulkUpdate( $hash, "Trigger_log", 'off' ); } if ( $args[2] eq 'ja' ) { readingsBulkUpdate( $hash, "Trigger_log", 'on' ); } readingsBulkUpdate( $hash, ".Trigger_cmd_on", $triggercmdon ); readingsBulkUpdate( $hash, ".Trigger_cmd_off", $triggercmdoff ); readingsEndUpdate( $hash, 0 ); return; } ############################## if ( $cmd eq "devices" ) { # setze devices my $devices = $args[0]; if ( $devices eq 'null' ) { readingsSingleUpdate( $hash, ".Device_Affected", 'no_device', 0 ); return; } my @olddevices = split( /,/, ReadingsVal( $name, '.Device_Affected', 'no_device' ) ); my @devices = split( /,/, $args[0] ); my $addolddevice = ''; foreach (@devices) { my $testdev = $_; LOOP6: foreach my $olddev (@olddevices) { my $oldcmd = ''; my $oldname = ''; ( $oldname, $oldcmd ) = split( /-AbsCmd/, $olddev ); if ( !defined $oldcmd ) { $oldcmd = '' } if ( $oldcmd eq '1' ) { next LOOP6 } if ( $oldname eq $testdev ) { $addolddevice = $addolddevice . $olddev . ','; } } $_ = $_ . '-AbsCmd1'; } chop($addolddevice); $devices = join( ',', @devices ) . ',' . $addolddevice; my @sortdevices = split( /,/, $devices ); @sortdevices = sort @sortdevices; $devices = join( ',', @sortdevices ); readingsSingleUpdate( $hash, ".Device_Affected", $devices, 0 ); $devices = MSwitch_makeAffected($hash); if ( defined $hash->{DEF} ) { my $devhash = $hash->{DEF}; my @dev = split( /#/, $devhash ); $hash->{DEF} = $dev[0] . ' # ' . $devices; } else { $hash->{DEF} = ' # ' . $devices; } return; } ############################## if ( $cmd eq "details" ) { # setze devices details $args[0] = urlDecode( $args[0] ); $args[0] =~ s/#\[pr\]/%/g; #devicehasch my %devhash = split( /#\[DN\]/, $args[0] ); my @devices = split( /,/, ReadingsVal( $name, '.Device_Affected', '' ) ); my @inputcmds = split( /#\[ND\]/, $args[0] ); my $error = ''; my $key = ''; my $savedetails = ''; LOOP10: foreach (@devices) { my @devicecmds = split( /#\[NF\]/, $devhash{$_} ); $savedetails = $savedetails . $_ . '#[NF]'; $savedetails = $savedetails . $devicecmds[0] . '#[NF]'; $savedetails = $savedetails . $devicecmds[1] . '#[NF]'; $savedetails = $savedetails . $devicecmds[2] . '#[NF]'; $savedetails = $savedetails . $devicecmds[3] . '#[NF]'; $savedetails = $savedetails . $devicecmds[4] . '#[NF]'; $savedetails = $savedetails . $devicecmds[5] . '#[NF]'; $savedetails = $savedetails . $devicecmds[7] . '#[NF]'; $savedetails = $savedetails . $devicecmds[6] . '#[NF]'; if ( defined $devicecmds[8] ) { $savedetails = $savedetails . $devicecmds[8] . '#[NF]'; } else { $savedetails = $savedetails . '' . '#[NF]'; } if ( defined $devicecmds[9] ) { $savedetails = $savedetails . $devicecmds[9] . '#[NF]'; } else { $savedetails = $savedetails . '' . '#[NF]'; } if ( defined $devicecmds[10] ) { $savedetails = $savedetails . $devicecmds[10] . '#[NF]'; } else { $savedetails = $savedetails . '' . '#[NF]'; } if ( defined $devicecmds[11] ) { $savedetails = $savedetails . $devicecmds[11] . '#[NF]'; } else { $savedetails = $savedetails . '' . '#[NF]'; } # priority if ( defined $devicecmds[12] && $devicecmds[12] ne 'undefined' ) { $savedetails = $savedetails . $devicecmds[12] . '#[NF]'; } else { $savedetails = $savedetails . '1' . '#[NF]'; } # id if ( defined $devicecmds[13] && $devicecmds[13] ne 'undefined' ) { $savedetails = $savedetails . $devicecmds[13] . '#[NF]'; } else { $savedetails = $savedetails . '0' . '#[NF]'; } # comment if ( defined $devicecmds[14] && $devicecmds[14] ne 'undefined' ) { $savedetails = $savedetails . $devicecmds[14] . '#[NF]'; } else { $savedetails = $savedetails . '' . '#[NF]'; } # exit1 if ( defined $devicecmds[15] && $devicecmds[15] ne 'undefined' ) { $savedetails = $savedetails . $devicecmds[15] . '#[NF]'; } else { $savedetails = $savedetails . '0' . '#[NF]'; } # exit2 if ( defined $devicecmds[16] && $devicecmds[16] ne 'undefined' ) { $savedetails = $savedetails . $devicecmds[16] . '#[NF]'; } else { $savedetails = $savedetails . '0' . '#[NF]'; } # show if ( defined $devicecmds[17] && $devicecmds[17] ne 'undefined' ) { $savedetails = $savedetails . $devicecmds[17] . '#[ND]'; } else { $savedetails = $savedetails . '1' . '#[ND]'; } # $counter++; } chop($savedetails); chop($savedetails); chop($savedetails); chop($savedetails); chop($savedetails); # ersetzung sonderzeichen etc mscode # auskommentierte wurden bereits dur jscript ersetzt $savedetails =~ s/\n/#[nl]/g; $savedetails =~ s/\t/ /g; $savedetails =~ s/ /#[sp]/g; $savedetails =~ s/\\/#[bs]/g; $savedetails =~ s/,/#[ko]/g; $savedetails =~ s/^#\[/#[eo]/g; $savedetails =~ s/^#\]/#[ec]/g; $savedetails =~ s/\|/#[wa]/g; $savedetails =~ s/\|/#[ti]/g; readingsSingleUpdate( $hash, ".Device_Affected_Details", $savedetails, 0 ); return; } ################################################################## my $update = ''; # unbedingt überarbeiten !!! my @testdetails = qw(_on _off _onarg _offarg _playback _record _timeon _timeoff _conditionon _conditionoff); my @testdetailsstandart = ( 'no_action', 'no_action', '', '', 'nein', 'nein', 0, 0, '', '' ); ################################## #neu ausführung on/off if ( $cmd eq "off" || $cmd eq "on" ) { ### neu if ( $delaymode eq '1' ) { MSwitch_Delete_Delay( $hash, $name ); } ############ # ausführen des off befehls my $zweig = 'nicht definiert'; $zweig = "cmd1" if $cmd eq "on"; $zweig = "cmd2" if $cmd eq "off"; my $exittest = ''; $exittest = "1" if $cmd eq "on"; $exittest = "2" if $cmd eq "off"; my $ekey = ''; my $out = '0'; MSwitch_Safemode($hash); MSwitch_LOG( $name, 6, "----------------------------------------" ); MSwitch_LOG( $name, 6, "$name: aufruf on/off -> $cmd" ); MSwitch_LOG( $name, 6, "----------------------------------------" ); my @cmdpool; my %devicedetails = MSwitch_makeCmdHash($name); my @devices = split( /,/, ReadingsVal( $name, '.Device_Affected', '' ) ); # liste anpassen ( reihenfolge ) wenn expert = 1 @devices = MSwitch_priority( $hash, $execids, @devices ); my $expertmode = AttrVal( $name, 'MSwitch_Expert', "0" ); my $randomtime = AttrVal( $name, 'MSwitch_RandomTime', '' ); LOOP1: foreach my $device (@devices) { $out = '0'; if ( $expertmode eq '1' ) { $ekey = $device . "_exit" . $exittest; $out = $devicedetails{$ekey}; } MSwitch_LOG( $name, 6, "$name: angesprochener zweig " . $zweig . " -> device -> -" . $device . "-" ); # teste auf on kommando next LOOP1 if $device eq "no_device"; my @devicesplit = split( /-AbsCmd/, $device ); my $devicenamet = $devicesplit[0]; my $count = 0; foreach my $testset (@testdetails) { if ( !defined( $devicedetails{ $device . $testset } ) ) { my $key = ''; $key = $device . $testset; $devicedetails{$key} = $testdetailsstandart[$count]; } $count++; } my $key = $device . "_" . $cmd; my $timerkey = $device . "_time" . $cmd; my $testtstate = $devicedetails{$timerkey}; # teste auf delayinhalt MSwitch_LOG( $name, 6, "$name: teste auf timerstatus -> $testtstate" ); $testtstate =~ s/[A-Za-z0-9#\.\-_]//g; if ( $testtstate eq "[:]" || $testtstate eq "[\$:]" ) { $devicedetails{$timerkey} = eval MSwitch_Checkcond_state( $devicedetails{$timerkey}, $name ); if ( $devicedetails{$timerkey} =~ m/[0-9]\d:[0-9]\d:[0-9]\d/ ) { MSwitch_LOG( $name, 6, "$name: format ok " ); my $hdel = ( substr( $devicedetails{$timerkey}, 0, 2 ) ) * 3600; my $mdel = ( substr( $devicedetails{$timerkey}, 3, 2 ) ) * 60; my $sdel = ( substr( $devicedetails{$timerkey}, 6, 2 ) ) * 1; $devicedetails{$timerkey} = $hdel + $mdel + $sdel; } else { MSwitch_LOG( $name, 1, "$name: ERROR Timerformat " . $devicedetails{$timerkey} . " fehlerhaf " ); $devicedetails{$timerkey} = 0; } } MSwitch_LOG( $name, 6, "$name: timerstatus nach test -> " . $devicedetails{$timerkey} ); # suche befehl if ( $devicedetails{$key} ne "" && $devicedetails{$key} ne "no_action" ) #befehl gefunden { my $cs = ''; $cs = "set $devicenamet $devicedetails{$device.'_off'} $devicedetails{$device.'_offarg'}" if $cmd eq "off"; $cs = "set $devicenamet $devicedetails{$device.'_on'} $devicedetails{$device.'_onarg'}" if $cmd eq "on"; if ( $devicenamet eq 'FreeCmd' ) { $cs = "$devicedetails{$device.'_'.$cmd.'arg'}"; $cs = MSwitch_makefreecmd( $hash, $cs ); } MSwitch_LOG( $name, 6, "$name: befehl gefunden -> " . $cs ); MSwitch_LOG( $name, 6, "$name: teste auf delay -> " . $devicedetails{$timerkey} ); my $conditionkey = $device . "_condition" . $cmd; MSwitch_LOG( $name, 6, "$name: TIMERKEY -> " . $devicedetails{$timerkey} ); if ( $devicedetails{$timerkey} eq "0" || $devicedetails{$timerkey} eq "" ) { # $conditionkey = $device . "_conditionoff"; MSwitch_LOG( $name, 6, "$name: teste auf condition -> aufruf sub checkcondition mit " . $devicedetails{$conditionkey} ) if $devicedetails{$conditionkey} ne ''; MSwitch_LOG( $name, 6, "$name: teste auf condition -> wird nicht getestet - kein eintrag" . $devicedetails{$conditionkey} ) if $devicedetails{$conditionkey} eq ''; my $execute = "true"; $execute = MSwitch_checkcondition( $devicedetails{$conditionkey}, $name, $args[0] ) if $devicedetails{$conditionkey} ne ''; 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, "$name: in exec-cmdpool geschrieben ->" . $cs ); push @cmdpool, $cs . '|' . $device; $update = $device . ',' . $update; if ( $out eq '1' ) { MSwitch_LOG( $name, 6, "$name: Abbruchbefehl erhalten von " . $device ); last LOOP1; } } } else { MSwitch_LOG( $name, 6, "$name: teste auf condition -> keine vorhanden " ); if ( $randomtime ne '' && $devicedetails{$timerkey} eq '[random]' ) { MSwitch_LOG( $name, 6, "$name: randomtimer gefunden attr gesetzt -> " . $devicedetails{$timerkey} ); $devicedetails{$timerkey} = MSwitch_Execute_randomtimer($hash); # ersetzt $devicedetails{$timerkey} gegen randomtimer MSwitch_LOG( $name, 6, "$name: timerd ersetzt-> " . $devicedetails{$timerkey} ); } elsif ($randomtime eq '' && $devicedetails{$timerkey} eq '[random]' ) { MSwitch_LOG( $name, 6, "$name: randomtimer gefunden attr nicht gesetzt -> 0" ); $devicedetails{$timerkey} = 0; } # ? my $execute = "true"; # conditiontest nur dann, wenn cond-test nicht nur nach verzögerung if ( $devicedetails{ $device . "_delayat" . $cmd } ne "delay2" && $devicedetails{ $device . "_delayat" . $cmd } ne "at02" ) { MSwitch_LOG( $name, 6, "$name: checkcondition bei gefundem delay -> " . $devicedetails{ $device . "_delayat" . $cmd } ); $execute = MSwitch_checkcondition( $devicedetails{$conditionkey}, $name, $args[0] ); MSwitch_LOG( $name, 6, "$name: ergebniss checkcondition für delay-> " . $execute ); } MSwitch_LOG( $name, 6, "$name: ----------------- Delay -> " . $devicedetails{$timerkey} ); if ( $execute eq 'true' ) { MSwitch_LOG( $name, 6, "$name: conidtion ok - Befehl mt at/delay wird ausgefuehrt -> " . $cs ); my $delaykey = $device . "_delayat" . $cmd; my $delayinhalt = $devicedetails{$delaykey}; my $delaykey1 = $device . "_delayat" . $cmd . "org"; my $teststateorg = $devicedetails{$delaykey1}; MSwitch_LOG( $name, 6, "$name: delaykey -> " . $delaykey ); MSwitch_LOG( $name, 6, "$name: delaykeyinhalt -> " . $delayinhalt ); MSwitch_LOG( $name, 6, "$name: delaykeyinhaltorg -> " . $teststateorg ); if ( $delayinhalt eq 'at0' || $delayinhalt eq 'at1' ) { MSwitch_LOG( $name, 6, "$name: delay mit at erkannt -> " . $devicedetails{$timerkey} ); MSwitch_LOG( $name, 6, "$name: delay wird ersetzt " ); $devicedetails{$timerkey} = MSwitch_replace_delay( $hash, $teststateorg ); MSwitch_LOG( $name, 6, "$name: delay ersetzt -> " . $devicedetails{$timerkey} ); } if ( $delayinhalt eq 'at1' || $delayinhalt eq 'delay0' ) { MSwitch_LOG( $name, 6, "$name: delay ohne zusatzprüfung erkannt -> " . $delayinhalt ); $conditionkey = 'nocheck'; MSwitch_LOG( $name, 6, "$name: conditionkey ersetzt -> " . $conditionkey ); } my $timecond = gettimeofday() + $devicedetails{$timerkey}; my $msg = $cs . "#[tr]" . $name . "#[tr]" . $conditionkey . "#[tr]#[tr]" . $timecond . "#[tr]" . $device; # variabelersetzung $msg =~ s/\$NAME/$hash->{helper}{eventfrom}/; $msg =~ s/\$SELF/$name/; $hash->{helper}{delays}{$msg} = $timecond; InternalTimer( $timecond, "MSwitch_Restartcmd", $msg ); MSwitch_LOG( $name, 6, "$name: verzögerte befehl gesetzt -> " . $timecond . " : " . $msg ); if ( $out eq '1' ) { MSwitch_LOG( $name, 6, "$name: Abbruchbefehl erhalten von " . $device ); last LOOP1; } } } } } if ( $devicemode ne "Notify" ) { readingsSingleUpdate( $hash, "state", $cmd, 1 ); } else { readingsSingleUpdate( $hash, "state", 'active', $showevents ); } #MSwitch_EventBulk($hash,$args[0],'0','MSwitch_set'); my $anzahl = @cmdpool; MSwitch_LOG( $name, 6, "$name: anzahl der auszufuehrenden befehle -> " . $anzahl ); MSwitch_LOG( $name, 6, "$name: uebergabe an sub execute " ) if $anzahl > 0; MSwitch_Cmd( $hash, @cmdpool ) if $anzahl > 0; return; } return; } ################################### sub MSwitch_Cmd(@) { my ( $hash, @cmdpool ) = @_; my $Name = $hash->{NAME}; my $lastdevice; my $showevents = AttrVal( $Name, "MSwitch_generate_Events", 1 ); 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 #change # $cmds =~ s/#\[wa\]/|/g; #neu my $device = $cut[1]; $lastdevice = $device; my $toggle = ''; if ( $cmds =~ m/set (.*)(MSwitchtoggle)(.*)/ ) { MSwitch_LOG( $Name, 6, "$Name: togglemode erkannt -> " . $cmds ); $toggle = $cmds; $cmds = MSwitch_toggle( $hash, $cmds ); } if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' && $devicedetails{ $device . '_repeatcount' } ne '' ) { MSwitch_LOG( $Name, 6, "$Name: teste auf repeatcount -> " . $devicedetails{ $device . '_repeatcount' } ); my $x = 0; while ( $devicedetails{ $device . '_repeatcount' } =~ m/\[(.*)\:(.*)\]/ ) { $x++; # exit last if $x > 20; # exitg my $setmagic = ReadingsVal( $1, $2, 0 ); $devicedetails{ $device . '_repeatcount' } = $setmagic; } MSwitch_LOG( $Name, 6, "$Name: repeatcount nach setmagicersetzung -> " . $devicedetails{ $device . '_repeatcount' } ); } if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' && $devicedetails{ $device . '_repeattime' } ne '' ) { MSwitch_LOG( $Name, 6, "$Name: teste auf repeattime -> " . $devicedetails{ $device . '_repeattime' } ); my $x = 0; while ( $devicedetails{ $device . '_repeattime' } =~ m/\[(.*)\:(.*)\]/ ) { $x++; # exit last if $x > 20; # exitg my $setmagic = ReadingsVal( $1, $2, 0 ); $devicedetails{ $device . '_repeattime' } = $setmagic; } MSwitch_LOG( $Name, 6, "$Name: _repeattime nach setmagicersetzung -> " . $devicedetails{ $device . '_repeattime' } ); } if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' && $devicedetails{ $device . '_repeatcount' } > 0 && $devicedetails{ $device . '_repeattime' } > 0 ) { my $i; for ( $i = 0 ; $i <= $devicedetails{ $device . '_repeatcount' } ; $i++ ) { my $msg = $cmds . "|" . $Name; if ( $toggle ne '' ) { $msg = $toggle . "|" . $Name; } my $timecond = gettimeofday() + ( ( $i + 1 ) * $devicedetails{ $device . '_repeattime' } ); $msg = $msg . "|" . $timecond; $hash->{helper}{repeats}{$timecond} = "$msg"; MSwitch_LOG( $Name, 6, "$Name: repeat gesetzt -> " . $timecond . " : " . $msg ); InternalTimer( $timecond, "MSwitch_repeat", $msg ); } } my $todec = $cmds; $cmds = MSwitch_dec( $hash, $todec ); MSwitch_LOG( $Name, 6, "$Name: cmd nach decodierung -> " . $cmds ); ############################ # debug2 mode , kein execute if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '2' ) { MSwitch_LOG( $Name, 6, "$Name: exec comand -> " . $cmds ); } else { if ( $cmds =~ m/{.*}/ ) { MSwitch_LOG( $Name, 6, "$Name: exec als perlcode -> " . $cmds ); my $out = eval($cmds); if ($@) { MSwitch_LOG( $Name, 1, "$Name MSwitch_Set: ERROR $cmds: $@ " . __LINE__ ); } } else { MSwitch_LOG( $Name, 6, "$Name: execute als fhemcode -> " . $cmds ); my $errors = AnalyzeCommandChain( undef, $cmds ); if ( defined($errors) ) { MSwitch_LOG( $Name, 1, "$Name MSwitch_Set: ERROR $cmds: $errors " . __LINE__ ); } } } ############################# } my $showpool = join( ',', @cmdpool ); if ( length($showpool) > 100 ) { $showpool = substr( $showpool, 0, 100 ) . '....'; } readingsSingleUpdate( $hash, "last_exec_cmd", $showpool, $showevents ) if $showpool ne ''; if ( AttrVal( $Name, 'MSwitch_Expert', '0' ) eq "1" ) { readingsSingleUpdate( $hash, "last_cmd", $hash->{helper}{priorityids}{$lastdevice}, $showevents ); } } #################### sub MSwitch_toggle($$) { my ( $hash, $cmds ) = @_; my $Name = $hash->{NAME}; $cmds =~ m/(set) (.*)( )MSwitchtoggle (.*)/; my @tcmd = split( /\//, $4 ); if ( !defined $tcmd[2] ) { $tcmd[2] = 'state' } if ( !defined $tcmd[3] ) { $tcmd[3] = $tcmd[0] } if ( !defined $tcmd[4] ) { $tcmd[4] = $tcmd[1] } my $cmd1 = $1 . " " . $2 . " " . $tcmd[0]; my $cmd2 = $1 . " " . $2 . " " . $tcmd[1]; my $chk1 = $tcmd[0]; my $chk2 = $tcmd[1]; my $testnew = ReadingsVal( $2, $tcmd[2], 'undef' ); if ( $testnew =~ m/$tcmd[3]/ ) { $cmds = $cmd2; } elsif ( $testnew =~ m/$tcmd[4]/ ) { $cmds = $cmd1; } else { $cmds = $cmd1; } return $cmds; } ############################## sub MSwitch_Log_Event(@) { my ( $hash, $msg, $me ) = @_; my $Name = $hash->{NAME}; my $triggerdevice = ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ); my $re = qr/$triggerdevice/; if ( $triggerdevice eq 'no_trigger' ) { delete( $hash->{helper}{writelog} ); return; } if ( $triggerdevice ne 'Logfile' && $triggerdevice ne 'all_events' && ( $hash->{helper}{writelog} !~ /$re/ ) ) { delete( $hash->{helper}{writelog} ); return; } MSwitch_Check_Event( $hash, $hash ); delete( $hash->{helper}{writelog} ); return; } ############################## sub MSwitch_Attr(@) { my ( $cmd, $name, $aName, $aVal ) = @_; my $hash = $defs{$name}; if ( $aName eq 'MSwitch_Debug' && ( $aVal == 0 || $aVal == 1 || $aVal == 2 || $aVal == 3 ) ) { delete( $hash->{READINGS}{Bulkfrom} ); delete( $hash->{READINGS}{Device_Affected} ); delete( $hash->{READINGS}{Device_Affected_Details} ); delete( $hash->{READINGS}{Device_Events} ); } if ( $aName eq 'MSwitch_RandomTime' && $aVal ne '' ) { if ( $aVal !~ m/([0-9]{2}:[0-9]{2}:[0-9]{2}-[0-9]{2}:[0-9]{2}:[0-9]{2})/ ) { return 'wrong syntax !
the syntax must be: HH:MM:SS-HH:MM:SS'; } else { $aVal =~ s/\://g; my @test = split( /-/, $aVal ); if ( $test[0] >= $test[1] ) { return 'fist ' . $test[0] . ' parameter must be lower than second parameter ' . $test[1]; } } return; } if ( $cmd eq "set" && $aName eq "MSwitch_Read_Log" ) { if ( defined($aVal) && $aVal eq "1" ) { $logInform{$name} = sub($$) { my ( $me, $msg ) = @_; return if ( defined( $hash->{helper}{writelog} ) ); $hash->{helper}{writelog} = $msg; MSwitch_Log_Event( $hash, $msg, $me ); } } else { delete( $hash->{helper}{writelog} ); delete $logInform{$name}; } } if ( $cmd eq 'set' && $aName eq 'disable' && $aVal == 1 ) { $hash->{NOTIFYDEV} = 'no_trigger'; MSwitch_Delete_Delay( $hash, 'all' ); MSwitch_Clear_timer($hash); } if ( $cmd eq 'set' && $aName eq 'disable' && $aVal == 0 ) { delete( $hash->{helper}{savemodeblock} ); delete( $hash->{READINGS}{Safemode} ); MSwitch_Createtimer($hash); } if ( $cmd eq 'set' && $aName eq 'disable' && $aVal == 0 && ReadingsVal( $name, 'Trigger_device', 'no_trigger' ) ne 'no_trigger' ) { $hash->{NOTIFYDEV} = ReadingsVal( $name, 'Trigger_device', 'no_trigger' ); } if ( $cmd eq 'del' && $aName eq 'disable' && ReadingsVal( $name, 'Trigger_device', 'no_trigger' ) ne 'no_trigger' ) { $hash->{NOTIFYDEV} = ReadingsVal( $name, 'Trigger_device', 'no_trigger' ); } if ( $aName eq 'MSwitch_Activate_MSwitchcmds' && $aVal == 1 ) { addToAttrList('MSwitchcmd'); } if ( $aName eq 'MSwitch_Debug' && $aVal eq '0' ) { unlink("./log/MSwitch_debug_$name.log"); } if ( $aName eq 'MSwitch_Debug' && $aVal eq '2' || $aVal eq '3' ) { MSwitch_clearlog($hash); } if ( $cmd eq 'set' && $aName eq 'MSwitch_Inforoom' ) { my $testarg = $aVal; foreach my $testdevices ( keys %{ $modules{MSwitch}{defptr} } ) { $attr{$testdevices}{MSwitch_Inforoom} = $testarg; } } if ( $aName eq 'MSwitch_Mode' && ( $aVal eq 'Full' || $aVal eq 'Toggle' ) ) { my $cs = "setstate $name ???"; my $errors = AnalyzeCommandChain( undef, $cs ); $hash->{MODEL} = 'Full' if $aVal eq 'Full'; $hash->{MODEL} = 'Toggle' if $aVal eq 'Toggle'; } if ( $aName eq 'MSwitch_Mode' && ( $aVal eq 'Dummy' ) ) { MSwitch_Delete_Delay( $hash, 'all' ); MSwitch_Clear_timer($hash); $hash->{NOTIFYDEV} = 'no_trigger'; $hash->{MODEL} = 'Dummy'; } if ( $aName eq 'MSwitch_Mode' && $aVal eq 'Notify' ) { readingsSingleUpdate( $hash, "state", 'active', 1 ); $hash->{MODEL} = 'Notify'; my $cs = "setstate $name active"; my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { MSwitch_LOG( $name, 1, "$name MSwitch_Notify: Fehler bei Befehlsausführung $errors -> Comand: $_ " . __LINE__ ); } } ############# if ( $cmd eq 'del' ) { my $testarg = $aName; my $errors; if ( $testarg eq 'MSwitch_Inforoom' ) { LOOP21: foreach my $testdevices ( keys %{ $modules{MSwitch}{defptr} } ) { if ( $testdevices eq $name ) { next LOOP21; } delete( $attr{$testdevices}{MSwitch_Inforoom} ); } } if ( $testarg eq 'disable' ) { MSwitch_Delete_Delay( $hash, "all" ); MSwitch_Clear_timer($hash); delete( $hash->{helper}{savemodeblock} ); delete( $hash->{READINGS}{Safemode} ); } if ( $testarg eq 'MSwitch_Reset_EVT_CMD1_COUNT' ) { delete( $hash->{READINGS}{EVT_CMD1_COUNT} ); } if ( $testarg eq 'MSwitch_Reset_EVT_CMD2_COUNT' ) { delete( $hash->{READINGS}{EVT_CMD2_COUNT} ); } } return undef; } #################### sub MSwitch_Delete($$) { my ( $hash, $name ) = @_; RemoveInternalTimer($hash); return undef; } #################### sub MSwitch_Undef($$) { my ( $hash, $name ) = @_; RemoveInternalTimer($hash); delete( $modules{MSwitch}{defptr}{$name} ); return undef; } #################### sub MSwitch_Notify($$) { my $testtoggle = ''; my ( $own_hash, $dev_hash ) = @_; my $ownName = $own_hash->{NAME}; # own name / hash my $devName; $devName = $dev_hash->{NAME}; if ( $own_hash->{helper}{testevent_device} && $own_hash->{helper}{testevent_device} eq 'Logfile' ) { $devName = 'Logfile'; } my $events = deviceEvents( $dev_hash, 1 ); my $trigevent = ''; my $eventset = '0'; my $execids = "0"; my $foundcmd1 = 0; my $foundcmd2 = 0; my $showevents = AttrVal( $ownName, "MSwitch_generate_Events", 1 ); my $resetcmd1 = AttrVal( $ownName, "MSwitch_Reset_EVT_CMD1_COUNT", 0 ); my $resetcmd2 = AttrVal( $ownName, "MSwitch_Reset_EVT_CMD2_COUNT", 0 ); if ( $resetcmd1 > 0 && ReadingsVal( $ownName, 'EVT_CMD1_COUNT', '0' ) >= $resetcmd1 ) { readingsSingleUpdate( $own_hash, "EVT_CMD1_COUNT", 0, $showevents ); } if ( $resetcmd2 > 0 && ReadingsVal( $ownName, 'EVT_CMD2_COUNT', '0' ) >= $resetcmd1 ) { readingsSingleUpdate( $own_hash, "EVT_CMD2_COUNT", 0, $showevents ); } # nur abfragen für eigenes Notify if ( $init_done && $devName eq "global" && grep( m/^MODIFIED $ownName$/, @{$events} ) ) { # reaktion auf eigenes notify start / define / modify my $timecond = gettimeofday() + 5; InternalTimer( $timecond, "MSwitch_LoadHelper", $own_hash ); } if ( $init_done && $devName eq "global" && grep( m/^DEFINED $ownName$/, @{$events} ) ) { # reaktion auf eigenes notify start / define / modify my $timecond = gettimeofday() + 5; InternalTimer( $timecond, "MSwitch_LoadHelper", $own_hash ); } if ( $devName eq "global" && grep( m/^INITIALIZED|REREADCFG$/, @{$events} ) ) { # reaktion auf eigenes notify start / define / modify MSwitch_LoadHelper($own_hash); } # nur abfragen für eigenes Notify ENDE return "" 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} && ReadingsVal( $ownName, 'Trigger_device', 'no_triggen' ) ne "all_events" ); # startverzöferung abwarten my $diff = int(time) - $fhem_started; if ( $diff < $startdelay ) { MSwitch_LOG( $ownName, 6, 'Anfrage fuer ' . $ownName . ' blockiert - Zeit seit start:' . $diff ); return; } # safemode testen MSwitch_Safemode($own_hash); MSwitch_LOG( $ownName, 6, "----------------------------------------" ); MSwitch_LOG( $ownName, 6, "$ownName: eingehendes Event von -> " . $devName ); MSwitch_LOG( $ownName, 6, "----------------------------------------" ); # versionscheck if ( ReadingsVal( $ownName, '.V_Check', $vupdate ) ne $vupdate ) { my $ver = ReadingsVal( $ownName, '.V_Check', '' ); MSwitch_LOG( $ownName, 4, $ownName . ' Versionskonflikt, aktion abgebrochen ! erwartet:' . $vupdate . ' vorhanden:' . $ver ); return; } if ( $attrrandomnumber ne '' ) { # create randomnumber wenn attr an MSwitch_Createnumber1($own_hash); } if ( ReadingsVal( $ownName, "waiting", '0' ) > time ) { MSwitch_LOG( $ownName, 6, '$ownName: Aktion abgebrochen - wait gesetzt ->' . ReadingsVal( $ownName, "waiting", '0' ) ); # teste auf attr waiting verlesse wenn gesetzt return ""; } else { # reading löschen delete( $own_hash->{READINGS}{waiting} ); } MSwitch_LOG( $ownName, 6, "-------------waiting passiert-----------------" ); my $incommingdevice = ''; if ( defined( $own_hash->{helper}{testevent_device} ) ) { # unklar $events = 'x'; $incommingdevice = ( $own_hash->{helper}{testevent_device} ); } else { $incommingdevice = $dev_hash->{NAME}; # aufrufendes device } #readingsSingleUpdate( $own_hash, "trigdev", 'vor erste ', 1 ); # nur zu testzwecken if ( !$events && $own_hash->{helper}{testevent_device} ne 'Logfile' ) { return; } #readingsSingleUpdate( $own_hash, "trigdev1", 'nach erste ', 1 ); # nur zu testzwecken my $triggerdevice = ReadingsVal( $ownName, 'Trigger_device', '' ); # Triggerdevice my @cmdarray; my @cmdarray1; # enthält auszuführende befehle nach conditiontest ########### ggf. löschen my $triggeron = ReadingsVal( $ownName, '.Trigger_on', '' ); my $triggeroff = ReadingsVal( $ownName, '.Trigger_off', '' ); my $triggercmdon = ReadingsVal( $ownName, '.Trigger_cmd_on', '' ); my $triggercmdoff = ReadingsVal( $ownName, '.Trigger_cmd_off', '' ); if ( $devicemode eq "Notify" ) { # passt triggerfelder an attr an $triggeron = 'no_trigger'; $triggeroff = 'no_trigger'; } if ( $devicemode eq "Toggle" ) { # passt triggerfelder an attr an $triggeroff = 'no_trigger'; $triggercmdon = 'no_trigger'; $triggercmdoff = 'no_trigger'; } my $set = "noset"; my $eventcopy = ""; # notify für eigenes device my $devcopyname = $devName; $own_hash->{helper}{eventfrom} = $devName; my @eventscopy; if ( defined( $own_hash->{helper}{testevent_event} ) ) { @eventscopy = "$own_hash->{helper}{testevent_event}"; } else { @eventscopy = ( @{$events} ); } my $triggerlog = ReadingsVal( $ownName, 'Trigger_log', 'off' ); if ( $incommingdevice eq $triggerdevice || $triggerdevice eq "all_events" ) { # teste auf triggertreffer oder GLOBAL trigger my $activecount = 0; my $anzahl; EVENT: foreach my $event (@eventscopy) { MSwitch_LOG( $ownName, 5, "$ownName: event -> $event " ); if( $event =~ m/(.*)(\{.*\})(.*)/ ) { MSwitch_LOG( $ownName, 5, "$ownName: changedevent1 -> $1 " ); MSwitch_LOG( $ownName, 5, "$ownName: changedevent2 -> $2 " ); MSwitch_LOG( $ownName, 5, "$ownName: changedevent3 -> $3 " ); my $p1 = $1; my $json = $2; my $p3 = $3; $json =~ s/:/[dp]/g; $json =~ s/\"/[dst]/g; $event = $p1.$json.$p3; MSwitch_LOG( $ownName, 5, "$ownName: changedevent -> $event " ); #next EVENT; } $own_hash->{eventsave} = 'unsaved'; MSwitch_LOG( $ownName, 5, "$ownName: eingehendes Event -> " . $incommingdevice . " " . $event ); # durchlauf für jedes ankommende event # $event = "" if ( !defined($event) ); $eventcopy = $event; $eventcopy =~ s/: /:/s; # BUG !!!!!!!!!!!!!!!!!!!!!!!! $event =~ s/: /:/s; # Teste auf einhaltung Triggercondition für ausführung zweig 1 und zweig 2 # kann ggf an den anfang der routine gesetzt werden ? test erforderlich my $triggercondition = ReadingsVal( $ownName, '.Trigger_condition', '' ); $triggercondition =~ s/#\[dp\]/:/g; $triggercondition =~ s/#\[pt\]/./g; $triggercondition =~ s/#\[ti\]/~/g; $triggercondition =~ s/#\[sp\]/ /g; if ( $triggercondition ne '' ) { MSwitch_LOG( $ownName, 6, "$ownName: teste Triggercondition -> " . $triggercondition ); my $ret = MSwitch_checkcondition( $triggercondition, $ownName, $eventcopy ); MSwitch_LOG( $ownName, 6, "$ownName: ergebniss Triggercondition -> " . $ret ); if ( $ret eq 'false' ) { MSwitch_LOG( $ownName, 6, "$ownName: ergebniss Triggercondition false-> abbruch" ); MSwitch_LOG( $ownName, 6, "-----------------" ); next EVENT; } } # wird nur ausgefüht wenn ankommende events gelogd werden 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 $eventcopy1 = "$devName:$eventcopy"; } my @filters = split( /,/, $devicefilter ) ; # beinhaltet filter durch komma getrennt MSwitch_LOG( $ownName, 5, "$ownName: Filtertest Event -> " . $eventcopy ); foreach my $filter (@filters) { if ( $filter eq "*" ) { $filter = ".*"; } MSwitch_LOG( $ownName, 5, "$ownName: eingehendes Event teste Filter -> " . $filter ); if ( $eventcopy1 =~ m/$filter/ ) { MSwitch_LOG( $ownName, 6, "$ownName: eingehendes Event durch MSwitch_Trigger_Filter ausgefiltert: " . $eventcopy1 ); next EVENT; } } } if ( $triggerlog eq 'on' ) { if ( $triggerdevice eq "all_events" ) { $own_hash->{helper}{events}{'all_events'} { $devName . ':' . $eventcopy } = "on"; } else { $own_hash->{helper}{events}{$devName}{$eventcopy} = "on"; } } ############################################################################################################ #anzahl checken / ggf nicht mehr nötig #check checken / ggf nicht mehr nötig if ( $event ne '' ) { my $eventcopy1 = $eventcopy; if ( $triggerdevice eq "all_events" ) { # fügt dem event den devicenamen hinzu , wenn global getriggert wird $eventcopy1 = "$devName:$eventcopy"; } MSwitch_LOG( $ownName, 5, "rufe eventbulk auf" ); MSwitch_EventBulk( $own_hash, $eventcopy1, '0', 'MSwitch_Notify' ); } # Teste auf einhaltung Triggercondition ENDE ############################################################################################################ my $eventcopy1 = $eventcopy; if ( $triggerdevice eq "all_events" ) { # fügt dem event den devicenamen hinzu , wenn global getriggert wird $eventcopy1 = "$devName:$eventcopy"; } my $direktswitch = 0; my @eventsplit = split( /\:/, $eventcopy ); my $eventstellen = @eventsplit; my $testvar = ''; my $check = 0; #test auf zweige cmd1/2 and switch MSwitch on/off if ( $triggeron ne 'no_trigger' ) { MSwitch_LOG( $ownName, 6, "$ownName: checktrigger trigger cmd1 -> " ); $testvar = MSwitch_checktrigger( $own_hash, $ownName, $eventstellen, $triggeron, $incommingdevice, 'on', $eventcopy, @eventsplit ); if ( $testvar ne 'undef' ) { $set = $testvar; $check = 1; $foundcmd1 = 1; $trigevent = $eventcopy; #readingsSingleUpdate( $own_hash, "incomming", $eventcopy, 0 ); } MSwitch_LOG( $ownName, 6, "$ownName: checktrigger ergebniss -> " . $testvar ); } if ( $triggeroff ne 'no_trigger' ) { MSwitch_LOG( $ownName, 6, "$ownName: checktrigger trigger cmd2 -> " ); $testvar = MSwitch_checktrigger( $own_hash, $ownName, $eventstellen, $triggeroff, $incommingdevice, 'off', $eventcopy, @eventsplit ); if ( $testvar ne 'undef' ) { $set = $testvar; $check = 1; $foundcmd2 = 1; $trigevent = $eventcopy; #readingsSingleUpdate( $own_hash, "incomming", $eventcopy, 0 ); } MSwitch_LOG( $ownName, 6, "$ownName: checktrigger ergebniss -> " . $testvar ); } #test auf zweige cmd1/2 and switch MSwitch on/off ENDE #test auf zweige cmd1/2 only # ergebnisse werden in @cmdarray geschrieben if ( $triggercmdoff ne 'no_trigger' ) { MSwitch_LOG( $ownName, 6, "$ownName: checktrigger trigger cmd4 -> " ); $testvar = MSwitch_checktrigger( $own_hash, $ownName, $eventstellen, $triggercmdoff, $incommingdevice, 'offonly', $eventcopy, @eventsplit ); if ( $testvar ne 'undef' ) { push @cmdarray, $own_hash . ',off,check,' . $eventcopy1; $check = 1; $foundcmd2 = 1; } MSwitch_LOG( $ownName, 6, "$ownName: checktrigger ergebniss -> " . $testvar ); } if ( $triggercmdon ne 'no_trigger' ) { MSwitch_LOG( $ownName, 6, "$ownName: checktrigger trigger cmd4 -> " ); $testvar = MSwitch_checktrigger( $own_hash, $ownName, $eventstellen, $triggercmdon, $incommingdevice, 'ononly', $eventcopy, @eventsplit ); if ( $testvar ne 'undef' ) { push @cmdarray, $own_hash . ',on,check,' . $eventcopy1; $check = 1; $foundcmd1 = 1; } MSwitch_LOG( $ownName, 6, "$ownName: checktrigger ergebniss -> " . $testvar ); } #test auf zweige cmd1/2 only ENDE $anzahl = @cmdarray; MSwitch_LOG( $ownName, 6, "$ownName: anzahl gefundener Befehle -> " . $anzahl ); MSwitch_LOG( $ownName, 6, "$ownName: inhalt gefundener Befehle -> @cmdarray" ); $own_hash->{IncommingHandle} = 'fromnotify'; $event =~ s/~/ /g; #? if ( $devicemode eq "Notify" and $activecount == 0 ) { # reading activity aktualisieren readingsSingleUpdate( $own_hash, "state", 'active', $showevents ); $activecount = 1; } # abfrage und setzten von blocking # schalte blocking an , wenn anzahl grösser 0 und MSwitch_Wait gesetzt my $mswait = $attr{$ownName}{MSwitch_Wait}; if ( !defined $mswait ) { $mswait = '0'; } if ( $anzahl > 0 && $mswait > 0 ) { readingsSingleUpdate( $own_hash, "waiting", ( time + $mswait ), 0 ); } # abfrage und setzten von blocking ENDE if ( $devicemode eq "Toggle" && $set eq 'on' ) { # umschalten des devices nur im togglemode my $cmd = ''; my $statetest = ReadingsVal( $ownName, 'state', 'on' ); $cmd = "set $ownName off" if $statetest eq 'on'; $cmd = "set $ownName on" if $statetest eq 'off'; MSwitch_LOG( $ownName, 6, "$ownName: togglemode execute -> " . $cmd ); if ( $debugmode ne '2' ) { my $errors = AnalyzeCommandChain( undef, $cmd ); if ( defined($errors) ) { MSwitch_LOG( $ownName, 1, "$ownName MSwitch_Notify: Fehler bei Befehlsausführung $errors -> Comand: $_ " . __LINE__ ); } } return; } } #foundcmd1/2 if ( $foundcmd1 eq "1" && AttrVal( $ownName, "MSwitch_Reset_EVT_CMD1_COUNT", 'undef' ) ne 'undef' ) { my $inhalt = ReadingsVal( $ownName, 'EVT_CMD1_COUNT', '0' ); if ( $resetcmd1 == 0 ) { $inhalt++; readingsSingleUpdate( $own_hash, "EVT_CMD1_COUNT", $inhalt, $showevents ); } elsif ( $resetcmd1 > 0 && $inhalt < $resetcmd1 ) { $inhalt++; readingsSingleUpdate( $own_hash, "EVT_CMD1_COUNT", $inhalt, $showevents ); } } if ( $foundcmd2 eq "1" && AttrVal( $ownName, "MSwitch_Reset_EVT_CMD2_COUNT", 'undef' ) ne 'undef' ) { my $inhalt = ReadingsVal( $ownName, 'EVT_CMD2_COUNT', '0' ); if ( $resetcmd2 == 0 ) { $inhalt++; readingsSingleUpdate( $own_hash, "EVT_CMD2_COUNT", $inhalt, $showevents ); } elsif ( $resetcmd2 > 0 && $inhalt < $resetcmd2 ) { $inhalt++; readingsSingleUpdate( $own_hash, "EVT_CMD2_COUNT", $inhalt, $showevents ); } } #ausführen aller cmds in @cmdarray nach triggertest aber vor conditiontest #my @cmdarray1; #enthält auszuführende befehle nach conditiontest #schaltet zweig 3 und 4 # ACHTUNG if ( $anzahl && $anzahl != 0 ) { MSwitch_LOG( $ownName, 6, "$ownName: abarbeiten aller befehle aus eventprüfung " ); #aberabeite aller befehlssätze in cmdarray MSwitch_Safemode($own_hash); LOOP31: foreach (@cmdarray) { MSwitch_LOG( $ownName, 6, "$ownName: Befehl -> " . $_ ); if ( $_ eq 'undef' ) { next LOOP31; } my ( $ar1, $ar2, $ar3, $ar4 ) = split( /,/, $_ ); if ( !defined $ar2 ) { $ar2 = ''; } if ( $ar2 eq '' ) { next LOOP31; } my $returncmd = 'undef'; $returncmd = MSwitch_Exec_Notif( $own_hash, $ar2, $ar3, $ar4, $execids ); if ( defined $returncmd && $returncmd ne 'undef' ) { # datensatz nur in cmdarray1 übernehme wenn chop $returncmd; #CHANGE MSwitch_LOG( $ownName, 5, "$ownName: ergebniss execnotif datensatz to array -> " . $returncmd ); push( @cmdarray1, $returncmd ); } } my $befehlssatz = join( ',', @cmdarray1 ); foreach ( split( /,/, $befehlssatz ) ) { my $ecec = $_; if ( !$ecec =~ m/set (.*)(MSwitchtoggle)(.*)/ ) { if ( $attrrandomnumber ne '' ) { MSwitch_Createnumber($own_hash); } MSwitch_LOG( $ownName, 6, "$ownName: Befehlsausfuehrung -> " . $ecec ); if ( $debugmode ne '2' ) { my $errors = AnalyzeCommandChain( undef, $_ ); if ( defined($errors) ) { MSwitch_LOG( $ownName, 1, "$ownName MSwitch_Notify: Fehler bei Befehlsausführung $errors -> Comand: $_ " . __LINE__ ); } } if ( length($ecec) > 100 ) { $ecec = substr( $ecec, 0, 100 ) . '....'; } readingsSingleUpdate( $own_hash, "last_exec_cmd", $ecec, $showevents ) if $ecec ne ''; } else { } } } # ende loopeinzeleventtest # schreibe gruppe mit events my $events = ''; my $eventhash = $own_hash->{helper}{events}{$devName}; if ( $triggerdevice eq "all_events" ) { $eventhash = $own_hash->{helper}{events}{all_events}; } else { $eventhash = $own_hash->{helper}{events}{$devName}; } foreach my $name ( keys %{$eventhash} ) { $events = $events . $name . '#[tr]'; } chop($events); chop($events); chop($events); chop($events); chop($events); if ( $events ne "" ) { readingsSingleUpdate( $own_hash, ".Device_Events", $events, 1 ); } # schreiben ende # schalte modul an/aus bei entsprechendem notify # teste auf condition return if $set eq 'noset'; # keine MSwitch on/off incl cmd1/2 gefunden ############################################################################################################### # schaltet zweig 1 und 2 , wenn $set befehl enthält , es wird nur MSwitch geschaltet, Devices werden dann 'mitgerissen' my $cs; if ( $triggerdevice eq "all_events" ) { $cs = "set $ownName $set $devName:$trigevent"; } else { $cs = "set $ownName $set $trigevent"; } MSwitch_LOG( $ownName, 6, "$ownName MSwitch_Notif: Befehlsausfuehrung -> $cs " . __LINE__ ); # variabelersetzung $cs =~ s/\$NAME/$own_hash->{helper}{eventfrom}/; $cs =~ s/\$SELF/$ownName/; if ( $attrrandomnumber ne '' ) { MSwitch_Createnumber($own_hash); } MSwitch_LOG( $ownName, 6, "$ownName: Befehlsausführung -> " . $cs ); if ( $debugmode ne '2' ) { my $errors = AnalyzeCommandChain( undef, $cs ); } return; } } ######################### sub MSwitch_fhemwebFn($$$$) { # my $loglevel = 5; my ( $FW_wname, $d, $room, $pageHash ) = @_; # pageHash is set for summaryFn. my $hash = $defs{$d}; my $Name = $hash->{NAME}; 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; } #versetzen nach ATTR if ( AttrVal( $Name, 'MSwitch_RandomNumber', '' ) eq '' ) { delete( $hash->{READINGS}{RandomNr} ); delete( $hash->{READINGS}{RandomNr1} ); } #################### ### teste auf new defined device my $hidden = ''; if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '4' ) { $hidden = ''; } else { $hidden = 'hidden'; } my $triggerdevices = ''; my $events = ReadingsVal( $Name, '.Device_Events', '' ); my @eventsall = split( /#\[tr\]/, $events ); my $Triggerdevice = ReadingsVal( $Name, 'Trigger_device', '' ); my $triggeron = ReadingsVal( $Name, '.Trigger_on', '' ); if ( !defined $triggeron ) { $triggeron = "" } my $triggeroff = ReadingsVal( $Name, '.Trigger_off', '' ); if ( !defined $triggeroff ) { $triggeroff = "" } my $triggercmdon = ReadingsVal( $Name, '.Trigger_cmd_on', '' ); if ( !defined $triggercmdon ) { $triggercmdon = "" } my $triggercmdoff = ReadingsVal( $Name, '.Trigger_cmd_off', '' ); if ( !defined $triggercmdoff ) { $triggercmdoff = "" } my $disable = ""; my %korrekt; foreach (@eventsall) { $korrekt{$_} = 'ok'; } $korrekt{$triggeron} = 'ok'; $korrekt{$triggeroff} = 'ok'; $korrekt{$triggercmdon} = 'ok'; $korrekt{$triggercmdoff} = 'ok'; my @eventsallnew; for my $name ( sort keys %korrekt ) { push( @eventsallnew, $name ); } @eventsall = @eventsallnew; if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Notify" ) { readingsSingleUpdate( $hash, "state", 'active', 1 ); $triggeroff = ""; $triggeron = ""; } if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Toggle" ) { $triggeroff = ""; $triggercmdoff = ""; $triggercmdon = ""; } #eigene trigger festlegen my $optionon = ''; my $optiongeneral = ''; my $optioncmdon = ''; my $alltriggers = ''; my $to = ''; my $toc = ''; LOOP12: foreach (@eventsall) { $alltriggers = $alltriggers . ""; if ( $_ eq 'no_trigger' ) { next LOOP12; } if ( $triggeron eq $_ ) { $optionon = $optionon . ""; $to = '1'; } else { $optionon = $optionon . ""; } if ( $triggercmdon eq $_ ) { $optioncmdon = $optioncmdon . ""; $toc = '1'; } else { $optioncmdon = $optioncmdon . ""; } #################### nur bei entsprechender regex my $test = $_; if ( $test =~ m/(.*)\((.*)\)(.*)/ ) { } else { if ( index( $_, '*', 0 ) == -1 ) { if ( ReadingsVal( $Name, 'Trigger_device', '' ) ne "all_events" ) { $optiongeneral = $optiongeneral . ""; } else { $optiongeneral = $optiongeneral . ""; } } } ##################### } if ( $to eq '1' ) { $optionon = "" . $optionon; } else { $optionon = "" . $optionon; } if ( $toc eq '1' ) { $optioncmdon = "" . $optioncmdon; } else { $optioncmdon = "" . $optioncmdon; } my $optioncmdoff = ''; my $optionoff = ''; $to = ''; $toc = ''; LOOP14: foreach (@eventsall) { if ( $_ eq 'no_trigger' ) { next LOOP14 } if ( $triggeroff eq $_ ) { $optionoff = $optionoff . ""; $to = '1'; } else { $optionoff = $optionoff . ""; } if ( $triggercmdoff eq $_ ) { $optioncmdoff = $optioncmdoff . ""; $toc = '1'; } else { $optioncmdoff = $optioncmdoff . ""; } } if ( $to eq '1' ) { $optionoff = "" . $optionoff; } else { $optionoff = "" . $optionoff; } if ( $toc eq '1' ) { $optioncmdoff = "" . $optioncmdoff; } else { $optioncmdoff = "" . $optioncmdoff; } $optionon =~ s/\[bs\]/|/g; $optionoff =~ s/\[bs\]/|/g; $optioncmdon =~ s/\[bs\]/|/g; $optioncmdoff =~ s/\[bs\]/|/g; #################### # mögliche affected devices und mögliche triggerdevices my $devicesets; my $deviceoption = ""; my $selected = ""; my $errors = ""; my $javaform = ""; # erhält javacode für übergabe devicedetail my $cs = ""; my %cmdsatz; # ablage desbefehlssatzes jedes devices my $globalon = 'off'; my $globalon1 = 'off'; if ( ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ) eq 'no_trigger' ) { $triggerdevices = ""; } else { $triggerdevices = ""; } if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' ) { if ( ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ) eq 'all_events' ) { $triggerdevices .= ""; $globalon = 'on'; } else { $triggerdevices .= ""; } } if ( AttrVal( $Name, 'MSwitch_Read_Log', "0" ) eq '1' ) { if ( ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ) eq 'Logfile' ) { $triggerdevices .= ""; #$globalon = 'on'; } else { $triggerdevices .= ""; } } 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 my %usedevices; my @deftoarray = split( /,/, $affecteddevices ); my $anzahl = @deftoarray; my $anzahl1 = @deftoarray; my $anzahl3 = @deftoarray; my @testidsdev = split( /#\[ND\]/, ReadingsVal( $Name, '.Device_Affected_Details', 'no_device' ) ); #PRIORITY # teste auf grössere PRIORITY als anzahl devices foreach (@testidsdev) { MSwitch_LOG( $Name, 5, "dev @testidsdev" ); my @testid = split( /#\[NF\]/, $_ ); my $x = 0; MSwitch_LOG( $Name, 5, "devfelder @testid" ); my $id = $testid[13]; MSwitch_LOG( $Name, 5, "id $id" ); $anzahl = $id if $id > $anzahl; } ################################# my $reihenfolgehtml = ""; if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' ) { $reihenfolgehtml = ""; } ######################################### # SHOW # teste auf grössere PRIORITY als anzahl devices foreach (@testidsdev) #if (1 == 2) { MSwitch_LOG( $Name, 5, "dev @testidsdev" ); my @testid = split( /#\[NF\]/, $_ ); my $x = 0; MSwitch_LOG( $Name, 5, "devfelder @testid" ); my $id = $testid[18]; MSwitch_LOG( $Name, 5, "id $id" ); $anzahl1 = $id if $id > $anzahl; } ################################# my $showfolgehtml = ""; $showfolgehtml = ""; ###################################### #ID my $idfolgehtml = ""; if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' ) { $idfolgehtml = ""; } foreach (@deftoarray) { my ( $a, $b ) = split( /-/, $_ ); $usedevices{$a} = 'on'; } 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 = AttrVal( $name, 'webCmd', "noArg" ); # webcmd des devices my $devicehash = $defs{$name}; #devicehash my $deviceTYPE = $devicehash->{TYPE}; # triggerfile erzeugen if ( ReadingsVal( $Name, 'Trigger_device', '' ) eq $name ) { $selectedtrigger = 'selected=\"selected\"'; if ( $name eq 'all_events' ) { $globalon = 'on' } } $triggerdevices .= ""; # filter auf argumente on oder off ; if ( $name eq '' ) { next LOOP9; } my $cs = "set $name ?"; # abfrage und auswertung befehlssatz if ( AttrVal( $Name, 'MSwitch_Include_Devicecmds', "1" ) eq '1' ) { $errors = AnalyzeCommandChain( undef, $cs ); if ($errors) { } } else { $errors = ''; } if ( !defined $errors ) { $errors = '' } my @tmparg = split( /of /, $errors ); if ( !defined $tmparg[1] ) { $tmparg[1] = "" } if ( $tmparg[1] ne '' ) { $errors = $tmparg[1]; } else { $errors = ''; } $errors = '|' . $errors; $errors =~ s/\| //g; $errors =~ s/\|//g; if ( $errors eq '' && AttrVal( $Name, 'MSwitch_Include_Webcmds', "1" ) eq '1' ) { if ( $devicewebcmd ne "noArg" ) { my $device = ''; my @webcmd = split( /:/, $devicewebcmd ); foreach (@webcmd) { $_ =~ tr/ /:/; my @parts = split( /:/, $_ ); if ( !defined $parts[1] || $parts[1] eq '' ) { $device .= $parts[0] . ':noArg '; } else { $device .= $parts[0] . ':' . $parts[1] . ' '; } } chop $device; $devicewebcmd = $device; $errors = $devicewebcmd; } } my $usercmds = AttrVal( $name, 'MSwitchcmd', '' ); if ( $usercmds ne '' && AttrVal( $Name, 'MSwitch_Include_MSwitchcmds', "1" ) eq '1' ) { $usercmds =~ tr/:/ /; $errors .= ' ' . $usercmds; } my $extensions = AttrVal( $Name, 'MSwitch_Extensions', "0" ); if ( $extensions eq '1' ) { $errors .= ' ' . 'MSwitchtoggle'; } if ( $errors ne '' ) { $selected = ""; if ( exists $usedevices{$name} && $usedevices{$name} eq 'on' ) { $selected = "selected=\"selected\" "; } $deviceoption = $deviceoption . ""; # befehlssatz für device in scalar speichern $cmdsatz{$name} = $errors; } else { } } my $select = index( $affecteddevices, 'FreeCmd', 0 ); $selected = ""; if ( $select > -1 ) { $selected = "selected=\"selected\" " } $deviceoption = "" . $deviceoption; $select = index( $affecteddevices, 'MSwitch_Self', 0 ); $selected = ""; if ( $select > -1 ) { $selected = "selected=\"selected\" " } $deviceoption = "" . $deviceoption; #################### # #devices details # detailsatz in scalar laden # my @devicedatails = split(/:/,ReadingsVal($Name, '.Device_Affected_Details', '')); #inhalt decice und cmds # durch komma getrennt my %savedetails = MSwitch_makeCmdHash($Name); my $detailhtml = ""; my @affecteddevices = split( /,/, ReadingsVal( $Name, '.Device_Affected', 'no_device' ) ); ##################################### MSwitch_LOG( $Name, 5, "$Name: -> @affecteddevices" ); if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' && ReadingsVal( $Name, '.sortby', 'none' ) eq 'priority' ) { #sortieren my $typ = "_priority"; @affecteddevices = MSwitch_sort( $hash, $typ, @affecteddevices ); } if ( ReadingsVal( $Name, '.sortby', 'none' ) eq 'show' ) { #sortieren my $typ = "_showreihe"; @affecteddevices = MSwitch_sort( $hash, $typ, @affecteddevices ); } MSwitch_LOG( $Name, 5, "$Name: -> @affecteddevices" ); ###################################### if ( $affecteddevices[0] ne 'no_device' ) { $detailhtml = ""; #start my $alert; foreach (@affecteddevices) { $alert = ''; my @devicesplit = split( /-AbsCmd/, $_ ); my $devicenamet = $devicesplit[0]; # prüfe auf nicht vorhandenes device if ( $devicenamet ne "FreeCmd" && $devicenamet ne "MSwitch_Self" && !defined $cmdsatz{$devicenamet} ) { $alert = '
Achtung: Dieses Device ist nicht vorhanden , bitte mit "set changed_renamed" korrigieren !
'; $cmdsatz{$devicenamet} = $savedetails{ $_ . '_on' } . " " . $savedetails{ $_ . '_off' }; } my $zusatz = ""; my $add = $devicenamet; if ( $devicenamet eq "MSwitch_Self" ) { $devicenamet = $Name; $zusatz = "MSwitch_Self -> "; $add = "MSwitch_Self"; } my $devicenumber = $devicesplit[1]; my @befehlssatz = ''; if ( $devicenamet eq "FreeCmd" ) { $cmdsatz{$devicenamet} = ''; } @befehlssatz = split( / /, $cmdsatz{$devicenamet} ); my $aktdevice = $_; ## optionen erzeugen my $option1html = ''; my $option2html = ''; my $selectedhtml = ""; if ( !defined( $savedetails{ $aktdevice . '_on' } ) ) { my $key = ''; $key = $aktdevice . "_on"; $savedetails{$key} = 'no_action'; } if ( !defined( $savedetails{ $aktdevice . '_off' } ) ) { my $key = ''; $key = $aktdevice . "_off"; $savedetails{$key} = 'no_action'; } if ( !defined( $savedetails{ $aktdevice . '_onarg' } ) ) { my $key = ''; $key = $aktdevice . "_onarg"; $savedetails{$key} = ''; } if ( !defined( $savedetails{ $aktdevice . '_offarg' } ) ) { my $key = ''; $key = $aktdevice . "_offarg"; $savedetails{$key} = ''; } if ( !defined( $savedetails{ $aktdevice . '_delayaton' } ) ) { my $key = ''; $key = $aktdevice . "_delayaton"; $savedetails{$key} = 'delay1'; } if ( !defined( $savedetails{ $aktdevice . '_delayatoff' } ) ) { my $key = ''; $key = $aktdevice . "_delayatoff"; $savedetails{$key} = 'delay1'; } if ( !defined( $savedetails{ $aktdevice . '_timeon' } ) ) { my $key = ''; $key = $aktdevice . "_timeon"; #$savedetails{$key} = '000000'; #change $savedetails{$key} = '00:00:00'; } if ( !defined( $savedetails{ $aktdevice . '_timeoff' } ) ) { my $key = ''; $key = $aktdevice . "_timeoff"; #$savedetails{$key} = '000000'; #change $savedetails{$key} = '00:00:00'; } if ( !defined( $savedetails{ $aktdevice . '_conditionon' } ) ) { my $key = ''; $key = $aktdevice . "_conditionon"; $savedetails{$key} = ''; } if ( !defined( $savedetails{ $aktdevice . '_conditionoff' } ) ) { my $key = ''; $key = $aktdevice . "_conditionoff"; $savedetails{$key} = ''; } foreach (@befehlssatz) #befehlssatz einfügen { my @aktcmdset = split( /:/, $_ ); # befehl von noarg etc. trennen $selectedhtml = ""; next if !defined $aktcmdset[0]; #changed 19.06 if ( $aktcmdset[0] eq $savedetails{ $aktdevice . '_on' } ) { $selectedhtml = "selected=\"selected\""; } $option1html = $option1html . ""; $selectedhtml = ""; if ( $aktcmdset[0] eq $savedetails{ $aktdevice . '_off' } ) { $selectedhtml = "selected=\"selected\""; } $option2html = $option2html . ""; } if ( '' eq $savedetails{ $aktdevice . '_delayaton' } ) { $savedetails{ $aktdevice . '_delayaton' } = 'delay1'; } if ( '' eq $savedetails{ $aktdevice . '_delayatoff' } ) { $savedetails{ $aktdevice . '_delayatoff' } = 'delay1'; } if ( '' eq $savedetails{ $aktdevice . '_timeoff' } ) { $savedetails{ $aktdevice . '_timeoff' } = '0'; } if ( '' eq $savedetails{ $aktdevice . '_timeon' } ) { $savedetails{ $aktdevice . '_timeon' } = '0'; } $savedetails{ $aktdevice . '_onarg' } =~ s/#\[ti\]/~/g; $savedetails{ $aktdevice . '_offarg' } =~ s/#\[ti\]/~/g; $savedetails{ $aktdevice . '_onarg' } =~ s/#\[wa\]/|/g; #neu $savedetails{ $aktdevice . '_offarg' } =~ s/#\[wa\]/|/g; #neu my $dalias = ''; if ( $devicenamet ne "FreeCmd" ) { $dalias = "(a: " . AttrVal( $devicenamet, 'alias', "no" ) . ")" if AttrVal( $devicenamet, 'alias', "no" ) ne "no"; } my $realname = ''; if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '4' ) { $realname = ""; } else { $realname = ""; } if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; ###################### priority my $aktfolge = $reihenfolgehtml; my $newname = "reihe" . $_; my $tochange = ""; my $change = ""; $aktfolge =~ s/reihe/$newname/g; $aktfolge =~ s/$tochange/$change/g; $detailhtml = $detailhtml . ""; # ende } else { $detailhtml = $detailhtml . " "; my $aktfolge = $showfolgehtml; my $newname = "showreihe" . $_; my $tochange = ""; my $change = ""; $aktfolge =~ s/showreihe/$newname/g; $aktfolge =~ s/$tochange/$change/g; $detailhtml = $detailhtml . ""; my $noschow = "style=\"display:none\""; if ( AttrVal( $Name, 'MSwitch_Comments', "0" ) eq '1' ) { $noschow = ''; } $detailhtml = $detailhtml . ""; $detailhtml = $detailhtml . ""; my $rephide = "style='display:none;'"; my $rows = 7; if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' ) { $rephide = ''; $rows = 8; } $detailhtml = $detailhtml . ""; $detailhtml = $detailhtml . " "; # block off #$devicename if ( $devicenamet ne 'FreeCmd' ) { $detailhtml = $detailhtml . " "; $detailhtml = $detailhtml . " "; $detailhtml = $detailhtml . " "; $detailhtml = $detailhtml . ""; $detailhtml = $detailhtml . ""; $detailhtml = $detailhtml . ""; #middle ####################change1 = change.replace(/,/g,'##'); # javazeile für übergabe erzeugen $javaform = $javaform . " devices += \$(\"[name=devicename$_]\").val(); devices += '#[DN]'; devices += \$(\"[name=cmdon$_]\").val()+'#[NF]'; devices += \$(\"[name=cmdoff$_]\").val()+'#[NF]'; change = \$(\"[name=cmdonopt$_]\").val(); devices += change+'#[NF]';; change = \$(\"[name=cmdoffopt$_]\").val(); devices += change+'#[NF]';; devices += \$(\"[name=onatdelay$_]\").val(); devices += '#[NF]'; devices += \$(\"[name=offatdelay$_]\").val(); devices += '#[NF]'; delay1 = \$(\"[name=timesetoff$_]\").val(); devices += delay1+'#[NF]'; delay2 = \$(\"[name=timeseton$_]\").val(); devices += delay2+'#[NF]'; devices1 = \$(\"[name=conditionon$_]\").val(); devices1 = devices1.replace(/\\|/g,'(DAYS)'); devices2 = \$(\"[name=conditionoff$_]\").val(); devices2 = devices2.replace(/\\|/g,'(DAYS)'); devices += devices1+'#[NF]'; devices += devices2; devices += '#[NF]'; devices3 = \$(\"[name=repeatcount$_]\").val(); devices += devices3; devices += '#[NF]'; devices += \$(\"[name=repeattime$_]\").val(); devices += '#[NF]'; devices += \$(\"[name=reihe$_]\").val(); devices += '#[NF]'; devices += \$(\"[name=idreihe$_]\").val(); devices += '#[NF]'; devices += \$(\"[name=cmdcomment$_]\").val(); devices += '#[NF]'; devices += \$(\"[name=exit1$_]\").prop(\"checked\") ? \"1\":\"0\"; devices += '#[NF]'; devices += \$(\"[name=exit2$_]\").prop(\"checked\") ? \"1\":\"0\"; devices += '#[NF]'; devices += \$(\"[name=showreihe$_]\").val(); devices += '#[DN]'; "; } #################### $detailhtml = $detailhtml; $detailhtml = $detailhtml . "
device actions sortby: "; my $select = ReadingsVal( $Name, '.sortby', 'none' ); if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) ne '1' && $select eq 'priority' ) { $select = 'none'; readingsSingleUpdate( $hash, ".sortby", $select, 0 ); } my $nonef = ""; #my $namef =""; my $priorityf = ""; my $showf = ""; $nonef = 'selected="selected"' if $select eq 'none'; $priorityf = 'selected="selected"' if $select eq 'priority'; $showf = 'selected="selected"' if $select eq 'show'; $detailhtml .= '
"; $detailhtml = $detailhtml . "$zusatz $devicenamet $realname   $dalias $alert "; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . "priority: " . $aktfolge . " "; # ende # show # showfolgehtml $aktfolge = $showfolgehtml; $newname = "showreihe" . $_; $tochange = ""; $change = ""; $aktfolge =~ s/showreihe/$newname/g; $aktfolge =~ s/$tochange/$change/g; $detailhtml = $detailhtml . "show: " . $aktfolge . " "; # ID $aktfolge = $idfolgehtml; $newname = "idreihe" . $_; $tochange = ""; $change = ""; $aktfolge =~ s/idreihe/$newname/g; $aktfolge =~ s/$tochange/$change/g; $detailhtml = $detailhtml . "ID: " . $aktfolge; $detailhtml = $detailhtml . "
"; $detailhtml = $detailhtml . "$zusatz $devicenamet $realname   $dalias $alert "; $detailhtml = $detailhtml . "show: " . $aktfolge . " "; } $detailhtml = $detailhtml . "
              "; if ( $devicenamet ne 'FreeCmd' ) { $detailhtml = $detailhtml . "

"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . "MSwitch 'cmd1': Set
 
 
   "; } else { $savedetails{ $aktdevice . '_onarg' } =~ s/'/'/g; $detailhtml = $detailhtml . "
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . "MSwitch 'cmd1':
 
"; } $detailhtml = $detailhtml . "
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . "MSwitch 'cmd2': Set  
   "; } else { $savedetails{ $aktdevice . '_offarg' } =~ s/'/'/g; $detailhtml = $detailhtml . "
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . "MSwitch 'cmd2':
"; } $detailhtml = $detailhtml . "
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . "'cmd1' condition:    "; my $exit1 = ''; $exit1 = 'checked' if $savedetails{ $aktdevice . '_exit1' } eq '1'; if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' ) { if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . " execute and exit if applies"; } else { $detailhtml = $detailhtml . " "; } if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '1' ) { $detailhtml = $detailhtml . " with \$EVENT="; } #alltriggers $detailhtml = $detailhtml . "
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . "'cmd2' condition:    "; my $exit2 = ''; $exit2 = 'checked' if $savedetails{ $aktdevice . '_exit2' } eq '1'; if ( AttrVal( $Name, 'MSwitch_Expert', "0" ) eq '1' ) { if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . " execute and exit if applies"; } else { $detailhtml = $detailhtml . " "; } if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '1' ) { $detailhtml = $detailhtml . " with \$EVENT="; } #### zeitrechner my $delaym = 0; my $delays = 0; my $delayh = 0; my $timestroff; my $testtimestroff = $savedetails{ $aktdevice . '_timeoff' }; if ( $testtimestroff ne '[random]' ) { $testtimestroff =~ s/[A-Za-z0-9#\.\-_]//g; if ( $testtimestroff eq "[:]" || $testtimestroff eq "[\$:]" ) { $timestroff = $savedetails{ $aktdevice . '_timeoff' }; #sekunden } else { $timestroff = $savedetails{ $aktdevice . '_timeoff' }; #sekunden $delaym = int $timestroff / 60; $delays = $timestroff - ( $delaym * 60 ); $delayh = int $delaym / 60; $delaym = $delaym - ( $delayh * 60 ); $timestroff = sprintf( "%02d:%02d:%02d", $delayh, $delaym, $delays ); } } else { $timestroff = "[random]"; } my $timestron; my $testtimestron = $savedetails{ $aktdevice . '_timeon' }; if ( $testtimestron ne '[random]' ) { $testtimestron =~ s/[A-Za-z0-9#\.\-_]//g; if ( $testtimestron eq "[:]" || $testtimestron eq "[\$:]" ) { $timestron = $savedetails{ $aktdevice . '_timeon' }; #sekunden } else { $timestron = $savedetails{ $aktdevice . '_timeon' }; #sekunden $delaym = int $timestron / 60; $delays = $timestron - ( $delaym * 60 ); $delayh = int $delaym / 60; $delaym = $delaym - ( $delayh * 60 ); $timestron = sprintf( "%02d:%02d:%02d", $delayh, $delaym, $delays ); } } else { $timestron = "[random]"; } $detailhtml = $detailhtml . "
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . "'cmd1'  (hh:mm:ss)
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . "'cmd2'  (hh:mm:ss)   "; $detailhtml = $detailhtml . "
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $detailhtml = $detailhtml . " "; } $detailhtml = $detailhtml . "Repeats:     Repeatdelay in sec:

"; if ( $devicenumber == 1 ) { $detailhtml = $detailhtml . ""; } $detailhtml = $detailhtml . ""; $detailhtml = $detailhtml . "
 
"; #end } #################### my $triggercondition = ReadingsVal( $Name, '.Trigger_condition', '' ); $triggercondition =~ s/~/ /g; $triggercondition =~ s/#\[dp\]/:/g; $triggercondition =~ s/#\[pt\]/./g; $triggercondition =~ s/#\[ti\]/~/g; $triggercondition =~ s/#\[sp\]/ /g; my $triggertime = ReadingsVal( $Name, '.Trigger_time', '' ); $triggertime =~ s/#\[dp\]/:/g; my @triggertimes = split( /~/, $triggertime ); my $condition = ReadingsVal( $Name, '.Trigger_time', '' ); my $lenght = length($condition); my $timeon = ''; 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 = ''; $ret .= "

"; ######################## my $blocking = ''; $blocking = $hash->{helper}{savemodeblock}{blocking} if ( defined $hash->{helper}{savemodeblock}{blocking} ); if ( $blocking eq 'on' ) { $ret .= "
 
ACHTUNG: Der Safemodus hat eine Endlosschleife erkannt, welche zum Fhemabsturz führen könnte.
Dieses Device wurde automatisch deaktiviert ( ATTR 'disable') !
 

 
"; } my $errortest = ""; $errortest = $hash->{helper}{error} if ( defined $hash->{helper}{error} ); if ( $errortest ne "" ) { $ret .= "
 
AT-Kommandos können nicht ausgeführt werden !
" . $errortest . "
 

 
"; } if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '2' || AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '3' ) { my $Zeilen = (""); open( BACKUPDATEI, "./log/MSwitch_debug_$Name.log" ); while () { $Zeilen = $Zeilen . $_; } close(BACKUPDATEI); my $text = ""; $text = "Das Device befindet sich im Debug 2 Mode. Es werden keine Befehle ausgeführt, sondern nur protokolliert." if AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '2'; $text = "Das Device befindet sich im Debug 3 Mode. Alle Aktionen werden protokolliert." if AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '3'; $ret .= "
 
$text
 

 

 


"; } if ( ReadingsVal( $Name, '.info', 'undef' ) ne "undef" ) { $ret .= "

 "; $ret .= ReadingsVal( $Name, '.info', '' ); $ret .= "
 


"; } # anpassung durch configeinspielung if ( ReadingsVal( $Name, '.change', 'undef' ) ne "undef" ) { # geräteliste my $dev; for my $name ( sort keys %defs ) { my $devicealias = AttrVal( $name, 'alias', "" ); my $devicewebcmd = AttrVal( $name, 'webCmd', "noArg" ); my $devicehash = $defs{$name}; my $deviceTYPE = $devicehash->{TYPE}; $dev .= ""; } my $sel = ""; my @change = split( "\\|", ReadingsVal( $Name, '.change', 'undef' ) ); my $out = ''; my $count = 0; foreach my $changes (@change) { my @set = split( "#", $changes ); $out .= ""; $out .= ""; $out .= $set[1]; $out .= ""; $out .= ""; $out .= ""; $out .= ""; $out .= " ersetzen durch:"; if ( $set[2] eq "device" ) { my $newstring = $sel; my $newname = "cdnew" . $count; $newstring =~ s/CID/$newname/g; $out .= $newstring; } else { $out .= " "; } $out .= ""; $out .= ""; $count++; } $ret .= " " . $out . "
 
Eingriff erforderlich !
 "; $ret .= ReadingsVal( $Name, '.change_info', '' ); $ret .= "
 

 


"; $j1 = ""; return "$ret" . "$j1"; } if ( ReadingsVal( $Name, '.wrong_version', 'undef' ) ne "undef" ) { $ret .= "
 
Einspielen des Configfiles nicht möglich !
falsche Versionsnummer: " . ReadingsVal( $Name, '.wrong_version', '' ) . "
geforderte Versionsnummer $vupdate
 


"; fhem("deletereading $Name .wrong_version"); } if ( ReadingsVal( $Name, '.V_Check', $vupdate ) ne $vupdate ) { my $ver = ReadingsVal( $Name, '.V_Check', '' ); $ret .= "
 
Versionskonflikt erkannt!
Das Device führt derzeit keine Aktionen aus. Bitte ein Update des Devices vornehmen.
Erwartete Strukturversionsnummer: $vupdate
Vorhandene Strukturversionsnummer: $ver
 

 


"; $j1 = ""; return "$ret" . "$j1"; } $ret .= "
 
Device is disabled, configuration avaible
 

" if ( IsDisabled($Name) ); #################### $ret .= ""; $ret .= " "; $ret .= ""; my $visible = 'visible'; if ( $globalon ne 'on' ) { $visible = 'collapse'; } my $visible1 = 'visible'; if ( $globalon1 ne 'on' ) { $visible1 = 'collapse'; } $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 :"; my $inhalt5 = "switch $Name on + execute 'cmd1'"; my $displaynot = ''; my $displayntog = ''; my $help = ""; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $help = " "; } if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Notify" ) { $displaynot = "style='display:none;'"; $inhalt = "execute 'cmd1' at :"; $inhalt1 = "execute 'cmd2' at :"; $inhalt2 = $help . "execute 'cmd1'"; $inhalt3 = $help . "execute 'cmd2'"; } if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Toggle" ) { $displayntog = "style='display:none;'"; $inhalt4 = "toggle $Name + execute 'cmd1/cmd2' at :"; $inhalt5 = "toggle $Name + execute 'cmd1/cmd2'"; } $ret = $ret . " "; my $triggerinhalt = "Trigger condition (events only): "; if ( AttrVal( $Name, 'MSwitch_Condition_Time', "0" ) eq '1' ) { $triggerinhalt = "Trigger condition (time&events): "; } $ret = $ret . ""; $ret = $ret . "
trigger device/time:   "; $ret = $ret . "
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $ret = $ret . " "; } $ret .= "Trigger device:
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $ret = $ret . " "; } $ret = $ret . "Trigger Device Global Whitelist: "; $ret = $ret . "
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $ret = $ret . " "; } $ret = $ret . "Trigger time:
" . $inhalt4 . "
switch MSwitch off + execute 'cmd2' at :
" . $inhalt . "
" . $inhalt1 . "
" . $inhalt6 . "
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $ret = $ret .= " "; } $ret = $ret . $triggerinhalt . " "; if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '1' ) { $ret = $ret . " "; } $ret = $ret . "

"; #################### # triggerdetails my $selectedcheck3 = ""; my $SELF = $Name; my $testlog = ReadingsVal( $Name, 'Trigger_log', 'on' ); if ( $testlog eq 'on' ) { $selectedcheck3 = "checked=\"checked\""; } if ( ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ) ne 'no_trigger' ) { $ret .= ""; $ret .= ""; $ret .= "
trigger details :
"; $ret .= $inhalt5 . ""; $ret .= "Trigger " . $Triggerdevice . " : "; $ret .= ""; ############## my $fieldon = ""; if ( $triggeron =~ m/{(.*)}/ ) { my $exec = "\$fieldon = " . $1; eval($exec); $ret .= ""; } ##################### $ret .= "
switch " . $Name . " off + execute 'cmd2' Trigger " . $Triggerdevice . " : "; $ret .= ""; ############## my $fieldoff = ""; if ( $triggeroff =~ m/{(.*)}/ ) { my $exec = "\$fieldoff = " . $1; eval($exec); $ret .= ""; } ##################### $ret .= "
 
" . $inhalt2 . " Trigger " . $Triggerdevice . " : "; ############## my $fieldcmdon = ""; if ( $triggercmdon =~ m/{(.*)}/ ) { my $exec = "\$fieldcmdon = " . $1; eval($exec); $ret .= ""; } ##################### $ret .= "
" . $inhalt3 . " Trigger " . $Triggerdevice . " : "; ############## my $fieldcmdoff = ""; if ( $triggercmdoff =~ m/{(.*)}/ ) { my $exec = "\$fieldcmdoff = " . $1; eval($exec); $ret .= ""; } ##################### $ret .= "
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $ret = $ret . " "; } $ret = $ret . "Save incomming events :
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $ret = $ret . " "; } $ret .= "Add event manually : "; $ret .= "
    "; if ( AttrVal( $Name, 'MSwitch_Debug', "0" ) eq '1' && $optiongeneral ne '' ) { $ret .= ""; } $ret .= "

"; } else { $ret .= "

"; } # affected devices $ret .= "
affected devices :
"; if ( AttrVal( $Name, 'MSwitch_Help', "0" ) eq '1' ) { $ret .= " "; } $ret .= "multiple selection with ctrl + mousebutton


quickedit locked

   
"; #################### #javascript$jsvarset my $triggerdevicehtml = $Triggerdevice; $triggerdevicehtml =~ s/\(//g; $triggerdevicehtml =~ s/\)//g; $j1 = ""; return "$ret
$detailhtml
$j1"; } #################### sub MSwitch_makeCmdHash($) { my $loglevel = 5; my ($Name) = @_; # detailsatz in scalar laden my @devicedatails; @devicedatails = split( /#\[ND\]/, ReadingsVal( $Name, '.Device_Affected_Details', 'no_device' ) ) if defined ReadingsVal( $Name, '.Device_Affected_Details', 'no_device' ) ; #inhalt decice und cmds durch komma getrennt my %savedetails; foreach (@devicedatails) { # ersetzung $_ =~ s/#\[sp\]/ /g; $_ =~ s/#\[nl\]/\n/g; $_ =~ s/#\[se\]/;/g; $_ =~ s/#\[dp\]/:/g; $_ =~ s/\(DAYS\)/|/g; $_ =~ s/#\[ko\]/,/g; #neu $_ =~ s/#\[bs\]/\\/g; #neu 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"; $savedetails{$key} = $detailarray[7]; if ( $testtimestroff ne '[random]' ) { $testtimestroff =~ s/[A-Za-z0-9#\.\-_]//g; if ( $testtimestroff ne "[:]" && $testtimestroff ne "[\$:]" ) { my $hdel = ( substr( $detailarray[7], 0, 2 ) ) * 3600; my $mdel = ( substr( $detailarray[7], 3, 2 ) ) * 60; my $sdel = ( substr( $detailarray[7], 6, 2 ) ) * 1; $detailarray[7] = $hdel + $mdel + $sdel; } } my $testtimestron = $detailarray[8]; $key = $detailarray[0] . "_delayatofforg"; $savedetails{$key} = $detailarray[8]; if ( $testtimestron ne '[random]' ) { $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; $detailarray[8] = $hdel + $mdel + $sdel; } } $key = $detailarray[0] . "_on"; $savedetails{$key} = $detailarray[1]; $key = $detailarray[0] . "_off"; $savedetails{$key} = $detailarray[2]; $key = $detailarray[0] . "_onarg"; $savedetails{$key} = $detailarray[3]; $key = $detailarray[0] . "_offarg"; $savedetails{$key} = $detailarray[4]; $key = $detailarray[0] . "_delayaton"; $savedetails{$key} = $detailarray[5]; $key = $detailarray[0] . "_delayatoff"; $savedetails{$key} = $detailarray[6]; $key = $detailarray[0] . "_timeon"; $savedetails{$key} = $detailarray[7]; $key = $detailarray[0] . "_timeoff"; $savedetails{$key} = $detailarray[8]; $key = $detailarray[0] . "_repeatcount"; if ( defined $detailarray[11] && $detailarray[11] ne "" ) { $savedetails{$key} = $detailarray[11]; } else { $savedetails{$key} = 0; } $key = $detailarray[0] . "_repeattime"; if ( defined $detailarray[12] && $detailarray[12] ne "" ) { $savedetails{$key} = $detailarray[12]; } else { $savedetails{$key} = 0; } $key = $detailarray[0] . "_priority"; if ( defined $detailarray[13] ) { $savedetails{$key} = $detailarray[13]; } else { $savedetails{$key} = 1; } $key = $detailarray[0] . "_id"; if ( defined $detailarray[14] ) { $savedetails{$key} = $detailarray[14]; } else { $savedetails{$key} = 0; } ### $key = $detailarray[0] . "_exit1"; if ( defined $detailarray[16] ) { $savedetails{$key} = $detailarray[16]; } else { $savedetails{$key} = 0; } ### $key = $detailarray[0] . "_exit2"; if ( defined $detailarray[17] ) { $savedetails{$key} = $detailarray[17]; } else { $savedetails{$key} = 0; } ### ### $key = $detailarray[0] . "_showreihe"; if ( defined $detailarray[18] ) { $savedetails{$key} = $detailarray[18]; } else { $savedetails{$key} = 0; } ### $key = $detailarray[0] . "_comment"; if ( defined $detailarray[15] ) { $savedetails{$key} = $detailarray[15]; } else { $savedetails{$key} = ''; } $key = $detailarray[0] . "_conditionon"; if ( defined $detailarray[9] ) { $savedetails{$key} = $detailarray[9]; } else { $savedetails{$key} = ''; } $key = $detailarray[0] . "_conditionoff"; if ( defined $detailarray[10] ) { $savedetails{$key} = $detailarray[10]; } else { $savedetails{$key} = ''; } } my @pass = %savedetails; return @pass; } ######################################## sub MSwitch_Delete_Triggermemory($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $events = ReadingsVal( $Name, '.Device_Events', '' ); my $Triggerdevice = $hash->{Trigger_device}; my $triggeron = ReadingsVal( $Name, '.Trigger_on', 'no_trigger' ); if ( !defined $triggeron ) { $triggeron = "" } my $triggeroff = ReadingsVal( $Name, '.Trigger_off', 'no_trigger' ); if ( !defined $triggeroff ) { $triggeroff = "" } my $triggercmdon = ReadingsVal( $Name, '.Trigger_cmd_on', 'no_trigger' ); if ( !defined $triggercmdon ) { $triggercmdon = "" } my $triggercmdoff = ReadingsVal( $Name, '.Trigger_cmd_off', 'no_trigger' ); if ( !defined $triggercmdoff ) { $triggercmdoff = "" } my $triggerdevice = ReadingsVal( $Name, 'Trigger_device', '' ); delete( $hash->{helper}{events} ); $hash->{helper}{events}{$triggerdevice}{'no_trigger'} = "on"; $hash->{helper}{events}{$triggerdevice}{$triggeron} = "on"; $hash->{helper}{events}{$triggerdevice}{$triggeroff} = "on"; $hash->{helper}{events}{$triggerdevice}{$triggercmdon} = "on"; $hash->{helper}{events}{$triggerdevice}{$triggercmdoff} = "on"; readingsSingleUpdate( $hash, ".Device_Events", 'no_trigger', 1 ); my $eventhash = $hash->{helper}{events}{$triggerdevice}; $events = ""; foreach my $name ( keys %{$eventhash} ) { $name =~ s/#\[tr//ig; $events = $events . $name . '#[tr]'; } chop($events); chop($events); chop($events); chop($events); chop($events); readingsSingleUpdate( $hash, ".Device_Events", $events, 0 ); return; } ########################################################################### sub MSwitch_Exec_Notif($$$$$) { #Inhalt Übergabe -> push @cmdarray, $own_hash . ',on,check,' . $eventcopy1 my ( $hash, $comand, $check, $event, $execids ) = @_; my $name = $hash->{NAME}; my $protokoll = ''; my $satz; MSwitch_LOG( $name, 5, "$name: execnotif -> $execids " ); if ( !$execids ) { $execids = "0" } my $showevents = AttrVal( $name, "MSwitch_generate_Events", 1 ); 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"; my $ekey = ''; my $out = '0'; MSwitch_LOG( $name, 5, "$name: execnotif -> $hash, $comand, $check, $event,$execids " ); return "" if ( IsDisabled($name) ) ; # Return without any further action if the module is disabled my %devicedetails = MSwitch_makeCmdHash($name); # betroffene geräte suchen my @devices = split( /,/, ReadingsVal( $name, '.Device_Affected', 'no_device' ) ); my $update = ''; my $testtoggle = ''; MSwitch_LOG( $name, 6, "$name: zu schaltende devices -> " . @devices . " @devices" ); #Log3( $name, 0, "devices 1: ".@devices." @devices" ); # liste nach priorität ändern , falls expert @devices = MSwitch_priority( $hash, $execids, @devices ); #Log3( $name, 0, "devices 2: ".@devices." @devices" ); my $lastdevice; LOOP45: foreach my $device (@devices) { $out = '0'; if ( $expertmode eq '1' ) { $ekey = $device . "_exit" . $exittest; $out = $devicedetails{$ekey}; } # MSwitch_LOG( $name, 0,"$name: delaymode -> " . $delaymode ." - ".$device ); if ( $delaymode eq '1' ) { MSwitch_Delete_Delay( $hash, $device ); } my @devicesplit = split( /-AbsCmd/, $device ); my $devicenamet = $devicesplit[0]; # teste auf on kommando my $key = $device . "_" . $comand; my $timerkey = $device . "_time" . $comand; my $testtstate = $devicedetails{$timerkey}; $testtstate =~ s/[A-Za-z0-9#\.\-_]//g; if ( $testtstate eq "[:]" || $testtstate eq "[\$:]" ) { $devicedetails{$timerkey} = eval MSwitch_Checkcond_state( $devicedetails{$timerkey}, $name ); if ( $devicedetails{$timerkey} =~ m/[0-9]\d:[0-9]\d:[0-9]\d/ ) { MSwitch_LOG( $name, 5, "$name: format ok " ); my $hdel = ( substr( $devicedetails{$timerkey}, 0, 2 ) ) * 3600; my $mdel = ( substr( $devicedetails{$timerkey}, 3, 2 ) ) * 60; my $sdel = ( substr( $devicedetails{$timerkey}, 6, 2 ) ) * 1; $devicedetails{$timerkey} = $hdel + $mdel + $sdel; } else { MSwitch_LOG( $name, 1, "$name: ERROR Timerformat " . $devicedetails{$timerkey} . " fehlerhaf " ); $devicedetails{$timerkey} = 0; } } MSwitch_LOG( $name, 6, "$name: timer des devices -> " . $devicedetails{$timerkey} ); # teste auf condition # antwort $execute 1 oder 0 ; my $conditionkey = $device . "_condition" . $comand; if ( $devicedetails{$key} ne "" && $devicedetails{$key} ne "no_action" ) { my $cs = ''; if ( $devicenamet eq 'FreeCmd' ) { $cs = " $devicedetails{$device.'_'.$comand.'arg'}"; $cs = MSwitch_makefreecmd( $hash, $cs ); } else { $cs = "set $devicenamet $devicedetails{$device.'_'.$comand} $devicedetails{$device.'_'.$comand.'arg'}"; } #Variabelersetzung $cs =~ s/\$NAME/$hash->{helper}{eventfrom}/; $cs =~ s/\$SELF/$name/; if ( $devicedetails{$timerkey} eq "0" || $devicedetails{$timerkey} eq "" ) { # teste auf condition # antwort $execute 1 oder 0 ; $conditionkey = $device . "_condition" . $comand; my $execute = MSwitch_checkcondition( $devicedetails{$conditionkey}, $name, $event ); $testtoggle = 'undef'; if ( $execute eq 'true' ) { $lastdevice = $device; $testtoggle = $cs; ############# MSwitch_LOG( $name, 3, "$name MSwitch_Restartcm: Befehlsausfuehrung -> $cs " . __LINE__ ); my $toggle = ''; if ( $cs =~ m/set (.*)(MSwitchtoggle)(.*)/ ) { $toggle = $cs; $cs = MSwitch_toggle( $hash, $cs ); } MSwitch_LOG( $name, 6, "$name: auszufuehrender Befehl -> " . $cs ); # neu $devicedetails{ $device . '_repeatcount' } = 0 if !defined $devicedetails{ $device . '_repeatcount' }; $devicedetails{ $device . '_repeattime' } = 0 if !defined $devicedetails{ $device . '_repeattime' }; MSwitch_LOG( $name, 6, "$name: teste auf repeasts " ); my $x = 0; while ( $devicedetails{ $device . '_repeatcount' } =~ m/\[(.*)\:(.*)\]/ ) { $x++; # exit last if $x > 20; # exit my $setmagic = ReadingsVal( $1, $2, 0 ); $devicedetails{ $device . '_repeatcount' } = $setmagic; } $x = 0; while ( $devicedetails{ $device . '_repeattime' } =~ m/\[(.*)\:(.*)\]/ ) { $x++; # exit last if $x > 20; # exit my $setmagic = ReadingsVal( $1, $2, 0 ); $devicedetails{ $device . '_repeattime' } = $setmagic; } if ( $devicedetails{ $device . '_repeatcount' } eq "" ) { $devicedetails{ $device . '_repeatcount' } = 0; } if ( $devicedetails{ $device . '_repeattime' } eq "" ) { $devicedetails{ $device . '_repeattime' } = 0; } MSwitch_LOG( $name, 6, "$name: anzahl repeats -> " . $devicedetails{ $device . '_repeatcount' } ); MSwitch_LOG( $name, 6, "$name: delay repeats -> " . $devicedetails{ $device . '_repeattime' } ); if ( $expertmode eq '1' && $devicedetails{ $device . '_repeatcount' } > 0 && $devicedetails{ $device . '_repeattime' } > 0 ) { my $i; for ( $i = 0 ; $i <= $devicedetails{ $device . '_repeatcount' } ; $i++ ) { my $msg = $cs . "|" . $name; if ( $toggle ne '' ) { $msg = $toggle . "|" . $name; } my $timecond = gettimeofday() + ( ( $i + 1 ) * $devicedetails{ $device . '_repeattime' } ); $msg = $msg . "," . $timecond; $hash->{helper}{repeats}{$timecond} = "$msg"; MSwitch_LOG( $name, 6, "$name: repeat gesetzt -> " . $timecond . " " . $msg ); InternalTimer( $timecond, "MSwitch_repeat", $msg ); if ( $out eq '1' ) { MSwitch_LOG( $name, 6, "$name: Abbruchbefehl erhalten von " . $device ); $lastdevice = $device; last LOOP45; } } } my $todec = $cs; $cs = MSwitch_dec( $hash, $todec ); ############################ if ( $debugmode eq '2' ) { MSwitch_LOG( $name, 6, "$name: execute -> " . $cs ); } else { if ( $cs =~ m/{.*}/ ) { eval($cs); if ($@) { 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; } } else { my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { 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; } } } my $msg = $cs; if ( length($msg) > 100 ) { $msg = substr( $msg, 0, 100 ) . '....'; } readingsSingleUpdate( $hash, "last_exec_cmd", $msg, $showevents ) if $msg ne ''; } } else { if ( $attrrandomtime ne '' && $devicedetails{$timerkey} eq '[random]' ) { $devicedetails{$timerkey} = MSwitch_Execute_randomtimer($hash); # ersetzt $devicedetails{$timerkey} gegen randomtimer } elsif ($attrrandomtime eq '' && $devicedetails{$timerkey} eq '[random]' ) { $devicedetails{$timerkey} = 0; } my $timecond = gettimeofday() + $devicedetails{$timerkey}; my $delaykey = $device . "_delayat" . $comand; my $delayinhalt = $devicedetails{$delaykey}; my $delaykey1 = $device . "_delayat" . $comand . "org"; my $teststateorg = $devicedetails{$delaykey1}; $conditionkey = $device . "_condition" . $comand; my $execute = "true"; if ( $delayinhalt ne "delay2" && $delayinhalt ne "at02" ) { $execute = MSwitch_checkcondition( $devicedetails{$conditionkey}, $name, $event ); } if ( $execute eq "true" ) { if ( $delayinhalt eq 'at0' || $delayinhalt eq 'at1' ) { $timecond = MSwitch_replace_delay( $hash, $teststateorg ); } if ( $delayinhalt eq 'at1' || $delayinhalt eq 'delay0' ) { $conditionkey = "nocheck"; } $cs =~ s/,/##/g; my $msg = $cs . "#[tr]" . $name . "#[tr]" . $conditionkey . "#[tr]" . $event . "#[tr]" . $timecond . "#[tr]" . $device; $hash->{helper}{delays}{$msg} = $timecond; $testtoggle = 'undef'; MSwitch_LOG( $name, 6, "$name: timer gesetzt -> " . $cs ); MSwitch_LOG( $name, 6, "$name: timer gesetzt name -> " . $name ); MSwitch_LOG( $name, 6, "$name: timer gesetzt conditionkey-> " . $conditionkey ); MSwitch_LOG( $name, 6, "$name: timer gesetzt event-> " . $event ); MSwitch_LOG( $name, 6, "$name: timer gesetzt timecond-> " . $timecond ); MSwitch_LOG( $name, 6, "$name: timer gesetzt -> device " . $device ); InternalTimer( $timecond, "MSwitch_Restartcmd", $msg ); if ( $expertmode eq "1" && $device ) { readingsSingleUpdate( $hash, "last_cmd", $hash->{helper}{priorityids}{$device}, $showevents ); } if ( $out eq '1' ) { MSwitch_LOG( $name, 6, "$name: Abbruchbefehl erhalten von " . $device ); $lastdevice = $device; last LOOP45; } } } } if ( $testtoggle ne '' && $testtoggle ne 'undef' ) { $satz .= $testtoggle . ','; } } if ( $expertmode eq "1" && $lastdevice ) { readingsSingleUpdate( $hash, "last_cmd", $hash->{helper}{priorityids}{$lastdevice}, $showevents ); } MSwitch_LOG( $name, 6, "$name: return aus execnotif -> " . $satz ) if $satz; return $satz; } #################### sub MSwitch_Filter_Trigger($) { my ($hash) = @_; my $Name = $hash->{NAME}; MSwitch_LOG( $Name, 5, "$Name: filter saved vents " ); my $Triggerdevice = $hash->{Trigger_device}; my $triggeron = ReadingsVal( $Name, '.Trigger_on', 'no_trigger' ); if ( !defined $triggeron ) { $triggeron = "" } my $triggeroff = ReadingsVal( $Name, '.Trigger_off', 'no_trigger' ); if ( !defined $triggeroff ) { $triggeroff = "" } my $triggercmdon = ReadingsVal( $Name, '.Trigger_cmd_on', 'no_trigger' ); if ( !defined $triggercmdon ) { $triggercmdon = "" } my $triggercmdoff = ReadingsVal( $Name, '.Trigger_cmd_off', 'no_trigger' ); if ( !defined $triggercmdoff ) { $triggercmdoff = "" } my $triggerdevice = ReadingsVal( $Name, 'Trigger_device', '' ); delete( $hash->{helper}{events}{$Triggerdevice} ); $hash->{helper}{events}{$Triggerdevice}{'no_trigger'} = "on"; $hash->{helper}{events}{$Triggerdevice}{$triggeron} = "on"; $hash->{helper}{events}{$Triggerdevice}{$triggeroff} = "on"; $hash->{helper}{events}{$Triggerdevice}{$triggercmdon} = "on"; $hash->{helper}{events}{$Triggerdevice}{$triggercmdoff} = "on"; my $events = ReadingsVal( $Name, '.Device_Events', '' ); MSwitch_LOG( $Name, 5, "$Name: eventfile " . $events ); my @eventsall = split( /#\[tr\]/, $events ); EVENT: foreach my $eventcopy (@eventsall) { MSwitch_LOG( $Name, 5, "$Name: getestetes event " . $eventcopy ); my @filters = split( /,/, AttrVal( $Name, 'MSwitch_Trigger_Filter', '' ) ) ; # beinhaltet filter durch komma getrennt foreach my $filter (@filters) { if ( $filter eq "*" ) { $filter = ".*"; } MSwitch_LOG( $Name, 5, "$Name: getesteter Filter -> " . $filter ); if ( $eventcopy =~ m/$filter/ ) { MSwitch_LOG( $Name, 5, "$Name: eingehendes Event ausgefiltert " ); next EVENT; } } $hash->{helper}{events}{$Triggerdevice}{$eventcopy} = "on"; } my $eventhash = $hash->{helper}{events}{$Triggerdevice}; $events = ""; foreach my $name ( keys %{$eventhash} ) { $events = $events . $name . '#[tr]'; } chop($events); chop($events); chop($events); chop($events); chop($events); readingsSingleUpdate( $hash, ".Device_Events", $events, 0 ); return; } #################### sub MSwitch_Restartcmd($) { my $incomming = $_[0]; my @msgarray = split( /#\[tr\]/, $incomming ); my $name = $msgarray[1]; my $hash = $modules{MSwitch}{defptr}{$name}; my $showevents = AttrVal( $name, "MSwitch_generate_Events", 1 ); return "" if ( IsDisabled($name) ); return if ( AttrVal( $name, 'MSwitch_Mode', "Full" ) eq 'Dummy' ); $hash->{eventsave} = 'unsaved'; 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 ) { my $ver = ReadingsVal( $name, '.V_Check', '' ); MSwitch_LOG( $name, 5, "$name: Versionskonflikt - aktion abgebrochen" ); return; } my $cs = $msgarray[0]; $cs =~ s/##/,/g; my $conditionkey = $msgarray[2]; 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); } ############ teste auf condition ### antwort $execute 1 oder 0 ; my $execute = "true"; $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} ); $execute = MSwitch_checkcondition( $devicedetails{$conditionkey}, $name, $event ); MSwitch_LOG( $name, 5, "$name: ergebniss checkcondition -> " . $execute ); } my $toggle = ''; if ( $execute eq 'true' ) { MSwitch_LOG( $name, 3, "$name MSwitch_Restartcm: Befehlsausfuehrung -> $cs " . __LINE__ ); if ( $cs =~ m/set (.*)(MSwitchtoggle)(.*)/ ) { $toggle = $cs; $cs = MSwitch_toggle( $hash, $cs ); } MSwitch_LOG( $name, 5, "$name: teste repeat -> " . $devicedetails{ $device . '_repeatcount' } ); my $x = 0; while ( $devicedetails{ $device . '_repeatcount' } =~ m/\[(.*)\:(.*)\]/ ) { $x++; # notausstieg notausstieg last if $x > 20; # notausstieg notausstieg my $setmagic = ReadingsVal( $1, $2, 0 ); $devicedetails{ $device . '_repeatcount' } = $setmagic; } $x = 0; while ( $devicedetails{ $device . '_repeattime' } =~ m/\[(.*)\:(.*)\]/ ) { $x++; # notausstieg notausstieg last if $x > 20; # notausstieg notausstieg my $setmagic = ReadingsVal( $1, $2, 0 ); $devicedetails{ $device . '_repeattime' } = $setmagic; } MSwitch_LOG( $name, 5, "$name: repetcount nach test -> " . $devicedetails{ $device . '_repeatcount' } ); MSwitch_LOG( $name, 5, "$name: repeattime nach test -> " . $devicedetails{ $device . '_repeattime' } ); ###################################### if ( AttrVal( $name, 'MSwitch_Expert', "0" ) eq '1' && $devicedetails{ $device . '_repeatcount' } > 0 && $devicedetails{ $device . '_repeattime' } > 0 ) { my $i; for ( $i = 0 ; $i <= $devicedetails{ $device . '_repeatcount' } ; $i++ ) { my $msg = $cs . "|" . $name; if ( $toggle ne '' ) { $msg = $toggle . "|" . $name; } my $timecond = gettimeofday() + ( ( $i + 1 ) * $devicedetails{ $device . '_repeattime' } ); $msg = $msg . "|" . $timecond; $hash->{helper}{repeats}{$timecond} = "$msg"; MSwitch_LOG( $name, 5, "$name: repeat gesetzt -> " . $timecond . " - " . $msg ); InternalTimer( $timecond, "MSwitch_repeat", $msg ); } } my $todec = $cs; $cs = MSwitch_dec( $hash, $todec ); ############################ if ( AttrVal( $name, 'MSwitch_Debug', "0" ) eq '2' ) { MSwitch_LOG( $name, 5, "$name: exec comand -> " . $cs ); } else { if ( $cs =~ m/{.*}/ ) { MSwitch_LOG( $name, 5, "$name: exec als perlcode -> " . $cs ); eval($cs); if ($@) { MSwitch_LOG( $name, 1, "$name MSwitch_Set: ERROR $cs: $@ " . __LINE__ ); } } else { MSwitch_LOG( $name, 5, "$name: execute als fhemcode -> " . $cs ); my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { MSwitch_LOG( $name, 1, "$name MSwitch_Restartcmd :Fehler bei Befehlsausfuehrung ERROR $errors " . __LINE__ ); } } } if ( length($cs) > 100 && AttrVal( $name, 'MSwitch_Debug', "0" ) ne '4' ) { $cs = substr( $cs, 0, 100 ) . '....'; } readingsSingleUpdate( $hash, "last_exec_cmd", $cs, $showevents ) if $cs ne ''; } RemoveInternalTimer($incomming); delete( $hash->{helper}{delays}{$incomming} ); return; } #################### sub MSwitch_checkcondition($$$) { # antwort execute 0 oder 1 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; $condition =~ s/\[\$EVTPART1\]/"\$EVTPART1"/g; $condition =~ s/\[\$EVTPART2\]/"\$EVTPART2"/g; $condition =~ s/\[\$EVTPART3\]/"\$EVTPART3"/g; $condition =~ s/\[\$EVT_CMD1_COUNT\]/"\$EVT_CMD1_COUNT"/g; $condition =~ s/\[\$EVT_CMD2_COUNT\]/"\$EVT_CMD2_COUNT"/g; MSwitch_LOG( $name, 6, "$name: Checkcondition - Parameter condition -> " . $condition ); MSwitch_LOG( $name, 6, "$name: Checkcondition - Parameter event -> " . $event ); if ( !defined($condition) ) { return 'true'; } if ( $condition eq '' ) { return 'true'; } ###### perlersetzung ############## my $x = 0; my $field = ""; my $SELF = $name; while ( $condition =~ m/(.*)\{(.+)\}(.*)/ ) { my $firstpart = $1; my $secondpart = $2; my $lastpart = $3; my $exec = "\$field = " . $2; if ( $secondpart =~ m/(!\$.*|\$.*)/ ) { #MSwitch_LOG( $name, 0,"$name: found var exec -> " .$field ); $field = $secondpart; } else { eval($exec); } 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 } if ( $attrrandomnumber ne '' ) { MSwitch_Createnumber($hash); } my $anzahlk1 = $condition =~ tr/{//; my $anzahlk2 = $condition =~ tr/}//; if ( $anzahlk1 ne $anzahlk2 ) { $hash->{helper}{conditioncheck} = "Klammerfehler"; return "false"; } $anzahlk1 = $condition =~ tr/(//; $anzahlk2 = $condition =~ tr/)//; if ( $anzahlk1 ne $anzahlk2 ) { $hash->{helper}{conditioncheck} = "Klammerfehler"; return "false"; } $anzahlk1 = $condition =~ tr/[//; $anzahlk2 = $condition =~ tr/]//; if ( $anzahlk1 ne $anzahlk2 ) { $hash->{helper}{conditioncheck} = "Klammerfehler"; return "false"; } my $arraycount = '0'; my $finalstring; my $answer; my $i; my $pos; my $pos1; my $part; my $part1; my $part2; my $part3; my $lenght; # wildcardcheck my $we = AnalyzeCommand( 0, '{return $we}' ); my @perlarray; ### perlteile trennen ####################### 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}; unshift( @evtparts, $eventfrom ); $evtsanzahl = @evtparts; } my $evtfull = join( ':', @evtparts ); $evtparts[2] = '' if !defined $evtparts[2]; $condition =~ s/\$EVENT/$event/ig; $condition =~ s/\$EVTFULL/$evtfull/ig; $condition =~ s/\$EVTPART1/$evtparts[0]/ig; $condition =~ s/\$EVTPART2/$evtparts[1]/ig; $condition =~ s/\$EVTPART3/$evtparts[2]/ig; my $evtcmd1 = ReadingsVal( $name, 'EVT_CMD1_COUNT', '0' ); my $evtcmd2 = ReadingsVal( $name, 'EVT_CMD2_COUNT', '0' ); $condition =~ s/\$EVT_CMD1_COUNT/$evtcmd1/ig; $condition =~ s/\$EVT_CMD2_COUNT/$evtcmd2/ig; MSwitch_LOG( $name, 5, "condition: " . $condition ); ###################################### $condition =~ s/{!\$we}/ !\$we /ig; $condition =~ s/{\$we}/ \$we /ig; $condition =~ s/{sunset\(\)}/{ sunset\(\) }/ig; $condition =~ s/{sunrise\(\)}/{ sunrise\(\) }/ig; $x = 0; while ( $condition =~ m/(.*?)(\$NAME)(.*)?/ ) { my $firstpart = $1; my $secondpart = $2; my $lastpart = $3; $condition = $firstpart . $name . $lastpart; $x++; last if $x > 10; #notausstieg } $x = 0; while ( $condition =~ m/(.*?)(\$SELF)(.*)?/ ) { my $firstpart = $1; my $secondpart = $2; my $lastpart = $3; $condition = $firstpart . $name . $lastpart; $x++; last if $x > 10; #notausstieg } my $searchstring; $x = 0; while ( $condition =~ m/(.*?)(\[\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\]-\[[a-zA-Z][a-zA-Z0-9_]{0,30}:[a-zA-Z0-9_]{0,30}\]\])(.*)?/ ) { my $firstpart = $1; $searchstring = $2; my $lastpart = $3; $x++; last if $x > 10; #notausstieg my $x = 0; # Searchstring -> [[t1:state]-[t2:state]] 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; my $lastpart = $3; if ( $secsearchstring =~ m/\[(.*):(.*)\]/ ) { $read1 = ReadingsVal( $1, $2, 'undef' ); } $searchstring = $firstpart . $read1 . $lastpart; $x++; last if $x > 10; #notausstieg } $condition = $firstpart . $searchstring . $lastpart; } $x = 0; while ( $condition =~ m/(.*)({ )(.*)(\$we)( })(.*)/ ) { last if $x > 20; # notausstieg $condition = $1 . " " . $3 . $4 . " " . $6; } ################################################### # ersetzte sunset sunrise $x = 0; # notausstieg while ( $condition =~ m/(.*)({ )(sunset\([^}]*\)|sunrise\([^}]*\))( })(.*)/ ) { $x++; # notausstieg last if $x > 20; # notausstieg if ( defined $2 ) { my $part2 = eval $3; 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; } $condition = $part2; $condition = $1 . $condition if ( defined $1 ); $condition = $condition . $5 if ( defined $5 ); } } my $conditioncopy = $condition; my @argarray; $arraycount = '0'; $pos = ''; $pos1 = ''; $part = ''; $part1 = ''; $part2 = ''; $part3 = ''; $lenght = ''; ## verursacht fehlerkennung bei angabe von regex [a-zA-Z] ARGUMENT: for ( $i = 0 ; $i <= 10 ; $i++ ) { $pos = index( $condition, "[", 0 ); my $x = $pos; if ( $x == '-1' ) { last ARGUMENT; } $pos1 = index( $condition, "]", 0 ); $argarray[$arraycount] = substr( $condition, $pos, ( $pos1 + 1 - $pos ) ); $lenght = length($condition); $part1 = substr( $condition, 0, $pos ); $part2 = 'ARG' . $arraycount; $part3 = substr( $condition, ( $pos1 + 1 ), ( $lenght - ( $pos1 + 1 ) ) ); $condition = $part1 . $part2 . $part3; $arraycount++; } $condition =~ s/ AND / && /ig; $condition =~ s/ OR / || /ig; #$condition =~ s/~/ /ig; $condition =~ s/ = / == /ig; END: # teste auf typ my $count = 0; my $testarg; my @newargarray; foreach my $args (@argarray) { $testarg = $args; $testarg =~ s/[0-9]+//gs; if ( $testarg eq '[:-:|]' || $testarg eq '[:-:]' ) { # timerformatierung erkannt - auswerten über sub # my $param = $argarray[$count]; $newargarray[$count] = MSwitch_Checkcond_time( $args, $name ); } elsif ( $testarg =~ '[.*:.*]' ) { # stateformatierung erkannt - auswerten über sub $newargarray[$count] = MSwitch_Checkcond_state( $args, $name ); } else { $newargarray[$count] = $args; } $count++; } $count = 0; my $tmp; foreach my $args (@newargarray) { $tmp = 'ARG' . $count; $condition =~ s/$tmp/$args/ig; $count++; } $finalstring = "if (" . $condition . "){\$answer = 'true';} else {\$answer = 'false';} "; MSwitch_LOG( $name, 6, "$name: Checkcondition - finalstring -> " . $finalstring ); #MSwitch_LOG( $name, 0,"name $name "); my $ret = eval $finalstring; MSwitch_LOG( $name, 6, "$name: Checkcondition - return -> " . $ret ); if ($@) { MSwitch_LOG( $name, 1, "$name ERROR: $@ " . __LINE__ ); MSwitch_LOG( $name, 1, "$name $finalstring " . __LINE__ ); $hash->{helper}{conditionerror} = $@; return 'false'; } my $test = ReadingsVal( $name, 'last_event', 'undef' ); $hash->{helper}{conditioncheck} = $finalstring; return $ret; } #################### #################### sub MSwitch_Checkcond_state($$) { my ( $condition, $name ) = @_; MSwitch_LOG( $name, 6, "----------------------------------------" ); MSwitch_LOG( $name, 6, "$name: MSwitch_Checkcond_state -> " . $condition ); MSwitch_LOG( $name, 6, "----------------------------------------" ); my $x = 0; while ( $condition =~ m/(.*?)(\$SELF)(.*)?/ ) { my $firstpart = $1; my $secondpart = $2; my $lastpart = $3; $condition = $firstpart . $name . $lastpart; $x++; last if $x > 10; #notausstieg } $condition =~ s/\[//; $condition =~ s/\]//; my @reading = split( /:/, $condition ); my $return = "ReadingsVal('$reading[0]', '$reading[1]', '00:00:00')"; my $test = ReadingsVal( $reading[0], $reading[1], 'undef' ); MSwitch_LOG( $name, 6, "$name: MSwitch_Checkcond_state OUT -> " . $return ); return $return; } #################### sub MSwitch_Checkcond_time($$) { my ( $condition, $name ) = @_; $condition =~ s/\[//; $condition =~ s/\]//; my $adday = 0; my $days = ''; my $daycondition = ''; ( $condition, $days ) = split( /\|/, $condition ) if index( $condition, "|", 0 ) > -1; my $hour1 = substr( $condition, 0, 2 ); my $min1 = substr( $condition, 3, 2 ); my $hour2 = substr( $condition, 6, 2 ); my $min2 = substr( $condition, 9, 2 ); if ( $hour1 eq "24" ) # test auf 24 zeitangabe { $hour1 = "00"; } if ( $hour2 eq "24" ) { $hour2 = "00"; } my $time = localtime; $time =~ s/\s+/ /g; my ( $day, $month, $date, $n, $time1 ) = split( / /, $time ); my ( $akthour, $aktmin, $aktsec ) = split( /:/, $n ); ############ timecondition 1 my $timecondtest; my $timecond1; my $timecond2; my ( $tday, $tmonth, $tdate, $tn ); #my ($tday,$tmonth,$tdate,$tn,$time1); $timecondtest = localtime; $timecondtest =~ s/\s+/ /g; ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest ); $timecond1 = timelocal( '00', $min1, $hour1, $tdate, $tmonth, $time1 ); $timecond2 = timelocal( '00', $min2, $hour2, $tdate, $tmonth, $time1 ); my $timeaktuell = timelocal( '00', $aktmin, $akthour, $date, $month, $time1 ); ### new if ( $timeaktuell < $timecond2 && $timecond2 < $timecond1 ) { use constant SECONDS_PER_DAY => 60 * 60 * 24; $timecond1 = $timecond1 - SECONDS_PER_DAY; $adday = 1; } if ( $timeaktuell > $timecond1 && $timecond2 < $timecond1 ) { use constant SECONDS_PER_DAY => 60 * 60 * 24; $timecond2 = $timecond2 + SECONDS_PER_DAY; $adday = 1 } ######## old # if ( ( $akthour < $hour1 && $akthour <= $hour2 ) && $hour2 < $hour1 ) # und # { # use constant SECONDS_PER_DAY => 60 * 60 * 24; # $timecondtest = localtime( time - SECONDS_PER_DAY ); # $timecondtest =~ s/\s+/ /g; # ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest ); # $timecond1 = timelocal( '00', $min1, $hour1, $tdate, $tmonth, $time1 ); # $adday = 1; # } # else { # $timecondtest = localtime; # $timecondtest =~ s/\s+/ /g; # ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest ); # $timecond1 = timelocal( '00', $min1, $hour1, $tdate, $tmonth, $time1 ); # } ################## ############# timecondition 2 # my $timecond2; # $timecondtest = localtime; # if ( $hour2 < $hour1 ) { # if ( $akthour < $hour1 && $akthour < $hour2 ) { # $timecondtest = localtime; # $timecondtest =~ s/\s+/ /g; # ( $tday, $tmonth, $tdate, $tn, $time1 ) = # split( / /, $timecondtest ); # $timecond2 = # timelocal( '00', $min2, $hour2, $tdate, $tmonth, $time1 ); # } # else { # use constant SECONDS_PER_DAY => 60 * 60 * 24; # $timecondtest = localtime( time + SECONDS_PER_DAY ); # $timecondtest =~ s/\s+/ /g; # my ( $tday, $tmonth, $tdate, $tn, $time1 ) = # split( / /, $timecondtest ); # $timecond2 = # timelocal( '00', $min2, $hour2, $tdate, $tmonth, $time1 ); # $adday = 1; # } # } # else { # $timecondtest = localtime; # $timecondtest =~ s/\s+/ /g; # ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest ); # $timecond2 = timelocal( '00', $min2, $hour2, $tdate, $tmonth, $time1 ); # } # my $timeaktuell = # timelocal( '00', $aktmin, $akthour, $date, $month, $time1 ); my $return = "($timecond1 < $timeaktuell && $timeaktuell < $timecond2)"; if ( $days ne '' ) { $daycondition = MSwitch_Checkcond_day( $days, $name, $adday, $day ); $return = "($return $daycondition)"; } return $return; } #################### sub MSwitch_Checkcond_day($$$$) { my ( $days, $name, $adday, $day ) = @_; my %daysforcondition = ( "Mon" => 1, "Tue" => 2, "Wed" => 3, "Thu" => 4, "Fri" => 5, "Sat" => 6, "Sun" => 7 ); $day = $daysforcondition{$day}; my @daycond = split //, $days; my $daycond = ''; foreach my $args (@daycond) { if ( $adday == 1 ) { $args++; } if ( $args == 8 ) { $args = 1 } $daycond = $daycond . "($day == $args) || "; } chop $daycond; chop $daycond; chop $daycond; chop $daycond; $daycond = "&& ($daycond)"; return $daycond; } #################### sub MSwitch_Createtimer($) { my ($hash) = @_; 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; } my $lenght = length($condition); #remove all timers MSwitch_Clear_timer($hash); if ( $lenght == 0 ) { return; } # trenne timerfile my $key = 'on'; $condition =~ s/$key//ig; $key = 'off'; $condition =~ s/$key//ig; $key = 'ly'; $condition =~ s/$key//ig; $x = 0; # achtung perl 5.30 while ( $condition =~ m/(.*)\{(.*)\}(.*)/ ) { $x++; # notausstieg last if $x > 20; # notausstieg if ( defined $2 ) { my $part1 = $1; my $part3 = $3; 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 " ); return; } $part2 = substr( $part2, 0, 5 ); my $test = substr( $part2, 0, 2 ) * 1; $part2 = "" if $test > 23; $condition = $part1 . $part2 . $part3; } } my @timer = split /~/, $condition; $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" ) { $timer[0] = ''; $timer[1] = ''; } if ( AttrVal( $Name, 'MSwitch_Mode', 'Full' ) eq "Toggle" ) { $timer[1] = ''; $timer[2] = ''; $timer[3] = ''; $timer[4] = ''; } my $akttimestamp = TimeNow(); my ( $aktdate, $akttime ) = split / /, $akttimestamp; my ( $aktyear, $aktmonth, $aktmday ) = split /-/, $aktdate; $aktmonth = $aktmonth - 1; $aktyear = $aktyear - 1900; my $jetzt = gettimeofday(); # aktuelle zeit setzen my $time = localtime; $time =~ s/\s+/ /g; my ( $day, $month, $date, $n, $time1 ) = split( / /, $time ); # day enthält aktuellen tag als wochentag my $aktday = $day; my %daysforcondition = ( "Mon" => 1, "Tue" => 2, "Wed" => 3, "Thu" => 4, "Fri" => 5, "Sat" => 6, "Sun" => 7 ); $day = $daysforcondition{$day}; # enthält aktuellen tag ### ## 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; $key = '\['; $option =~ s/$key//ig; $key = '\]'; $option =~ s/$key//ig; if ( $option =~ m/(.*?)([0-9]{2}):([0-9]{2})\*([0-9]{2}:[0-9]{2})-([0-9]{2}:[0-9]{2})\|?([0-9]{0,7})(.*)?/ ) { my $part1 = ''; $part1 = $1 . ' ' if defined $1; my $part6 = ''; if ( defined $6 && $part6 ne '' ) { $part6 = '|' . $6 } my $part7 = ''; $part7 = ' ' . $7 if defined $7; my $sectoadd = $2 * 3600 + $3 * 60; my $t1 = $4; my $t2 = $5; my $timecondtest = localtime; $timecondtest =~ s/\s+/ /g; my ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest ); my $timecond1 = timelocal( '00', substr( $t1, 3, 2 ), substr( $t1, 0, 2 ), $tdate, $tmonth, $time1 ); my $timecond2 = timelocal( '00', substr( $t2, 3, 2 ), substr( $t2, 0, 2 ), $tdate, $tmonth, $time1 ); my @newarray; while ( $timecond1 < $timecond2 ) { #my $timestamp = FmtDateTime($timecond1); my $timestamp = substr( FmtDateTime($timecond1), 11, 5 ) . $part6; $timecond1 = $timecond1 + $sectoadd; push( @newarray, $timestamp ); } my $newopt = join( ' ', @newarray ); my $newoption = $part1 . $newopt . $part7; $newoption =~ s/ / /g; $option = $newoption; } my @optionarray = split / /, $option; # für jede angabe eines files LOOP3: foreach my $option1 (@optionarray) { $id = ""; #Log3( $Name, 0, "option: $option1" ); if ( $option1 =~ m/(.*)\|(ID.*)$/ ) { $id = $2; $option1 = $1; #Log3( $Name, 0, "id: $id" ); #Log3( $Name, 0, "option1: $option1" ); } if ( $option1 =~ m/\?(.*)(-)([0-9]{2}:[0-9]{2})(\|[0-9]{0,7})?(.*)?/ ) { my $testrandom = $1 . $2 . $3; my $part4 = ''; $part4 = $4 if defined $4; my $opdays = $part4; #testrandomsaved erstellen my $newoption1 = MSwitch_Createrandom( $hash, $1, $3 ); $option1 = $newoption1 . $opdays; } if ( $option1 =~ m/{/i || $option1 =~ m/}/i ) { my $newoption1 = MSwitch_ChangeCode( $hash, $option1 ); $option1 = $newoption1; } my ( $time, $days ) = split /\|/, $option1; $time = '' if ( !defined $time ); $days = '' if ( !defined $days ); if ( $days eq '!$we' || $days eq '$we' ) { my $we = AnalyzeCommand( 0, '{return $we}' ); if ( $days eq '$we' && $we == 1 ) { $days = $day; } if ( $days eq '!$we' && $we == 0 ) { $days = $day; } } if ( !defined($days) ) { $days = '' } if ( $days eq '' ) { $days = '1234567' } if ( index( $days, $day, 0 ) == -1 ) { next LOOP3; } $time = $time . ':00'; delete( $hash->{helper}{error} ); my $timecond = timelocal( substr( $time, 6, 2 ), substr( $time, 3, 2 ), substr( $time, 0, 2 ), $date, $aktmonth, $aktyear ); my $test = FmtDateTime($timecond); my $sectowait = $timecond - $jetzt; if ( $timecond > $jetzt ) { my $number = $i; #Log3( $Name, 0, "i: $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 . " " . $number . $id; #Log3( $Name, 0, "number: $number" ); #Log3( $Name, 0, "id: $id" ); #Log3( $Name, 0, "msg: $msg" ); InternalTimer( $timecond, "MSwitch_Execute_Timer", $msg ); } } } # berechne zeit bis 23,59 und setze timer auf create timer my $newask = timelocal( '00', '59', '23', $date, $aktmonth, $aktyear ); $newask = $newask + 70; my $newassktest = FmtDateTime($newask); my $msg = $Name . " " . $newask . " " . 5; my $inhalt = $newask . "-" . 5; $hash->{helper}{timer}{$newask} = "$inhalt"; InternalTimer( $newask, "MSwitch_Execute_Timer", $msg ); } ############################## sub MSwitch_Createrandom($$$) { my ( $hash, $t1, $t2 ) = @_; my $Name = $hash->{NAME}; my $testrandom = $t1 . "-" . $t2; my $testt1 = $t1; my $testt2 = $t2; $testt1 =~ s/\://g; $testt2 =~ s/\://g; my $timecondtest = localtime; $timecondtest =~ s/\s+/ /g; my ( $tday, $tmonth, $tdate, $tn, $time1 ) = split( / /, $timecondtest ); my $timecond1 = timelocal( '00', substr( $t1, 3, 2 ), substr( $t1, 0, 2 ), $tdate, $tmonth, $time1 ); my $timecond2 = timelocal( '00', substr( $t2, 3, 2 ), substr( $t2, 0, 2 ), $tdate, $tmonth, $time1 ); if ( $testt2 < $testt1 ) { $timecond2 = $timecond2 + 86400 } my $newtime = int( rand( $timecond2 - $timecond1 ) ) + $timecond1; my $timestamp = FmtDateTime($newtime); my $timestamp1 = substr( $timestamp, 11, 5 ); return $timestamp1; } ########################### sub MSwitch_Execute_Timer($) { my ($input) = @_; 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', '' ); MSwitch_LOG( $Name, 1, $Name . ' Versionskonflikt, aktion abgebrochen ! erwartet:' . $vupdate . ' vorhanden:' . $ver ); return; } if ( AttrVal( $Name, 'MSwitch_RandomNumber', '' ) ne '' ) { MSwitch_Createnumber1($hash); } if ( $param eq '5' ) { MSwitch_Createtimer($hash); return; } if ( AttrVal( $Name, 'MSwitch_Condition_Time', "0" ) eq '1' ) { my $triggercondition = ReadingsVal( $Name, '.Trigger_condition', '' ); # $triggercondition =~ s/\./:/g; $triggercondition =~ s/#\[dp\]/:/g; $triggercondition =~ s/#\[pt\]/./g; $triggercondition =~ s/#\[ti\]/~/g; $triggercondition =~ s/#\[sp\]/ /g; if ( $triggercondition ne '' ) { my $ret = MSwitch_checkcondition( $triggercondition, $Name, '' ); if ( $ret eq 'false' ) { return; } } } my $extime = POSIX::strftime( "%H:%M", localtime ); readingsBeginUpdate($hash); readingsBulkUpdate( $hash, "EVENT", $Name . ":execute_timer_P" . $param . ":" . $extime ); readingsBulkUpdate( $hash, "EVTFULL", $Name . ":execute_timer_P" . $param . ":" . $extime ); readingsBulkUpdate( $hash, "EVTPART1", $Name ); readingsBulkUpdate( $hash, "EVTPART2", "execute_timer_P" . $param ); readingsBulkUpdate( $hash, "EVTPART3", $extime ); readingsEndUpdate( $hash, 1 ); if ( $param eq '1' ) { my $cs = "set $Name on"; MSwitch_LOG( $Name, 3, "$Name MSwitch_Execute_Timer: Befehlsausfuehrung -> $cs" . __LINE__ ); my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { MSwitch_LOG( $Name, 1, "$Name MSwitch_Execute_Timer: Fehler bei Befehlsausfuehrung ERROR $Name: $errors " . __LINE__ ); } return; } if ( $param eq '2' ) { my $cs = "set $Name off"; MSwitch_LOG( $Name, 3, "$Name MSwitch_Execute_Timer: Befehlsausfuehrung -> $cs" . __LINE__ ); my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { MSwitch_LOG( $Name, 1, "$Name MSwitch_Execute_Timer: Fehler bei Befehlsausfuehrung ERROR $Name: $errors " . __LINE__ ); } return; } if ( $param eq '3' ) { MSwitch_Exec_Notif( $hash, 'on', 'nocheck', '', 0 ); return; } if ( $param eq '4' ) { 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; } #################### sub MSwitch_ChangeCode($$) { my ( $hash, $option ) = @_; my $Name = $hash->{NAME}; my $x = 0; # exit secure #achtung perl5.30 while ( $option =~ m/(.*)\{(sunset|sunrise)(.*)\}(.*)/ ) { $x++; # exit secure last if $x > 20; # exit secure if ( defined $2 ) { my $part2 = eval $2 . $3; chop($part2); chop($part2); chop($part2); $option = $part2; $option = $1 . $option if ( defined $1 ); $option = $option . $4 if ( defined $4 ); } } return $option; } #################### sub MSwitch_Add_Device($$) { my ( $hash, $device ) = @_; my $Name = $hash->{NAME}; my @olddevices = split( /,/, ReadingsVal( $Name, '.Device_Affected', '' ) ); my $count = 1; LOOP7: foreach (@olddevices) { my ( $devicename, $devicecmd ) = split( /-AbsCmd/, $_ ); if ( $device eq $devicename ) { $count++; } } my $newdevices .= ',' . $device . '-AbsCmd' . $count; my $newset = ReadingsVal( $Name, '.Device_Affected', '' ) . $newdevices; $newdevices = join( ',', @olddevices ) . ',' . $newdevices; my @sortdevices = split( /,/, $newdevices ); @sortdevices = sort @sortdevices; $newdevices = join( ',', @sortdevices ); $newdevices = substr( $newdevices, 1 ); readingsSingleUpdate( $hash, ".Device_Affected", $newdevices, 1 ); return; } ################################### sub MSwitch_Del_Device($$) { my ( $hash, $device ) = @_; my $Name = $hash->{NAME}; my @olddevices = split( /,/, ReadingsVal( $Name, '.Device_Affected', '' ) ); my @olddevicesset = split( /#\[ND\]/, ReadingsVal( $Name, '.Device_Affected_Details', '' ) ); my @newdevice; my @newdevicesset; my $count = 0; LOOP8: foreach (@olddevices) { if ( $device eq $_ ) { $count++; next LOOP8; } push( @newdevice, $olddevices[$count] ); push( @newdevicesset, $olddevicesset[$count] ); $count++; } my ( $devicemaster, $devicedeleted ) = split( /-AbsCmd/, $device ); $count = 1; my @newdevice1; LOOP9: foreach (@newdevice) { my ( $devicename, $devicecmd ) = split( /-AbsCmd/, $_ ); if ( $devicemaster eq $devicename ) { my $newname = $devicename . '-AbsCmd' . $count; $count++; push( @newdevice1, $newname ); next LOOP9; } push( @newdevice1, $_ ); } $count = 1; my @newdevicesset1; LOOP10: foreach (@newdevicesset) { my ( $name, @comands ) = split( /#\[NF\]/, $_ ); my ( $devicename, $devicecmd ) = split( /-AbsCmd/, $name ); if ( $devicemaster eq $devicename ) { my $newname = $devicename . '-AbsCmd' . $count . '#[NF]' . join( '#[NF]', @comands ); push( @newdevicesset1, $newname ); $count++; next LOOP10; } push( @newdevicesset1, $_ ); } my $newaffected = join( ',', @newdevice1 ); if ( $newaffected eq '' ) { $newaffected = 'no_device' } my $newaffecteddet = join( '#[ND]', @newdevicesset1 ); #return; readingsBeginUpdate($hash); readingsBulkUpdate( $hash, ".Device_Affected", $newaffected ); readingsBulkUpdate( $hash, ".Device_Affected_Details", $newaffecteddet ); readingsEndUpdate( $hash, 0 ); my $devices = MSwitch_makeAffected($hash); my $devhash = $hash->{DEF}; my @dev = split( /#/, $devhash ); $hash->{DEF} = $dev[0] . ' # ' . $devices; } ################################### sub MSwitch_Debug($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $debug1 = ReadingsVal( $Name, '.Device_Affected', 0 ); my $debug2 = ReadingsVal( $Name, '.Device_Affected_Details', 0 ); my $debug3 = ReadingsVal( $Name, '.Device_Events', 0 ); $debug2 =~ s/:/ /ig; $debug3 =~ s/,/, /ig; readingsBeginUpdate($hash); readingsBulkUpdate( $hash, "Device_Affected", $debug1 ); readingsBulkUpdate( $hash, "Device_Affected_Details", $debug2 ); readingsBulkUpdate( $hash, "Device_Events", $debug3 ); readingsEndUpdate( $hash, 0 ); } ################################### sub MSwitch_Delete_Delay($$) { my ( $hash, $device ) = @_; my $Name = $hash->{NAME}; my $timehash = $hash->{helper}{delays}; MSwitch_LOG( $Name, 5, "$Name: Delays geloescht ! " ); if ( $device eq 'all' ) { foreach my $a ( keys %{$timehash} ) { my $inhalt = $hash->{helper}{delays}{$a}; RemoveInternalTimer($a); RemoveInternalTimer($inhalt); delete( $hash->{helper}{delays}{$a} ); } } else { foreach my $a ( keys %{$timehash} ) { my $pos = index( $a, "$device", 0 ); if ( $pos != -1 ) { RemoveInternalTimer($a); my $inhalt = $hash->{helper}{delays}{$a}; RemoveInternalTimer($a); RemoveInternalTimer($inhalt); delete( $hash->{helper}{delays}{$a} ); } } } } ################################### sub MSwitch_Clear_timer($) { my ( $hash, $device ) = @_; my $name = $hash->{NAME}; my $timehash = $hash->{helper}{timer}; foreach my $a ( keys %{$timehash} ) { my $inhalt = $hash->{helper}{timer}{$a}; RemoveInternalTimer($inhalt); $inhalt = $hash->{helper}{timer}{$a}; $inhalt =~ s/-/ /g; $inhalt = $name . ' ' . $inhalt; RemoveInternalTimer($inhalt); } delete( $hash->{helper}{timer} ); } ################################## # Eventsimulation sub MSwitch_Check_Event($$) { my ( $hash, $eventin ) = @_; my $Name = $hash->{NAME}; $eventin =~ s/~/ /g; my $dev_hash = ""; if ( $eventin ne $hash ) { if ( ReadingsVal( $Name, 'Trigger_device', '' ) eq "all_events" ) { my @eventin = split( /:/, $eventin ); $dev_hash = $defs{ $eventin[0] }; $hash->{helper}{testevent_device} = $eventin[0]; $hash->{helper}{testevent_event} = $eventin[1] . ":" . $eventin[2]; # $hash->{helper}{testevent_event} = $eventin[1] . ":" . $eventin[2]; } else { my @eventin = split( /:/, $eventin ); $dev_hash = $defs{ ReadingsVal( $Name, 'Trigger_device', '' ) }; $hash->{helper}{testevent_device} = ReadingsVal( $Name, 'Trigger_device', '' ); $hash->{helper}{testevent_event} = $eventin[0] . ":" . $eventin[1]; } } if ( $eventin eq $hash ) { my $logout = $hash->{helper}{writelog}; $logout =~ s/:/[#dp]/g; my $triggerdevice = ReadingsVal( $Name, 'Trigger_device', 'no_trigger' ); if ( ReadingsVal( $Name, 'Trigger_device', '' ) eq "all_events" ) { $dev_hash = $hash; $hash->{helper}{testevent_device} = 'Logfile'; $hash->{helper}{testevent_event} = "writelog:" . $logout; } elsif ( ReadingsVal( $Name, 'Trigger_device', '' ) eq "Logfile" ) { $dev_hash = $hash; $hash->{helper}{testevent_device} = 'Logfile'; $hash->{helper}{testevent_event} = "writelog:" . $logout; } else { $dev_hash = $defs{ ReadingsVal( $Name, 'Trigger_device', '' ) }; $hash->{helper}{testevent_device} = ReadingsVal( $Name, 'Trigger_device', '' ); $hash->{helper}{testevent_event} = "writelog:" . $logout; } } my $we = AnalyzeCommand( 0, '{return $we}' ); MSwitch_Notify( $hash, $dev_hash ); delete( $hash->{helper}{testevent_device} ); delete( $hash->{helper}{testevent_event} ); delete( $hash->{helper}{testevent_event1} ); return; } ######################################### sub MSwitch_makeAffected($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $devices = ''; my %saveaffected; my @affname; my $affected = ReadingsVal( $Name, '.Device_Affected', 'nodevices' ); my @affected = split( /,/, $affected ); LOOP30: foreach (@affected) { @affname = split( /-/, $_ ); $saveaffected{ $affname[0] } = 'on'; } foreach my $a ( keys %saveaffected ) { $devices = $devices . $a . ' '; } chop($devices); return $devices; } ############################# sub MSwitch_checktrigger(@) { my ( $own_hash, $ownName, $eventstellen, $triggerfield, $device, $zweig, $eventcopy, @eventsplit ) = @_; my $triggeron = ReadingsVal( $ownName, '.Trigger_on', '' ); my $triggeroff = ReadingsVal( $ownName, '.Trigger_off', '' ); my $triggercmdon = ReadingsVal( $ownName, '.Trigger_cmd_on', '' ); my $triggercmdoff = ReadingsVal( $ownName, '.Trigger_cmd_off', '' ); my $answer = ""; if ( $triggerfield =~ m/{(.*)}/ ) { my $SELF = $ownName; my $exec = "\$triggerfield = " . $1; eval($exec); } unshift( @eventsplit, $device ) if ReadingsVal( $ownName, 'Trigger_device', '' ) eq "all_events"; if ( ReadingsVal( $ownName, 'Trigger_device', '' ) eq "all_events" ) { $eventcopy = $device . ":" . $eventcopy; if ( $triggerfield eq "*" ) { $triggerfield = "*:*:*"; } } if ( $triggerfield eq "*" && ReadingsVal( $ownName, 'Trigger_device', '' ) ne "all_events" ) { $triggerfield = "*:*"; } $triggerfield =~ s/\*/.*/g; # erkennunhg der formartierung bis v1.66 ( <1.67) my $x = 0; while ( $triggerfield =~ m/(.*)(\()(.*)(\/)(.*)(\))(.*)/ ) { $x++; # exit secure last if $x > 20; # exit secure $triggerfield = $1 . $3 . "|" . $5 . $7; } ################ if ( $eventcopy =~ m/^$triggerfield/ ) { $answer = "wahr"; } return 'on' if $zweig eq 'on' && $answer eq 'wahr' && $eventcopy ne $triggercmdoff && $eventcopy ne $triggercmdon && $eventcopy ne $triggeroff; return 'off' if $zweig eq 'off' && $answer eq 'wahr' && $eventcopy ne $triggercmdoff && $eventcopy ne $triggercmdon && $eventcopy ne $triggeron; return 'offonly' if $zweig eq 'offonly' && $answer eq 'wahr'; return 'ononly' if $zweig eq 'ononly' && $answer eq 'wahr'; return 'undef'; } ############################### sub MSwitch_VUpdate($) { my ($hash) = @_; my $Name = $hash->{NAME}; readingsSingleUpdate( $hash, ".V_Check", $vupdate, 0 ); # my $devs = ReadingsVal( $Name, '.Device_Affected_Details', '' ); # # 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; # # 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; # # 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 ); #fhem("deletereading $Name Exec_cmd"); return; } ################################ sub MSwitch_backup($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $testreading = $hash->{READINGS}; my @areadings = ( keys %{$testreading} ); my %keys; open( BACKUPDATEI, ">MSwitch_backup_$vupdate.cfg" ) ; # Datei zum Schreiben öffnen print BACKUPDATEI "# Mswitch Devices\n"; # foreach my $testdevice ( keys %{ $modules{MSwitch}{defptr} } ) # { print BACKUPDATEI "$testdevice\n"; } print BACKUPDATEI "# Mswitch Devices END\n"; # print BACKUPDATEI "\n"; # HTML-Datei schreiben foreach my $testdevice ( keys %{ $modules{MSwitch}{defptr} } ) # { print BACKUPDATEI "#N -> $testdevice\n"; # foreach my $key (@areadings) { my $tmp = ReadingsVal( $testdevice, $key, 'undef' ); print BACKUPDATEI "#S $key -> $tmp\n"; } my %keys; foreach my $attrdevice ( keys %{ $attr{$testdevice} } ) #geht { print BACKUPDATEI "#A $attrdevice -> " . AttrVal( $testdevice, $attrdevice, '' ) . "\n"; } print BACKUPDATEI "#E -> $testdevice\n"; print BACKUPDATEI "\n"; } close(BACKUPDATEI); } ################################ sub MSwitch_backup_this($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $Zeilen = (""); my $Zeilen1 = ""; open( BACKUPDATEI, ") { $Zeilen = $Zeilen . $_; } close(BACKUPDATEI); $Zeilen =~ s/\n/[NL]/g; if ( $Zeilen !~ m/#N -> $Name\[NL\](.*)#E -> $Name\[NL\]/ ) { return "no Backupfile found\n"; } my @found = split( /\[NL\]/, $1 ); foreach (@found) { if ( $_ =~ m/#S (.*) -> (.*)/ ) # setreading { if ( $2 eq 'undef' || $2 eq '' || $2 eq ' ' ) { } else { $Zeilen1 = $2; readingsSingleUpdate( $hash, "$1", $Zeilen1, 0 ); } } if ( $_ =~ m/#A (.*) -> (.*)/ ) # setattr { my $cs = "attr $Name $1 $2"; my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { MSwitch_LOG( $Name, 1, "ERROR $cs" ); } } } MSwitch_LoadHelper($hash); return "MSwitch $Name restored.\nPlease refresh device."; } # ################################ sub MSwitch_Getsupport($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $out = ''; $out .= "Modulversion: $version\\n"; $out .= "Datenstruktur: $vupdate\\n"; $out .= "\\n----- Devicename -----\\n"; $out .= "$Name\\n"; $out .= "\\n----- Attribute -----\\n"; my %keys; foreach my $attrdevice ( keys %{ $attr{$Name} } ) #geht { my $tmp = AttrVal( $Name, $attrdevice, '' ); $tmp =~ s//\\>/g; $tmp =~ s/'/\\'/g; $out .= "Attribut $attrdevice: " . $tmp . "\\n"; } $out .= "\\n----- Trigger -----\\n"; $out .= "Trigger device: "; my $tmp = ReadingsVal( $Name, 'Trigger_device', 'undef' ); $out .= "$tmp\\n"; $out .= "Trigger time: "; $tmp = ReadingsVal( $Name, '.Trigger_time', 'undef' ); $tmp =~ s/~/ /g; $out .= "$tmp\\n"; $out .= "Trigger condition: "; $tmp = ReadingsVal( $Name, '.Trigger_condition', 'undef' ); $out .= "$tmp\\n"; $out .= "Trigger Device Global Whitelist: "; $tmp = ReadingsVal( $Name, '.Trigger_Whitelist', 'undef' ); $out .= "$tmp\\n"; $out .= "\\n----- Trigger Details -----\\n"; $out .= "Trigger cmd1: "; $tmp = ReadingsVal( $Name, '.Trigger_on', 'undef' ); $out .= "$tmp\\n"; $out .= "Trigger cmd2: "; $tmp = ReadingsVal( $Name, '.Trigger_off', 'undef' ); $out .= "$tmp\\n"; $out .= "Trigger cmd3: "; $tmp = ReadingsVal( $Name, '.Trigger_cmd_on', 'undef' ); $out .= "$tmp\\n"; $out .= "Trigger cmd4: "; $tmp = ReadingsVal( $Name, '.Trigger_cmd_off', 'undef' ); $out .= "$tmp\\n"; my %savedetails = MSwitch_makeCmdHash($hash); $out .= "\\n----- Device Actions -----\\n"; my @affecteddevices = split( /#\[ND\]/, ReadingsVal( $Name, '.Device_Affected_Details', 'no_device' ) ); foreach (@affecteddevices) { my @devicesplit = split( /#\[NF\]/, $_ ); $devicesplit[4] =~ s/'/\\'/g; $devicesplit[5] =~ s/'/\\'/g; $out .= "\\nDevice: " . $devicesplit[0] . "\\n"; $out .= "cmd1: " . $devicesplit[1] . " " . $devicesplit[3] . "\\n"; $out .= "cmd2: " . $devicesplit[2] . " " . $devicesplit[4] . "\\n"; $out .= "cmd1 condition: " . $devicesplit[9] . "\\n"; $out .= "cmd2 condition: " . $devicesplit[10] . "\\n"; $out .= "cmd1 delay: " . $devicesplit[7] . "\\n"; $out .= "cmd2 delay: " . $devicesplit[8] . "\\n"; $out .= "repeats: " . $devicesplit[11] . "\\n"; $out .= "repeats delay: " . $devicesplit[12] . "\\n"; $out .= "priority: " . $devicesplit[13] . "\\n"; $out .= "id: " . $devicesplit[14] . "\\n"; $out .= "comment: " . $devicesplit[15] . "\\n"; $out .= "cmd1 exit: " . $devicesplit[16] . "\\n"; $out .= "cmd2 exit: " . $devicesplit[17] . "\\n"; } $out =~ s/#\[dp\]/:/g; $out =~ s/#\[pt\]/./g; $out =~ s/#\[ti\]/~/g; $out =~ s/#\[sp\]/ /g; $out =~ s/#\[nl\]/\\n/g; $out =~ s/#\[se\]/;/g; $out =~ s/#\[dp\]/:/g; $out =~ s/\(DAYS\)/|/g; $out =~ s/#\[ko\]/,/g; #neu $out =~ s/#\[bs\]/\\/g; #neu asyncOutput( $hash->{CL}, "
Supportanfragen bitte im Forum stellen:Fhem-Forum
Bei Devicespezifischen Fragen bitte untenstehene Datei anhängen, das erleichtert Anfragen erheblich.
 

" ); return; } ################## sub MSwitch_Getconfig($) { my ($hash) = @_; my $Name = $hash->{NAME}; 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; $tmp =~ s/#\[sp\]/ /g; $tmp =~ s/#\[nl\]/\\n/g; $tmp =~ s/#\[se\]/;/g; $tmp =~ s/#\[dp\]/:/g; $tmp =~ s/\(DAYS\)/|/g; $tmp =~ s/#\[ko\]/,/g; #neu $tmp =~ s/#\[wa\]/|/g; $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" ) { } if ( $key eq ".Device_Events" ) { $tmp =~ s/#\[tr\]/ /g; } $out .= "#S $key -> $tmp\\n"; $count++; } # my %keys; foreach my $attrdevice ( keys %{ $attr{$testdevice} } ) #geht { my $tmp = AttrVal( $testdevice, $attrdevice, '' ); $tmp =~ s//\\>/g; $tmp =~ s/'/\\'/g; $out .= "#A $attrdevice -> " . $tmp . "\\n"; $count++; } $count++; $count++; my $client_hash = $hash->{CL}; my $ret = asyncOutput( $hash->{CL}, "Änderungen sollten hier nur von erfahrenen Usern durchgeführt werden.
" . "" . "" ); return; } ####################################################### sub MSwitch_Sysextension($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $count = 30; my $out = ReadingsVal( $Name, '.sysconf', '' ); $out =~ s/#\[sp\]/ /g; $out =~ s/#\[nl\]/\\n/g; $out =~ s/#\[se\]/;/g; $out =~ s/#\[dp\]/:/g; $out =~ s/#\[st\]/\\'/g; $out =~ s/#\[dst\]/\"/g; $out =~ s/#\[tab\]/ /g; $out =~ s/#\[ko\]/,/g; $out =~ s/#\[wa\]/|/g; $out =~ s/#\[bs\]/\\\\/g; my $client_hash = $hash->{CL}; asyncOutput( $hash->{CL}, "
Achtung! Hier angegebener Code greift direkt in das Programm 98_MSwitch ein und wird unmittelbar zu beginn der Routine X_Set ausgeführt

" ); return; } ################################ sub MSwitch_backup_all($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $answer = ''; my $Zeilen = (""); open( BACKUPDATEI, ") { $Zeilen = $Zeilen . $_; } close(BACKUPDATEI); foreach my $testdevice ( keys %{ $modules{MSwitch}{defptr} } ) # { my $devhash = $defs{$testdevice}; $Zeilen =~ s/\n/[NL]/g; if ( $Zeilen !~ m/#N -> $testdevice\[NL\](.*)#E -> $testdevice\[NL\]/ ) { $answer = $answer . "no Backupfile found for $testdevice\n"; } my @found = split( /\[NL\]/, $1 ); foreach (@found) { if ( $_ =~ m/#S (.*) -> (.*)/ ) # setreading { if ( $2 eq 'undef' || $2 eq '' || $2 eq ' ' ) { } else { readingsSingleUpdate( $devhash, "$1", $2, 0 ); } } if ( $_ =~ m/#A (.*) -> (.*)/ ) # setattr { my $cs = "attr $testdevice $1 $2"; my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { MSwitch_LOG( $testdevice, 1, "ERROR $cs" ); } } } my $cs = "attr $testdevice verbose 0"; my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { MSwitch_LOG( $testdevice, 1, "ERROR $cs" ); } MSwitch_LoadHelper($devhash); $answer = $answer . "MSwitch $testdevice restored.\n"; } return $answer; } ################################################ 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; $cont =~ s/\\/#[bs]/g; $cont =~ s/,/#[ko]/g; $cont =~ s/^#\[/#[eo]/g; $cont =~ s/^#\]/#[ec]/g; $cont =~ s/\|/#[wa]/g; if ( !defined $cont ) { $cont = ""; } if ( $cont ne '' ) { readingsSingleUpdate( $hash, ".sysconf", $cont, 0 ); } else { fhem("deletereading $name .sysconf"); } return; } ################################################ sub MSwitch_saveconf($$) { my ( $hash, $cont ) = @_; my $name = $hash->{NAME}; my $contcopy = $cont; $cont =~ s/#c\[sp\]/ /g; $cont =~ s/#c\[se\]/;/g; $cont =~ s/#c\[dp\]/:/g; my @changes; my $info = ""; my @found = split( /#\[EOL\]/, $cont ); foreach (@found) { if ( $_ =~ m/#Q (.*)/ ) # setattr { push( @changes, $1 ); } if ( $_ =~ m/#I (.*)/ ) # setattr { $info = $1; } if ( $_ =~ m/#VS (.*)/ ) # setattr { if ( $1 ne $vupdate ) { readingsSingleUpdate( $hash, ".wrong_version", $1, 0 ); return; } } if ( $_ =~ m/#S (.*) -> (.*)/ ) # setreading { if ( $2 eq 'undef' || $2 eq '' || $2 eq ' ' ) { delete( $hash->{READINGS}{$1} ); } else { my $newstring = $2; if ( $1 eq ".Device_Affected_Details" ) { $newstring =~ s/;/#[se]/g; $newstring =~ s/:/#[dp]/g; $newstring =~ s/\t/ /g; $newstring =~ s/ /#[sp]/g; $newstring =~ s/\\/#[bs]/g; $newstring =~ s/,/#[ko]/g; $newstring =~ s/^#\[/#[eo]/g; $newstring =~ s/^#\]/#[ec]/g; $newstring =~ s/\|/#[wa]/g; $newstring =~ s/#\[se\]#\[se\]#\[se\]/#[se]#[nl]/g; $newstring =~ s/#\[se\]#\[se\]/#[nl]/g; } if ( $1 eq ".sysconf" ) { } if ( $1 eq ".Device_Events" ) { $newstring =~ s/ /#[tr]/g; } readingsSingleUpdate( $hash, "$1", $newstring, 0 ); } } if ( $_ =~ m/#A (.*) -> (.*)/ ) # setattr { $attr{$name}{$1} = $2; } } MSwitch_set_dev($hash); if ( @changes > 0 ) { my $save = join( '|', @changes ); readingsSingleUpdate( $hash, ".change", $save, 0 ); } if ( $info ne "" ) { readingsSingleUpdate( $hash, ".change_info", $info, 0 ); } return; } ################################################ sub MSwitch_backup_done($) { my ($string) = @_; return unless ( defined($string) ); my @a = split( "\\|", $string ); my $Name = $a[0]; my $answer = $a[1]; my $hash = $defs{$Name}; delete( $hash->{helper}{RUNNING_PID} ); my $client_hash = $hash->{helper}{RESTORE_ANSWER}; $answer =~ s/\[nl\]/\n/g; foreach my $testdevice ( keys %{ $modules{MSwitch}{defptr} } ) # { my $devhash = $defs{$testdevice}; MSwitch_Createtimer($devhash); } asyncOutput( $client_hash, $answer ); return; } ########################################### sub MSwitch_Execute_randomtimer($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $param = AttrVal( $Name, 'MSwitch_RandomTime', '0' ); my $min = substr( $param, 0, 2 ) * 3600; $min = $min + substr( $param, 3, 2 ) * 60; $min = $min + substr( $param, 6, 2 ); my $max = substr( $param, 9, 2 ) * 3600; $max = $max + substr( $param, 12, 2 ) * 60; $max = $max + substr( $param, 15, 2 ); my $sekmax = $max - $min; my $ret = $min + int( rand $sekmax ); return $ret; } ############################################ sub MSwitch_replace_delay($$) { my ( $hash, $timerkey ) = @_; my $name = $hash->{NAME}; my $time = time; my $ltime = TimeNow(); MSwitch_LOG( $name, 5, "----------------------------------------" ); MSwitch_LOG( $name, 5, "$name: MSwitch_replace_delay-> $timerkey" ); MSwitch_LOG( $name, 5, "----------------------------------------" ); my ( $aktdate, $akttime ) = split / /, $ltime; my $hh = ( substr( $timerkey, 0, 2 ) ); my $mm = ( substr( $timerkey, 2, 2 ) ); my $ss = ( substr( $timerkey, 4, 2 ) ); my $referenz = time_str2num("$aktdate $hh:$mm:$ss"); if ( $referenz < $time ) { $referenz = $referenz + 86400; } if ( $referenz >= $time ) { } $referenz = $referenz - $time; my $timestampGMT = FmtDateTimeRFC1123($referenz); return $referenz; } ############################################################ sub MSwitch_repeat($) { my ( $msg, $name ) = @_; my $incomming = $_[0]; my @msgarray = split( /\|/, $incomming ); $name = $msgarray[1]; my $time = $msgarray[2]; my $cs = $msgarray[0]; my $hash = $defs{$name}; $cs =~ s/\n//g; MSwitch_LOG( $name, 5, "----------------------------------------" ); MSwitch_LOG( $name, 5, "$name: Repeat -> " . $cs ); MSwitch_LOG( $name, 5, "----------------------------------------" ); if ( $cs =~ m/set (.*)(MSwitchtoggle)(.*)/ ) { $cs = MSwitch_toggle( $hash, $cs ); MSwitch_LOG( $name, 5, "$name: fround toggle -> " . $cs ); } MSwitch_LOG( $name, 5, "$name: execute repeat $time -> " . $cs ); if ( AttrVal( $name, 'MSwitch_Debug', "0" ) ne '2' ) { if ( $cs =~ m/{.*}/ ) { eval($cs); if ($@) { MSwitch_LOG( $name, 1, "$name MSwitch_repeat: ERROR $cs: $@ " . __LINE__ ); } } else { my $errors = AnalyzeCommandChain( undef, $cs ); if ( defined($errors) ) { MSwitch_LOG( $name, 1, "$name Absent_repeat $cs: ERROR : $errors -> Comand: $cs" ); } } } delete( $hash->{helper}{repeats}{$time} ); } ######################### sub MSwitch_Createnumber($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $number = AttrVal( $Name, 'MSwitch_RandomNumber', '' ) + 1; my $number1 = int( rand($number) ); readingsSingleUpdate( $hash, "RandomNr", $number1, 1 ); return; } ################################ sub MSwitch_Createnumber1($) { my ($hash) = @_; my $Name = $hash->{NAME}; my $number = AttrVal( $Name, 'MSwitch_RandomNumber', '' ) + 1; my $number1 = int( rand($number) ); readingsSingleUpdate( $hash, "RandomNr1", $number1, 1 ); return; } ############################### sub MSwitch_Safemode($) { my ($hash) = @_; my $Name = $hash->{NAME}; if ( AttrVal( $Name, 'MSwitch_Safemode', '0' ) == 0 ) { return; } my $time = gettimeofday(); $time =~ s/\.//g; my $time1 = int($time); my $count = 0; my $timehash = $hash->{helper}{savemode}; foreach my $a ( keys %{$timehash} ) { $count++; if ( $a < $time1 - 1000000 ) # für 10 sekunden { delete( $hash->{helper}{savemode}{$a} ); $count = $count - 1; } } $hash->{helper}{savemode}{$time1} = $time1; if ( $count > $savecount ) { MSwitch_LOG( $Name, 1, "Das Device " . $Name . " wurde automatisch deaktiviert ( Safemode )" ); $hash->{helper}{savemodeblock}{blocking} = 'on'; readingsSingleUpdate( $hash, "Safemode", 'on', 1 ); foreach my $a ( keys %{$timehash} ) { delete( $hash->{helper}{savemode}{$a} ); } $attr{$Name}{disable} = '1'; } return; } ############################################################### sub MSwitch_EventBulk($$$$) { my ( $hash, $event, $update, $from ) = @_; my $name = $hash->{NAME}; MSwitch_LOG( $name, 5, "aufruf eventbulk eventin: " . $event ); my $showevents = AttrVal( $name, "MSwitch_generate_Events", 1 ); return if !defined $event; return if !defined $hash; if ( $hash eq "" ) { return; } my @evtparts = split( /:/, $event ); $update = '1'; my $evtsanzahl = @evtparts; MSwitch_LOG( $name, 5, "aufruf eventzahl: " . $evtsanzahl ); if ( $evtsanzahl < 3 ) { my $eventfrom = $hash->{helper}{eventfrom}; unshift( @evtparts, $eventfrom ); $evtsanzahl = @evtparts; } my $evtfull = join( ':', @evtparts ); $evtparts[2] = '' if !defined $evtparts[2]; $event =~ s/\[dp\]/:/g; $evtfull =~ s/\[dp\]/:/g; $evtparts[1] =~ s/\[dp\]/:/g if $evtparts[1]; $evtparts[2] =~ s/\[dp\]/:/g if $evtparts[2]; $event =~ s/\[dst\]/"/g; $evtfull =~ s/\[dst\]/"/g; $evtparts[1] =~ s/\[dst\]/"/g if $evtparts[1]; $evtparts[2] =~ s/\[dst\]/"/g if $evtparts[2]; $event =~ s/\[#dp\]/:/g; $evtfull =~ s/\[#dp\]/:/g; $evtparts[1] =~ s/\[#dp\]/:/g if $evtparts[1]; $evtparts[2] =~ s/\[#dp\]/:/g if $evtparts[2]; MSwitch_LOG( $name, 5, "aufruf eventbulk eventfullout: " . $evtfull ); MSwitch_LOG( $name, 5, "aufruf eventbulk event " . $event ); MSwitch_LOG( $name, 5, "aufruf eventbulk eventset " . $hash->{eventsave} ); if ( ReadingsVal( $name, 'last_event', '' ) ne $event && $event ne '' && $hash->{eventsave} ne 'saved' ) { $hash->{eventsave} = "saved"; readingsBeginUpdate($hash); readingsBulkUpdate( $hash, "EVENT", $event, $showevents ) if $event ne ''; readingsBulkUpdate( $hash, "EVTFULL", $evtfull, $showevents ) if $evtfull ne ''; readingsBulkUpdate( $hash, "EVTPART1", $evtparts[0], $showevents ) if $evtparts[0] ne ''; readingsBulkUpdate( $hash, "EVTPART2", $evtparts[1], $showevents ) if $evtparts[1] ne ''; readingsBulkUpdate( $hash, "EVTPART3", $evtparts[2], $showevents ) if $evtparts[2] ne ''; readingsBulkUpdate( $hash, "last_event", $event, $showevents ) if $event ne ''; readingsEndUpdate( $hash, $update ); } return; } ########################################################## # setzt reihenfolge und testet ID 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; } my %devicedetails = MSwitch_makeCmdHash($name); my %new; foreach my $device (@devices) { # $execids beinhaltet auszuführende ids gesetzt bei init my $key1 = $device . "_id"; MSwitch_LOG( $name, 6, "$name: device hat die ID $device - $devicedetails{$key1}" ); MSwitch_LOG( $name, 6, "$name: zulaessige IDS - @execids " ); if (! grep { $_ eq $devicedetails{$key1} } @execids ) { MSwitch_LOG( $name, 6, "$name: abbruch -> unzulaessige ID " ); next; } my $key = $device . "_priority"; my $prio = $devicedetails{$key}; MSwitch_LOG( $name, 6, "$name: device hat die priority $device - $prio" ); $new{$device} = $prio; $hash->{helper}{priorityids}{$device} = $prio; } my @new = %new; my @newlist; for my $key ( sort { $new{$a} <=> $new{$b} } keys %new ) { if ( $key ne "" && $key ne " " ) { push( @newlist, $key ); my $key = $key . "_priority"; } } my $anzahl = @newlist; MSwitch_LOG( $name, 5, "$name: anzahl $anzahl" ); @devices = @newlist if $anzahl > 0; @devices = () if $anzahl == 0; return @devices; } ########################################################## ########################################################## # setzt reihenfolge und testet ID sub MSwitch_sort(@) { my ( $hash, $typ, @devices ) = @_; my $name = $hash->{NAME}; MSwitch_LOG( $name, 5, "$name: zuweisung der reihenfolge" ); my %devicedetails = MSwitch_makeCmdHash($name); my %new; foreach my $device (@devices) { my $key = $device . $typ; my $prio = $devicedetails{$key}; MSwitch_LOG( $name, 5, "$name: device hat $typ $device - $devicedetails{$key}" ); $new{$device} = $prio; } my @new = %new; my @newlist; for my $key ( sort { $new{$a} <=> $new{$b} } keys %new ) { if ( $key ne "" && $key ne " " ) { push( @newlist, $key ); } } my $anzahl = @newlist; MSwitch_LOG( $name, 5, "$name: anzahl $anzahl" ); @devices = @newlist if $anzahl > 0; return @devices; } ########################################################## sub MSwitch_set_dev($) { # setzt NOTIFYDEF my ($hash) = @_; my $name = $hash->{NAME}; my $not = ReadingsVal( $name, 'Trigger_device', '' ); if ( $not ne 'no_trigger' ) { if ( $not eq "all_events" ) { delete( $hash->{NOTIFYDEV} ); if ( ReadingsVal( $name, '.Trigger_Whitelist', '' ) ne '' ) { $hash->{NOTIFYDEV} = ReadingsVal( $name, '.Trigger_Whitelist', '' ); } } else { $hash->{NOTIFYDEV} = $not; my $devices = MSwitch_makeAffected($hash); $hash->{DEF} = $not . ' # ' . $devices; } } else { $hash->{NOTIFYDEV} = 'no_trigger'; delete $hash->{DEF}; } } ############################################################## sub MSwitch_dec($$) { # ersetzungen direkt vor befehlsausführung my ( $hash, $todec ) = @_; my $name = $hash->{NAME}; $todec =~ s/\n//g; $todec =~ s/#\[wa\]/|/g; $todec =~ s/\$NAME/$hash->{helper}{eventfrom}/; $todec =~ s/MSwitch_Self/$name/; my $x = 0; while ( $todec =~ m/(.*?)(\$SELF)(.*)?/ ) { my $firstpart = $1; my $secondpart = $2; my $lastpart = $3; $todec = $firstpart . $name . $lastpart; $x++; last if $x > 10; #notausstieg } # setmagic ersetzun $x = 0; while ( $todec =~ m/(.*)\[(.*)\:(.*)\](.*)/ ) { $x++; # notausstieg notausstieg last if $x > 20; # notausstieg notausstieg my $setmagic = ReadingsVal( $2, $3, 0 ); $todec = $1 . $setmagic . $4; } return $todec; } ################################################################ sub MSwitch_clearlog($) { my ( $hash, $cs ) = @_; my $name = $hash->{NAME}; open( BACKUPDATEI, ">./log/MSwitch_debug_$name.log" ); print BACKUPDATEI localtime() . " Starte Log\n"; # close(BACKUPDATEI); } ################################################################ sub MSwitch_debug2($$) { my ( $hash, $cs ) = @_; my $name = $hash->{NAME}; return if $cs eq ''; open( BACKUPDATEI, ">>./log/MSwitch_debug_$name.log" ) ; # Datei zum Schreiben öffnen print BACKUPDATEI localtime() . ": -> $cs\n"; # close(BACKUPDATEI); } ################################## sub MSwitch_LOG($$$) { my ( $name, $level, $cs ) = @_; my $hash = $defs{$name}; if ( ( AttrVal( $name, 'MSwitch_Debug', "0" ) eq '2' || AttrVal( $name, 'MSwitch_Debug', "0" ) eq '3' ) && ( $level eq "6" || $level eq "1" ) ) { MSwitch_debug2( $hash, $cs ); } $level = 5 if $level eq "6"; #$hash->{helper}{writelog} ='on'; Log3( $name, $level, $cs ); #delete( $hash->{helper}{writelog} ); } ######################### sub MSwitch_confchange($$) { # change wenn folgende einträge vorhanden #I testinfo #Q dummy1#zu schaltendes geraet#device my ( $hash, $cs ) = @_; my $name = $hash->{NAME}; MSwitch_clearlog($hash); $cs = urlDecode($cs); $cs =~ s/#\[sp\]/ /g; my @changes = split( /\|/, $cs ); foreach my $change (@changes) { my @names = split( /#/, $change ); # afected devices my $tochange1 = ReadingsVal( $name, ".Device_Affected", "" ); my $oldname = $names[0] . "-"; my $newname = $names[1] . "-"; my @devices = split( /,/, $tochange1 ); my $x = 0; foreach (@devices) { $_ =~ s/$oldname/$newname/g; $devices[$x] = $_; $x++; } my $newdevices = join( ',', @devices ); readingsSingleUpdate( $hash, ".Device_Affected", $newdevices, 0 ); #details my $tochange2 = ReadingsVal( $name, ".Device_Affected_Details", "" ); my @devicesdetails = split( /#\[ND\]/, $tochange2 ); $x = 0; foreach (@devicesdetails) { $_ =~ s/$oldname/$newname/g; $devicesdetails[$x] = $_; $x++; } $tochange2 = join( '#[ND]', @devicesdetails ); $x = 0; while ( $tochange2 =~ m/(.*?)($names[0])(.*)?/ ) { my $firstpart = $1; my $secondpart = $2; my $lastpart = $3; $tochange2 = $firstpart . $names[1] . $lastpart; $x++; last if $x > 10; #notausstieg } readingsSingleUpdate( $hash, ".Device_Affected_Details", $tochange2, 0 ); } fhem("deletereading $name .change"); fhem("deletereading $name .change_info"); } ######################### sub MSwitch_makefreecmd($$) { #ersetzungen und variablen für freecmd my ( $hash, $cs ) = @_; my $name = $hash->{NAME}; my $ersetzung = ""; # entferne kommntarzeilen $cs =~ s/\\#/comment/g; $cs =~ s/#.*\n//g; $cs =~ s/comment/#/g; # entferne zeilenumbruch $cs =~ s/\n//g; # ersetze Eventvariablen $ersetzung = ReadingsVal( $name, "EVTPART3", "" ); $cs =~ s/\$EVTPART3/$ersetzung/g; $ersetzung = ReadingsVal( $name, "EVTPART2", "" ); $cs =~ s/\$EVTPART2/$ersetzung/g; $ersetzung = ReadingsVal( $name, "EVTPART1", "" ); $cs =~ s/\$EVTPART1/$ersetzung/g; $ersetzung = ReadingsVal( $name, "EVENT", "" ); $cs =~ s/\$EVENT/$ersetzung/g; $ersetzung = ReadingsVal( $name, "EVENTFULL", "" ); $cs =~ s/\$EVENTFULL/$ersetzung/g; $cs =~ s/\$NAME/$hash->{helper}{eventfrom}/; my $x = 0; while ( $cs =~ m/(.*?)(\$SELF)(.*)?/ ) { my $firstpart = $1; my $secondpart = $2; my $lastpart = $3; $cs = $firstpart . $name . $lastpart; $x++; last if $x > 10; #notausstieg } # setmagic ersetzun MSwitch_LOG( $name, 5, "vor freecmd: " . $cs ); $x = 0; while ( $cs =~ m/(.*)\[(.*)\:(.*)\](.*)/ ) { $x++; # notausstieg notausstieg last if $x > 20; # notausstieg notausstieg my $setmagic = ReadingsVal( $2, $3, 0 ); $cs = $1 . $setmagic . $4; } MSwitch_LOG( $name, 5, "after freecmd: " . $cs ); return $cs; } ################################# 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 =item helper =item summary MultiswitchModul =item summary_DE Modul zum event und zeitgesteuerten Schalten von Devices etc. =begin html

MSwitch

    MSwitch
    MSwitch is an auxiliary module that works both event- and time-controlled.
    For a detailed description see Wiki

    Define

      define < Name > MSwitch;

      Beispiel:

        define Schalter MSwitch

      The command creates a device of type MSwitch named Switch.
      All further configuration takes place at a later time and can be modified and adjusted within the device at any time


    Set
    • inactive - sets the device inactive
    • active - sets the device active
    • backup MSwitch - creates a backup file with the configuration of all MSwitch devices
    • del_delays - deletes all pending timed commands
    • exec_cmd1 - immediate execution of the command branch1
    • exec_cmd2 - immediate execution of command branch2
    • fakeevent [event] - simulation of an incoming event
    • wait [sec] - no acceptance of events for given period



    Get
    • active_timer show - displays a list of all pending timers and delays
    • active_timer delete - deletes all pending timers and delays. Timers are recalculated
    • get_config - shows the config set associated with the device
    • restore_Mswitch_date this_device - restore the device from the backupfile
    • restore_Mswitch_date all_devices - restore all MSwitchdevices from the backupfile



    Attribute
    • MSwitch_Help: 0.1 - displays help buttons for all relevant fields
    • MSwitch_Debug: 0,1,2,3 - 1. switches test fields to Conditions etc. / 2. Testmode, no active cmds / 3. pure development mode
    • MSwitch_Expert: 0.1 - 1. enables additional options such as global triggering, priority selection, command repetition, etc.
    • MSwitch_Delete_Delays: 0.1 - 1. deletes all pending delays when another suitable event arrives
    • MSwitch_Include_Devicecmds: 0,1 - 1. all devices with own command set (set?) are included in affected devices
    • MSwitch_Include_Webcmds: 0.1 - 1. all devices with existing WbCmds are included in affected devices
    • MSwitch_Include_MSwitchcmds: 0.1 - 1. all devices with existing MSwitchcmds are included in affected devices
    • MSwitch_Activate_MSwitchcmds: 0.1 - 1. activates the attribute MSwitchcmds in all devices
    • MSwitch_Lock_Quickedit: 0,1 - 1. activates the lock of the selection field 'affected devices'
    • MSwitch_Ignore_Types: - List of all device types that are not displayed in the 'affected devices'
    • MSwitch_Trigger_Filter - List of events to ignore
    • MSwitch_Extensions: 0.1 - 1. Enables additional option Devicetogggle
    • MSwitch_Startdelay - delays the start of MSwitch after Fhemstart by the specified time in seconds. Recommended: 30 seconds
    • MSwitch_Inforoom - contains a room name where MSwitches are displayed in detail
    • MSwitch_Mode: Full, Notify, Toggle - Device Operation Mode
    • MSwitch_Condition_Time: 0.1 - activation of the trigger conditions for timed triggering
    • MSwitch_Safemode: 0.1 - 1. aborts all actions of the device if more than 20 calls per second take place
    • MSwitch_RandomTime - see Wiki
    • MSwitch_RandomNumber - see Wiki
=end html =begin html_DE

MSwitch

    MSwitch
    MSwitch ist ein Hilfsmodul , das sowohl event-, als auch zeitgesteuert arbeitet. Das Modul übernimmt alle Arten von Schaltvörgängen in Abhängigkei von Bedingungen etc. Es vereint die Funktionalität von diversen Hilfsmodulen unter einem Modul ( z.b DOIF,Notify,At,Watchdog,Dummy etc.)
    Für eine umfangreche Beschreibung siehe Wiki: https://wiki.fhem.de/wiki/MSwitch

    Define

      define < Name > MSwitch;

      Beispiel:

        define Schalter MSwitch

      Der Befehl legt ein Device vom Typ MSwitch an mit dem Namen Schalter.
      sämtliche weitere Konfiguration erfolgt zu einem späteren Zeitpunkt und kann innerhalb des Devices jerderzeit verändert und angepasst werden


    Set
    • inactive
      setzt das Device inaktiv
    • active
      setzt das Device aktiv
    • backup MSwitch
      legt eine Backupdatei mit der Konfiguration aller MSwitchdevices an
    • del_delays
      löscht alle anstehenden timer für zeitversetzte Befehle
    • exec_cmd1
      sofortiges Ausführen des Kommandozweiges1
    • exec_cmd2
      sofortiges Ausführen des Kommandozweiges2
    • fakeevent [event]
      simulation eines eingehenden Events
    • wait [sek]
      keine annahme von Events für vorgegebenen Zeitraum



    Get
    • active_timer show - zeigt eine Liste aller anstehenden Timer und Delays
    • active_timer delete - löscht alle anstehenden Timer und Delays. Timer werden neu berechnet
    • get_config - zeigt den dem Device zugeordneten Configsatz
    • restore_Mswitch_date this_device - restore des Devices aus dem Backupfile
    • restore_Mswitch_date all_devices - restore aller MSwitchdevices aus dem Backupfile



    Attribute
    • MSwitch_Help:0,1
      zeigt Hilfebuttons zu allen relevanten Feldern
    • MSwitch_Debug:0,1,2,3,4
      1. schaltet Prüffelder zu Conditions etc. an
      2. Simulationsmode -  schreibt alle Aktionen in ein seperates Log, Befehle werden aber nicht ausgeführt
      3. schreibt alle Aktionen in ein seperates Log
      4. reiner Entwicklungsmode (ausführlichere Readings / Layout etc.)
    • MSwitch_Expert:0,1
      1. aktiviert Zusatzoptionenv wi z.B globales triggern, prioritätsauswahl, Befehlswiederholungesn etc.
    • MSwitch_Delete_Delays:0,1
      1. löscht alle anstehenden Delays bei erneutem eintreffen eines erneutem passenden Events
    • MSwitch_Include_Devicecmds:0,1
      1. alles Devices mit eigenem Befehlssatz (set <´DEVICE> ?) werden in affected Devices einbezogen
    • MSwitch_Include_Webcmds:0,1
      1. alles Devices mit vorhandenen WbCmds werden in affected Devices einbezogen
    • MSwitch_Include_MSwitchcmds:0,1
      1. alles Devices mit vorhandenen MSwitchcmds werden in affected Devices einbezogen
    • MSwitch_Activate_MSwitchcmds:0,1
      1. aktiviert in allen Devices das Attribut MSwitchcmds
    • MSwitch_Lock_Quickedit:0,1
      1. aktiviert die sperre des Auswahlfeldes 'affected devices'
    • MSwitch_Ignore_Types:
      Liste aller DeviceTypen , die nicht in den 'affected devices' dargestellt werden'
      Hier kann eine durch Leerzeichen getrennte Listen vom Modultypen angegeben werden , die nicht berücksichtigt wird.
      Lternativ kann eine Selektion nach den Regeln der "devspec" erfolgen. Zu beachten ist , das die auswahl in diesem fall "negiert" wird, d.H es erfolgt dann eine Auswahl der zu berücksichtigten Parameter. Die Angabe muss in diesem Fall in Anführungszeichen gesetzt werden.
      zB : "TYPE=MSwitch" - berücksichtigt alle Devices vom Typ MSwitch
      zB : "TYPE!=MSwitch" - unterdrückt alle Devices vom Typ MSwitch
    • MSwitch_Trigger_Filter - Liste aller zu ignorierenden Events
    • MSwitch_Extensions:0,1
      1. aktiviert zusatzoption Devicetogggle
    • MSwitch_Startdelay(wert)
      verzögert den Start von MSwitch nach Fhemstart um die angegebene Zeit in Sekunden . Empfohlen:30 sekunden
    • MSwitch_Inforoom
      beinhalttet einen Raumnamen , in dem MSwitches detailiert dargestellt werden
    • MSwitch_Mode:Full,Notify,Toggle
      Betriebsmodus des Devices
    • MSwitch_Condition_Time:0,1
      1. zuschaltung der Triggerconditions für zeitgesteuertes Auslösen
    • MSwitch_Safemode:0,1
      1. bricht alle Aktionen des Devices ab, wenn mehr als 20 Aufrufe pro Sekunde erfolgen. Sicherheitsoption, um Endlosschleifen zu vermeiden.
    • MSwitch_RandomTime
      siehe Wiki
    • MSwitch_RandomNumber
      siehe Wiki
    • MSwitch_Read_Log
    • MSwitch_Generate_Events
    • MSwitch_Comments
    • MSwitch_Condition_Time
=end html_DE