2 # * * * * * nice -n20 /root/bin/heat -s
13 my $F=do { local $/; <F>; };
14 defined $F or die "read $fname: $!";
15 close F or die "read-close $fname: $!";
19 my($fname,$content)=@_;
21 open F,">$fname" or die "$fname: $!";
22 print F $content or die "write $fname: $!";
23 close F or die "write-close $fname: $!";
28 system $cmd or return 1;
32 my($trash,$min,$hour)=localtime;
33 my $minutes=$hour*60+$min;
34 if (($ARGV[0]||"")=~/^[@]0?(\d+):0?(\d+)$/) {
38 my $schedulefile="/root/heat.schedule";
39 my $statefile="/root/heat.state";
40 my $resetfile="/root/heat.reset";
41 my $usbrelay="/root/bin/usbrelay";
42 my $schedule=readfile $schedulefile;
45 while ($schedule=~s/^(0?(\d+):0?(\d+)) ([01s])\n//) {
47 warn "$schedulefile set twice for: $1" if defined $schedule{$tm};
48 $schedule{$tm-24*60}="$1 $4\n";
49 $schedule{$tm }="$1 $4\n";
50 $schedule{$tm+24*60}="$1 $4\n";
52 warn "$schedulefile garbage: $schedule" if $schedule ne "";
55 my($bestprev,$prev,$bestnext,$next);
56 for my $found (keys(%schedule)) {
58 next if defined $bestprev&&$bestprev>$found;
60 $prev=$schedule{$found};
62 next if defined $bestnext&&$bestnext<$found;
64 $next=$schedule{$found};
67 die "No bestprev" if !defined $bestprev;
68 die "No bestnext" if !defined $bestnext;
71 $finishline=schedulenext $minutes;
72 my $silent=shift if ($ARGV[0]||"") eq "-s";
78 info join("",@$finishline) if defined $finishline;
81 my $reset=readfile $resetfile if -e $resetfile;
82 my($resetminutes,$resetstate);
84 $reset=~/^0?(\d+):0?(\d+) ([01s]|reset)\n$/ or warn "Invalid $resetfile: $reset";
85 $resetminutes=$1*60+$2;
86 $resetstate=($3 eq "reset"?undef:$3);
90 if ($resetminutes==$minutes) {
91 unlink $resetfile or die "$resetfile: $!";
92 $reset=$resetminutes=undef;
95 sub finishlinereset() {
96 $finishline=schedulenext $resetminutes;
97 splice @$finishline,1,0,$reset;
99 finishlinereset if defined $reset;
100 my $state=readfile $statefile;
104 $newstate=$resetstate if !defined $newstate&&defined $resetstate&&!defined $resetminutes;
105 sub printminutes($) {
107 return sprintf "%02d:%02d",int($m/60),$m%60;
110 if (!defined $newstate&&!defined $reset) {
111 my $prev=schedulenext($minutes)->[0];
112 $newstate=$prev if $prev=~s{^@[ printminutes $minutes ] (.)\n$}{$1} or $prev=undef;
114 $newstate=$state if !defined $newstate;
116 if (!defined $newstate) {
120 die "state!={s|0|1}" if $newstate!~/^[s01]$/;
123 my $both={"s"=>[0,0],"0"=>[1,0],"1"=>[1,1]}->{$newstate};
124 $state eq $newstate or unlink $statefile or warn "$statefile: $!";
125 ( spawn "$usbrelay 1 ".$both->[0]
126 and spawn "$usbrelay 2 ".$both->[1])
127 or do { unlink $statefile; die "usbrelay error"; };
128 $state eq $newstate or writefile $statefile,"$newstate\n";
132 die "Excessive args: ".join(" ",@ARGV) if @ARGV;
133 if (!defined $newreset) {
135 if (!$silent&&defined $reset) {
136 unlink $resetfile or die "$resetfile: $!";
137 $finishline=schedulenext $minutes;
142 if ($reset=~/^\d+$/) {
143 $resetminutes=$reset+$minutes;
144 $reset=printminutes($resetminutes)." reset\n";
147 $reset.=" $newstate\n";
151 writefile $resetfile,$reset;