Skip to content
ggodart edited this page Jan 12, 2021 · 2 revisions

The .mht File

Do you create X10_Item or X10_Appliance objects in various places? Do you find it difficult to remember what X10 codes are being used and where? Wouldn't you like to have all of these types of things in one easy-to-read location? This is exactly why the MHT (MisterHouse Table) file was created. In addition to being consolidated, this file also makes the task of initializing such objects easier. All you do is add the item in the proper format, and MisterHouse will take care of all of the proper code generation automatically.

The file format is very simple. The first line should start with the text 'Format = A'. This line allows for future changes to the format of the file. Each item is then listed, one per line, following a simple format. See the list of types and their formats at the bottom of this document. When MisterHouse starts or reloads its code, this file is parsed and the appropriate code is automatically generated, which is then used by MisterHouse as if you had written it yourself. The file you should create is named items.mht. The file that MisterHouse auto generates is called items.mhp. You should never hand edit the MHP file - always make your changes to the MHT file.

The generated code will create the object, name it, create the groups, add the object to the groups, etc.

You can add comments to the file, just use a # as the first character on the line.

If you use the text HIDDEN in the group name, the item will be set as hidden. This will prevent it from showing up on the Tk and web menus.

As an example, here is a shortened version of my MHT file:

Format = A

# noloop=start
#
# Type Address Name Groups Other Info
#

# A Appliances
X10A, A2, Humidifier, Appliances|Downstairs|Living_Room

# C Motion Detectors & Switches using RR501 Transceiver in Study
X10A, C1, Front_Porch_Motion, Hidden
X10A, C2, Front_Porch_Darkness, Hidden

# D Downstairs Lights
X10I, D1, Formal_Living_Lights, Lights|Downstairs|Formal_Living_Room

# noloop=stop
# Voice Commands
VOICE, Humidifier, Humidifier

The above MHT entries would result in the following auto-generated MH code, located in the MHP file:

# noloop=start
# A Appliances
$Humidifier = new X10_Appliance('A2', );
$Appliances = new Group;
$Appliances -> add($Humidifier);
$Downstairs -> add($Humidifier);
$Living_Room = new Group;
$Living_Room -> add($Humidifier);

# C Motion Detectors & Switches using RR501 Transceiver in Study
$Front_Porch_Motion = new X10_Appliance('C1', );
$Hidden -> add($Front_Porch_Motion);
$Front_Porch_Motion -> hidden(1);

$Front_Porch_Darkness = new X10_Appliance('C2', );
$Hidden -> add($Front_Porch_Darkness);
$Front_Porch_Darkness -> hidden(1);

# D Downstairs Lights
$Formal_Living_Lights = new X10_Item('D1', );
$Lights = new Group;
$Lights -> add($Formal_Living_Lights);
$Downstairs = new Group;
$Downstairs -> add($Formal_Living_Lights);
$Formal_Living_Room = new Group;
$Formal_Living_Room -> add($Formal_Living_Lights);

# noloop=stop
# Voice Commands
my $v_Humidifier_state;
$v_Humidifier = new Voice_Cmd("Humidifier [ON,OFF]");
if ($v_Humidifier_state = said $v_Humidifier) {
  set $Humidifier $v_Humidifier_state;
  speak "Turning Humidifier $v_Humidifier_state";
}

The noloop=start and noloop=stop Tags

MisterHouse is pretty much one great big loop which runs house-keeping and user code over and over and over again. Some things are best done once and not repeated in main loop. So a # noloop=start and # noloop=stop was added to MisterHouse. Any code that only needs to be run once is handle between these two tags. Any code outside this loop will be run in the main loop.

In the MHT file, almost everything belongs between these two tags. That is except the VOICE tag. When the Perl code is generated from the MHT file the generated Voice code needs to be in the main loop. It is there for recommended to add VOICE commands at the end of the MHT file after the closing # noloop=stop< tag.

Also note that the '# noloop=start and # noloop=stop tags are a matching pair. If one or the other is missing then the gnashing of teeth will begin as MisterHouse doesn't run as expected.

MHT File Basic Entry Format

In general, all entry types begin with a line type identifier which is followed by various parameters such as Address, Name, Grouplist, and/or Other.

  • Address: This is the first parameter used in the object's "new" method.
  • Name: This is what the object is to be named.
  • Grouplist: This is one or more groups that this object is to be included in. Multiple groups should be separated by the | pipe character.
  • Other: This is an optional field typically used as the second parameter in the object's "new" method.
TYPE, Address, Name, GroupList, Other

List of MHT Types

You can find a list of Item types here and protocols, interfaces and how to guides here. In addition to this you can use CODE to include one line of Perl code in the MHT file. This can be useful when you want to change an objects attributes. Use this tag with caution, it is not meant to replace user code files.

#
X10I, M11, HutchLights, M|LivingRoom(0;3), PLM
# The following attributes are used in conjunction with Floorplan_svg.pl
CODE, $HutchLights->set_fp_icons(on => 'fp-hutch-on.png', off => 'fp-hutch-off.png');
CODE, $HutchLights->{fp_icon_w} = 20;  # px
CODE, $HutchLights->{fp_icon_h} = 100; # px

See Floor Plan for details on what the above means.

Reverse Engineering MHT Support

The MHT file is parsed by ./lib/read_table_A.pl

To understand how a specific type is implemented, start by opening ./lib/read_table_A.pl and studying the code used to parse the MHT options. There are two steps in parsing. The first parse is at the top of the file where the type is retrieved. The remaining comma separated items remain split into @item_info

my(@item_info) = split(',\s*', $record);
my $type = uc shift @item_info;

Next locate the type in read_table_A.pl. Each item has unique logic used to create an instance definition for the item. Most if not all items datafile $object and $grouplist although looking at the code I see that some of the items have broken logic for group list so be carful; the logic in the example below is the correct way to quote the remaining parameters. In the item specific code you will see how the various fields in the MHT file are used to create the perl object.

    elsif($type eq "X10A") {
        ($address, $name, $grouplist, @other) = @item_info;
        $other = join ', ', (map {"'$_'"} @other); # Quote data
        $object = "X10_Appliance('$address', $other)";
    }

If you look at the bottom of the file, you will see how $object and $group list are used to make the code stubs that create instances of the item's perl object.

Lastly, you will need to search for the object definition. These definitions can be nearly anywhere but by convention should be in the lib directory. In the example above the require line is very likely the location of the object definition. Otherwise it is also customary for item object definitions to be in a file named for the object (i.e. SERIAL creates an instance of Serial_Item() which is defined in ./lib/Serial_Item.pm) As a last resort you can always search the MH code for the definition using egrep:

mh@deb:/usr/local/misterhouse/mh$ egrep -r "package +X10_Appliance" *
lib/X10_Items.pm:package X10_Appliance;
lib/X10_Items.pm:package X10_Appliancelinc;

The object definition is where you should look to see how the "other" parameters are used.

Clone this wiki locally