#!/usr/bin/perl # #sift.pl - web interface for topfield/sift / T. Rintala 2006 # #flush output buffer $|++; use CGI qw(:standard); use Device::SerialPort; chdir("/data/www/cgi-bin/siftdata"); $SER_PORT="/dev/ttyUSB0"; #which is connected to topfield $ENV{PATH}=""; $VERS="WebSift 0.40"; $OUTPUTF="siftcom.txt"; @weekdays = ('Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'); #channel list which we are interested in @channel_list = ('1', '2', '3', '4', '5', '6', '7', '8', '9'); $p_epg = url_param('epg'); $p_cmd = url_param('cmd'); $f_pw = param('password'); #start html page print header; print start_html(-title=>$VERS); print "
";

access_module(0); #newer return if problem with access/password

#logout
if ($p_cmd eq 'logout') { access_module(1); }

#menu
printf "[List Timers] ";
printf "[Add Timer] ";
printf "[Remove Timer] ";
printf "[Info] ";
printf "[Read Epg] ";
printf "    [Logout]\n";

foreach $cl (@channel_list) {
  printf "[$cl] ";
}

$sf=0;
($sec,$min,$hou,$mda,$mon,$yea,$wday,$yda,$isd) = localtime();
$today=sprintf("%04d%02d%02d", 1900+$yea, $mon+1, $mda);
printf("\nTime %d.%d.%d %d:%02d", 1900+$yea, $mon+1, $mda, $hou, $min);

print hr;

#execute timer add command
if ($p_cmd eq 'addexe' && param('formbutton') eq 'Add') {
  my $a='a:';

  $a = $a . param('tuner') . '|' . param('channel') . '|';
  $a = $a . param('freq') . '|' . param('length') . '|';
  $a = $a . param('year') . '|' . param('month') . '|';
  $a = $a . param('day') . '|' . param('hour') . '|';
  $a = $a . param('min') . '|' . param('name');

  print "string to send:$a\n";
  exe_siftcom("$a", $OUTPUTF);
  @xlist = read_siftcom($OUTPUTF);
  print "Result:\n";
  foreach $i (@xlist) { print $i };
}

#add new timer form
if ($p_cmd eq 'addform') {
  print "Add timer:\n";
  print start_form(-action=>"sift.pl?cmd=addexe");
  print "Tuner: ";
  print radio_group(-name=>'tuner',
		    -values=>['1','2'],
		    -default=>'2',
		    -labels=>{1=>'Tuner 1',2=>'Tuner 2'});
  print "\nFrequency: ";
  print popup_menu(-name=>'freq',
		   -values=>['1','2','3','4','5','6'],
		   -default=>'1',
		   -labels=>{1=>'OneTime',2=>'EveryDay',3=>'WeekEnds',
			     4=>'Weekly',5=>'EveryWeekday',6=>'NoType'});
  print "\nChannel: ";
  print textfield(-name=>'channel',
		  -default=>'' . url_param('ch'),
		  -size=>3,
		  -columns=>3);
  ($fyy, $fmm, $fdd, $fhh, $fmi) = split_date_data(url_param('time'));
  print "\nDate&Time y m d h:m ";
  print textfield(-name=>'year',
		  -default=>$fyy,
		  -size=>4,
		  -columns=>4);
  print textfield(-name=>'month',
		  -default=>$fmm,
		  -size=>2,
		  -columns=>2);
  print textfield(-name=>'day',
		  -default=>$fdd,
		  -size=>2,
		  -columns=>2);
  print " ";
  print textfield(-name=>'hour',
		  -default=>$fhh,
		  -size=>2,
		  -columns=>2);
  print ":";
  print textfield(-name=>'min',
		  -default=>$fmi,
		  -size=>2,
		  -columns=>2);
  print "\nLength: ";
  print textfield(-name=>'length',
		  -default=>'' . url_param('len'),
		  -size=>3,
		  -columns=>3);
  print " min.\nName: ";
  print textfield(-name=>'name',
		  -default=> '' . url_param('name'),
		  -size=>50,
		  -columns=>50);
  print "\n\n";
  print submit(-name=>'formbutton', -label=>'Add');
  print submit(-name=>'formbutton', -label=>'Cancel');
  print end_form;
}

