NAME

mh - MisterHouse Home Automation Program


SYNOPSIS

mh is a perl program for time, event, web, socket, and voice based home control functions. It currently runs on Windows 95/98/NT and on Unix platforms, including Linux.

perl objects are used for various types of objects to give a powerful but concise programming interface. Here is some example code:

   $dishwasher = new X10_Item 'B1';         # B1 is the dishwasher X10 code 

   set $dishwasher ON if time_now '10:30 PM';

   speak "I am now closing the curtains at $Time_Now" if time_now "$Time_Sunset + 0:15"; 

   speak "The time is $Time_Now" if time_cron '30,35,40,45,50 6 * * 1-5'; 

   play(file => 'stairs_creek*.wav') if state_now $movement_sensor eq ON;

   $v_bedroom_curtain = new Voice_Cmd '[open,close] the bedroom curtains';

   curtain_on('bedroom', $state) if $state = said $v_bedroom_curtain;


Usage Options

mh [options] [files]

options are controlled in the mh\bin\mh.ini file. You can override the default mh.ini parameters in a 'private' parm file and point to that with a mh_parms environmental variable.

files is a list of members in the -code_dir that you want to run. The default is to run all .pl files.


Usage Examples

These give the help text:

   mh -h

   mh -help

This is the normal usage:

   mh

This will only run the 3 specified members:

   mh items.pl test1.pl test2.pl

This will disable the tk interface and change the code dir to the Bruce directory:

   mh -tk 0 -code_dir c:\mh\code\Bruce

This will log all 'print' statements to /mh/test1.log and turn on all serial related debug messages:

   mh -log_file test1.log -debug serial


Installation

The system requirements and installation instructions are detailed in

mh/docs/install.html

There is also a FAQ that covers misc topics in

mh/docs/faq.html


DESCRIPTION


mh overview

Items and events are defined by using your favorite text editor and creating members of perl code in a directory of your choice. For example, all the code that runs my house is in the /mh/code/bruce directory.

After starting mh, in addition to the timed, serial, or X10 based events that you defined, you can trigger mh actions with any of the following:

  - Voice commands.  On Windows platforms, you can use the MSVOICE icon in your tray 

    (the green V) to control the Voice Recognition (VR) mode (manual, 

    keyword-activated, or continuous). You also select your TTS (Text To Speech) 

    voice with MSVOICE.

    On Unix platforms you can use the Festival TTS engine and pick among different

    accents and languages.  On Linux, you can install IBM's ViaVoice SDK 

    to enable Voice Recognition. 

  - A web browser pointed to http://localhost:8080 .  In addition to several

    example web interfaces, if you are familiar with HTML, you can write your 

    own customized interface.

  - Typing any voice command in a telnet window.  This is customizable

    with the telnet.pl module.

  - Typing any voice command in the command box in the mh tk gui window.

  - Typing any voice command from a dos box, using the mh/bin/house command

  - Having any program write voice commands to the 'xcmd_file' (see mh.ini)

  - Triggering on user defined Socket or Serial port events.

Here are the basic steps of the mh program:

   1: Read config files and initialize things

 

       Setup the OLE Text To Speech (TTS) object or Festival socket port

       Setup the OLE Voice Recognition object or socket to the viavoice_server on linux

       Setup the serial objects 

       Setup the tcp socket ports

   2: Read and evaluate/compile the user event code into the mh_temp.user_code file:

       Optional *.mht files are processed by mh/lib/read_table_*.pl, creating *.mhp files

       Objects are evaluated and created. 

       Everything else is put into a &user_loop function (at the end of mh_temp.user_code file).

   3: Loop until exit, each pass executing:

       Set global time/date variables 

       Check for voice commands 

       Read/write socket data 

       Read/write serial data 

       Check for timers actions 

       Check for external command files 

       Evaluate the &user_loop function 

       Sleep for a while (default is 100 milliseconds), so mh does not hog the cpu.

The interpreted nature of perl allows us to change/add/delete an event member quickly, without re-starting mh. After changing code, you tell mh to re-load the user event code (step 2 above). If there is a syntax error with the new code, the previous version of the code is re-loaded.

Re-loading 20 event members with 1500 lines of event code takes about 2 seconds. With a 50 millisecond sleep time, mh takes about 2->5% of the cpu and loops about 18 times per second on our our 150 MHz PPro system.


Perl Info

There is lots of good perl info is at http://www.perl.com . The reference book is ``Programming Perl, 2nd edition'' by Larry Wall, Tom Christensen, & Randall Schwartz. ISBN 1-56592-149-6. It is available from http://www.oreilly.com . ``The Perl Cookbook'' is another good book that has a ton of examples in it.

For those of you using the compiled, instead of the interpreted, version of mh, the standard perl documentation can be found at http://www.perl.com/pub/v/documentation , http://language.perl.com/CPAN/doc/manual/html/index.html and/or http://www.activestate.com/ActivePerl/docs

Perl can be a pretty intimidating language to learn, due to its many options and functions, but for the purposes of using it to code mh events, there are only a few simple rules to keep in mind. Here are a few of them:

   Variables start with a $ 

   Strings are quoted with ' or ". Use " if you want variables within 

   the string to be substituted. 

   Commands end with ; 

   Comments start with # 

   You can implement block comments with =begin, =cut records, as follows:

       

      print "this will run\n";

      =begin

      print "this";

      print " will not run\n";

      =cut

      print "all done\n";

   Do loops start and end with { }

   If statements can be done either of the following ways:

   

      if (test) {action} 

      action if test;

   If tests are == (or !=) for numeric data and eq (or ne) for string data.

   Object methods can be specified 2 ways.

   Here are both examples on how use the method 'set' for an X10 object:

      set $dishwasher ON;    # Indirect object form

      $dishwasher->set(ON);  # Classic 'object oriented' form

   Regular expressions are used to parse strings.  They are very powerful

   and can be quite complex, but here are a few simple rules:

      They are triggered with the =~ operator

      By default, they are delimited with //

      .  stands for any character (including blanks)

      \S stands for non blank characters (\s is for blanks)

      \d stands for digits

      * is a modifier that means 'zero or more of the previous type of character'

      + is a modifier that means 'one  or more of the previous type of character'

      ? is a modifier that means 'zero or one  of the previous type of character'

      () captures whatever is inside for use via $1, $2, $3, etc

   For example:

    $data = 'Mar 25, 1998 - 11:53 AM EST / 1998.03.25 1653 UTC';

    $date = $1, $year = $2, $time = $3 if $data =~ /(.+), (\d\d\d\d) - (.+) EST /;

   On Windows systems, path names can use the Unix convention of / instead

   of the DOS convention of \.  You can also use \, by typically you must

   'escape it' (e.g. 'c:\\mh' instead of 'c:\mh').  


List of supported hardware interfaces

You can get the ActiveHome kit for $50 from at http://www.x10.com . This includes a 2 way X10 CM11 interface a lamp module and a couple of remote controllers. They also sell the CM17 firecracker interface which mh supports, but is a one way interface only (does not receive X10 signals).

X10.com also sells a $50 IR transimiter that works through the CM17 interface. Info is at http://www.x10.com/products/ux17a_bj2.htm. This is supported via the mh IR_Item object.

Europeans can get X10 stuff from http://www.intellihome.be and http://www.hwg-telekom.de

Weeder Technologies, http://www.weedtech.com , offers the following kits priced from $30 to $50 each. All of these kits can share the same serial port:

   2 way X10 interface 

   12 bit Digital IO (can be input or output, switch or button) 

   8 port Analog IO, 10 bit resolution 

   Caller ID, name and number 

   Outgoing DTMF phone monitor

The HomeBase.pm module to supports the JDS interfaces, http://www.jdstechnologies.com . See member mh/code/public/test_homebase.pl for example code.

The Homevison.pm module to supports HomeVision controler, http://www.csi3.com/homevis2.htm . This controler does 2 way X10, 2 way IR, 24 digital IO, and can output its menus to TV. See member mh/code/public/test_homevision.pl for example code.

