Skip to content

IsWe() logic, namespace usage and holiday quirks

I'm in the second day of digging through (and understanding) the IsWe() subroutine.

In that effort, I started documenting/testing it:

sub IsWe {
    my $when = shift;
    my $wday = shift;

    # if $when is true (probably meant defined) and a date of the form
    # YYYY-MM-DD or MM-DD, then $date will be true
    my $date = ($when && $when =~ m/^((\d{4})-)?([01]\d)-([0-3]\d)$/);
    # that match - if it matches - leaves us with
    # $1 - always undefined
    # $2 - year (if defined, else undefined)
    # $3 - month
    # $4 - day

    # if $when false or $when given as yesterday/tomorrow AND $date not true,
    # define when as "state"
    $when = "state" if (!$when || ($when !~ m/^(yesterday|tomorrow)$/ && !$date));

    if (!defined($wday)) {                             # $wday probably means "week-day"
        if ($date) {                                   # if $wday is not defined and $date is
                                                       # let's compute weekday from the date given
            my ($y,$m,$d) = ($2 ? $2-1900 : (localtime())[5], $3-1, $4);
            $wday = (localtime(mktime(1,1,1,$d,$m,$y,0,0,-1)))[6];
        }
        else {                                         # neither $wday nor $date is defined
            $wday = (localtime(gettimeofday()))[6];    # get $wday from localtime (basically "now")
        }
    }

    my ($we, $wf);
#    for my $h2we (split(",", AttrVal("global", "holiday2we", ""))) {
#        my $b = $date ? CommandGet(undef, "$h2we $when") : ReadingsVal($h2we, $when, 0);
#        if ($b && $b ne "none") {
#            return 0 if ($h2we eq "noWeekEnd");
#            $we = 1 if ($b && $b ne "none");
#        }
#        $wf = 1 if ($h2we eq "weekEnd");
#    }

    if (!$wf && !$we) {
        $we = ($when eq "yesterday" ? ($wday == 0 || $wday == 1) :
              ($when ne "tomorrow"  ? ($wday == 6 || $wday == 0) :
                                      ($wday == 5 || $wday == 6))); # tomorrow
    }

    return $we ? 1 : 0;
}

Of course the usual FHEM-related problems of not distinguishing between true/defined still apply.

Descending into the pit of its usage (who uses it and how). In this quest, I found a good example in the 73_AutoShuttersControl.pm module. The module is ok in that it tries to detach it's namespace from main, by immediately defining it's own namespace as FHEM::AutoShuttersControl and to fetch only that from main that is required.

sub IsWe() {
    my $we = main::IsWe();
    return $we;
}

sub IsWeTomorrow() {
    my $we = main::IsWe('tomorrow');
    return $we;
}

However, there is room for improvement. Use an argument pass-through:

sub IsWe {
    return main::IsWe(@_);
}

and then of course removing the IsWeTomorrow facade: d582626b


Now for 95_holiday.pm

It seems to be a very baroque system of defining absolute and relative dates and I yet have to dig into that, but it's inevitable for a full unterstanding of - among others - IsWe.

For now, correcting some spelling errors, removing "return undef", prototypes and indentation has to be sufficient: a3bf87df