#list timers or make delete options
if ($p_cmd eq 'listtimers' || $p_cmd eq 'listremove') {
  if ($p_cmd eq 'listremove') {
    print "Select timer to remove:\n";
  }
  exe_siftcom("l", $OUTPUTF);
  @xlist = read_siftcom($OUTPUTF);
  foreach $i (@xlist) {
    if ($i =~ m/^-----/) {
      print hr;
    }
    elsif ($p_cmd eq 'listremove' && $i =~ m/^RecordNumber/) {
      ($text, $number) = split(/=/, $i);
      print "[Delete $number]\n";
    }
    else {
      print "$i\n";
    }
  }
}

#execute timer delete command
if ($p_cmd eq 'del') {
  $p_rec = url_param('rec');
  exe_siftcom("d$p_rec", $OUTPUTF);
  @xlist = read_siftcom($OUTPUTF);
  print "Result:\n";
  foreach $i (@xlist) { print $i };
}

#execute info command
if ($p_cmd eq 'info') {
  print "Result (wait 10 sec):\n";
  exe_siftcom("i", $OUTPUTF);
  @xlist = read_siftcom($OUTPUTF);
  foreach $i (@xlist) { print "$i\n" };
}

#refresh epg data from topfield
if ($p_cmd eq 'readepg') {
  foreach $ch (@channel_list) {
    print "Reading channel $ch epg data.\n";
    exe_siftcom("e$ch", "$ch.epg");
  }
  print "Done.\n";
}

#generate epgdata page
if ($p_epg ne '') {
  @siftlist = read_siftcom("$p_epg.epg");
  $old_dayp='';
  foreach $i (@siftlist) {
    if ($i =~ /^EPGLIST/) {
      print "$i\n";
    }
    else {
      ($edate, $elen, $ename, $edes) = split(/\|/, $i);
      $dayp = substr($edate, 0, 8);
      if ($dayp >= $today) {
	($yy, $mm, $dd, $hh, $mi) = split_date_data($edate);
	$wdt = @weekdays[get_weekday($yy, $mm, $dd)];
	if ($old_dayp ne $dayp) {
	  printf "%s.%s.%s %s\n", $yy, $mm, $dd, $wdt;
	  $old_dayp = $dayp;
	}
	#make hyperlink to fill timer form
	$tref="$hh.$mi";
	printf("%s %s [%s]\n", $tref, $ename, $edes);
	#printf("%s.%s %s [%s]\n", $hh, $mi, $ename, $edes);
      }
    }
  }
}