The CPU-XA, Ocelot, and Leopard controlers from Applied Digital Inc (http://www.appdig.com/adicon.html ) are supported thru network calls to the cpuxad deamon, part of the XALIB package.

There is a $30 (assembled) pic base IR receiver you can order from the Netherlands ($3 shipping):

  http://www.evation.com/irman/ 

In addition to the mh/code/bruce/irman.html code, there there is free winamp, windows, and linux software for it. The schematics that it is built from are also posted on the net (elsewhere), but for $30, it hardly seems worth building it from scratch.

Here are 2 LCD displays with programable serial interfaces:

  http://www.crystalfontz.com/products/634/index.html  $60

  http://linuxcentral.com  $80 ($101 with keypad interface)

The first display is a bit newer, bigger, brighter, cheaper. But the second one has a version that include a 4x4 keypad interface (keypad available from DigiKey for $20). Both are 4 lines x 20 characters (they also have a 4x40, but no keypad interface). I ordered the 2nd one from linuxcentral, with a keypad from http://www.digikey.com (pn CKN6011-ND or GH5010-ND). A comparison of the 2, plus some nifty linux software for them, can be found at http://lcdproc.omnipotent.net

An example on how to use these displays is in mh/code/bruce/lcdproc.pl. See the header of that file for more info.

Using a these devices, and a new MP3 perl module/player, we should be able to build ourselves a mh based home MP3 Stereo! Someone has already built a perl base one at http://aelix.cs.iastate.edu/lcdat/

Here are a few other devices which look useful, but have not had code written for them:

 http://www.nirvis.com/  $180 2-way IR device

 http://www.cc-concepts.com/  iButton DigiLock interface as electronic keychain

The Serial_Item object can read and write to any serially connect device. There is example code in the code/public directory that shows how to interface to a ham radio TNC receiver to decode and track a GPS transmitters position.

Byterunner offers lots of types of serial cards: http://www.byterunner.com

Good sources of information on the WX200/WM918 weather stations are at http://wx200.planetfall.com/ and http://www.weatherwatchers.org/wxstation/WX-200/ . $200->$300 at Radio Shack or $200 from http://www.heartlandamerica.com (search for weather, model WW22- 3350)

There is also now a new WMR-918, which is a wireless version, available for about $350. An mh interface is being worked on.

iButton is a family of devices that can all talk to a '1 wire' interface. Here are some urls and prices:

  http://www.ibutton.com (pick shop online)

    - $15 DS9097U-009 or -S09 + DS1402D-DR8l for the serial interface

      Note:  The DS9097, DS9097E, or parallel port adaptors will not work with mh

    -  $3 DS1990A-F5  for 64 bit ID buttons.

 

  http://www.pointsix.com

    - They also sell the $15 interface (under iButton Products) 

    - $10 for a 1 port relay card

    - $10 for a 2 port digital input or ouptut card

    - $6  for a 1820 temperature sensor

    - Info on how to wire up a 1 wire bus: 

      http://www.pointsix.com/cgi-bin/PointSix.cgi?AppNotes&;app010

If you want more reliable VR without having to use a headset, you can try these to digital array microphones:

 - Labtec LVA-7280 ClearVoice Digital Microphone ($130)

   http://www.labtec.com/product/family.cfm?CategoryID=2

 - Andrea Desktop array DA-400 ($150)

   http://www.andreaelectronics.com

The Labtec has a push button on top to turn it on and off and a red/green LED that blinks green when sound is heard. The Andrea has a slide switch on the side to turn it on and off. The Andrea has a bit clearer sound and is about 2/3 the size. Having a hardware switch to disable VR is handy.

Both of these mikes are ment to be used when you are at the desktop. The idea is that they filter out background noise better, so you can use them in slightly noise environments, where headsets were normally required.


List of startup options

The complete list of valid startup options is in the mh.ini file. Here are a few of the more important ones and their defaults:

code_dir=\mh\code\test

Points to the directory that has the user code files in it.

html_root=$Pgm_Root/web
html_file=mh_default/index.html

Points to where the web interface html files are.

http_port=8080

Use 80 if you want to use the normal web port (i.e. http://localhost ). If using something other than 80 (because you already have a web server running), add :port to url (e.g. http://localhost:8080 ).

server_telnet_port=23

Use 23 to enable access via 'telnet localhost', if you are running the mh/code/testtelnet.pl member. If you use a different port, you can still get to the port with 'telnet localhost port_number'.

diagnostics=1

Set this (or w=1) to enable perl -w warning messages on potential code errors. mh runs about 10% slower with this option on.

run=perl_script

This parms allow the compile mh.exe to act as a general purpose perl interpreter, so we can run any arbitrary perl script, without having to have perl installed. See the get_weather.bat, get_tv_grid.bat, or set_clock.bat files for examples. This also allows is to use the mh run command to spawn a separate mh process to run longer running perl steps, even if we do not have perl installed. A Win32 'fork' command would be cleaner, but alas, no forks.

 

debug=
log=

You can use the -debug and -log and options to turn on debug and/or log the console errata to a file. For example:

  mh -debug http -log http_socket.log

will turn on socket related debug messages and log all errata to the file http_socket.log

 

  

time_start=
time_stop=
time_increment=

Use time_start and time_stop to run mh in 'fast test mode', useful for debugging events. The time_increment parm sets how many simulated seconds to increment per pass. Default is 60. If only time_start is specified, normal mode will resume when the current time is reached. If time_stop is specified, mh will exit when reached. These parameters can be any time/date string, as recognized by the time_now function (see docs)

Here are some examples:

  mh -time_start 0 -time_stop 24 -tk 0 -voice_text 0

  mh -time_start "6 AM" -time_stop "11 PM"  -time_increment 1

  mh -time_start "5/14 7:10" -time_stop "5/15 10 PM" -time_increment 300

 


List of global variables

Time/Date Variables

  $Time_Startup, $Time_Startup_time, $Time_Sunrise, $Time_Sunset

  $Time_Now, $Date_Now, $Year_Month_Now

  $Second, $Minute, $Hour, $Mday, $Wday, $Day, $Month, $Year, $Holiday

  $New_Second, $New_Minute, $New_Hour, $New_Day, $New_Month, $New_Year

  $Season, $Weekday, $Weekend $Time_Of_Day

  %Moon

The complete list of global variables can be found on the Widgets menu of the default web page or at the top of mh/bin/mh.

The %Moon array has $Moon{phase}, $Moon{brightness}, $Moon{age}, and $Moon{new,first,full,last} entries.

The $Time_Now and $Date_Now variables return a formated time and date.

The $New_* variables are true only on the pass that we enter a new Second, Minute, Hour, etc.

$Startup is true on the first pass after starting mh.

$Reload is true when the Reload(F1) is requested AND the code been reloaded because one or more code members have been changed.

$Reread is always true after Reload(F1), even if no code members have changed.


List of objects and their methods

File_Item

You can use File_Item to read a line of data from a file. Note: These methods currently read the entire file, so if have big files (say, >1 meg) we want to read, we should invent some new methods.

  Methods:

     new('file_name')

     name         : Returns 'file_name'

     read_all     : Returns contents for the file. If used in a list context,

                    a list is returned, otherwise a string of all the lines.

     read_head    : Returns the first few lines of a file.  See file_head.

     read_tail    : Returns the last  few lines of a file.  See file_tail.

     read_random  : Reads a random record. 

                    This also re-sets the index to the random position.

     read_next    : Reads the next record, according to the index.

     read_current : Reads the current record, according to the index.

     index        : Which record was last read.  A couple of notes:

                      - The index is saved between mh sessions.

                      - If you use a File_Item that does not yet have 

                        an index set, a random index will be used and stored.

     set_index    : Set the index. 

     set_watch('flag') : Sets the 'changed' time check.  

     changed      : Returns 0 if the file was not changed since a set_watch call.

                    When the file changes:

                     - If 'flag' was specified in the new method, 'flag' is returned.

                     - Otherwise, it returns the number of seconds since a set_watch call.

     said         : Returns data added to a file since the last call.

                    Only one record is returned per call.

                    This is useful for monitoring log files.

                    See mh/code/bruce/shoutcast.pl  for an example.

  Examples:

     $f_deep_thoughts = new File_Item("$Pgm_Root/data/remarks/deep_thoughts.txt");

     my $thought = read_next $f_deep_thoughts;

     set_index $f_deep_thoughts 1;

     $f_weather_forecast = new File_Item("$Pgm_Root/data/web/weather_forecast.txt");

     set_watch $f_weather_forecast;

     display name $f_weather_forecast if changed $f_weather_forecast;

     $shoutcast_log = new File_Item 'd:/shoutcast/sc_serv.log';  

     print "Log data: $state" if $New_Second and $state = said $shoutcast_log;

Generic_Item

You can use this object to store and query arbitrary data. This is more useful than 'my' variables, if you need to share data between code files, since 'my' variables are local to a code file. States of these items are also saved/restored when mh is stopped/started.

All other items that have states (e.g. X10_Item, Serial_Item, iButton, Voice_Cmd, Group) inherit all Generic_Item methods.

  Methods:

     new

     state        :

     state_now    :

     set          :

     hidden(1/0)        :  If set to 1, the object will not show up on Tk or Web menus.

     tie_items($item)   :  If the state of the generic_item changes, then 

                           the state of $item will be set to that same state

     untie_items($item) :  Untie $item

     tie_events($code)  :  It the state of the generic_item changes, then

                           Code string $code will trigger, with the variable

                           $state getting expanded.

     untie_items($code) :  Untie $code

     get_chaged_by      :  Returns which tied object caused this objects state to change.

The tie/untie methods can be done conditionally, so you can change what is tied to what on the fly. If you do this, however, you need to also make sure you also make the tie* methode call on $Reload, as the objects tie items/events are currently not stored between reloads.

  Examples:

     $tv_grid = new Generic_Item;

     set $tv_grid 'channel 2 from 7:00 to 8:00 on 1/24 for This Old House';

     speak "tv set to $state" if $state = state_now $tv_grid;

     $wakeup_time = new Generic_Item;

     speak "Your wakeup time is set for $state" if $state = state_now $wakeup_time;

     speak "Time to wake up" if time_now state $wakeup_time;

   # Since Voice_Cmd objects inherit Generic_Items methods, we can 

   # use tie_items and tie_event like this:

     $indoor_fountain    = new X10_Appliance('OB');

     $v_indoor_fountain  = new Voice_Cmd 'Indoor fountain [on,off]';

     $v_indoor_fountain -> tie_items($indoor_fountain);

     $v_indoor_fountain -> tie_event('speak "Ok, fountain was turned $state"');

     if ($state = state_now $test_button) {

        my $ref = get_changed_by $test_button;

        print_log "Test button's was set to $state by $ref->{object_name}" if $ref;

     }

See mh/code/examples/generic_item.pl for more examples. See mh/code/examples/test_tie.pl for more examples on how to tie/untie items/events.

Group

You can use this object to group and operate on groups of items:

  Methods:

     new(@item_list)

     add(@item_list)

     set  

     state        : Returns the last state that the group was set to

     state_log    : Returns a list array of the last max_state_log_entries (mh.ini parm)

                    time_date stamped states.

  Examples:

     $outside_lights = new Group($light1, $light2, $light3);

     $outside_lights-> add($light4, $light5);

     $outside_lights-> add($light6);

     set $outside_lights ON if time_now("$Time_Sunset + 0:15");

See mh/code/examples/test_group.pl for more examples.

iButton_Item

This is used to query and/or control an iButton device (for more info on iButton, see the hardware section). To enable ibutton support in mh, set the mh.ini parm ibutton_port.

  Methods:

     new $id

     set $state   : Sets the item to the specified state.

     state        : Returns the last state that was received or sent

     state_now    : Returns the state that was received or sent in the current pass.

     state_log    : Returns a list array of the last max_state_log_entries (mh.ini parm)

                    time_date stamped states.

     read_temp    : Returns the temperature of temperature devices.

   In addition to the above, all of the methods provided by the Hardware/iButton/Device.pm 

   module are available (documented in mh/lib/site/Hardware/iButton/Device.pm).

   

   

   These methods are also part of the iButton module, but not associated with an object: 

     scan        $family : Returns a object list of iButton devices that match $family 

     scan_report $family : Returns a report of      iButton devices that match $family 

     monitor             : Checks the one wire bus for iButton activity

     connect             : Connect to the one wire bus

     disconnect          : Disconnect to the one wire bus

   The $id required when creating new iButton_Item is the 16 hex character (64 bit) iButton id that

   is unique to every device.  This is often printed on the larger devices.  If not, you can use: 

      $v_iButton_list      = new Voice_Cmd "List all the iButton buttons";

      print_log &iButton::scan_report if said $v_iButton_list;

   The last 2 characters are CRC bits and are optional.  If missing (i.e. you only specify 

   the first 14 characters), mh will calculate it.

   

   The first 2 characters are the iButton family type.  Here is a list of family types:  

     Field Index:

      ------------

      (1) Family code in hex

      (2) Number of regular memory pages

      (3) Length of regular memory page in bytes

      (4) Number of status memory pages

      (5) Length of status memory page in bytes

      (6) Max communication speed (0 regular, 1 Overdrive)

      (7) Memory type (see below)

      (8) Part number in iButton package

      (9) Part number in non-iButton package

      (10) Brief descriptions

      

      (1)   (2)  (3)  (4)  (5)  (6)  (7)   (8)   (9)   (10)

      -------------------------------------------------------

      01,    0,   0,   0,   0,   1,   0, DS1990A,DS2401,Unique Serial Number

      02,    0,   0,   0,   0,   0,   0, DS1991,DS1205, MultiKey iButton

      04,   16,  32,   0,   0,   0,   1, DS1994,DS2404,4K-bit NVRAM with Clock

      05,    0,   0,   0,   0,   0,   0, DS2405,,Single Addressable Switch

      06,   16,  32,   0,   0,   0,   1, DS1993,DS2403,4K-bit NVRAM

      08,    4,  32,   0,   0,   0,   1, DS1992,DS2402,1K-bit NVRAM

      09,    4,  32,   1,   8,   1,   2, DS1982,DS2502,1K-bit EPROM

      0A,   64,  32,   0,   0,   1,   1, DS1995,DS2416,16K-bit NVRAM

      0B,   64,  32,  40,   8,   1,   3, DS1985,DS2505,16K-bit EPROM

      0C,  256,  32,   0,   0,   1,   1, DS1996,DS2464,64K-bit NVRAM

      0F,  256,  32,  64,   8,   1,   3, DS1986,DS2506,64K-bit EPROM

      10,    0,   0,   0,   0,   0,   0, DS1920,DS1820,Temperature iButton with Trips

      11,    2,  32,   1,   8,   0,   2, DS1981,DS2501,512-bit EPROM

      12,    4,  32,   1,   8,   0,   4, DS2407,,Dual Addressable Switch

      13,   16,  32,  34,   8,   0,   3, DS1983,DS2503,4K-bit EPROM

      14,    1,  32,   0,   0,   0,   5, DS1971,DS2430A,256-bit EEPROM, plus

      64-bit

      OTP

      15,    0,   0,   0,   0,   1,   0, DS87C900,,Lock Processor

      16,    0,   0,   0,   0,   0,   0, DS1954,,Crypto iButton

      18,    4,  32,   0,   0,   1,   6, DS1963S,4K-bit Transaction iButton with

      SHA

      1A,   16,  32,   0,   0,   1,   6, DS1963,,4K-bit Transaction iButton

      1C,    4,  32,   0,   0,   1,   6, DS2422,,1K-bit EconoRAM with Counter

      Input

      1D,   16,  32,   0,   0,   1,   6, DS2423,,4K-bit EconoRAM with Counter

      Input

      1F,    0,  32,   0,   0,   0,   0, DS2409,,One-Wire Net Coupler

      20,    3,   8,   0,   0,   1,   9, DS2450,,Quad A-D Converter

      21,   16,  32,   0,   0,   1,   8, DS1921,,Temperature Recorder iButton

      23,   16,  32,   0,   0,   1,   7, DS1973,DS2433,4K-bit EEPROM

      22                                 DS1822 temperature button   

      40,   16,  32,   0,   0,   0,   1, DS1608,,Battery Pack Clock

  Examples:

    $v_iButton_connect = new Voice_Cmd "[Connect,Disconnect] to the iButton bus";

    if ($state = said $v_iButton_connect) {

      if ($state eq 'Connect') {

        print_log &iButton::connect($config_parms{iButton_port});

      }

      else {

        print_log &iButton::disconnect;

      }

    }

    $ib_bruce  = new iButton '010000012345ef';

    speak 'Hi Bruce'  if ON  eq state_now $ib_bruce;

    speak 'Later'     if OFF eq state_now $ib_bruce;

    $ib_relay1 = new iButton '12000000123456ff';

    $v_iButton_relay1    = new Voice_Cmd "Turn relay1 [on,off]";

    if ($state = said $v_iButton_relay1) {

       print_log "Setting iButton relay1 to $state";

       set $ib_relay1 $state;

    }

    $ib_temp1  = new iButton '1000000029a14f';

    $ib_temp2  = new iButton '1000000029f5d6';

    my @ib_temps = ($ib_temp1, $ib_temp2);

    $v_iButton_readtemp  = new Voice_Cmd "Read the iButton temperature [1,2]";

    if ($state = said $v_iButton_readtemp) {

       my $b = $ib_temps[$state-1];

       my $temp = read_temp $b;

       print_log "Temp for sensor $state: $temp F";

       logit("$config_parms{data_dir}/iButton_temps.log",  "$state: $temp");

    }

    if ($New_Second and !($Minute % 5)) {

       run_voice_cmd 'Read the iButton temperature 1' if $Second == 11;

       run_voice_cmd 'Read the iButton temperature 2' if $Second == 22;

    }

IR_Item

This object controls IR transmiters. Currently only the X10 IR Commander (http://www.x10.com/products/ux17a_bj2.htm) is supported. The X10 IR Commander receives commands from the wireless CM17 (firecracker) interface.

Currently, you must use the X10 supplied software (http://www.x10.com/commander.htm and/or ftp://ftp.x10.com/pub/applications/commander/) to program the IR Commander to use the codes for your various remotes.

  Methods:

     new $type, $code : Creates a new Item.  

        Here are the valid types:

           TV, VCR, CAB, CD, SAT, DVD

        Currently, $code simply controls if 2 or 3 digits are transmited for channels:

           2digit  (this is the default if $code is not spedified)

           3digit

     state        : Returns the last state that was sent

     state_now    : Returns the state that was sent in the current pass.

     state_log    : Returns a list array of the last max_state_log_entries (mh.ini parm)

                    time_date stamped states.

     set $command : Sends out commands to the IR device.  Here is a list of valid commands:

                    Note:  Commands are case insensitive

        POWER      MUTE      

        CH+        CH-      

        VOL+       VOL-     

        1          2        

        3          4        

        5          6        

        7          8        

        9          0        

        MENU       ENTER    

        FF         REW      

        RECORD     PAUSE     

        PLAY       STOP     

        AVSWITCH   DISPLAY  

        UP         DOWN      

        LEFT       RIGHT    

        SKIPDOWN   SKIPUP   

        TITLE      SUBTITLE 

        EXIT       OK       

        RETURN   

  Examples:

    $TV = new IR_Item 'TV';

    $v_tv_control = new  Voice_Cmd("tv [power,on,off,mute,vol+,vol-,ch+,ch-]");

    set $TV $state if $state = said $v_tv_control;

    $VCR = new IR_Item 'vcr', '3digit';

    set $VCR "12,RECORD" if time_cron('59 19 * * 3');

    set $VCR "STOP"      if time_cron('00 20 * * 3');

Process_Item

You can use this object to run external programs. On Win32 systems, the Win32::Process function is used. On Unix systems, the fork function is used. On either system, the following methods work in the same way:

  Methods:

     new('program1 arguments', 'program2 arguments', ...)

     set('program1 arguments', 'program2 arguments', ...)

     add('program3 arguments', 'program4 arguments', ...)

        If you specify more than one program, they are run sequentially.  done_now returns

        1 after the last program is done.

        If program starts with &, then 'program arguments' is eval-ed as an internal mh function.

        Otherwise, 'program arguments' is run as an external command.

        On Windows, the &-> eval trick is supposed to work with perl 5.6+ (which has fork), but

        unfortunatly, it causes perl to crash often, so is probably not useful yet.

     start          : Starts the process.

     stop           : Stops the process.

                      If not process is specified, all active Process_Items are stopped.

     done           : Returns the time (seconds since epoch) that the process finished.  If

                      the process has been started, but has not yet finished, it returns 0.

     done_now       : Is true for the pass that the process finished on.

  Examples:

     my $slashdot_news = "$Pgm_Root/data/web/slashdot_news.txt";

     $p_slashdot_news = new Process_Item("get_slashdot_news > $slashdot_news");

     start $p_slashdot_news if time_now('6:30 AM');

     display $slashdot_news if done_now $p_slashdot_news;

     $p_report_weblog = new Process_Item;

     if (time_now '2 AM') {

         set   $p_report_weblog "report_weblog /mh/data/logs/server.$Year_Month_Now.log";

         start $p_report_weblog;

     }

                    # Example of multiple commands

     $test_process1 = new Process_Item;

     set $test_process1 'sleep 1', 'sleep 2';

     add $test_process1 'sleep 1';

                    # Example of running an internal mh subroutine

    $v_test_ftp = new Voice_Cmd 'Test background ftp [get,put]';

    $p_test_ftp = new Process_Item;

    if ($state = said $v_test_ftp) {

      set $p_test_ftp "&main::net_ftp(file => '/tmp/junk1.txt', " .

                      "file_remote => 'incoming/junk1.txt'," . 

                      "command => '$state')";

      start $p_test_ftpb;

    }

    print_log "Ftp command done" if done_now $p_test_ftp;

Serial_Item

Serial_Item is used whenever you want read or write serial port data.

  Methods:

     new('data_stream', 'state_name', 'serial_port')

     add('data_stream', 'state_name')

        If 'serial_port' is not specified, then:

           For outgoing X10 data, the first valid port from this list is used:

               cm11, cm17, homevision, homebase, weeder, serial1, serial2, ...

           For other outgoing data, the first valid port from this list is used:

               weeder, serial1, serial2, ...

           For incoming data, the 'serial_port' parm is not important, as 

           data from the cm11, homebase, and weeder ports is processed in the same way.

           For the generic ports (serial1, serial2, ...), incoming data is processed

           only by user specified 'said' methods.

     state        : Returns the last state that was received or sent

     state_now    : Returns the state that was received or sent in the current pass.

     state_log    : Returns a list array of the last max_state_log_entries (mh.ini parm)

                    time_date stamped states.

     set_dtr      : Sets/resets the DTR line

     set_rcs      : Sets/resets the RCS line.  For example:

                      set_dtr $port 1;

                      set_rcs $port 0;

     set          : Sets the item to the specified state.

                     - If the specified state has not been defined with 'new' or 'add', 

                       the state data is sent.  Otherwise the data_stream associated

                       with that state is sent.

     set_data     : Use this to put data back into the serial read buffer.  Typically used

                    when you have processed only some of the serial data, and you want to 

                    put the rest back because it is incomplete.  Here is an example:

                   if (my $data = said $wx200_port) {

                      my $remainder = &read_wx200($data, \%weather);

                      set_data $wx200_port $remainder if $remainder;

                   }   

     said         : Returns a data record received by the port.  

                     - Characters are spooled into one record until a '\n' (newline) is

                       received.  Only then does 'said $item' become valid, and it is

                       reset as soon as the said method is executed.  

                     - Note: If you want to process binary serial data, specify 

                             serial#_datatype=raw in the mh.ini file.  This

                             will cause said to return any data read immediately, 

                             rather than buffering up data until a newline is read.

     start        : Re-starts the serial port after a stop command or after starting 

                    with the port already in use.

     stop         : Stops using the serial port for this item.  That allows other programs

                    to share the port (e.g. let mh use the modem for caller ID, but turn

                    that function off when using the modem to call out).

     is_stopped   : True if the port is not active

     is_available : True if the port is not in used by another program

     set_icon : Point to the icon member you want the web interface to use.

                See the 'Customizing the web interface' section of this document for details.

     set_info : Adds additional information.  This will show up as a popup window

                on the web interface, when the mouse hovers over the command text.

     set_order: Contols the order that the commands are listed in web Category list.

                The default is alphabetically by file, then by name.

will show up as a popup window on the web interface, when the mouse hovers over the command text.

  Examples:

     $garage_movement = new Serial_Item('XI2');

     speak "Someone is in the garage" if state_now $garage_movement;

     $tnc_output = new Serial_Item ('CONV', 'converse', 'serial1');

     $tnc_output -> add            ('?WX?', 'wxquery');

     set $tnc_output 'converse';

     set $tnc_output "EMAIL    :userid\@computers.com Test E-Mail - $CurrentTemp deg.{0";

     my $serial_data = said $tnc_output;

     $v_tnc_close = new  Voice_Cmd("close the tnc serial port");

     stop  $tnc_output if said $v_tnc_close;

     start $tnc_output if $New_Minute and is_stopped $tnc_output

                          and is_available $tnc_output; 

See mh/code/examples/serial_port_examples.pl for more Serial_Item examples.

X10_Item

Same as Serial_Item, except the 'X' prefix is prepended, to indicate an X10 command, and it has pre-defined states 'on', 'off'. 'brighten', 'dim', and '+5'->'+95 and '-5'->'-95'. The +-## states increase/decrease brightness by ## percent.

You can specify a 2nd argument, if you are using more than one X10 interface and you want to control an X10_Item with a specific interface. For example, if you want to control the local module on a RF Transeiver, you can tell mh to use the RF CM17 interface, like this:

    $test_light = new X10_Item('A1', 'CM17');

Note that the X10 device code is numbered 1->9,A->G. For example device 16 in house code P would be PG.

If a single character is use (e.g. X10_Item('D')), then 'on' and 'off' states are translated to ALL_ON and ALL_OFF commands for that house code. For example:

   $v_test_lights = new Voice_Cmd("All lights [on,off]");

   $test_lights   = new X10_Item("O");

   set $test_lights $state if $state = said $v_test_lights;

This item also has a built in timer with the set_with_timer method. For example, this event will turn on a on a warning light to 20% for 5 seconds:

   set_with_timer $watchdog_light '20%', 5 if file_unchanged $watchdog_file;

If you have one of the newer (more expensive) LM14A/PLM21 2 way X10 pro lamp modules, you can tell mh to send an extended X10 codes that let them be set directly to a specific brightness level using a Preset Dim extended code. The older modules can only be brightened/dimed.

The 64 extened X10 Preset Dim codes can used most easily by using the '#%' state. Note this differs from the +-# states described above, which increase/decrease brightness relative to the current state. The #% state goes directly to that level, independent of the existing state.

To use the #% preset dim states, you need to use a 3rd argument on X10_Item to tell it that you have a LM14 lamp module (the only module that currently supports Preset Dim). For example:

  $test_light2 = new X10_Lamp('O7', 'CM11', 'LM14');

  $v_test_light2 = new Voice_Cmd("Set test light to [on,off,bright,dim,5%,10%,20%,30%,40%,50%,60%,70%,80%,90%]");

  set $test_light2 $state if $state = said $v_test_light2;

You can also use them directly, using &P## (## = 1->64) as shown in this example:

  $test_light1 = new X10_Item('O7');

  $v_test_light1 = new Voice_Cmd("Set test light to [on,off,bright,dim,&P3,&P10,&P30,&P40,&P50,&P60]");

  set $test_light1 $state if $state = said $v_test_light1;

There is another set of Preset Dim commands that are used by some modules (e.g. the RCS TX15 thermostate). These 32 non-extended Preset Dim codes can be coded directly, using the following table:

  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15   PRESET_DIM1

  M  N  O  P  C  D  A  B  E  F  G  H  K  L  I  J

  16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31  PRESET_DIM2

  M  N  O  P  C  D  A  B  E  F  G  H  K  L  I  J

For example:

  $TX10 = new Serial_Item('XM4' . 'E' . 'PRESET_DIM1', 'Increase temp');  #preset  8='E'

  $TX10 -> add           ('XM4' . 'F' . 'PRESET_DIM1', 'Decrease temp');  #preset  9='F'

  $TX10 -> add           ('XM4' . 'O' . 'PRESET_DIM2', 'Preset on');      #preset 18='O'

  $TX10 -> add           ('XM4' . 'P' . 'PRESET_DIM2', 'Preset off');     #preset 19='P'

X10_Appliance

Same as X10_Item, except it has only has pre-defined states 'on' and 'off'

RCS_TX15

Craig is working on this one.

Socket_Item

You can use the Socket_Item object to read and/or write to TCP/IP socket ports.

Server socket ports are specified with mh.ini parms (see 'server options' in mh.ini)

  Methods:

     new('data_stream', 'state_name', 'host_port', 'name', 'host_protocol')

     add('data_stream', 'state_name')

        'host_port' must be of the form ip_address:port or 

        it must match a server* parm in mh.ini (e.g. server1).

        'host_protocol' can be 'tcp' or 'udp'.  Default is 'tcp'

        'name' is optional.  If used you can set debug to this string

        to turn on debug for just this socket data.

        

     set_port     : Allows you to change the server_name/port.

     state        : Returns the last state that was received or sent

     state_now    : Returns the state that was received or sent in the current pass.

     set          : Sets the item to the specified state.

                     - If the specified state has not been defined with 'new' or 'add', 

                       the state data is sent.  Otherwise the data_stream associated

                       with that state is sent.

     set_echo     : Use this to control echoing of incoming characters:

                     set_echo $my_socket 0   -> Do not echo incoming characters

                     set_echo $my_socket 1   -> echo incoming characters

                     set_echo $my_socket '*' -> echo incoming characters with *

     said         : Returns a data record received by the port.  

                     - Note: If you want to process binary socket data, specify 

                             server_*_datatype = raw in the mh.ini file.  This

                             will cause said to return any data read immediately, 

                             rather than buffering up data until a newline is read.

     handle       : Returns the socket handle, so you can loop on reading/writing data

                    to it directly.

     start        : Connect to the specified port.  This allows mh to act as a client,

                    rather than a server, and initiate communications with a server.

     stop         : This will drop the client or server from mh and free up the port.

     active       : True if the port is active

     active_now   : True for the mh pass that the socket first becomes active.

     inactive_now : True for the mh pass that the socket first becomes inactive.

  Examples:

    $socket_server = new  Socket_Item(undef, undef, 'server_speak');

    if (my $data = said $socket_server) {

       print "speak_server socket data: $data\n";

       speak $data;

    }

    my $lcdproc_address = 'misterhouse:13666';

    $lcdproc = new  Socket_Item(undef, undef, $lcdproc_address, 'lcdproc');

    $Vcmd_viavoice = new  main::Socket_Item(undef, undef, 'localhost:3234', 'viavoice');

More examples are in mh/code/bruce/telnet.pl, mh/code/public/Brian/tracker.pl, my/code/bruce/mh_watchdog.pl, and mh/code/test/socket_test.pl

Timer

The Timer object can be used to run an action one or more times, at a specified interval.

  Methods:

    new        : Used to create the object.

    set($period, $action, $cycles)

        $period is the timer period in seconds

        $action (optional) is the command to run when the timer expires

        $cycles (optional) is how many times to repeat the timer

    unset      : Unset the timer.  'set $my_timer 0' has the same effect.

    active     : Returns true if the timer is still running.

    inactive   : Returns true if the timer is has expired or has not been set.

    expired    : Returns true for the one pass after the timer has expired.

    run_action : Runs the timers action, even if the timer has not expired.

    hours_remaining,   hours_remaining_now

    minutes_remaining, minutes_remaining_now

    seconds_remaining, seconds_remaining_now

        These methods return the hours, minutes or seconds remaining on the timer.

        The _now methods only return the remaining time on the hour, minute,

        or second boundary.

  Examples:    

    $timer_laundary = new  Timer;

    $v_laundary_timer = new  Voice_Cmd('Laundary timer [on,off]');

    if ($state =  said $v_laundary_timer) {

       if ($state eq ON) {

          play('rooms' => 'shop', 'file' => 'cloths_started.wav');

          set $timer_laundary 35*60, 'speak "rooms=all The laundary clothes done"', 4;

       }

       else {

          speak 'rooms=shop The laundry timer has been turned off.';

          unset $timer_laundary;

       }

    }

    See mh/code/bruce/timer_minutes.pl and timer_seconds.pl for more examples.

Voice_Cmd

Use the Voice_Cmd object to create voice commands. Even without a Voice Recognition engine installed, this is useful as these commands can also be run from the Tk, web, telnet, and file interfaces.

  Methods:

     new($command, $response, $confirm, $vocabulary)

        $command can be a simple string (e.g. 'What time is it') or it can 

        include a list of 'states' (e.g. 'Turn the light [on,off]').  The state

        enumeration group is a comma delimited string surrounded with [].

        In addition to one state enumeration group, you can specify any number

        of phrase enumeration groups.  These are comma delimited strings

        surounded by {} (e.g. 'Turn the {family room,downstairs} TV [on,off]').

        Use this when you have several different ways to describe the same thing.

        $response is the text or wave file that will be played back when the

        VR engine detects this command.  If not defined, the response 

        is : "you said $command"

        You can put %STATE% or any variable in the response string and have it

        substituted/evaluated when the response is spoken

        $confirm is either 0 or 1 (default is 0).  If set to 1, then mh will

        ask 'Confirm with a yes or a no'.  If yes or no is not heard within

        10 seconds, the command is aborted.

        $vocabulary allows you to define multiple vocabularies.  You 

        can then use these functions to enable and disable the vocabularies:

             &Voice_Cmd::enablevocab($vocabulary)

             &Voice_Cmd::disablevocab($vocabulary)

        Vocabularies are enabled by default.  The default vocabulary

        is 'misterhouse'.  See mh/code/bruce/viavoice_control.pl for examples.

        This code allows you to switch between 'awake', 'asleep', and 'off' VR modes.

        NOTE:  

           Currently only the viavoice VR engine (mh.ini parm voice_cmd=viavoice)

           will use the $response, $confirm, and $vocabulary_name options.

           We may be able to create a viavoice_server for windows, but that would

           probably not be free like it is on linux.  If you have a linux box

           on your network, you can have your windows mh use the linux

           viavoice_server process.

 

     said  : Is true for the one pass after the command was issued.

             If the command was built from a list of possible states, 

             then said returns the state that matches.

     state : Returns the same thing as said, except it is valid for all passes,

             not just the pass after the command was issued.

 

     set_icon : Point to the icon member you want the web interface to use.

                See the 'Customizing the web interface' section of this document for details.

  Examples:        

    $v_backyard_light = new  Voice_Cmd 'Backyard Light [on,off]';

    set $backyard_light $state if $state = said $v_backyard_light;

    $v_test1 = new Voice_Cmd '{turn,set} the {living,famliy} room {light,lights} [on,off]';

    $v_test2 = new Voice_Cmd '{Please, } tell me the time';

    $v_test3 = new Voice_Cmd '{What time is it,Tell me the time}';

    $v_fan   = new Voice_Cmd 'Fan [on,off]', 'Ok, I turned the fan $v_indoor_fountain->{said}';

    $v_fan   = new Voice_Cmd 'Fan [on,off]', 'Ok, I turned the fan %STATE%';

See mh/code/examples/Voice_Cmd_enumeration.pl for more Voice_Cmd examples

In addition to the said command on a specific object, you can use &Voice_Cmd::said_this_pass to detect which command was spoken this pass and &Voice_Cmd::noise_this_pass to detect if noise was detected this pass (this function currently only works with viavoice).

  Examples:

   if (my $speak_num = &Voice_Cmd::said_this_pass) {

      my $text = &Voice_Cmd::text_by_num($speak_num);

      print_log "spoken text: $speak_num, $text";

   }

   if (my $text = &Voice_Cmd::noise_this_pass) {

      print_log "Noise detected" if $text eq 'Noise';

   }

See mh/code/bruce/lcdproc.pl for more examples.


List of functions

browser

Calls up the web browser defined my the mh.ini browser parm

  Examples: 

    browser 'http://misterhouse.net';

    browser "$config_parms{tracking_dir}/today.html" if said $v_show_tracking;

convert_k2f
convert_c2f

Converts from degrees Kelvin/Centigrade to Farenheight

  Example: 

    $weather{TempF} = convert_c2f($weather{TempC});

convert_direction

Converts 0->360 degrees into north, north east, east, etc

  Example: 

    speak "Wind speed is " . round($weather{WindAvgSpeed}) .

          " from the " . convert_wind_direction($weather{WindAvgDir});

display

Displays the specified text string, text file contents, or bitmap (.gif or .jpg).

  Usage:

    display($file_or_text, $time, $title, $font);

      $file_or_text can be a file or a text string.

      $time  (optional) is how long (in seconds) till the box will auto-close.

             Defaults to 120.  Use 0 to disable auto-close.

      $title (optional) is the title of the display box.

  Examples:

    display "Internet message: $msg", 300, 'Internet message'; 

    display $f_trivia_answer;

    display '/pictures/photo.jpg';

  

file_changed (or older name of file_change)

Returns 1 if the specified file has change since last checked. Returns 0 if the file has not changed. Returns undef if we don't know (i.e. first check after mh was started).

  Example:

    print_log "File $file has change" if file_change($file);

file_unchanged

Returns 0 if the specified file has change since last checked. Returns 1 if the file has not changed. Returns undef if we don't know (i.e. first check after mh was started).

  Example:

    my $watchdog_file = '//dm/d/misterhouse/mh/data/mh.time';

    if (file_unchanged $watchdog_file) {

        speak "MisterHouse has stopped running on the Nick's box";

        set_with_timer $watchdog_light '20%', 5;

    }

file_diff

Returns true if the contents of the 2 specified files are different.

  Example:

    print_log "Files are different" if file_diff($file1, $file2);

file_read

Reads data from a file. If used in a list context, a list is returned, otherwise a string of all the lines.

  Examples:

     @data = file_read($file);

     $data = file_read($file);

file_write

Writes data into a file. Like logit, except it writes over, rather than appends to, a file.

  Examples:

     file_write($file, $data);

file_cat

Concatonates data from one file onto another.

  Examples:

    file_cat $file, $file_total;

    file_cat "$config_parms{html_dir}/aprs/week2.html", "$config_parms{html_dir}/aprs/old/${Year_Month_Now}.html";

file_head file_tail

Returns the first/last few lines of a file

  Examples:

     @data = file_head($file, $lines);

     $data = file_tail($file, $lines);

   If $lines is not specified, the default is 3.

   If used in a list context, a list is returned,

   otherwise a string of all the requested lines is returned.

filter_cr

Returns the given string, with carriage returns and line feeds filtered out

  Examples:

    print_log filter_cr get "$url/play?p=$config_parms{mp3_program_password}";

logit

Appends data into a log file. Use file_write to write over a file.

  Usage:

    logit($log_file, $log_data, $log_format, $head_tail);

      $log_format=0  =>  Data is written as is, no /n, no time_date stamp.

      $log_format=## =>  Every log entry is preceded with a time_date stamp.

                         ## is passed to &time_date_stamp to determine the format.

                         Also, /r/n is stripped so we get only one record per call.

                         The default  $log_format is 14.

      $head_tail     =>  If 1, data is logged to the top of the file, otherwise

                         it is added to the bottom.

  Examples:

   logit("$Pgm_Root/data/logs/wx200.$Year_Month_Now.log",  $data, 0);

   logit("$Pgm_Root/data/phone/logs/callerid.$Year_Month_Now.log", "$cid_number $cid_name");

logit_dbm

Logs data into a dbm file. If data for that key exists, it is overwritten. dbm files are useful if you want to store key-value data or hash arrays onto disk for later use.

  Usage:

    logit_dbm($log_file, $log_key, $log_data);

  Examples:

    logit_dbm("$Pgm_Root/data/phone/callerid.dbm",

              $cid_number, "$Time_Now $Date_Now $Year name=$cid_name");

    See display_callers for an example of how to read dbm files.

play

Use this to play wave or system sound files. There are 2 modes of calling it:

   Simple mode:

     play  $file_name

   Options mode:

     play(option => 'value', file => $file_name);

     Options are:

       rooms => 'room_names'  You need to code a pa_stub.pl routine to allow this

                              to work with your PA relays.

       time  => $time         The amount of time to leave the PA speakers on for rooms

       mode  => $mode         $mode can be:

         wait  : mh will pause (hang), until wav file finishes

         loop  : mh will loop on the wav file

         stop  : mh will stop playing the previous file

         async : mh will play wave file asynchronously (in the background).  This is the default.

       mode   => 'unmuted'     Forces speech, even in mute and offline mode

       You can control the default mode parm with the mh.ini play_mode parm.

   

If $file_name is a blank or comma delimited list of files, they are played sequentially. If it is a wild-carded file specification (e.g. ``movement*.wav''), then a file is picked at random from the files that match.

If the file does not include a path specification, the file is looked for in the mh/sounds directory.

If the file starts with System or with sound_, the sound file is NOT logged in the speak log.

Here are the names of some of the Windows System sounds. Use the Control Panel Sounds menu to change their associated wav files:

   - MenuPopup

   - SystemDefault

   - SystemAsterisk

   - SystemExclamation

   - SystemExit

   - SystemHand

   - SystemQuestion

   - SystemStart

   Examples:

                        # Play a random 'garage open/close' wav file

     if($state = state_now $garage_door) {   # $state will be open or close

       play(rooms => 'all', file => "garage_door_" . $state . "*.wav");

     }

     play(file => 'SystemAsterisk') if $Reload;

     play "fun/*.wav" if time_cron '* 9 * * 6';

print_log =item print_msg =item print_speaklog

Use these to print to the various logs. These logs are listed in Tk and web frames.

print_log is typically used for fairly frequent, not too important messages.

print_msg is typically used for less frequent, more important messages.

print_speaklog is called by the speak and play functions, so should not be normally used in user code.

 

run

You can use the run function to run a program as a separate process. On Windows, the perl Win32::Process function is used, and on Unix, the program is forked with &.

If you specify 'inline' as the first argument, the program will not be a background process/forked. mh will pause until the program is done.

  Examples:

     run('IR_cmd VCR,3,6,RECORD');  # Start a VCR recording

     run 'rasdial /disconnect';     # Log off from the net (on Windows)

     run 'inline', 'some_fast_command_here';

     run 'mplayer.exe /play /close c:\win98\media\canyon.mid'; # Play a midi file

run_voice_cmd

You can use this to have one event trigger another voice command event.

   Example:

      run_voice_cmd 'Get the top10 list' if time_now('6:30 AM');

read_dbm

Read data from a dbm file. If a key is passed, only that one record is returned. Otherwise, the whole dbm is read.

  Usage: 

    $value = read_dbm($dbm_file, $key);

    %data  = read_dbm($dbm_file);

search_dbm

Search a dbm file for matches to a string. It currently searches both key and value.

  Usage: 

    ($count_searched, $count_matched, %results) = search_dbm($dbm_file, $search_string);

  See mh/code/bruce/phone.pl and mh/bin/display_callers for examples.

SendKeys WaitForAnyWindow sendkeys_find_window

On Windows systems, use these functions to control other programs. Full documentation is mh/lib/site/Win32/setupsup.html.

   SendKeys($window, $keystr, $activate, [$timeout])

   WaitForAnyWindow($title, \$window, $timeout, [$refresh])

WaitForAnyWindow will set the window handle for the window that matches the (sub)string specified in $title.

SendKeys sends the keys. Here is an excerpt of the valid key list:

   ALT+ alt down ALT- alt up CTRL+ ctrl down CTRL- ctrl up SHIFT+ shift down SHIFT- shift up

   TAB tabulator RET return ESC escape BACK backspace DEL delete INS insert HELP help

   LEFT arrow left RIGHT arrow right UP arrow up DN arrow down PGUP page up PGDN page down

   BEG pos1 END end F1 function 1 ... F12 function 12

   NUM0 0 on the num block ... NUM9 9 on the num block 

   NUM* multiply key on the num block 

   NUM+ add key on the num block NUM- minus key on the num block NUM/ divide key on the num block 

sendkeys_find_window is an mh subroutine that calls WaitForAnyWindow. If the window is not found and $program is specified, it will start $program and wait for the window to appear, then return the window handle.

   sendkey_find_window($title, [$program]);

  

Here are a few examples:

                    # Start winamp, if it is not running

   unless (&WaitForAnyWindow('Winamp', \$window, 100,100)) {

       print_log "Starting winamp";

       run $config_parms{mp3_program};

   }

                    # Send/receive mail, using sendkeys_find_window to start the program 

                    # if it is not already running

   if (my $window = &sendkeys_find_window('Outlook', 'D:\msOffice\Office\OUTLOOK.EXE')) {

      my $keys = '\\alt+\\tss\\alt-\\';  # For Outlook Express

      my $keys = '\\alt\\te\\ret\\';     # For Outlook

      &SendKeys($window, $keys, 1, 500);

   }

speak

Passes specified text to the TTS program. There are 2 modes of calling it:

   Simple mode:

     speak "text to speak"

   Options mode:

     speak(option => 'value', text => "text to speak");

    

     Options are:

       rooms  => 'room_name'   You need to code a pa_stub.pl routine to allow this

                              to work with your PA relays.

       mode   => 'unmuted'     Forces speech, even in mute and offline mode

     These options are for the Festival speech engine (but don't work yet):

       volume => 'loud' or 'soft'

       rate   => '+-nn%'       (e.g. +10% or -30%)

       voice  => 'name' 

 

   Examples:

    $test_voice1 = new Voice_Cmd "Say something with a [loud,soft] voice";

    $test_voice2 = new Voice_Cmd "Say something at a [fast,slow] speed";

    $test_voice3 = new Voice_Cmd "Say something in voice [male1,female1]";

    speak(volume => $state, 

          text => "This is an example of $state text")    if $state = said $test_voice1;

    speak(rate   => $state,

          text => "This is an example of $state text")    if $state = said $test_voice2;

    speak(voice  => $state,

          text => "This is an example of a $state voice") if $state = said $test_voice3;

  

time_date_stamp

You can use this function to return a time/date string.

  Usage:

    time_date_stamp($format, $file_or_time);

    $format can be any of the following:

      1:   Monday, 08/26/96  11:01 PM

      2:   Monday Jul 27 14:00 1996  (seems to be more compatable with javascript parsing)

      3:   Monday Jul 27 at 6 AM

      4:   6:05 AM on Monday, Jul 27

      5:   6:05 AM

      6:   Mon, Jul 27

      7:   Mon 01:02PM 

      8:   6:05 (skip the AM PM)

      9:   04/14/97 10:28 PM 

     10:   year_month, with leading 0, so log files are sorted ok (e.g. 97_01)

     11:   01/31/98 (mm/dd/yy)

     12:   04/14/97 14:28:00 

     13:   14:28:33

     14:   Mon 04/14/99 14:28:00

     15:   Sunday, December 25th

     16:   04/14/97  2:28:00 PM

The second argument can be either time (in epoc seconds) or a file, where it will use the time that it was last modified. The default is $Time (current time).

    $lcd_data{1} = &time_date_stamp(14, $Time);

    speak "File was changed today" if time_date_stamp(6, $file) eq time_date_stamp(6);

Note: The mh.ini time_format and date_format parms can be used to modify these formats to non-us standards (e.g. no AM/PM, use dd/mm instead of mm/dd).

time_cron

The cron time format matches the unix cron format.

    Cron Format:

      minutes hours day_of_month month day_of_week

 

        minutes: 0-59

        hours:   0-23

        dom:     1-31  (day of month)

        month:   1-12

        dow:     0-6   (day of week 0=Sunday 6=Saturday)

      You can use a comma delimited list for any of these fields.  * matches all values.

   Examples:

                 # Speak time every 15 minutes, between 7 am and 8 am on weekdays only  

    speak $Time_Now  if time_cron '0,15,30,45 7,8 * * 1-5';

                 # Change PA speaker mode at 9 pm, every day

    pa_sleep_mode('kids', 1) if time_cron '* 21 * * * ';

time_greater_than
time_less_than

These return true if the specified time is greater or less than the current time. Format can have the same sorts of offsets as described in time_now below. Note unlike time_now which is only true once, these functions will return a true value for every pass that they are true.

   Example: curtain_on('bedroom', OPEN) if 

                    time_cron('22 6 * * 1-5') and 

                    time_greater_than("$Time_Sunrise + 0:15");

time_now

time_now is evaluate to true for the 1 pass that matches the specified time/date. Date is optional. You can specify + or - offset, in hours:minutes:seconds. Time can include AM/PM or be in 24 hour format. The best way to see how it works is to look the following examples:

   Examples:

     run_voice_cmd 'close the living room curtains'  if time_now $Time_Sunset;

     set $backyard_light ON if time_now("$Time_Sunset + 0:15");

     set $left_bedroom_light +50 if $Weekday and time_now "$wakeup_time - 0:01";

     speak "Remember dentist appointment" if time_now '5/27/98 8:15 AM';

     run('min', 'IR_cmd VCR,4,RECORD') if time_now '2/07 18:00';

     run('min', 'IR_cmd VCR,STOP') if time_now "$date $stop - 00:02";

time_random

Use time_random to code random events. It uses the same time format as time_cron, but includes frequency parameter that specifies how often the event should trigger.

  Usage:

     time_random($cron_spec, $frequency)

  Examples:

              # Speak something goofy once an hour on weekends

    speak(read_next $april_fools) if time_random('* 8-22 * * 0,6', 60);

              # Toggle a light on an off randomly every 30 minutes

    if (time_random('* 18-22 * * *', 30)) {

      $state = (ON eq state $bedroom_light) ? OFF : ON;

      set $bedroom_light $state;

    }


List of tk widget functions

tk_button tk_mbutton

Use these functions to add a Tk button widget to the mh tk grid (tk_button) or the tk menu_bar (tk_mbutton). &tk_button will accept multiple variables, displaying them in a row in the grid.

   Usage:

    &tk_mbutton('Button Name', \&subroutine);

    &tk_button('Button1', \&sub1);

    &tk_button('Button1', \&sub1, 'Button2', \&sub2,'Button3', \&sub3);

   Examples:

    &tk_mbutton('Help', \&help);

    &tk_button('Reload(F1)', \&read_code, 'Pause (F2)', \&pause,

               ' Exit (F3) ', \&sig_handler, 'Debug(F4)',  \&toggle_debug,

               'Log(F5)', \&toggle_log);

tk_checkbutton

tk_checkbutton adds a Tk checkbutton widget to the mh tk grid. It will accept multiple variables, displaying them in a row in the grid.

   Usage:

    &tk_checkbutton('text',  \&var1);

    &tk_checkbutton('test1', \&var1, 'text22', \&var22, 'text3', \&var33);

   Examples:

    &tk_checkbutton('Debug on', \$config_parms{debug});

    &tk_checkbutton('Sleeping Parents', \$Save{sleeping_parents}, 

                    'Sleeping Kids', \$Save{sleeping_kids});

tk_entry

Use this function to allow for arbitrary data to be entered via the mh tk grid.

   Usage:

    &tk_entry('Entry label:', $state_based_object);

    &tk_entry('Entry label:', \$variable);

    &tk_entry('Entry label:', \$variable, 'Entry label2:, \$variable2);

   Example:

    &tk_entry('Sleep time:', \$Loop_Sleep_Time);

    &tk_entry('Test in 1', \$Save{test_input1}, 'Test in 2', \$Save{test_input2});

 

Note:  The $variable reflects the data, as it is being entered.  If you want to test on the data

only after the RETURN key has been hit, use %Tk_results array.

The $variable is copied to $Tk_results{'Entry label:'} only after the RETURN key has been entered. 

Now you can now also use a state based object (like Generic_Item) to store/monitor/change the tk_entry text.

   Examples:

    &tk_entry('TV search', \$Save{tv_search});

    if ($state = $Tk_results{'TV search'}) {

       run qq[get_tv_info -times all -keys "$state"];

       set_watch $f_tv_file;

       undef $Tk_results{'TV search'};

    }

   $mp3_search_text =  new Generic_Item;

   $mp3_search_text -> tie_event('print_log "mp3 search text is now $state"');

   &tk_entry('mp3 Search', $mp3_search_text);

tk_label tk_mlabel

Use these functions to add a Tk label widget to the mh tk grid (tk_label) or the tk menu_bar (tk_mlabel). &tk_label will accept multiple variables, displaying them in a row in the grid.

   Usage:

   

     &tk_mlabel(\$variable);

     &tk_label(\$variable);

     &tk_label(\$variable1, \$variable2, \$variable3);

   Example:

     &tk_mlabel(\$Save{email_flag});

     $Save{email_flag} = file_read "$Pgm_Root/data/get_email.flag";

tk_radiobutton

Use this function to create radio buttons in the mh tk grid. If labels are not specified, the values are displayed.

   Usage:

    &tk_radiobutton('Button label:', $state_based_object, ['value1', 'value2', 'value3']);

    &tk_radiobutton('Button label:', \$variable, ['value1', 'value2', 'value3']);

    &tk_radiobutton('Button label:', \$variable, ['value1', 'value2', 'value3'], 

                                                 ['label1', 'label2', 'label3']);

   Examples:

    &tk_radiobutton('Mode',  \$Save{mode}, ['normal', 'mute', 'offline']);

    &tk_radiobutton('Debug', \$config_parms{debug}, [1, 0], ['On', 'Off']);

    &tk_radiobutton('Tracking', \$config_parms{tracking_speakflag}, [0,1,2,3],

                    ['None', 'GPS', 'WX', 'All']);

    my $alarm_states = "Disarmed,Disarming,Arming,Armed,Violated,Exit Delay,Entry Delay";

    my @alarm_states = split ',', $alarm_states;

    $alarm_status    = new Generic_Item;

    &tk_radiobutton('Security Status', $alarm_status, [@alarm_states]);

    $v_alarm_status  = new Voice_Cmd "Set the alarm to [$alarm_states]";

    $v_alarm_status -> tie_items($alarm_status);

    print_log "Alarm status changed to $state" if $state = state_now $alarm_status;

See mh/code/examples/tk_examples.pl for more tk_* examples.


List of Internet functions

get

This function will retrieve data from the web (http web pages or ftp files). If the web page is large or the site is slow, you may want to use a Process_Item call to the get_url program, so the request can be done as a separate process and mh will not get hung up while waiting.

  Examples:

    my $html = get 'http://marketing.cbs.com/lateshow/topten';

    Other examples are in mh/code/bruce/internet_data.pl

get_ip_addresses

Returns the numeric IP address of the specified hostname. If hostname is blank, localhost is used. If used in a list context, all associated IP address are returned (e.g. dial up address and local address).

  Examples:

    print_log "Current IP address " . get_ip_address;

                       #  Echo dynamic IP address to the Tk gui

    if ($New_Minute and net_connect_check) {

         $Tk_objects{ip_address} = "IP address: " . get_ip_address;

    }   

    tk_label(\$Tk_objects{ip_address});

html_unescape

Un-escapes ``%xx'' data back into the original characters. Use on HTML FORM data.

 

net_domain_name function

This will return the domain_name of the last client to access the specified port. If the mh.ini DNS_server parm is NOT set, it will return the IP address instead. You can also pass it a IP address, instead of a server port name.

If used in an array context, it returns the full domain name, and a short version of the domain name (e.g. 'www.ibm.com' and 'ibm').

  Examples:

   my $domain_name = &net_domain_name('http');

   my ($name, $name_short) = &net_domain_name('server_speak');

   my ($name, $name_short) = &net_domain_name('204.146.18.33');

     Restults $name = 'www.ibm.com', $name_short = 'ibm';

net_ping

Checks to see if an IP address is available. Returns true if pingable.

  Example:

    

    &ping($host);           #  Default protocol is specified in mh.ini

    &ping($host, $protocol);

net_ftp

Used to ftp data to or from an ftp server. There is also a stand alone version of this command in mh/bin/net_ftp, so you can run this command with a run or a Process_Item to avoid hanging mh with long running ftp sessions.

  Usage:

    net_ftp(option1 => $value1, option2 => value2 ...);

      

       These are the possible options:

            server          Default is mh.ini parm net_www_server

            user            Default is mh.ini parm net_www_user

            password        Default is mh.ini parm net_www_password

            dir             Default is mh.ini parm net_www_dir

            file            Name local/remote file to get/put

            file_remote     Name of remote file (if different from local file)

            command         get/put/delete.

            type            ascii/binary  (default is ascii)

   Example:

     net_ftp(file => 'index.html', command => 'put');

     my $rc = net_ftp(

        file => 'c:/junk1.txt', file_remote => 'incoming/junk1.txt',

        command => 'put', server => 'misterhouse.net',  

        user => 'anonymous', password => 'bruce@misterhouse.net');

     print_log "net_ftp put results: $rc";

   

    $v_test_ftp = new Voice_Cmd 'Test background ftp [get,put]';

    $p_test_ftp = new Process_Item;

    if ($state = said $v_test_ftp) {

      set $p_test_ftp

          "net_ftp -file c:\junk1.txt -file_remote incoming/junk1.txt " . 

          "-command $state -server misterhouse.net " . 

          "-user anonymous -password bruce\@misterhouse.net";

      start $p_test_ftp;

    }

    print_log "Ftp command done" if done_now $p_test_ftp;

net_connect_check

Returns true if connected to the Internet. If the mh.ini parm net_connect=persistent, this always returns true.

net_jabber_send or net_im_send

Used to send and AOL Instant Message or Jabber message across the internet.

Information on AIM clients (available for various different platforms) can be found at http://www.aol.com/aim/faq/getstarted.html . Tik, a tk based client for use on a Unix os, can be found at http://tarp.linuxos.org/tik . You can register for an AIM name at http://www.aol.com/aim/faq/registration.html .

Information on Jabber clients (many open sourced clients are available for different platforms AND the protocol is open) can be found at http://www.jabber.com and http://www.jabber.org.

 

  Usage:

    net_jabber_send(option => value);

    net_im_send(option => value);

     These are the options:

        password    Default is mh.ini parm net_jabber_password  or net_aim_password

        from        Default is mh.ini parm net_jabber_name      or net_aim_name

        to          Default is mh.ini parm net_jabber_name_send or net_aim_name_send

        server      Default is mh.ini parm net_jabber_server (e.g. jaber.com)

        resource    Default is mh.ini parm net_jabber_resource (this can be left blank)

        text        Message

        file        Message.  You can use the text and/or file options.

The first time you send a message, mh will pause for a few seconds while it logs onto AIM or a jabber server. Subsequent messages use the same signon, so are sent much faster.

Once you have been logged in, mh will also display incoming jabber messages. This code has lots of other possibilites that can be added, since jabber is XML based and very flexable.

  Example:

    net_jabber_send(text => "Stock summary\n  $Save{stock_data1}\n  $Save{stock_data2}")

    net_im_send(text => "Internet mail summary for $Date_Now $Time_Now",

                file => "$config_parms{data_dir}/get_email2.txt") if time_cron '05 12 * * 1-5';

 

net_mail_send

Used to send email. Usage: net_mail_send(option => value);

     These are the options:

        server      Default is mh.ini parm net_mail_ACCOUNT_server

        from        Default is mh.ini parm net_mail_ACCOUNT_address

        to          Default is mh.ini parm net_mail_ACCOUNT_address

        account     This is the ACCOUNT field used in finding the above parms.

                    It defaults to the mh.ini parm net_mail_send_account.

        subject     Default is 'Email from Mister House'

        text        Body of the message

        file        File with the body of the message.

        mime        Set to 1 if you want mail sent in mime format (e.g. file has html)

        baseref     If sending html with mime => 1, use this to set the BASE HREF

  Example:

    net_mail_send(text => "Test email sent at $Time_Now\n\n");

    net_mail_send(account => 'Bruce', to => 'winter@misterhouse.net', text => $msg);

net_mail_count

Returns the number of email message on the specified account.

  Usage:

    net_mail_count(option => value);

     These are the options:

        server      Default is mh.ini parm net_mail_ACCOUNT_server

        user        Default is mh.ini parm net_mail_ACCOUNT_user

        password    Default is mh.ini parm net_mail_ACCOUNT_password

        account     This is the ACCOUNT field used in finding the above parms.

                    It defaults to the mh.ini parm net_mail_send_account.

  Example:

    my $count = net_mail_count(account => 'Bruce');

    speak "Email account Bruce has $count new email messages";

net_mail_summary

This returns a pointer to a hash array containing info on mail for a specified email account. Check out the mh/bin/get_email program for a usage example. Rather than call this with mh code directly, calling get_email with a Process_Item, so mh does not pause while email is being checked. See mh/code/test/internet_mail.pl for an example.

 

net_mail_read

Returns a list array of pointers to data read from an email account. This is not tested and needs to be documented.

 


List of companion programs

These programs are included in mh mh/bin directory. Most of these are meant to be called from mh events, as separate processes, but they can also be run stand alone. You can get the help text for most of these programs with the -h option (e.g. get_tv_grid -h).

alpha_page

  alpha_page sends alphanumeric page.

  Usage:

    alpha_page [options]

      -h              => This help text

      -help           => This help text

      -name xxx       => name of recipient (must be defined in mh.ini)

      -pin xxx        => pin number

      -message xxx    => text of message to send

  Example:

    alpha_page -pin 123456 -message 'Bring home bread and milk'

    alpha_page -name craig -message 'Bring home bread and milk'

display

Use this to display a string of text or the contents of a file using a Tk window.

  Usage:

     display -options  text_or_file

  Options:

    -time  xxx to have the window auto-close in xxx seconds.  Set to 0 for no auto-close.

    -font  xxx to pick the font

    -title xxx to set the window title

  Examples:

    display weather_forcast.txt

    display -title 'triva answer' c:/data/triva_answer.txt

    display "Remember to take out the garbage" -time 0

display_callers

Use this to display a Tk window with a list of the incoming and outgoing phone logs. An example of how to create these logs is in mh/code/bruce/phone.pl

  Usage: 

    display_callers (no argument -> uses latest logs) 

    display_callers 1997_11  (Look only at November, 1997 logs) 

get_ceiva

get_ceiva gets pictures from the 'now showing' folder of a Ceiva.com web page.

  Usage: 

   get_ceiva [options]

    -h        => This help text

    -username xyz => xyz is a ceiva member name

    -password xyz => xyz is a ceiva password

    -frame_id xyz => xyz is a ceiva frame_id

    -outdir xyz   => xyz the directory the pictures will be put in

    -browser xyz  => xyz is the path to your html browser

    -reget        => Re-fetch the files, even if they look current

  Examples:

    get_ceiva -outdir /pictures/ceiva

    get_ceiva -reget

get_email

Use this program to check all the email accounts defined in your mh.ini file. It will create the following files:

  mh/data/get_email.data 

     It uses this database so see what email is new

     since it was last called.   To get a complete

     list of all email (not just new/recent mail).

     delete this file before running get_email

  mh/data/get_mail.txt 

     This summarizes how much mail there is and from who.

     Here is an example of what the file might look like:

       Email account bruce has 2 new email messages from John Doe and Bill Gates

  mh/data/get_mail.flag

     This has a string of digits, one for each account,

     that shows how much mail is each account.  

You can create a get_email_rule.pl file to control how this program summarizes mail. See get_email_rule_example.pl for an example.

Here is an example of how to call it from mh (see mh/code/test/internet_mail.pl for the complete example):

  $p_get_email = new Process_Item('get_email');

  start $p_get_email if !$Save{sleeping_parents} and 

                        $New_Minute and !($Minute % 20) and &net_connect_check;

  if (done_now $p_get_email) {

      my $email_text = file_read "$Pgm_Root/data/get_email.txt";

      speak "rooms=all $email_text" if $email_text;

      $Save{email_flag} = file_read "$Pgm_Root/data/get_email.flag";

  }

  &tk_mlabel(\$Save{email_flag});

get_mp3_data

get_mp3_data reads mp3 directories and stores the results in a dbm file. This data is used by mh/test/mp3_playlist/pl to search/play mp3 tag data, file names, and playlist files.

  Usage:

   get_mp3_data [options] dir1 dir2 etc

    -h        => This help text

    -help     => This help text

    -dbm  xyz => Stores the data in dbm file xyz.

  Examples:

    get_mp3_data c:\mp3 d:\mp3

    get_mp3_data -dbm e:\mh\data\mp3_dbm c:\mp3

get_tv_grid

get_tv_grid gets a TV grid/schedule from the web (clicktv.com) and changes so it to be used by the MisterHouse program to create VCR and TV event reminders. See mh/code/bruce/tv_grid.pl for a mh event example that uses get_tv_grid.

  Usage:

    get_tv_grid [options] 

  Options:

    -h        => This help text

    -help     => This help text

    -userid xyz   => xyz is your clicktv userid.  Go to http://www.clicktv.com  to create

                     one, or to find the generic one that matches your local tv schedule.

    -day xyz      => xyz is the day  to get/filter.  Default is today.

    -hour xyz     => xyz is the hour to get/filter.  Default is 6pm.

                     Can also be 'all' to get all hours.

    -days xyz     => xyz is the number of days to get/filter, starting with -day.

    -channels xyz => xyz is the number of channels to filter.  Default is 999.

    -infile  xyz  => xyz is  original input file.   Default is web/tv/clicktv/day_hour.html

                     If this file is missing or old, a new file will be retreived from

                     the web.

    -outfile xyz  => xyz the filtered output file. 

                     Default is -outdir/day_hour.html

    -outdir  xyz  => xyz the directory the outfiles will be put in.

                     Default is mh.ini parm html_dir/tv

    -label xyz    => Use xyz as the link lable.  Default is "Set the Vcr"

    -reget        => Re-read  the clicktv web page, even if a recent file it already exists.

    -redo         => Re-write -outfile xyz, even if it already exists.             

    -debug        => turn on debug info

    -mail_to      xyz => Will email the charts to xyz

    -mail_server  xyz => xyz is the SMTP host.  Default is localhost

    -mail_baseref xyz => xyz is the http address of your mh server.  Needed if you want to

                         control mh from the emailed web page

  Examples:

    get_tv_grid -day 25 -hour 4pm -outfile my_tv.html

    get_tv_grid -days 7 -hour all

    get_tv_grid -email bruce\@misterhouse.net -mail_baseref misterhouse.net:8080

get_tv_info

get_tv_info returns info about tv programs that match the requested parms. It uses a database created by the get_tv_grid program. See mh/code/bruce/tv_info.pl for examples on how to use this from mh.

  Usage:

    get_tv_info [options]

  Options:

    -h        => This help text

    -help     => This help text

    -channels xyz => Will return info only for channel numbers xyz.

                     Default is all the channels found by get_tv_grid.

    -dates    xyz => Will return info only for dates xyz.

                     Default is today.  Format: month/day (e.g. 4/22).

    -time     xyz => Will return info only for shows that start at xyz.

                     Default is '6pm-10pm'.  Use 'all' for all hours.

                     Valid formats: 1 pm, 1PM, 13, 13:00.

    -lengths  xyz => Will return info only for shows that are xyz hours long.

                     Default is any length.

    -keys     xyz => Will return info only for shows that have keywords

                     in the xyz list in their title or description.

      All of the above parms support these formats:

         : comma-seperated values (e.g. -dates 7/4,7/5,7/6)

         : - delimited ranges     (e.g. -dates 7/4-7/6)

         : + adder spec           (e.g. -dates 7/4+2)

           Starting spec is optional (e.g. -dates +2)

    -debug        => turn on debug info

  Examples:

    get_tv_info -channels "4-12" -lengths 2

    get_tv_info -channels "4,6,12" -time "7 pm"

    get_tv_info -dates "7/4-7/11" -keys "star trek,dilbert"

    get_tv_info -dates +14 -keys computer

get_url

get_url gets a web page and echos it to STDOUT or a local file.

  Usage:

    get_url url [local_file]

    If local_file is specified, data is stored there,

    otherwise it is echoed to STDOUT.

  Examples:

    get_url http://marketing.cbs.com/lateshow/topten/ $f_top10_html;

get_weather

get_weather gets weather info NOAA web servers.

  Usage:

    get_weather [options] 

  Options:

    -h         => This help text

    -help      => This help text

    -city     xxx => xxx is the City  you want.

    -state    xxx => xxx is the State you want.

    -data     xxx => xxx is either conditions, forecast, or all.  Default is all.

    -refresh  xxx => xxx is the number of minutes old the cached data can

                     before it will be refreshed from the net. 

                     The default is 60 minutes.

    -no_log       => Unless this option is used, the results also get filed 

                     into the mh/data/web directory

  Example:

    get_weather -city Rochester -state MN

Here is an example mh event for calling get_weather as a background process using the 'run' function:

  $v_get_internet_weather_data  = new  Voice_Cmd('Get internet weather data');

  $v_show_internet_weather_data = new  Voice_Cmd('Show internet weather data');

  if (said  $v_get_internet_weather_data) {

     run "get_weather -city $config_parms{city} -state $config_parms{state}";

     set_watch $f_weather_forecast;

  }

  if (said  $v_show_internet_weather_data or changed $f_weather_forecast) {

     print_log "Weather data displayed";

     display name $f_weather_forecast;

     display name $f_weather_conditions;

  }

house

This is a simple shell that echos whatever you type into the 'xcmd_file'. The name of the 'xcmd_file' is specified in mh.ini. If mh detects this file, it will read and execute its contents, then delete it.

  Examples:

    house speak hi there

    house display c:\autoexec.bat

    house Turn the backyard light on

    house XAJAK

mhl

You can use mhl to start mh (rather than calling mh directly) to help ensure that mh will always be running. This is a simple shell will restart mh if it detects that mh exited abnormally. You can pass in the same startup parms to mhl as you us for mh.

net_ftp

net_ftp sends, receives, or deletes a file to remote site via ftp. There is also an identical net_ftp function, if you want to call it directly from mh.

  Usage:

    net_ftp -option value -option value ...

    Where -option can be any of the following

       server          Default is mh.ini parm net_www_server

       user            Default is mh.ini parm net_www_user

       password        Default is mh.ini parm net_www_password

       dir             Default is mh.ini parm net_www_dir

       file            Name local/remote file to get/put

       file_remote     Name of remote file (if different from file)

       command         get/put/delete.

       type            ascii/binary  (default is ascii)

  Example:

    net_ftp -command put -file junk1.txt -file_remote /tmp/junk1.txt

outlook_read

outlook_read reads MS Outlook (a windows mail/calendar program) folder data and optionally creates a mh code file to implement calendar events.

  Usage:

    outlook_read [options]

  Options:

    -help    -> help text

    -version xyz -> Version of Outlook.  Use 98 if you have Outlook 98.

    -quiet       -> do not echo data to STDOUT

    -debug       -> print out debug

    -folder xyz  -> Get data from folder xyz.  It can be one of the following:

                      Deleted, Outbox, SentMail, Inbox, Calendar (default),

                      Contacts, Journal, Notes, Tasks

    -pl_file xyz -> Write out a mh perl code file.  These are the various

                    formats of Calendar subjects:

                      vcr channel_num show_name (e.g. VCR 8 Dilbert)

                      voice_command  (e.g. Christmas lights on)

                      message_to_speak (e.g. Today is national geek day)

                    Note:  If the text is not a vcr or voice_command, it

                           will be treated as a messages.

    -date xyz    -> Get data with a start_time on date xyz.  Default is today.

    -date_end xyz-> Get data with a start_time between -date and -date_end

    -days xyz    -> Look out xyz days from -date.  Default is 1 day.

  Examples:

    outlook_read -help

    outlook_read -date 1/17

    outlook_read -date 12/25/97 -days 2

    outlook_read -pl_file /projects/mhcode/outlook_events.pl

    outlook_read

report_weblog

report_weblog reads MisterHouse and/or Apache server logs and generates report graphs and optionally email them.

Usage:

  report_weblog [options] logfile(s)

    -h        => This help text

    -help     => This help text

    -ignore    xyz => A comma-delimited list of ip address to ignore.

    -mailto     xyz => Will email the charts to xyz

    -mailserver xyz => xyz is the SMTP host.  Default is localhost

    -runid      xyz => All graphs will have xyz as a prefix.  Default is blank.

    -outdir     xyz => All graphs be stored in directory xyz.  Default is .

  Examples:

    report_weblog -mailto 'bruce@misterhouse.net' /var/log/httpd/access_log

    report_weblog -mailto winters@home.net -mailserver 24.2.1.70 e:/mh/data/logs/server.1999_07.log

mhsend

mhsend allows you to send data to mh over the intra/internet. Data can be logged, filed, spoken, displayed, or run. The data processed by mh/code/test/mhsend_server.pl

  mhsend sends data to the MisterHouse program, through the internet/intranet.

  The following flags control what the companion mh server.pl code does:

    -file xxx    -> Files the data into mh/data/mhsend/xxx

    -log xxx     -> Logs  the data into mh/data/mhsend/xxx.log

    -run         -> Runs the data as command.

    -display xxx -> Displays the data.  xxx is how log to leave the display up.

    -speak       -> Speaks and displays the data.

    -pwfile xxx  -> Points to a password file. 

  Usage:

    mhsend 'hi there'

    mhsend -display 60 hi there Bruce

    mhsend -port 8083 -host misterhouse.net 'hi there'

    mhsend -speak file_to_speak.txt

    mhsend -file file1 file_to_send.txt

    mhsend -log This is a good url:  http://goodplace.com

    echo 'hi there' | mhsend -stdin

monitor_weblog

monitor_weblog monitors a Apache server log file. When the server logs hits, this code will summarize them and pass them onto the MisterHouse speak_server.pl code via a tcp/ip socket.

Usage:

  monitor_weblog [options] logfile

    -h        => This help text

    -help     => This help text

    -mh_server xyz => The ip address of your MisterHouse box.

    -mh_port   xyz => The ip port you set mh.ini server_speak to.

    -ignore    xyz => A comma-delimited list of ip address to ignore.

  Examples:

    monitor_weblog -mh_server house -ignore 'house,10.0.0.1' /var/log/httpd/access_log

set_clock

set_clock sets the clock according to the time from an internet connected NIST atomic clock server. Instead of requiring accurate time zone information, set_clock will simply set the time minute and second, but will keep to the nearest hour it was already set to.

  Usage:

    set_clock [options] 

  Options:

    -h         => This help text

    -help      => This help text

    -no_set    => Do NOT set the clock, only list the difference in time.

    -ignore xyz=> Do NOT reset the local clock if the time is more then xyz minutes off.

                  Default=10

    -method xyz=> xyz can be inet_time, http, or socket.  Default is socket.

    -server xyz=> xyz is the server to get the clock data from.  Here are a few:

                    time-a.timefreq.bldrdoc.gov:14  (default)

                    time.nist.gov:??

                    time-nw.nist.gov:??

  Example:

    set_clock 

    set_clock -server time-a.timefreq.bldrdoc.gov:14

  More info about NIST clock servers if available at:

    http://www.boulder.nist.gov/doc-tour/atomic_clock.html

Here is an example call from mh. Since this is typically quick, we do it here with a 'do' instead of a call with Process_Item:

   if (time_cron '7 6 * * * ') {

     my $status = do "$Pgm_Path/set_clock"; 

     speak $status unless $Save{sleeping_parents};

   }

set_password

set_password creates and/or queries the mh password file, using the crypt function. If this password is set, then web and telnet access will prompt for it. To reset the password, delete the mh/data/.password file.

  Usage:

    set_password [options] 

  Options:

    -h         => This help text

    -help      => This help text

    -password xxx => xxx is the password to check.

                     If not used, a TK popup window will prompt for it.

    -pw_file xxx  => xxx is the file that the crypt-ed password is read/written to.

                     Default is mh/data/.password

  Example:

    set_password 

speak

speak will pass the file or text to mh. It simply runs the house program. Example: speak ``Boo, did I scare you?''

 

=item trivia

This will update trivia question and answer files from the specified database. See mh/code/bruce/trivia.pl for an example of how to call it from mh.


Authentication

A one way crypt-ed password authentication scheme can be enabled for the web and telnet.pl interfaces.

The location of the crypt-ed password is controlled with the mh.ini password_file parm. The default location is in $Pgm_Root/data/.password.

If this file does not exist, the telnet.pl and web interface will be enable for anyone and everyone. If it does exist, and the correct password is not entered, the telnet.pl and web function will not implement the requested commands.

The set_password command is used to create and check this password. If you are running the un-compiled perl and do not have Tk installed, the password will have to be passed in with the -password parm (set_password -h for more help). This can be run from a shell prompt or with the mh mh_control ``set the password'' command.

If you want to change the password, delete the password file and rerun set_password.

When prompted for UserName and Password from your web browser, you can leave UserName blank ... it is not used.

Netscape appears to allow you to re-try a password, but MS Explorer must be re-started if you want to enter a different password.


Customizing the Tk Interface

You can modify what the Tk window displays by modifying the tk_frame.pl and tk_widgets.pl members. tk_frame.pl controls the general layout and size of the various scrolled lists. Modifying this member takes a little knowledge of perl Tk.

tk_widgets.pl shows how you can add widgets to display various info and allow for buttons for manual control. The mh tk_xxx subroutines used here will add widgets to either the menu_bar or to the 'grid' frame defined in tk_frame.pl.

Any change to tk_frame.pl or tk_widgets will be evaluated on a code reload, as will the tk_geometry parm in mh.ini.

tk_xxx widgets can be added anywhere in your mh code, not just the tk_widgets.pl member. See the weather_monitor.pl, internet_mail.pl, and tk_eye.pl members in mh/code/bruce for examples.

The tk_xxx widgets are 'packed' into the menu_bar or grid in the order that they are evaluated. You can use the 'Position' directive at the top of your member.pl code to control this. Position=1 is reserved for the tk_frame.pl member, as this must be evaluated first.

Note, you can also use native Perl tk commands, or create or override the tk_xxx subroutines in your own code for more flexibility.

For more info on the tk_xxx widgets, see look in the mh functions section of this document.


Customizing the Web Interface

You can write your own Web page interface. The examples under mh/web are frame html files that dictate the shape and positions of various mh-generated html frames.

You can use the html_root and html_file mh.ini parms to point to the directory and default web page. The html_default parm are the member names used when the URL points to a directory.

The html_style mh.ini parm points to a style sheet that will be loaded for all mh-generated pages. Style sheets allow default control of colors and fonts.

There are other, html_* parms in the mh.ini file to control how the auto-generated html data looks. For example, you can control table sizes and auto refresh rates. See the mh.ini file for more info.

The web Items and Groups displays will use icons to indicate the object state. Icons will be searched for in the mh/graphics directory according to the objects icon method, the object name, the object state, and the object type. For example, given this code:

    $fountain = new X10_Appliance('C3');

    set_icon $fountain 'water';

The search order for the ON state will be:

    water-on.gif

    fountain-on.gif

    x10_appliance-on.gif

    on.gif  

The web Category display will try to match icons to Voice_Cmd objects using the icon method, object name, voice command text, and filename. For example, given this code from the member internet_data.pl:

 $v_set_clock = new  Voice_Cmd('Set the clock via the internet');

 set_icon $v_set_clock 'time';

The search order will be:

 Look for icons that match time

 Look for icons that match set_clock

 Look for icons that match words in 'Set the clock via the internet'

 Look for icons that match internet_data.pl

All icons in the graphics directory are compared to each of the above. The first match (by search order) is used. If there are multiple matches, the match with the longest word is used. For example, if we had icons names 'clock.gif' and 'internet.gif' (but no 'time.gif'), 'internet.gif' would be used.

In all of the above examples, .gif was used as an example, but any browser compatable graphics file can be used (e.g. .png and .jpg). If you want to add new icons, some good sources are at http://www.freegraphicland.com/ , http://www.graphsearch.com/ , http://www.add-soft.com/icons/index.html , and http://www.rad.kumc.edu/icons/icons.htm

Important note: If you do play with adding/deleteing/renaming icons, you will want to do a reload before refreshing your browser. The icon directory is cached by mh (for efficiency). If no code has changed, the reload will run very quickly.

You can use the following html addresses to have mh return dynaically generated html:

  /category

    This will list all the Voice_Cmds, sorted by categories.  Categories are the member names of the 

    user code, or the value in the Category=value field specified in the user code.

    Items are also listed by Group, and Object Type

  /list?Category

    This can be used to list just the commands in the specified Category.

  /group

    This will return all the Group Items

  /group?$group_name

    This will return all the objects in $group_name

  /items

    This will return all the non Voice Objects (e.g. X10_Items)

  /items?object_type

    This will return all the objects of type object_type

  /widgets

    This lists all the Tk widgets.

  /widgets_label

    This returns just the label widgets

  /widgets_entry

    This returns just the entry widgets

  /widgets_radiobutton

    This returns just the radiobutton widgets

  /widgets_checkbox

    This returns just the checkbox widgets

  /speech

    This lists the most recently spoken text

  /print_log

    This lists the most recently print_log text.

If you want to generate your own html on-the-fly (like a cgi program would), instead of pointing to a .html file or or one of the above pre-defined mh-generated lists, point to a .pl file and have that perl code return the desired html. Note, this currently differs from how a classic cgi program would work (they return the html as STDOUT). Some examples of this can be found in the mh/web/test/*.pl files.

One other note on .pl web files. You can have them use variables you define in your mh user code, but only if those variables are defined with ``use vars '$my_var1', '$my_var2'''. Variables defined with ``my ($my_var1, $my_var2)'' are local only to the mh loop, and would not be available to any web .pl program.

In addition to calling the above mh-generated html directly, you can embed these lists in your own html using the server-side-include syntax. If the extention on your html is .shtml (for server-side html) then mh will parse the html, looking for the following string:

   <!--#include file="your_directive"-->

Anytime the above string is found, it will replace that record with whatever you specify in ``your_directive''. ``your_directive'' can either be another html (or shtml) file, or it can be one of the mh-generated lists from above. For example:

  <!--#include file="/mh/other_links.html"-->

  <!--#include file="category"-->

  <!--#include file="/mh_default/test/test1.pl"-->

You can use an #include var= directive, like file= above except it returns the contents of an mh variable. For example:

  <li><b>Version:</b> <!--#include var="$Version"-->

This what is used in the mh 'About' web button to return the mh version.

You can also define your own functions in your code files to return html, and then call them with the code= include directive. For example, add these to any of your code files:

  sub web_func1 {

      return "uptime = " . &time_diff($Time_Startup_time,$Time , undef, 'numeric');

  }

  sub web_func2 {

      return "results from function 2"; 

  }

Then call them like this:

 <p>Test web functions

 <!--#include code="&web_func1"-->

 <!--#include code="&web_func2"-->

One useful built in function is &dir_index, which can be used to create a directory listing of files in selected directories. For example, if you have a web directory called pictures, create an index.shtml file, and include the following line: <!--#include code=``&dir_index('/pictures','name',0)''-->

You can have &dir_index sort by name, type, size, or date. Set the 3rd argument to 1 for reverse sort order. See mh/web/graphics/index.shtml for an example.

If you want to have only a few specific html controls, you can write your own html using the RUN, SET, and SET_VAR url keywords to control mh. Here are a few examples:

 <a href=http://localhost:8080/SET?$test_lights?off >Turn the test light off</a>

 <a href=http://localhost:8080/SET_VAR?$Save{test_input1}?abc >Load test_input1 with abc</a>

 <a href=http://localhost:8080/RUN?WebCam_light_on >WebCam light on</a>

The SET command can set any object defined in your user code to a valid state. The SET_VAR command can set a variable to any arbitrary value. The RUN command can run any voice command. Use '_' to replace blanks in the command string.

SET, SET_VAR, and RUN can use an optional response field to decide what html will be returned:

  Format:

   SET_VAR:h_response?$var?value

   SET:h_response?object?value

   RUN:h_response?command

  Where h_response can be one of the following:

   &function:      The results of &function will be returned

   &function(arg): The results of &function(arg) will be returned

   last_response:  The last displayed or spoken text. 

   last_displayed: The last displayed text will be returned

   last_spoken:    The last spoken item will be returned

   filexyz.html:   The contents of filexyz.html will be returned

   string:         string will be returned

   blank:          A list of recently spoken text will be returned

Here are some examples demonstrating these options:

 This returns the last spoken line:

  <li><a href=http://localhost:8080/RUN:last_spoken?WebCam_light_on >Light on</a>

 This returns the string "Thanks for playing"

  <li><a href=http://localhost:8080/RUN:Thanks_for_playing?WebCam_light_off >Light off</a>

 This returns the contents of the mh/web/test/test3.html file:

  <li><a href=http://localhost:8080/RUN:test/test3.html?WebCam_light_+50 >+50</a>

 This returns a list of recently spoken text:

  <li><a href=http://localhost:8080/RUN?WebCam_light_-50 >-50</a>

 This will allow for text input, using a html FORM, and returning the the results form

 the user defined function &my_response:

  <FORM ACTION="SET_VAR:&my_response">Test 1<INPUT SIZE=5 NAME="$Save{test_input1}"</form>

You can also use RUN:h_response without a command. For example, if you want to get a directory listing, sorted by date (recent on top):

  <a href=http://localhost:8080/RUN:&;dir_index('/pictures','date',1)>List pictures by date </a>


Voice Recognition (VR) and Text To Speech (TTS) on windows

VR and TTS options are controlled with the Microsoft Voice application. It shows up as a 'green V' in your icon tray. Right clicking on this icon brings various menus for configuring your VR and TTS options.

You can pick between 3 VR modes, by right clicking on the MS Voice icon, or toggle between the modes by left clicking on the icon.

  - Listening for Voice Commands

    This mode will listen to anything and everything.  You can get lots of false

    recognition in noisy environments in this mode.

  - Not listening

    In this mode, VR will be turned on only when you hold down an activation key or

    move the mouse to a screen corner, depending on which 'Listening Mode' you

    pick in the 'Voice Command Options' menu.

  - Paused listening 

    This mode only listens for a specific trigger keyword.  If heard, then it

    temporarily switches to normal listening mode. The trigger keyword is listed 

    as your 'Computer Name' in the 'Voice Command Options' menu.

You can improve your Voice Recognition accuracy by talking through a 10 minute training session. Right click on the MS Voice icon and pick 'Voice Command Options', then click on the 'Advanced' tab, and finally click on the 'Optional Training' button.

You can pick the voice and speed of the TTS by clicking on the 'Computer Voice' tab on the same 'Voice Command Options' dialog.


Voice Recognition (VR) and Text To Speech (TTS) on Unix

Need notes on how to use viavoic on linux and how to enable different TTS engines with Festival.

For vr with viavoice, use mh/code/bruce/viavoice_control.pl


NOTES

This section has info that doesn't fit well anywhere else. Probably be better as a FAQ.

My hope is that mh will grow into a group project. There is so many, almost unlimited possibilities in Home Automation, that no one person could hope to implement them all.

If you feel so inclined, please send me any code that you develop that you think others might be interested in, and I'll include it in the distribution.

If you would rather see it mh in your windows tray, rather in the taskbar, here is a useful utility that will let you move any program to the tray: http://www.teamcti.com/TrayIt

Another handy utility for windows 95/98 users will help you monitor how much cpu and memory mh takes. TaskInfo80, available at http://www.iarsn.com/index.html

If you are getting the message ``Out of environment space'' try adding these records:

  config.sys:   shell=command.com /e:8000 /p

  autoexec.bat: set comspec=c:\command.com

If you want to use a program generated list in an Item declaration, you need to use add # noloop=start/stop comments before and after the code that should preceed the Item. Here is an example:

  # noloop=start

  my $mp3names;

  while ( my $mp3name = <d:/library/*.m3u> )

   {

    $mp3name =~ s#^.*/##;  # remove path

    $mp3name =~ s#\..*$##; # remove extension

    $mp3names .= "," if $mp3names;

    $mp3names .= $mp3name;

   }

  # noloop=stop

  $v_play_music = new Voice_Cmd("Play [$mp3names]");

  if ($state = said $v_play_music) {

    ... more code here ...

If you want to have a user defined function called once perl loop, but you want it before or after all the other user code has been called, use the &MainLoop_pre_add_hook and &MainLoop_post_add_hook functions to add callbacks to your functions. For example:

  $v_hook_pre_add   = new Voice_Cmd 'Add  pre  code hook';

  $v_hook_pre_drop  = new Voice_Cmd 'Drop pre  code hook';

  $v_hook_post_add  = new Voice_Cmd 'Add  post code hook';

  $v_hook_post_drop = new Voice_Cmd 'Drop post code hook';

  &MainLoop_pre_add_hook(  \&test_hook_pre)  if said $v_hook_pre_add;

  &MainLoop_pre_drop_hook( \&test_hook_pre)  if said $v_hook_pre_drop;

  &MainLoop_post_add_hook( \&test_hook_post) if said $v_hook_post_add;

  &MainLoop_post_drop_hook(\&test_hook_post) if said $v_hook_post_drop;

  sub test_hook_pre  { print "<"; }

  sub test_hook_post { print ">"; }

If you want your hook code to last between code reloads (e.g. added by startup code from a module), set the persistant flag by passing a 1 as a 2nd argument. For example:

  &main::MainLoop_post_drop_hook( \&jabber::process, 1 );

Here is a list of all the code hook locations:

  MainLoop_pre   => Run before user code 

  MainLoop_post  => Run before user code 

  Serial_match   => Run when incoming serial data matches

  Play_pre       => Run before playing wav files

  Play_post      => Run after  playing wav files

  Speak_pre      => Run before speaking text files

  Speak_post     => Run after  speaking text files

For more examples on code hooks, see mh/code/test_code_hooks.pl


KNOWN LIMITATIONS AND BUGS


General bugs/limitations

The JDS and Marrick interface modules are untested.

mh also has the the 'windows 49.7 day bug' (2**32 milliseconds) that has been in the news lately: http://www.news.com/News/Item/0,4,33117,00.html?st.ne.ni.rel .

Under windows, TK windows do not get focus and some keys and shortcuts do not work. Worse yet, the 'tear off' line (the dashed line on the pull down menus) causes mh to hang. Perl/tk on unix does not have either of these problems. Hopefully this will get fixed in a future release of perl/Tk. Note: if you have an old perl/tk (older than 8.0012), things are even more messed up.

If you have perl installed, you may get this message:

  Can't find 'boot_IO' symbol ...

The problem is there are two different IO.DLL files, one in the FTP module and one in the TK module. Do a find in IO.DLL in your perl directory, and rename the one in the tk path.


Windows bugs/limitations

If 'run' calls give you an 'out of environment memory' error, create a command.pif and change the memory, initial environment from auto to 4k.

Activestate perl 5.6 build 613 and 616 leaks memory. On my box about 30 Meg, once a day. Displaying .gif and .jpg files also leaks about 10x the picture size (e.g 10 50k photos -> 5 meg).

Some people are getting CRC errors when running iButton code under Windows NT.

Adding, deleting, or changing Voice commands does is not recognized by the Windows MSVoice applicatino while it is running. You have to exit and restart MSVoice, then restart mh to get it to recognize new commands. Hopefully we can get this to work with release 5.0 of the MS Speech SDK.


Unix bugs/limitations

Voice Recognition IS supported under linux using IBM's ViaVoice SDK. Potential candidates for VR engines other non-linux unix platforms are:

     http://www.speech.cs.cmu.edu/sphinx/

     http://cslu.cse.ogi.edu/index.html 

     http://WWW.ISIP.MsState.Edu/projects/speech_recognition/

     http://www.tmt.de/~stephan/ears.html

The control keys from the console window do not work (e.g. F1 to reload, F3 to exit). Ctl-C works :)

Disk drive info (need to port from DriveInfo to df)

Linux KDE users should uncheck ``Apply fonts and colors to non-KDE apps'', or the black text on white windows shows up as white text.


AUTHORS

Bruce Winter bruce@misterhouse.net http://misterhouse.net


SEE ALSO

mh can be download from http://misterhouse.net

Here is a list of other online mh sites:

  http://www.archer-online.net

Here is a list of articles written about MisterHouse:

  http://www.hometoys.com/htinews/jun99/articles/winter/winter.htm

  http://linuxworld.com/linuxworld/lw-1999-10/lw-10-mrhouse.html

  http://www.faribault.k12.mn.us/brian/aprs/

  http://www.circuitcellar.com/pastissues/articles/winter111/winter.pdf

  http://www.itknowledge.com/tpj/issues/vol5_1/tpj0501-0006.html

    (User login to The Perl Journal is required)

The Circuit Cellar Ink article includes a diagram of how to set up a house PA system, so you can control which rooms MisterHouse talks to.

You can suscribe and/or view the mailing list at http://sourceforge.net/mail/?group_id=1365 You can view the archive at http://lists.sourceforge.net/pipermail/misterhouse-users/ and search it at http://lists.sourceforge.net/mailman/listinfo/misterhouse-users

An older list with a searchable archive at <a href=http://www.onelist.com/messages/MisterHouse>here</a>).

Jan Dubois has a fun page of other ticks you can do with perl on windows at http://opensource.activestate.com/authors/jandubois/Perl/TPC3/fun.html

The comp.home.automation newsgroup is another handy resource, especially for X10 related questions.

Neil Cherry has created a home for linux related Home Automation programs at http://linuxha.sourceforge.net . This project is developing daemons for various interfaces (e.g. ADI Ocelot, CPUXA, and HCS II) that hopefully we can then link to with mh.

Rene Mueller has a nice set of web pages with lots of info on HomeAppliances at http://the-labs.com/HomeAppliance/


COPYRIGHT

Copyright (C) 1998-2000 Bruce Winter. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU public license.


DISCLAIMER

This program will most likely not cause your house to self destruct, but if it does, please don't call my lawyer. Actually, I suppose you could try to call my lawyer, since I don't have one I don't think you will get too far (grin).