[mythtv-users] MyBlaster/Dish Network

Steve Adeff adeffs at gmail.com
Thu Nov 17 10:28:33 EST 2005


On Wednesday 16 November 2005 17:32, Robert Denier wrote:
> I'm going to use the format [----FILENAME----] and then paste the file. 
> The only change to the perl script was just an edit to make it find the
> file easier.  Perhaps it wasn't even needed.  I have everything in
> /usr/local/bin. To use these you will need to copy paste these into files
> and make the scripts executable.  Myth calls the change_channel scripts.
>
> [Don't forget the alternate keys are for receiver remote code 2.  This is
> settable on the receiver, or at least the ones I have.]
>
> -Robert Denier
>
> [---/usr/local/bin/change_channel.sh---]
> #!/bin/bash
> perl /usr/local/bin/MyBlaster.pl $1
>
> [---/usr/local/bin/change_channel2.sh---]
> #!/bin/bash
> cd /usr/local/bin
> perl /usr/local/bin/MyBlaster.pl changechannel d2.keys $1
>
> [---/usr/local/bin/d2.keys---]
> power = 00001B008B0300C70C1700C7058900BE0354010091111121211111111100
> select = 00001B008C0300C90C1500C9058700C00352010091121111211111111100
> exit = 00001B008C0300C90C1400C9058600C00357010091121121211111111100
> 0 = 00001B008C0300C90C1400C9058700C00354010091121112211111111100
> 1 = 00001B008C0300C90C1500C9058700C00354010091111211211111111100
> 2 = 00001B008C0300C90C1400C9058700C00354010091111212211111111100
> 3 = 00001B008C0300C90C1400C9058700C00356010091111221211111111100
> 4 = 00001B008C0300C90C1500C9058700C9034A010091112111211111111100
> 5 = 00001B008C0300C90C1400C9058600C9034E010091112112211111111100
> 6 = 00001B008C0300C90C1400C9058600C90351010091112121211111111100
> 7 = 00001B008C0300C90C1400C9058700C9034D021091112211211111111100
> 8 = 00001B008C0300C90C1400C9058700C9034C010091112212211111111100
> 9 = 00001B008C0300C90C1400C9058700C9034C010091112221211111111100
>
> [---/usr/local/bin/MyBlaster.pl---]
> #!/usr/bin/perl
>
> # MyBlaster.pl:  Controller for the MyBlaster serial IR blaster
> (www.mytvstore.com)
> # By William Munson [wmunson] (July 26, 2004, ver-1.4)
> #
> # This code is being released into the public domain for non-profit use.
> # For commercial use please contact me at our support forum:
> # http://www.mythtvtalk.com/forum/viewtopic.php?p=622#622
> #
> # Version 1.0 - Initial release of code.
> # Version 1.1 - Added macro feature.
> # Version 1.2 - Fixed some timing issues in the data transfer to MyBlaster.
> # Version 1.3 - Fixed output for devices other than DSS/Satellite
> receivers. #             - Added support for port locking which keeps a
> second instance #                   suspended until the 1st has completed.
> # Version 1.4 - Public Release #1 - Updated documentation for release.
> # Version 1.4.1 - Added Learing and emitting learned keys - Vlado
>
>
> $|=1;
> use POSIX qw(:termios_h);
> use FileHandle;
> use Time::HiRes qw( sleep );
>
>
> # Defaults to standard COM2 port, 19200 baud.
> my $serial=init_serial("/dev/ttyS0","19200"); # Com 1
> # my $serial=init_serial("/dev/ttyS1","19200"); # Com 2
>
> # Device code for the piece of equipment you want to control. This info can
> # be found in the MyBlaster Library folder.
> #
> # 775 controls a standard Dishnet receiver.
> $remote_code="775";
>
> # Device Type is a hex value from 0 to A and represents the type of device
> you # want to control. Below is a list of the available device type codes.
> # 0=TV, 1=CABLE, 2=Video Acc, 3=DSS/Satellite, 4-VCR, 5=Laser Disk, 6=DVD #
> 7=Tuner/Amp, 8=Amplifier, 9=CD, A=Home Control
> $Device_Type="3";
>
> # Duplicate process protection. Enable this if you use the same blaster to
> control
> # multiple devices. With this enabled, multiple instances of the program
> will each
> # sleep until the blaster port is free. Uses a lock file.
> $Use_Locking=0;
>
> # Lock File name.
> $LockFile="/tmp/MyBlaster.lock";
>
> # remote file prefix. The file name will be $prefix_<remote>.keys
> $remote_prefix = "/home/mythtv/MyBlaster_";
>
> # Use verbose output mode for debugging.
> $verbose=0;
>
> # Time delay between each channel digit.
> $inter_key_delay=0.1;
>
> # Emit time. This is the length of time the command is sent. Probably a
> # good idea to leave this alone but if you are getting repeats of buttons
> # then you can shorten it a little bit.
> $Emit_Time=0.333;
>
> # Learn Time. This is the length of time we let MyBlaster to try to learn a
> command.
> $Learn_Time=3.0;
>
> # Enable to press a key to finalize channel entry
> $finalize=1;
>
> # Key used to finalize channel entry
> $finalize_key="select";
>
> # Enable to clear the on screen display more quickly.
> $quick_clear=1;
>
> # Key used to clear the display. Taken from keymap below.
> $quick_clear_key="exit";
>
> # Time to wait until clearing the display
> $clear_delay=2.0;
>
> # Misc variables needed by the program
> $Count=0;
>
> # These keys should be common to all device codes. The remote buttons
> # may have different names. Feel free to change the name but not the value.
> %keymap=(1 => "0x01",
>                  2 => "0x02",
>                  3 => "0x03",
>                  4 => "0x04",
>                  5 => "0x05",
>                  6 => "0x06",
>                  7 => "0x07",
>                  8 => "0x08",
>                  9 => "0x09",
>                  0 => "0x0a",
>     vol_up => "0x0b",
>     vol_dn => "0x0c",
>       mute => "0x0d",
>      ch_up => "0x0e",
>      ch_dn => "0x0f",
>      power => "0x10",
>      enter => "0x11",
>     ch_100 => "0x11",
>  last_chan => "0x12",
>     tv_sat => "0x13",
>      input => "0x13",
>       play => "0x14",
>       stop => "0x15",
>    page_up => "0x16",
>       ffwd => "0x16",
>        rew => "0x17",
>    page_dn => "0x17",
>      pause => "0x18",
>     record => "0x19",
>       menu => "0x1a",
>         up => "0x1b",
>       down => "0x1c",
>       left => "0x1d",
>      right => "0x1e",
>     select => "0x1f",
>       exit => "0x20",
>    display => "0x21",
>      guide => "0x22");
>
> #config file vars
> my %rem_keys;
> my @rem_lines;
>
>
>
> # Start of main code.
> #
> # Pull the command line info into the program
> $input_cmd=$ARGV[0];
>
> if ($Use_Locking) {
>         if (-e $LockFile) { #found a lock file so sleep
>                 sleep(5.0);
>         }
>         open(OUTFILE, ">$LockFile") || die "cannot open file"; # create our
> lock file
> }
>
> # These bits define which remote control protocol to use and the device
> type. #
> # Convert remote code to MyBlaster format
> $hex_remote_code = sprintf("%X", $remote_code);
>
> if ($remote_code > 255) {
>         $hi_bit="0x" . $Device_Type . substr($hex_remote_code, 0, 1);
>         $lo_bit="0x" . substr($hex_remote_code, 1, 2);
> } else {
>         $hi_bit="0x" . $Device_Type . "0";
>         if ($remote_code > 15) {
>                 $lo_bit="0x" . substr($hex_remote_code, 0, 2);
>         } else {
>                 $lo_bit="0x0" . substr($hex_remote_code, 0, 1);
>         }
> }
> print "hi bit = " if ($verbose);
> print $hi_bit if ($verbose);
> print "\n" if ($verbose);
> print "lo bit = " if ($verbose);
> print $lo_bit if ($verbose);
> print "\n" if ($verbose);
>
>
> # Start of command decoding
>
> if (length($input_cmd)) {
>         # Check to see if a channel number was entered.
>         if ($input_cmd != 0) {
>                 change_channel($input_cmd);
>                 if ($Use_Locking) {
>                         close(OUTFILE);
>                         unlink($LockFile);
>                 }
>                 exit;
>         }
>         if ($input_cmd eq "macro") {
>                 # Do macro command. Use your own key sequence here.
>                 # Change it around as required for your needs.
>                 mb_key("down");
>                 sleep(1.0);
>                 mb_key("up");
>                 sleep(1.0);
>                 mb_key("select");
>                 sleep(1.0);
>                 mb_key("display");
>                 if ($Use_Locking) {
>                         close(OUTFILE);
>                         unlink($LockFile);
>                 }
>                 exit;
>         }
>         # Attempt to learn a command
>         if ($input_cmd eq "learn") {
>                 $remote = $ARGV[1] || die "No remote name";
>                 $keyname = $ARGV[2] || die "No key name to learn";
>                 $keydata = learn_key($keyname);
>
>                 # WILL CREATE DUPLICATES and use the first (old one)
>                 open (FH, ">>" . $remote_prefix . $remote . ".keys");
>                 printf (FH "$keyname = $keydata\n");
>                 close (FH);
>                 print "$keyname = $keydata\n";
>                 exit;
>         }
>         # Emit learned key (raw or by name)
>         if ($input_cmd eq "send") {
>                 $key_data = $ARGV[1] || die "No key data\n";
>                 if (length($key_data) > 29) {                   #this
> should be a raw data - just send it
>                         emit_learned_key ($key_data);
>                         $stat = get_mb_status();
>                 }
>                 else {
>                         $remote = $key_data;                           
> #this is a remote, and we should have a key name
>                         $key_name = $ARGV[2] || die "No Key name\n";
>                         $key_data = lookup_key ($remote, $key_name);
>                         emit_learned_key($key_data);
>                 }
>                 exit;
>         }
>         if ($input_cmd eq "changechannel") {
>                 $remote = $ARGV[1] || die "No remote specified\n";
>                 $chan = $ARGV[2] || die "No channel number\n";
>                 change_channel_learned ($remote, $chan);
>                 exit;
>         }
>         # No special processing required. Send a single command.
>         mb_key($input_cmd);
>         if ($Use_Locking) {
>                 close(OUTFILE);
>                 unlink($LockFile);
>         }
> }
>
> # begin subroutines.
>
> sub emit_learned_key {
>         $key_data = shift;
>         my @bytes;
>         $len = length ($key_data);
>         die "Invalid key data" if ($len % 2 != 0);    #@@@ TODO: check for
> non hex symbols with a regexp
>         $t_len = sprintf("0x%2.2X", 4 + $len / 2);
>
>         @bytes = ("0xBC","0xAC","0x0D","0x00",$t_len,"0x0B","0x00","0x00",
> "0x10");
>         $i=0;
>                 while ($i < length($key_data) ) {
>                 push (@bytes,"0x" . substr($key_data,$i,2));
>                 $i++; $i++;
>         }
>         print "Will send bytes =@bytes\n" if ($verbose);
>
>
>         simple_command("0x00");         #wake up
>         sleep(0.1);
>         simple_command(@bytes);
>         sleep(0.333);
>         simple_command("0x00");         #wake up
>
>         return;
> }
>
> sub emit_learned_key_byname {
>         $remote = shift;
>         $key_name = shift;
>
>         print "elkn $remote/$key_name\n";
> }
>
> sub learn_key {
>         my $keyname=shift;
>
>         simple_command("0x00");         #wake up
>         sleep(0.1);
>         simple_command("0xBC","0xAC","0x0D","0x00","0x02","0x06","0x01"); 
> # reset
>         sleep(0.3);
>
>         print "*** Press and hold '$keyname' on the remote for 5 seconds...
> \n";        simple_command("0x00");         #wake up
>         sleep(0.1);
>         # send the data packet
>
> simple_command("0xBC","0xAC","0x0D","0x00","0x03","0x0C","0x00","0x00");
> #learn in buf 0 (always use buf 0)
>         sleep($Learn_Time);
>
>         $stat = get_mb_status();
>         die "Learning failed with status code $stat\n" if ($stat != 0);
>         simple_command("0x00");         #wake up
>         sleep(0.1);
>
> simple_command("0xBC","0xAC","0x0D","0x00","0x03","0x0D","0x00","0x00");
> #read buf 0 (always use buf 0)
>         sleep(0.1);
>         $stat = get_mb_status();
>         die "Reading learn code failed with status code $stat\n" if ($stat
> != 0);
>
>
>         $len = get_ser_byte();
>         $stat = get_ser_byte();
>         $len--;  #status was in the length the rest is the key
>         $count = 0;
>         $str = "";
>         while ($count < $len) {
>                 $b = get_ser_byte();
>                 $count++;
>                 $str = sprintf("%s%2.2X", $str, $b);
>         }
>         print "Learned Key $keyname: $str\n" if ($verbose);
>         print "  Length: $count\n" if ($verbose);
>         print "  (Suspicious = less then 30)\n" if ($verbose && $len < 30);
>         return $str;
> }
>
> sub get_mb_status {
>         $ret = get_ser_byte();  # get length
>         return  if ($ret ne 1);
>         return  get_ser_byte();
> }
>
> sub get_ser_byte {
>         my $starttime=time();
>         print "RECVB: " if ($verbose);
>
>         $size = 0;
>         while (!$size) {
>         $size=sysread($serial,$buf,1);
>                 if (time() - $starttime > 5) {
>                         print "time...\n" if ($verbose);
>                         return;
>                 }
>         next;
>         }
>         print ord($buf),"\n" if ($verbose);
>         return ord($buf);
> }
>
> sub change_channel_learned {
>         # Send a command for each digit of the channel number
>         my ($remote) = shift;
>         my ($channel_num)=shift;
>         my ($position)=0;
>         my ($digit)="";
>
>         if ($verbose){
>                 print "Channel number: ";
>                 print $channel_num;
>                 print "\n";
>         }
>         while ($position<length($channel_num)){
>                 $digit=substr($channel_num,$position,1);
>                 if ($verbose){
>                         print "Digit: ";
>                         print $digit;
>                         print "\n";
>                 }
>                 #@@@ look up name
>                 $key_data = lookup_key ($remote, $digit);
>                 emit_learned_key($key_data);
>                 $position++;
>                 sleep($inter_key_delay);
>         }
>         # wait a little bit and press enter to finalize channel entry
>         if ($finalize){
>                 print "Finalize Entry:\n" if ($verbose);
>                 $key_data = lookup_key ($remote, $finalize_key);
>                 emit_learned_key($key_data);
>         }
>
>         #If enabled, clear the display after sleeping one second
>         if ($quick_clear){
>                 sleep($clear_delay);
>                 print "Clear Display:\n" if ($verbose);
>                 $key_data = lookup_key ($remote, $quick_clear_key);
>                 emit_learned_key($key_data);
>         }
> }
>
>
> sub lookup_key {
>         $remote = shift;
>         $key_name = shift;
>         if (!%rem_keys) {
>                 #read it from the file
>                 print "Reading remote config file
> $remote_prefix$remote.keys\n" if ($verbose);
>                 open (FH, $remote);
>                 @rem_lines = <FH>;
>                 foreach $l (@rem_lines) {
>                         chomp($l);
>                         next if ($l =~ /^#/);
>                         next if ($l =~ /^\s*$/);
>                         next if ($l =~ /!=/);
>                         @val = split(/\s*=\s*/, $l);
>                         $rem_keys{@val[0]} = @val[1];
>                 }
>                 close (FH);
>         }
>         $key_data = $rem_keys{$key_name};
>         print "$key_name -> $key_data\n" ;#if ($verbose);
>         return $key_data;
> }
>
>
> sub change_channel {
>         # Send a command for each digit of the channel number
>         my ($channel_num)=@_;
>         my ($position)=0;
>         my ($digit)="";
>
>         if ($verbose){
>                 print "Channel number: ";
>                 print $channel_num;
>                 print "\n";
>         }
>         while ($position<length($channel_num)){
>                 $digit=substr($channel_num,$position,1);
>                 if ($verbose){
>                         print "Digit: ";
>                         print $digit;
>                         print "\n";
>                 }
>                 mb_key($digit);
>                 $position++;
>                 sleep($inter_key_delay);
>         }
>         # wait a little bit and press enter to finalize channel entry
>         if ($finalize){
>                 print "Finalize Entry:\n" if ($verbose);
>                 mb_key($finalize_key);
>         }
>
>         #If enabled, clear the display after sleeping one second
>         if ($quick_clear){
>                 sleep($clear_delay);
>                 print "Clear Display:\n" if ($verbose);
>                 mb_key($quick_clear_key);
>         }
> }
>
>
> sub mb_key {
>         my ($key)=@_;
>         my ($Count)=0;
>         my ($Looping)=1;
>         return undef unless $keymap{$key};
>         simple_command("0x00");
>                 sleep(0.1);
>                 # send the data packet
>                 simple_command("0xBC","0xAC","0x0D","0x00","0x06","0x01",
> $hi_bit,$lo_bit,$keymap{$key},"0x00","0x00");
>                 sleep($Emit_Time);      #Execution delay
>                 simple_command("0x00");
>                 print "\n" if ($verbose);
>                 get_reply();
> }
>
> sub simple_command {
>         if (defined(sendbytes(@_))) {
>                 return(1);
>         } else {
>                 return(undef);
>         }
> }
>
> sub mb_command {
>         sendbytes(@_);
> }
>
>
> sub sendbytes {
>         (@send)=@_;
>         foreach (@send) { s/^0x//g; $_=hex($_); }
>         print "SEND: " if ($verbose);
>         foreach $num (@send) {
>                 $str=pack('C',$num);
>                 printf("0x%X ", $num, $str) if ($verbose);
>                 syswrite($serial,$str,length($str));
>         }
>         print "\n" if ($verbose);
> }
>
> sub get_reply {
>         my $starttime=time();
>         my ($last,$ok, at ret);
>         my ($Expected_Count)=@_;
>         my ($Count)=0;
>         print "RECV: " if ($verbose);
>
>         while (1) {
>                 $ret=sysread($serial,$buf,1);
>                 $str=sprintf("0x%2.2X", ord($buf));
>
>                 # busy wait bad!
>                 die ("\n") if (time() - $starttime > 5);
>                 next if $str eq "0x00";
>                 $Count++;
>                 if ($pkt_decode{$str}) {
>                         print $str if ($verbose);
>                         print "[$pkt_decode{$str}] " if ($verbose);
>                 } else {
>                         $_=$str; s/^0x//g; $_=hex($_);
>                         printf("$str(%3.3s) ",$_) if ($verbose);
>                         push (@ret,$_);
>                 }
>
>                 $ok=1 if ($terminal{$str} > 0);
>                 last if $str eq "0x31";
>                 last if $str eq "0x01";
>                 next;
>         }
>         print "\n\n" if ($verbose);
>
>         return @ret if ($ok);
>         return undef;
> }
>
>
> sub init_serial {
>         my($port,$baud)=@_;
>         my($termios,$cflag,$lflag,$iflag,$oflag);
>         my($voice);
>
>         my $serial=new FileHandle("+>$port") || die "Could not open $port:
> $! \n";
>
>         $termios = POSIX::Termios->new();
>         $termios->getattr($serial->fileno()) || die "getattr: $!\n";
>         $cflag= 0 | CS8 | HUPCL | CREAD | CLOCAL;
>         $lflag= 0;
>         $iflag= 0 | IGNBRK | IGNPAR | IXON | IXOFF | IGNCR;
>         #$iflag= 0 | IGNBRK | IGNPAR | IGNCR;
>         $oflag= 0;
>
>         $termios->setcflag($cflag);
>         $termios->setlflag($lflag);
>         $termios->setiflag($iflag);
>         $termios->setoflag($oflag);
>         $termios->setattr($serial->fileno(),TCSANOW) || die "setattr:
> $!\n"; eval qq[
>                 \$termios->setospeed(POSIX::B$baud) || die "setospeed:
> \$!\n"; \$termios->setispeed(POSIX::B$baud) || die "setispeed: \$!\n"; ];
>
>         die $@ if $@;
>
>         $termios->setattr($serial->fileno(),TCSANOW) || die "setattr:
> $!\n";
>
>         # This gets rid of all the special characters..
>         $termios->getattr($serial->fileno()) || die "getattr: $!\n";
>         for (0..NCCS) {
>                 if ($_ == NCCS) { last; }
>
>                 # Dont mess up XON/XOFF..
> #               if ($_ == VSTART || $_ == VSTOP) { next; }
>
>                 $termios->setcc($_,0);
>         }
>         $termios->setattr($serial->fileno(),TCSANOW) || die "setattr:
> $!\n";
>
>         return $serial;
> }
>

You should add a TRAC for inclusion in the contrib folder.

Steve


More information about the mythtv-users mailing list