print "
"; print end_html; # # subroutines # #will calculate the day number of the week. 0 = saturday sub get_weekday { my ($yyyy, $mm, $dd) = @_; my $cc = substr($yyyy, 0, 2); my $yy = substr($yyyy, 2, 2); my $mod_dd = $dd % 7; if ($mm == 1 or $mm ==2) { if ((($yy % 4) == 0 && ($yy % 100) != 0) or ($yy % 400) == 0) { $mm += 12; } } ##### CALCULATING TABLE 1: my $h_month = 0; $h_month = 0 if $mm == 8 or ($mm == 14); $h_month = 1 if $mm == 2 or ($mm == 3) or ($mm == 11); $h_month = 2 if $mm == 6; $h_month = 3 if $mm == 9 or ($mm == 12); $h_month = 4 if $mm == 4 or ($mm == 7) or ($mm == 13); $h_month = 5 if $mm == 1 or ($mm == 10); $h_month = 6 if $mm == 5; $mm -= 12 if $mm > 12; my $table1 = $mod_dd + $h_month; ##### CALCULATING TABLE 2: my $year2 = ($yy * 1.25) % 7; my $ccTmp = (($cc - 1) % 4) +1; my $century2 = 0; if ($ccTmp == 4) { $century2 = 2 } else { $century2 = 9 - 2 * $ccTmp } my $table2 = $century2 + $year2; my $wd = ($table1 + $table2) % 7; return ($wd); } #splitt string yyyymmddhhmi -> 5 different variables sub split_date_data { my ($ldate) = @_; my $yy, $mm, $dd, $hh, $mi; if (length($ldate) != 12) {return('','','','','')}; $yy = substr($ldate, 0, 4); $mm = substr($ldate, 4, 2); $dd = substr($ldate, 6, 2); $hh = substr($ldate, 8, 2); $mi = substr($ldate, 10, 2); return($yy, $mm, $dd, $hh, $mi); } #read sift output file and parse irrelevant data. return list of data. #parameter: output_file sub read_siftcom { my ($outpf) = @_; my @slist = (); my @tlist = (); my $sf = 0; if (!open(DFH,"<$outpf")) { print "Error code: 1",br; } @tlist = ; close(DFH); chomp @tlist; foreach $i (@tlist) { $i =~ s/[\r\n]//g; $i =~ s/\ce//g; if ($i eq '') { next }; if ($i =~ m/^START/) {$sf = 1; next}; if ($i =~ m/^READY/) {$sf = 0}; if ($sf == 1) { push @slist, $i; } } return (@slist); } #execute command trough serialport to topfield #suppose sift daemon is running on topfield #two params: "command", "output_file" sub exe_siftcom { my ($execmd, $outputf) = @_; my $sp; $sp = tie(*SPF, 'Device::SerialPort', $SER_PORT) || die "Can't open port $SER_PORT!"; $sp->baudrate(115200) || die "fail setting baudrate"; $sp->parity("none") || die "fail setting parity"; $sp->databits(8) || die "fail setting databits"; $sp->stopbits(1) || die "fail setting stopbits"; $sp->handshake("none") || die "fail setting handshake"; $sp->read_char_time(0); $sp->read_const_time(500); #if no data after 0.5 second, we are ready if ($execmd eq 'i') { #info command, harddisk may be sleep, wait to spinup $sp->read_const_time(5000); } if (!open(DFH,">$outputf")) { print "Error: file create";} $sp->write("*\r*\r$execmd\r"); do { ($count,$sdata) = $sp->read(1024); syswrite(DFH, $sdata, $count); } while ($count != 0); $sp->read_const_time(500); $sp->write("#\r"); do { ($count,$sdata) = $sp->read(1024); syswrite(DFH, $sdata, $count); } while ($count != 0); close(DFH); undef $sp; } #access module #param: 0 = check access, 1 = clean login database sub access_module() { my ($act) = @_; #logout if ($act == 1) { if (!open(DFH,">session.dat")) { print "Error code: 4",br; } print DFH "NO-SIFT-SESSION\n"; close(DFH); print "Logged out.\n"; print "[Login]\n"; print ""; print end_html; exit 0; } #access key is simple the remote ip address $seskey=$ENV{REMOTE_ADDR}; #mayby already login if (!open(DFH,"; close(DFH); chomp @seslist; foreach $x (@seslist) { if ($x eq $seskey) {return}; } #password given, check out is it valid if ($f_pw ne '') { if (!open(DFH,"; close(DFH); chomp @pwlist; foreach $x (@pwlist) { if ($x eq $f_pw) { if (!open(DFH,">session.dat")) { print "Error code: 3",br; } print DFH $seskey,"\n"; close(DFH); return; } } print "Password not valid.\n"; print "[Login]\n"; print ""; print end_html; exit 0; } #ask password print start_form(-action=>"sift.pl"); print "Login: "; print password_field(-name=>"password", -size=>10, -maxlength=>10); print "\n"; print br, submit(-name=>'pwformbutton', -label=>'OK'); print end_form; print ""; print end_html; exit 0; }