http://www.perlmonks.org?node_id=178986

I wrote this little program to display random messages and caller ID information on my BetaBrite LED Sign. (These used to be available at Sam's club for about $200.) A word about the hardware setup: This is coded for an old PC of mine running Windows 98. The sign is connected to COM2 and my caller-id-capable modem is connected to COM1.

The program reads message strings to display from the file "messages." Each message is assumed to occupy one line. If the string begins with "sub {" it is treated as a subroutine that returns a string to be displayed -- good for random or other run-time content.

The program has a primitive gui that I built with the Gui Loft. The only option available is to display or suppress the random messages (via a checkbox). If the random messages are enabled, one is picked at random (duh!) and displayed with a random mode, e.g., flashing, "snowing", etc. A different message is selected every few seconds.

Caller ID info is displayed even when the random messages are suppressed. Polling the modem for incoming calls occurs in the my_sleep routine (while we're waiting to select the next message.)

Comments and suggestions are welcome.

laughingboy

#! perl -w use strict; use Win32::SerialPort; use Win32::GUI; use Win32; use Win32::GUI::Loft::Design; use constant ROTATE => 1; # "a" use constant HOLD => 2; # "b" use constant FLASH => 3; # "c" use constant ROLLUP => 4; # "e" use constant ROLLDOWN => 5; # "f" use constant ROLLLEFT => 6; # "g" use constant ROLLRIGHT => 7; # "h" use constant WIPEUP => 8; # "i" use constant WIPEDOWN => 9; # "j" use constant WIPELEFT => 10; # "k" use constant WIPERIGHT => 11; # "l" use constant SCROLL => 12; # "m" use constant AUTOMODE => 13; # "o" use constant ROLLIN => 14; # "p" use constant ROLLOUT => 15; # "q" use constant WIPEIN => 16; # "r" use constant WIPEOUT => 17; # "s" use constant COMPROTATE => 18; # "t" use constant TWINKLE => 19; # "n0" use constant SPARKLE => 20; # "n1" use constant SNOW => 21; # "n2" use constant INTERLOCK => 22; # "n3" use constant SWITCH => 23; # "n4" use constant SLIDE => 24; # "n5" use constant SPRAY => 25; # "n6" use constant STARBURST => 26; # "n7" use constant NUM_MODES => 26; my $bShowRandom = 0; my $ob; my $ob2; my @msgs; my %modestring = ( ROTATE , "a", HOLD , "b", FLASH , "c", ROLLUP , "e", ROLLDOWN , "f", ROLLLEFT , "g", ROLLRIGHT , "h", WIPEUP , "i", WIPEDOWN , "j", WIPELEFT , "k", WIPERIGHT , "l", SCROLL , "m", AUTOMODE , "o", ROLLIN , "p", ROLLOUT , "q", WIPEIN , "r", WIPEOUT , "s", COMPROTATE , "t", TWINKLE , "n0", SPARKLE , "n1", SNOW , "n2", INTERLOCK , "n3", SWITCH , "n4", SLIDE , "n5", SPRAY , "n6", STARBURST , "n7" ); sub ::winMain_Activate { # send twenty nulls so sign can detect baud rate my $nulls = pack("a20"); $ob->write($nulls); ClearDisplay(); my $counter = 1; my ($mode, $msgnum, $oldmsgnum, $msg); while (1) { Win32::GUI::DoEvents(); if ($bShowRandom) { $mode = int(rand NUM_MODES) + 1; $oldmsgnum = $msgnum; $msgnum = int(rand @msgs) until $msgnum != $oldmsgnum; $msg = $msgs[$msgnum]->(); SendMessage($msg, $mode); } my_sleep(6); } undef $ob; undef $ob2; return(1); } sub ::winMain_Terminate { return(-1); } sub ::chbShowRandom_Click { #The Name property of the loaded window is "winMain" defined(my $win = $Win32::GUI::Loft::window{winMain}) or return(1); $bShowRandom = $win->chbShowRandom->Checked(); ClearDisplay() if $bShowRandom == 0; return(1); } sub my_sleep { my ($delay) = @_; my ($date, $time, $name, $nmbr); $ob2->read_interval(100); $ob2->read_const_time($delay * 1000); my ($count, $result) = $ob2->read(1000); # print "waited $delay seconds, count = $count, result = *$result*\n +" if $count != 0; ($date, $time, $name, $nmbr) = ($result =~ /DATE = (.*)\nTIME = (. +*)\nNAME = (.*)\nNMBR = (.*)\n/); if ($name || $nmbr) { # print "name initialized to *$name*\n"; # print "length of name is ", length($name), "\n"; # print "nmbr initialized to *$nmbr*\n"; # print "length of nmbr is ", length($name), "\n"; $name = "Unknown Caller" if ($name =~ /^\s*O\s*$/); $nmbr = "Unknown Number" if ($nmbr =~ /^\s*O\s*$/); $nmbr =~ s/(\d\d\d)(\d\d\d)(\d\d\d\d)/($1)-$2-$3/; $nmbr =~ s/(\d\d\d)(\d\d\d\d)/$1-$2/; # print "name is $name\n"; # print "nmbr is $nmbr\n"; # print "date is $date\n"; # print "time is $time\n"; for (my $i = 1; $i <= 3; $i++) { # print "sending name...$name...\n"; SendMessage($name, HOLD); sleep(3); # print "sending number...$nmbr...\n"; SendMessage($nmbr, HOLD); sleep(3); } ClearDisplay(); } } sub SendMessage { my ($string, $mode) = @_; my $len = length($string); my $modestr = $modestring{$mode}; my $modelen = length($modestr); my $msg = pack("ca3ca2caa${modelen}a${len}c", 1, "Z00", 2, "AA", 27, + " ", $modestr, $string, 4); $ob->write($msg); } sub ClearDisplay { SendMessage(" ", HOLD); } print "reading messages...\n"; open(MSGS, "messages") || die("can't open messages: $!"); while (my $msg = <MSGS>) { chomp $msg; push @msgs, ($msg =~ /^sub \{/) ? eval $msg : sub { $msg; }; } print "Initializing sign port...\n"; $ob = Win32::SerialPort->new ('COM2') || die; $ob->user_msg(1); # misc. warnings $ob->error_msg(1); # hardware and data errors $ob->baudrate(9600); $ob->parity("even"); $ob->parity_enable(1); # for any parity except "none" $ob->databits(7); $ob->stopbits(1); $ob->handshake('none'); $ob->write_settings; my ($count, $result); print "Initializing modem port...\n"; $ob2 = Win32::SerialPort->new ('COM1') || die; $ob2->user_msg(1); # misc. warnings $ob2->error_msg(1); # hardware and data errors $ob2->baudrate(9600) || die "fail setting baud"; $ob2->parity('none') || die "fail setting parity"; $ob2->databits(8) || die "fail setting databits"; $ob2->stopbits(1) || die "fail setting stopbits"; $ob2->handshake('none') || die "fail setting handshake"; $ob2->write_settings || die "no settings"; print "Setting up caller ID...\n"; $ob2->write("at#cid=1\r"); $ob2->read_interval(100); $ob2->read_const_time(1000); ($count, $result) = $ob2->read(20); # print "count = $count, result = $result\n"; print "Finished setting up caller ID...\n"; my $fileWindow = "SignGUI.gld"; my $objDesign = Win32::GUI::Loft::Design->newLoad($fileWindow) or die("Could not open window file ($fileWindow)"); my $win = $objDesign->buildWindow() or die("Could not build window ($f +ileWindow)"); $win->{-dialogui} = 1; $win->Show(); Win32::GUI::Dialog();

Edited: ~Thu Jul 11 20:13:14 2002 (GMT), by footpad:
Added <readmore> tag

Replies are listed 'Best First'.
(jcwren) Re: Caller ID Display / LED Sign Driver
by jcwren (Prior) on Jul 02, 2002 at 20:28 UTC

    I have one of these signs in my warehouse. I used it to display a 'message of the day' on it, when I worked at Hayes.

    My friend did a similiar VB app, and had 6 of these signs throughout his apartment that displayed Caller ID, temperature, time, systems status, and anything else he could think of.

    Perhaps I'll dig mine out and put it to use now.

    --Chris

    e-mail jcwren

      Hey how are you doin..I was looking for any available information on caller-id`s..but can`t find any except yours, I was wondering if you know anything about this. I wanna make a program and I want a cgi to execute when someone calls with their phone number passed as an argument. :-p.I would appreciate any help. You can email me jazzy_gill@yahoo.com Thanx.