mh - MisterHouse Home Automation Program
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 and Mac OSX.
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;
mh [options] [files]
options are controlled in the mh\bin\mh.ini file. You can override the default mh.ini parameters with 'private' parm files and point to them 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.
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 test1.log and turn on all serial related debug messages:
mh -debug serial > test1.log
There is also a FAQ that covers misc. topics in mh/docs/faq.html
We have a wiki at http://misterhouse.wikispaces.com for user-supplied documentation.
Gordon Meyer wrote a nice getting started article.
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 150 MHz PPro system.
There is lots of good perl info is at http://www.perl.com . The reference book is "Programming Perl, 3rd 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.
I fun way to slowly learn perl is with to get a perl FAQ per day. You can sign up here: http://perl.faq-by-day.org
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 \.
For a list of the hardware in Bruce's house, see mh/pod/faq.* question 6.8.
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 transmitter 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.
Another nice X10 option are the X10 RF -> Serial interfaces. The MR26A is $30 from http://www.x10.com/products/x10_mr26a.htm . The W800RF32 is $50 from http://www.wgldesigns.com/w800.html . A comparison of them is here http://www.wgldesigns.com/comments.htm . These will receive the information coming from most of the X10 RF devices (e.g. motion sensors, keychains, palmpads, remote controls like UR19, UR47, JR20). The advantage to receiving X10 data this way, instead of a powerline device like a CM11, is it is much faster as data goes from RF -> MR26A/W800RF32 -> serial_port -> mh. Actions can be triggered in milliseconds, without having to wait for the 500+ millisecond time it takes to transmit data over the powerline. More info in mh/code/common/x10_rf_relay.pl .
This new RF->X10 interface now supports all house codes (older ones only support one house code each): http://www.letsautomate.com/10680.cfm?CFID=67097&CFTOKEN=4528584
Another supported X10 interface is the Marrick Lynx10-PLC controller: http://www.marrickltd.com See mh/lib/Lynx10PLC.pm
A nice summary of the different X10 controllers is here: http://www.geocities.com/ido_bartana/Which_controller.html
A survey of common X-10 devices and some hints as to their behavior is here: http://www.shed.com/x10stuff.html
Here is yet another site with X10 info: http://www.x10ideas.com
Europeans can get X10 stuff from http://www.intellihome.be , http://www.hwg-telekom.de , www.madomotique.com, www.letsautomate.com, and www.laser.com .
Europeans can also get iButton and Weeder boards from http://www.homechip.co.uk
Australians can get gear from www.digihouse.com.au , www.eon3.com , www.dse.com.au , and www.tecsol.com.au .
Note that the CM12 is the equivalent of a CM11 for 220v/240v locations.
Many X10 noise issues can be solved with the LEVHCA02 repeater and bridge, available here for $65: http://www.worthdist.com/Leviton/hca02-10e.htm
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
You can use 1->2 of the Weeder IO kits to drive the the 'universal relay kit' from http://jameco.com (do a search for 'relay card' or 128910). The $60 gets you 8 relays. Here is some more info:
1. The board is sold as 8 relays complete, upgradable to 16. If you only want to use 8 relays(in a limited fashion), the kit is all you need.
2. If you want more than 8, you need more than just the extra 8 relays them selves. - you will need 8 extra diodes(1n4148 in my kit) - you will need about 30 extra terminating blocks
3. The board comes with spots for LEDs to show activity, you will need to provide those as well as the resistors to drive them(none are provided).
4. As delivered, the Weeder board will not drive the relays, you will need to get 2 ULN2803 darligton transistor array chips to do that(The relays need 12V, the Weeders give 5V).
5. The board has the ability to be manually driven, you will need to buy 2 extra 8 pin dip switches to do that.
6. It comes as a bare open board, so think about an enclosure of some type.
7. All of these parts are available from jameco for nominal extra cost.
Danal Estes reports another relay option is the ELK-924-4 "Sensitive Relay": http://www.elkproducts.com/products/elk-924.htm. He used a couple of the four packs. Work like a charm, have been in an attic for over a year, no problems. Smarthome carries these for $38 a four-pack, you can probably find them cheaper, lots of alarm system places carry them. Search on "ELK-924".
Nico wrote an interface to the Velleman k8000 board: http://www.velleman.be/Product.asp?lan=1&id=9383, available from his site at http://yow.be
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 controller, http://www.csi3.com/homevis2.htm . This controller 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 DSC_Alarm.pm module supports the DSC PC5400 serial printer interface. This module prints all events that DSC logs to the event buffer. These events include arms/disarms/alarms, user code(s) that performed action(s), installer access, etc. DSC does not log individual zone open/close nor 'entry chime' events. See the mh/lib/DSC_Alarm.pm for further information. See also the DSC_Alarm item below.
The CPU-XA, Ocelot, and Leopard controllers from Applied Digital Inc (http://www.appdig.com/adicon.html ) are supported through network calls to the cpuxad daemon, part of the XALIB package, available at http://mywebpages.comcast.net/ncherry/common/cpuxad
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/public/irman.pl code, 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.
There is an X10 product called IR Commander that works with the Firecracker and sends infrared. It's not a learning remote and most people who try it are disapointed. The RedRat2 is supported by misterhouse, but doesn't seem too popular. David Norwood wrote the module for the UIRT2 and it is being used by a few on both Windows and Linux. He now also has a module for the USB-UIRT. The Ocelot is another option.
FireCracker: http://www.x10.com/products/ux17a_bj2.htm
RedRat: http://www.redrat.co.uk/
UIRT: http://www.fukushima.us/UIRT2/
UIRT USB: http://home.earthlink.net/~jrhees/USBUIRT/index.htm
As of 6/2004, the send/receive USB RedRat3 ($99 from http://www.redrat.co.uk/ ) is supported using the windows xAP RedRat Connector: http://www.xapframework.net/modules.php?name=Downloads&d_op=viewdownload&cid=45. RedRat3 is a great product with a growing online list of downloadable IR codes.
As of 6/2005, the send/receive multi-zone capable USB IRTrans interface (99 Euro from http://www.irtrans.com/) supports xAP, and thus MisterHouse.
Here are 2 LCD displays with programmable 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.
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
Nice big Alpha LED serial connnected signs are supported as of 6/2004. I picked up the Alpha 213C (a.k.a. BetaBrite, 2" x 24", 14 character) from the local Sam's Club for $150. Their web site only lists a bigger version, but info on BetaBrite I have can be seen here: http://www.betabrite.com/Pages/betabrite.htm . It displays in multiple colors, in either scrolling or fixed text. See Display_Alpha.pm header for details.
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.
An better, object-oriented way to write code to interface to a new hardware device is in mh/lib/example_interface.pm.
Byterunner offers lots of types of serial cards: http://www.byterunner.com. Note for windows users: with the PCI-800H, I found I had to click the 'use default baud rate' box under control panel -> device manager (under the 4th tab, data rate).
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). See mh/lib/Weather_wx200* for info on interface code.
There is also now a new WMR-918/968/Radio Shack Accuweather, which is a wireless version, available for about $350. See mh/code/public/weather_monitor_wmr968.pl.
See weather_monitor_ultimeter2000.pl for an example of interfacing to the Peet Bros. Ultimeter200 weather station: http://www.peetbros.com
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 adapters will not work with mh
- $3 DS1990A-F5 for 64 bit ID buttons.
http://www.ibuttonlink.com
- The $35 LINK interface has been reported as more reliable and
is more flexable than the DS9097 listed above.
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 output 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
http://www.aag.com.mx
- Sells an iButton weather station for $80
http://ibuttonlink.com/
- An improved $35 serial interface
http://weather.henriksens.net has free 1-Wire Weather station software
- It includes a tcp/ip server that (in theory) could talk to mh
Ray Dzek has a nice how to get started tutorial here:
http://www.solarbugs.com/home/ibutton.htm
Neil Wrightson also has some 1wire info here:
http://www.users.bigpond.com/nwrightson/1Wire%20Hardware.htm
A Linux "One Wire File System" that sets up the one wire bus to look like
a directory (not integrated to mh yet)
http://owfs.sourceforge.net/
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 meant 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.
The mh/code/common/barcode* members code will process data from the Cue Kat keyboard simulator barcode scanner, which used to be free from places like Radio Shack but are now discontinued.
If you would like to do call waiting caller id (normal callerid and caller id even while you are on the phone), you can a good deal on the NetCallerID box for $15 from here: http://www.dfwmetrotechs.com/misterhouse/calleridorder.html
Varous routers can be monitored and controled with code/common/monitor_router*.pl
5/2002: Bill Sobel added lib/AudiotronPlayer.pm, to support the Turtle Beach AudioTron.
5/2002: Pete Flaherty's created code/public/weather_iB_OWW_client.pl to read data from the OWW 1-wire ibutton weather station daemon
8/2002: Chris Witte created mh/lib/caddx.pm and mh/code/public/caddx.* for monitoring the outputs from a CADDX nx8e alarm panel.
9/2002: Richard Morgan's sent in mh/code/public/cbus_v2.0.zip, his set of code for talking to CBUS devices via the Australian Clipsal CGATE interface.
7/2003: Lincoln Foreman sent in mh/code/public/pha_k256.pl as an example of reading data from Phanderson's K256 kit which can monitor 256 DS1820 temperature sensors, 8 bits digital IO, and 11 bits of analog IO. Available for $50 from http://www.phanderson.com/t64.html
12/2003: Kirk Bauer created lib/RCSsTR40.pm for the RCS TR40 Theormostate: http://www.resconsys.com/products/stats/serial.htm
1/2004: Nick Maddock replaced mh/code/public/alarm_concept.* files with mh/code/public/concept_* for interfacing to the Concept 4000 alarm panel.
3/2004: Kirk Bauer created lib/Musica.pm to control the Musica whole-house audio system by Netstreams over the RS232 port. This system has provides 6 zones and 4 sources with very nice keypads: http://www.netstreams.com
4/2004: Dave Hall created code/public/robot_er1.pl for interacting with the Evolution Robotics ER1 robot: http://www.evolution.com/er1/
7/2004: Kirk Bauer created lib/Tivo_Control.pm for displaying text on a Tivo. See header for details.
7/204: Created code/common/robot_robosapien.pl for using IR to control the RoboSapien Robot: http://www.robosapienonline.com (got mine for $100 at Best Buy). It doesn't do anything practical, but it is a fun toy.
9/2004: Scott Johnson created mh/code/public/siteplayer.pl as an example of sending digital signals to a $30 siteplayer ethernet interface: http://www.siteplayer.com
11/2004: Created lib/Servo_Item.pm to supports servo motors via the $40 Mini SSC II serial servo control board, available from http://seetron.com .
11/2004: Created code/common/robot_esra.pl to control the $180 Robodyssy ESRA robot head from http://robodyssey.com . It has 5 servos (eye lid, eyes, lip top/bottom, and an optional neck) which are connected via the Mini SSC II serial servo controler. Pictures and a movie are at http://misterhouse.net/public/robot/ .
5/2005: Created mh/bin/xAP-bluetooth.pl (called with mh/bin/xAP-bluetooth) and mh/code/common/xAP_bluetooth.pl for monitoring when bluetooth enabled devices (e.g. phones) go in and out of range. The xAP daemon runs on Linux and requires the bluez lib to be installed (pointers in the header).
10/2005: Dan Wilga created mh/lib/X10_Wish.pm which interfaces to the Linux Wish X10 drivers: http://sourceforge.net/projects/wish . These are the currently supported device: PowerLinc Serial, PowerLinc 1132 USB, CM11A, and Firecracker/CM17A. Currently supports sending, but not receiving, X10 data. More info at the top of lib/X10_Wish.pm.
10/2005: Brent DeShazer created lib/Display_osd232.pl and code/common/display_osd232.pl for interfacing with Intuitive Curciuts OSD-232 On-screen video overlay interface, available from http://www.icircuits.com/prod_osd232.html
10/2005: Peter Sjodin added Linux support for EIB (European Installation Bus, info here: http://en.wikipedia.org/wiki/European_Installation_Bus ). New modules are lib/EIB_Items.pm and lib/EIB_Device.pm. Example items are in code/examples/eib_items.mht.
Info on an LCD internet appliances that makes an affordable touch screen controllers in the MisterHouse Internet Appliance FAQ here: mh/docs/ia.html
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:
Points to the directory that has the user code files in it. This can be a comma delimited set of paths if you want to keep your code files between different directories.
Points to where the web interface html files are.
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 ).
Use 23 to enable access via 'telnet localhost', if you are running the mh/code/common/telnet.pl member. If you use a different port, you can still get to the port with 'telnet localhost port_number'.
Set this (or w=1) to enable perl -w warning messages on potential code errors. mh runs about 10% slower with this option on.
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.
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. You can also stack debug flags, using ; as a separator. fro example:
mh -debug serial;x10
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
Time/Date Variables
$Time_Startup, $Time_Startup_time, $Time_Now, $Date_Now, $Date_Now_Speakable, $Year_Month_Now $Time_Sunrise, $Time_Sunset, $Time_Sunrise_Twilight, $Time_Sunset_Twilight $Second, $Minute, $Hour, $Mday, $Wday, $Day, $Month, $Year, $Holiday $New_Msecond_100, $New_Msecond_250, $New_Msecond_500, $New_Second, $New_Minute, $New_Hour, $New_Day, $New_Month, $New_Year $Season, $Weekday, $Weekend, $Time_Of_Day, $Dark %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 formatted time and date.
$Dark is true between $Time_Sunset_Twilight and $Time_Sunrise_Twilight, false otherwise.
The $New_* variables are true only on the pass that we enter a new Second, Minute, Hour, etc. $New_Msecond_100/250 are true every .1 and .25 seconds. There are also new_* functions if you want to test on every nth second/minute/hour (see new_second function).
$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.
$Keyboard echoes characters typed on the keyboard (currently windows only)
%Save is a hash in which the values of variables can be saved so that they remain unchanged after mh is re-started. The values can be checked using the web widgets menu.
%Misc is a hash in which other miscellaneous data can be stored. These values can also be checked using the web widgets menu. This is a handy place to put data you might want to display in .shml web pages.
These constants are defined, so we can use them without quoting them (e.g. if $state eq ON instead of if $state eq 'on'):
ON => 'on'; OFF => 'off'; DIM => 'dim'; BRIGHTEN=> 'brighten'; TOGGLE => 'toggle'; STATUS => 'status'; OPEN => 'open'; CLOSE => 'close'; OPENED => 'opened'; CLOSED => 'closed'; MOTION => 'motion'; STILL => 'still';
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.
After reading the last record, it wraps back to the first.
read_next_tail : Like read_next, except, it will not wrap back to
the first record (i.e. after reaching the end of the file,
it will alwasy return the last record).
read_current : Reads the current record, according to the index.
get_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.
exist : Returns 1 if the file exists
exist_now : Returns 1 if the file was created since the last exist_now test.
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_monitor.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;
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 : Creates an object of the specified name
state : Returns the state (e.g. on, off)
state_now : True only for one pass after object state is set.
state_changed : True only for one pass after object state changes.
Unlike state_now, state_changed will return undef (false) if
the item is set to the same state it is currently in.
state_final : Returns the state the object will be in after all queued
state changes have been processed.
set($state) : Places the value into the state field (e.g. set $light on)
Note: states are set at the start of the next mh pass.
set_now($state) : Like set, except states are set when called, not on the next pass.
set_with_timer($state, $time, $return_state)
: Like set, but will return to $return_state after $time.
If $return_state is not specified, it toggles $state.
If $return_state is previous, it returns to the previous state.
If set is called before the timer expires, the timer will be unset.
You can also stack a series of set_with_timer calls with one set call like this:
set('s1~t1~s2~t2...sn');
where s1, s2, ... sn are various states, and t1, t2 ... tn are the times to
wait between states. See example below.
If you want to stack a set of states without delays, you use ; like this:
set('on~2~random:on;repeat:on;play');
See mh/code/examples/test_states_stacked.pl for a complete example.
Note, this is turnded off by default for Serial_Item objects.
To enable, run: $object -> state_overload(ON);
set_casesensitive : By default, states are all lowercased, to allow for case
insensitive tests. To avoid this (for example on Serial Interfaces
that are case sensitive), call this method.
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_event($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
tie_filter($filter) : Use this to disable control of the item whenever
$filter returns true. Variables $state and $set_by
can be used in the $filter test.
untie_filter($filter):Untie $filter
tie_time($time,$state): Sets item to $state if the $time string evaluates true.
$time can be in either time_cron or time_now format.
untie_time($time) : Untie $time
time_idle($time) : Returns true when the object has had no state changes
since the specified time. $time can be be in seconds,
minutes, hours, or days (e.g. '90 s' or '7 days').
Optionally, $time can also specify a spefic state (e.g. '4 m on')
set_by : allows setting a description of why the last state change
- motion, sunrise, manual, serial, etc.. any string
is allowed value is returned by get_set_by below.
get_idle_time : Returns number of seconds since the last state change
get_set_by : Returns what caused this object to change. Values either:
- Name of the object
- web, tk, telnet, vr, xcmd, serial
An example is in mh/code/examples/test_set_by.pl
set_states(@states) : Sets valid states to @states
add_states(@states) : Adds @states to the list of valid states
get_states : Returns the list of valid states
restore_data(@vars) : Specifies which variables should be saved/restored between
mh reload/restarts. The state var is always saved.
set_authority('anyone') : Bypasses password control
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_label: Specify a text label, useful for creating touch screen interfaces.
set_web_style: Contols the style of we form used. Can be dropdown, radio, or url.
See mh/code/examples/test_web_styles.pl
set_count : Use these methods to control a count variable.
get_count
incr_count
reset_count
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* method call on $Reload, as the objects tie items/events are currently not stored between reloads.
The tie_* methods can also take 2 optional arguments. The first is the state you want the tie to apply to. If not specified, it defaults to all states. This is required for tie_time.
The 2nd optional tie_* argument is a print_log message you want whenever the tie_ event triggers.
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_set_by $test_button;
print_log "Test button's was set to $state by $ref->{object_name}" if $ref;
}
# This shows how to set states
$TV = new IR_Item 'TV';
my $tv_states = 'power,on,off,mute,vol+,vol-,ch+,ch-';
set_states $TV split ',', $tv_states; # causes $tv_states to be split into array
values via the split command deliminated by the ,
$v_tv_control = new Voice_Cmd("tv [$tv_states]");
# This shows how to save persistant arbitrary data
$Test = new Generic_Item;
$Test->{junk_data1} = $Time_Now if $Reload;
$Test->{junk_data2} = $Month if $Reload;
$Test->restore_data('junk_data1', 'junk_data2');
# Here are some tie* examples
$fountain -> tie_filter('state $windy eq ON', ON,
'Overriding item1 ON command because of wind');
$fountain -> tie_time('10PM', OFF, 'Fountain turned off');
# Disable an item when we are away
$item1 -> tie_filter('state $status_away eq ON');
$item1 -> tie_event('print_log "item1 toggled to $state"');
# Ignore RF sourced (e.g. W800 or MR26) X10 data
$light1 -> tie_filter('$set_by eq "rf"', , 'Ignoring x10 rf data');
# Disable callerid announcements when we are not at home
$cid_announce -> tie_filter('state $mode_occupied ne "home"');
# Set an item to multiple states, with 5 second a delay between states
$test_set1 = new Generic_Item;
$test_set1 -> set('0%~5~30%~5~60%~5~100%') if new_second 20;
$test_set1 -> tie_event('print_log "test set $state"');
print 'Item is idle' if $test_set1 -> time_idle('4 seconds');
See mh/code/examples/generic_item.pl for more examples, test_tie.pl for more examples on how to tie/untie items/events, and test_idle.pl for more examples on testing idle times.
You can use this object to group and operate on groups of items:
Methods:
new(@item_list)
add(@item_list)
list
set
state
state_now : Like the Generic_Item methods, these return
the last state that the group was set to.
If a group member changed, these methods will
return 'member $state_name' rather than just '$state_name'.
You can use the member_changed or get_set_by methods
to see which member changed.
state_log : Returns a list array of the last max_state_log_entries (mh.ini parm)
time_date stamped states.
member_changed: Returns a member object name whenever one changes
member_changed_log: Returns a list of recenty changed members.
The first one was the most recently changed.
remove : Remove an item from a group
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");
for my $item (list $outside_lights) {
print "member = $item->{object_name}\n";
}
if (my $member_name = member_changed $outside_lights) {
my $member = &get_object_by_name($member_name);
print_log "Group member $member_name changed to $member->{state}"
}
my @members = member_changed_log $sensors;
# turn off all but the bedroom light when we are getting ready for bed
if( state_now $bedroom_control eq ON ) {
my $all = new Group(list $All_Lights);
$all -> remove ( $master_bedroom );
set $master_bedroom ON;
set $all OFF;
}
See mh/code/examples/test_group.pl and mh/code/public/monitor_occupancy_jason.pl for more examples.
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_serial_port.
Methods:
new $id, $port, $channel
If $port is not specified, the port of the first iButton::connect
will be used.
$channel (used for switches like the DS2406) defaults to A
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.
read_switch : Reads iButton switch data
read_windspeed : Reads iButton weather station wind speed
read_dir : Reads iButton weather station wind direction
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 functions are also part of the iButton module, but not associated with an object:
scan $family, $port : Returns a object list of iButton devices that match $family
scan_report $family, $port : Returns a report of iButton devices that match $family
monitor $family, $port : Checks the one wire bus for iButton activity
connect $port : Connect to the one wire bus. Note you can now have multiple
iButton interfaces on multiple COM ports.
disconnect : Disconnect to the one wire bus
Note, all of these functions take an optional $port parm (required for connect). If not specified, the port of the first connect record will be used.
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_serial_port});
print_log &iButton::connect($config_parms{iButton_2_serial_port});
}
else {
print_log &iButton::disconnect;
print_log &iButton::disconnect, $config_parms{iButton_2_serial_port};
}
}
$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', undef, 'A';
$ib_relay2 = new iButton '12000000123456ff', undef, 'B';
$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', $config_parms{iButton_2_serial_port};
$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;
}
This object allows control of Homevision controller via the Homevision web server. Set homevision_url=<your homevision web server URL> in mh.ini. See the Homevision documentation for complete list of command formats. Configure Homevision Webserver to report command results.
Examples: $kitchen_light = new HVweb_Item('On', 'X10 G1 On'); $kitchen_light -> add ('Off', 'X10 G1 Off'); $vcr = new HVweb_Item('Power', 'IR 45 1 time'); $vcr -> add ('Play', 'IR 46 1 time');
set $kitchen_light 'On';
set $vcr 'Play';
This object controls IR transmiters. The devices currently supported are the X10 IR Commander, HomeVision, CPU-XA/Ocelot/Leopard, and UIRT2 (http://www.fukushima.us/UIRT2/).
The X10 IR Commander (http://www.x10.com/products/ux17a_bj2.htm) 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, $interface, $mapref : Creates a new Item.
$type is the type of device being controlled. Default is TV.
Here are the only valid types for the X10 IR Commander:
TV, VCR, CAB, CD, SAT, DVD
$code specifies how numbers will be treated. Default is 2digit.
noPad : numbers are not modified
2digit : single digits will be padded with a leading zero
3digit : numbers will be padded to 3 digits with leading zeros
addEnter: adds an ENTER command after any numbers, to make
changing channels faster on devices that wait for a
timeout (e.g. Sony TVs).
$interface is the transmitter to be used. Default is cm17.
cm17 : X10 IR Commander
homevision: HomeVision
ncpuxa : CPU-XA/Ocelot/Leopard
uirt2 : UIRT2 (http://www.fukushima.us/UIRT2/)
xAP : Sends / receives data via the xAP protocol.
$mapref is a reference to a hash that specifies commands to be
mapped to other commands. This is useful for transmitters
like the Ocelot which use slot numbers instead of device and
function name pairs. Default is a reference to a hash containing
ON => POWER,
OFF => POWER
Which you would not want if you had descrete ON and OFF codes.
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 for the X10 IR Commander::
Note: Commands are not 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');
This object is used to send and receive data to LCD type displays with keypads. An example is in mh/code/bruce/lcd.pl. To use simulate an LCD keypad with your pc keyboard, use mh/code/bruce/lcd_keyboard.pl.
Methods:
new $type, $port, $size, $menu_group, $keymap
$type: Either lcdproc or keyboard.
$port: The ip:port of where lcdproc is running.
$size: ROWSxCOLUMNS of the LCD display.
$menu_group: The menu parsed by menu_parse (see Menu section of this doc).
$keymap: A has that translates keys to usable names.
start => Connect to the LCD. Automatically called on startup
stop => Disconnect the LCD.
load $menu => Load menu $menu. Default menu is the first one.
check_key => Returns whatever key is keyed in
set @data => Sends @data to the LCD, one line per list element
set_key $key => Simulates the keyboard being pressed with $key
inactive => Returns true if no key has been pressed in 10 seconds.
Examples:
my %lcd_keymap1 = ( N => 'up', I => 'down', M => 'left', H => 'right',
F => 'exit', K => 'enter', L => 'left', G => 'right');
my %lcd_keymap2 = ( 38=> 'up', 40=> 'down', 37=> 'left',
39=> 'right', 17=> 'exit', 96=> 'enter') ;
$lcd1 = new LCD 'lcdproc', '192.168.0.5:13666', '4x20', 'default', \%lcd_keymap1;
$lcd2 = new LCD 'keyboard', undef, '4x20', 'mh', \%lcd_keymap2;
This module doesn't do much yet. Currently uses ping to detect when specified ip address is up.
Methods:
new $address, $interval
$address: Ip address of the box you want to ping
$interval: How often to ping (in seconds)
Examples:
$network_house = new Network_Item('192.168.0.2', 10);
$network_hp = new Network_Item('192.168.0.66', 20);
print_log "house just changed to $state" if $state = state_changed $network_house;
print_log "house is $state" if new_second 15 and $state = state $network_house;
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
unfortunately, it causes perl to crash often, so is probably not useful yet.
set_timeout $timeout : Process will timeout after $timeout seconds
set_output $output_file : Program STDOUT errata goes to $output_file
set_errlog $errlog_file : Program STDERR errata goes to $errlog_file
start : Starts the process.
start 'program arg' : Starts the process with program arg
stop : Stops the process. If called as a stand alone function
(not as an object method), 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.
pid : Returns the process id
timed_out : Returns the time when the process timed out.
done_now will still trigger for a timed_out process.
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;
$p_report_weblog ->set_output("$config_parms{data_dir}/weblog_results.txt");
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')";
set_timeout $p_test_ftpb 60*2;
start $p_test_ftpb;
}
print_log "Ftp command done" if done_now $p_test_ftp;
More examples are in mh/code/examples/test_process.pl
An RF_item is created to receive states from X10 security devices and RF TV style remote through a W800RF32 module or an MR26A module (the MR26A only passes TV remote style data through, it does not pass security data).
To configure the W800 or MR26 interfaces, see the comments at the top of mh/lib/X10_MR26.pm and mh/lib/X10_W800.pm.
RF items can be created in the items.mht in the following manner:
RF, 68, keychain_remote, Security
RF, System, security_system, Security
RF, Sensor, security_sensors, Security
RF, 81, door_sensor, Security
RF, Remote, tv_remote, TV
RF Items can be manually created in the following manner:
$keychain_remote = new RF_Item('68' , 'keychain_remote' );
$security_system = new RF_Item('system', 'security_system' );
$security_sensors = new RF_Item('sensor', 'security_sensors');
$door_sensor = new RF_Item('81' , 'door_sensor' );
$tv_remote = new RF_Item('remote', 'tv_remote' );
The 2nd column the items.mht file (or the 1st parameter when manually creating a new RF_Item) is the 2 digit hexadecimal unit id of the particular transmitter or one of the following classes:
system Any device that change the state of the security system.
States from any transmitters that go into this class are:
armawaymin, armawaymax, armhomemin, armhomemax, disarm, panic
sensor Any device that changes a sensor state.
States from any transmitters that go into this class are:
normal, normalmax, normalmin, alert, alertmin, alertmax
control Any device that changes some general feature:
States from any transmitter that go into this class are:
lightson, lightsoff
remote Any TV style remote control (UR51A, etc.).
States from any transmitter that go into this class are:
Power PC Title Display Enter Return Up Down Left Right Menu
Exit Rew Play FF Record Stop Pause Recall 0 1 2 3 4 5 6 7 8 9
AB Ch+ Ch- Vol- Vol+ Mute
Some transmitters have a min and max switch that cause the transmitter to send different states depending on that switch. If you don't care about the full detail of the state, you can do a test like:
if (my $state = state_now $door_sensor =~ /^alert/) { ... }
To determine what the 2 digit hexadecimal unit id for a particular security transmetter is, press the button on the transmitter (or open/close the sensor) and look at the misterhouse log to find the id that the unit transmitted.
Serial_Item is used whenever you want read or write serial port data. Like most mh objects, it inherits all the Generic_Item methods.
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.
Note that the a 'set' will trigger a state_now one the next 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.
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;
$serial_tom10port = new Serial_Item(undef, undef, 'serial_tom10');
$serial_tom10port -> set_casesensitive; # TOM10 needs lowercase commands
See mh/code/examples/serial_port_examples.pl for more Serial_Item examples.
This object can be used to track data stored in the global %Weather array.
Methods:
new $type
$type is the name of the %Weather index you want to monitor
$type can also have a =<> comparison operator in it so
you can make the object a true/false test.
state : Returns the last state, or 1/0 if $comparition and $limit were used.
state_now : Returns the state only when the weather data changed.
It also inherits the Generic_Item methods.
Examples:
$WindSpeed = new Weather_Item 'WindSpeed'; $WindSpeed-> tie_event('print_log "Wind speed is now at $state"');
$freezing = new Weather_Item 'TempOutdoor < 32'; if (state_now $fountain eq ON and state $freezing) { speak "Sorry fountains don't work too well when frozen"; set $fountain OFF }
$Windy = new Weather_Item 'WindSpeed > 15'; speak "Wind is gusting at $Weather{WindSpeed} mph" if state $Windy;
# For current state, easiest to use it directly
speak "Outdoor temperature is $Weather{TempOutdoor} degrees";
For examples on interface code that stores data into %Weather, see mh/code/bruce/weather_monitor.pl (uses mh/lib/Weather_wx200.pm), mh/code/public/iButton_ws_client.pl, and mh/code/public/weather_com.pl
This item is for controling X10 lamp modules and light switches. It is derived from Serial_Item and the strings it sends are like Serial Items, except an 'X' prefix is prepended to indicate an X10 command. The X strings are converted by one of the various X10 interfaces into the appropriate commands for that interface.
Methods:
new('house code[unit number]' [, 'interface'|undef [, 'option flags']])
'house code[unit number]' The first argument is required and is either a house
code by itself or a house code and unit number.
Note that the X10 unit code is numbered either 1->16 or 1->9,A->G.
For example device 16 in house code P could be P16 or PG
'interface' Optional, specifies which X10 interface to use
'option flags' Optional, specifies one or more module options (see below)
state : Returns the last state that was received or sent
state_now : Returns the state that was received or sent in the current pass
level : Returns the current brightness level of the item, 0->100
set_receive : Update the state and level when X10 commands are received
set_x10_level: Recalculates state whenever state is changed
set('state') : Sets the item to the specified state
'on'
'off'
'toggle' - toggles between on and off
'brighten'
'dim'
'+##' - increase brightness by ## points
'-##' - decrease brightness by ## points
'##%' - set brightness to ## percent
'+##%' - increase brightness by ## percent
'-##%' - decrease brightness by ## percent
'double on' - on some modules this sets full brightness at ramp rate
'double off' - on some modules this sets 0 brightness immediately
'triple on' - same as double on, but immediate
'triple off' - same as double off
'status' - requests status from a two-way capable module
'manual' - sends house code and unit number without a command
'&P##', 'PRESET_DIM1', 'PRESET_DIM2', 'ALL_LIGHTS_OFF', 'HAIL_REQUEST',
'HAIL_ACK', 'EXTENDED_CODE', 'EXTENDED_DATA', 'STATUS_ON', 'STATUS_OFF', 'Z##'
- these states are rarely used and provided for special cases
Note: not all states are supported by all lamp modules and X10 interfaces.
X10 items can be created in the items.mht in the following manner:
X10I, A1, Test_light, Bedroom, cm11, preset resume=80
If a single character is used (e.g. X10_Item 'D'), commands apply to all X10_Items with that house code. The '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