Skip to content
ggodart edited this page Jan 14, 2021 · 13 revisions

This page is intended to provide hints and tips for developers.

Why is my code not working

Many errors are flagged by MisterHouse on a Reload, but some can be difficult to spot.

Here is a list of common errors in Perl code which you can check for.

  • Perl code is case-sensitive. Check your capitalisation. In MisterHouse, $Day is right, and $day is wrong.
  • Commands end with ; But there should be no ; at the end of a line starting a do loop, an if, or a sub-routine.
  • Unmatched parentheses, curly braces, quotes and delimiters.
  • A line starting with if requires the condition to go between parentheses, eg if (time_now('2:00 PM')) { }
  • if ($string = "abc") is wrong. The correct syntax is if ($string eq "abc")
  • if ($number = 1) is wrong. The correct syntax is if ($number == "abc")
  • Many perl scripts (including the code in MisterHouse) start with use strict; This means that new variables must be pre-declared as $my variable. This error is flagged as Oops1: Global symbol "$variable" requires explicit package name at (eval 57) line 1056. (See below for a point on this which is specific to MisterHouse)
  • When declaring more than one variable, use parentheses: my ($variable1, $variable2);
  • VB programmers may accidentally type string$ instead of $string
  • A very long line may appear to have a carriage return at the end, but not have a carriage return at the end
  • # (which starts a Remark statement) may appear to be the first character of a line of code, but in fact be in the middle of a line of code
  • A dot may be missing before or after " or =
  • It is easy to forget to put \ before / or \ or $ or . or " or @ etc
  • In Windows and DOS, file-paths are typed as c:\filepath. In Perl this must appear as c:/filepath or (in some contexts for Windows users) c:\\filepath
  • ( or [ might be typed when { is required (etc)
  • It is easy to forget ~ after = in matches and substitutions
  • Wrong number of arguments in subroutines
  • Local variables lose their values outside their own section of code. A global variable should not be declared inside a sub-routine.
  • foreach must be typed, not for each
  • foreach $item (@list) is right. foreach $item @list is wrong.
  • In a substitution, s/(text1).+(text2)/ may fail by looking too far ahead. You may have meant s/(text1).+?(text2)/. The ? tells Perl to keep the number of characters between text 1 and text 2 to a minimum.
  • dot in a match will not match \n unless you use the /s modifier
  • A match or substitution in a string containing newlines may fail if you forget the /s modifier at the end
  • Arrays start at 0 not 1

This is a vital point which applies only to MisterHouse, not to Perl generally.

A new variable in a loop module is taken out of the loop if it is typed in the first column on the left of the screen. This is not a problem if the value of the variable is fixed from the outset (eg my $sky_color = 'blue'), but will cause an error if the value of the variable is based on the value of another variable, my $circumference = $radius * 3.14. A line like this must be indented by at least one space.

INI PARAMETERS

All the entries in mh.ini are read on MisterHouse Startup and on a Reload. They are stored in the %config_parms array. So, for example, if you added:

  myparm1=a b c

This will be available as $config_parms{myparm1}

Logging

These docs refer to MisterHouse versions after pull request #820 where print_log was renamed to print_log_simple and the new print_log was created which allows the developer to call print_log with 3 parameters e.g.

print_log("this is my message","WARNING","my subroutine")

Will produce an entry in print.log like this;

13/01/2021 17:08:06 [my subroutine] WARNING: this is my message

The second parameter severity should be one of EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFORMATIONAL, NONE or DEBUG, if NONE is set, the print_log_private() should just return and not print anything.

If MisterHouse cannot find a print_log_private() subroutine, it will pass the message concatenated with the severity and source to print_log_simple.

If you have created a print_log_private() subroutine, then your subroutine will be called instead of passing the message to print_log_simple. You can then decide on the destination of the message (email, SMS, twitter, whatever) or even the print_log_simple() subroutine.

A sample print_log_private() is provided in mh/code/examples/print_log_private.pl.

See here for the logging function definitions.

Clone this wiki locally