#!/usr/bin/perl # currently requests hdhomerun firmware 20130328 # (output format changed a bit in later firmwares) #tun: ch=auto:7 lock=8vsb:177000000 ss=79 snq=90 seq=100 dbg=-520/1509 #dev: bps=19395584 resync=0 overflow=0 #ts: bps=19395584 ut=99 te=0 miss=0 crc=0 #flt: bps=22560 #net: pps=0 err=0 stop=0 # current firmware tunerX/debug # from hdhomerun4_atsc 20170930 #tun: ch=auto:7 lock=8vsb:175500000 ss=78 snq=98 seq=100 dbg=-5200/10025 #dev: bps=19595616 resync=0 overflow=0 #ts: bps=19595616 te=0 crc=0 #net: pps=0 err=0 stop=0 my $HDHR = '103577B7'; my $HDCFG = '/usr/bin/hdhomerun_config'; my $TUNERS = 2; my $WAIT_FOR_LOCK = 5; my $WAIT_BETWEEN_POINTS = 1; my $NUM_DATAPOINTS = 30; my $FILE_PATH = "/home/toast/public_html/atscdata"; my @CHANNELS = (7, 35, 44, 48, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 47, 49, 50, 51); use strict; use warnings; use JSON; use Data::Dumper; use Date::Manip::Date; use File::Path qw/make_path/; use POSIX qw/strftime/; my $month_path = strftime("/%Y/%m/", localtime($^T)); my $day = strftime("%d", localtime($^T)); my $time_path = strftime("%d/", localtime($^T)); my $time = strftime("%H%M", localtime($^T)); # check if mythtv has anything scheduled if (system("mythtv_recording_soon 3600") >> 8 != 1) { exit; } my @channels = (); my $tuner = -1; for (my $i = 0; $i < $TUNERS; ++$i) { my $kid = fork(); if (!defined($kid)) { die "couldn't fork: $!"; } elsif ($kid == 0) { $tuner = $i; for (my $j = $i; $j < @CHANNELS; $j += $TUNERS) { push @channels, $CHANNELS[$j]; } last; } } foreach my $channel (@channels) { my $start = time(); my $initial = `$HDCFG $HDHR get /tuner$tuner/channel`; chomp($initial); die "tuner alread tuned to $initial" unless $initial eq 'none'; my $save_path = "$FILE_PATH/$channel$month_path"; make_path($save_path); system("$HDCFG $HDHR set /tuner$tuner/channel $channel") == 0 or die "couldn't tune channel $channel: $!"; sleep($WAIT_FOR_LOCK); # allow time to lock my $saver; if ($channel == -1) { make_path("$save_path$time_path"); system("$HDCFG $HDHR set /tuner$tuner/filter '0x0000-0x1FFF'") == 0 or die "couldn't set filter: $!"; $saver = spawn("$HDCFG $HDHR save $tuner $save_path$time_path$time.ts"); } my $streaminfo = `$HDCFG $HDHR get /tuner$tuner/streaminfo`; my @data; for (my $i = 0; $i < $NUM_DATAPOINTS; ++$i) { if ($i) { sleep($WAIT_BETWEEN_POINTS); } my $point = `$HDCFG $HDHR get /tuner$tuner/debug`; push @data, $point; } my $streaminfo2 = `$HDCFG $HDHR get /tuner$tuner/streaminfo`; if ($saver) { kill 'HUP', $saver or die "couldn't kill saver"; waitpid $saver, 0; } system("$HDCFG $HDHR set /tuner$tuner/channel none") == 0 or die "couldn't detune channel $channel: $!"; my $end = time(); my %out = ('streaminfo' => $streaminfo, 'start' => $start, 'end' => $end ); if ($streaminfo2 ne $streaminfo) { $out{'streaminfo2'} = $streaminfo2; } foreach (@data) { my ($ss, $snq, $seq, $bps, $ut, $te, $miss, $crc) = /ss=(\d+) snq=(\d+) seq=(\d+) .* bps=(\d+) ut=(\d+) te=(\d+) miss=(\d+) crc=(\d+)/s; push @{$out{'data'}{'strength'}}, $ss + 0; push @{$out{'data'}{'signal_to_noise'}}, $snq + 0; push @{$out{'data'}{'symbol_quality'}}, $seq + 0; push @{$out{'data'}{'bps'}}, $bps + 0; push @{$out{'data'}{'utilitization'}}, $ut + 0; push @{$out{'data'}{'transport_errors'}}, $te + 0; push @{$out{'data'}{'missed_packets'}}, $miss + 0; push @{$out{'data'}{'crc_errors'}}, $crc + 0; } my $json = encode_json (\%out); open (OUT, ">>$FILE_PATH/rf_$channel.json"); print OUT "$json\n"; close (OUT); open (OUT, ">>$save_path/$day.json"); print OUT "$json\n"; close (OUT); } while (wait() != -1) { } sub spawn { my $kid = fork(); if (!defined($kid)) { die "couldn't fork: $!"; } elsif ($kid == 0) { open (STDOUT, '>', '/dev/null') or die "Can't redirect STDOUT: $!"; open (STDERR, '>', '/dev/null') or die "Can't redirect STDERR: $!"; exec(@_); } else { return $kid; } }