Просмотр исходного кода

Move project power to state model

Zachary Kotlarek 13 лет назад
Родитель
Сommit
3f5d38892e

+ 0 - 1
dmx/amplifierPower.pl

@@ -57,7 +57,6 @@ while (1) {
 		$state = 'OFF';
 	}
 
-
 	# Force updates on a periodic basis
 	if (time() - $pushLast > $PUSH_TIMEOUT) {
 		# Not for the amp

+ 4 - 2
projector/launchd/com.uberzach.projector.power.plist → dmx/launchd/com.uberzach.projectorPower.plist

@@ -11,18 +11,20 @@
 	<key>RunAtLoad</key>
 	<true/>
 	<key>Label</key>
-	<string>com.uberzach.projector.power</string>
+	<string>com.uberzach.projectorPower</string>
 	<key>KeepAlive</key>
 	<dict>
 		<key>OtherJobEnabled</key>
 		<dict>
 			<key>com.uberzach.projector</key>
 			<true/>
+			<key>com.uberzach.state</key>
+			<true/>
 		</dict>
 	</dict>
 	<key>ProgramArguments</key>
 	<array>
-		<string>/Users/tv/bin/video/projector/projectorPower.pl</string>
+		<string>/Users/tv/bin/video/dmx/projectorPower.pl</string>
 	</array>
 </dict>
 </plist>

+ 138 - 0
dmx/projectorPower.pl

@@ -0,0 +1,138 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use POSIX qw(ceil floor);
+
+# Local modules
+use Cwd qw(abs_path);
+use File::Basename qw(dirname);
+use lib dirname(abs_path($0));
+use DMX;
+
+# Config
+my $TIMEOUT   = 900;
+my $COUNTDOWN = 300;
+
+# App config
+my $DATA_DIR     = DMX::dataDir();
+my $OUTPUT_FILE  = $DATA_DIR . 'PROJECTOR_POWER';
+my $STATE_SOCK   = $OUTPUT_FILE . '.socket';
+my $PROJ_SOCK    = $DATA_DIR . 'PROJECTOR.socket';
+my $PUSH_TIMEOUT = 20;
+my $PULL_TIMEOUT = $PUSH_TIMEOUT * 3;
+my $DELAY        = $PULL_TIMEOUT / 2;
+
+# Debug
+my $DEBUG = 0;
+if ($ENV{'DEBUG'}) {
+	$DEBUG = 1;
+}
+
+# Sockets
+DMX::stateSocket($STATE_SOCK);
+DMX::stateSubscribe($STATE_SOCK);
+my $proj = DMX::clientSock($PROJ_SOCK);
+
+# State
+my $state     = 'OFF';
+my $stateLast = $state;
+my %exists    = ();
+my $pushLast  = 0;
+my $pullLast  = time();
+my $update    = 0;
+my $lastCount = 0;
+my $lastUser  = time();
+
+# Loop forever
+while (1) {
+
+
+	# State is calculated; use newState to gather data
+	my $newState = $state;
+
+	# Wait for state updates
+	my $cmdState = DMX::readState($DELAY, \%exists, undef());
+	if (defined($cmdState)) {
+		$newState = $cmdState;
+		$pullLast = time();
+	}
+
+	# Record the lastUser time
+	if ($exists{'GUI'} || $exists{'PLAY_STATUS'}) {
+		$lastUser = time();
+	}
+	my $elapsed = time() - $lastUser;
+	if ($DEBUG) {
+		print STDERR 'Time since last user action: ' . $elapsed . "\n";
+	}
+
+	# Calculate the new state
+	$stateLast = $state;
+	if ($exists{'PROJECTOR'}) {
+		if ($elapsed > $TIMEOUT) {
+			$state = 'COUNTDOWN';
+			if ($elapsed > $TIMEOUT + $COUNTDOWN) {
+				$state = 'OFF';
+			}
+		}
+	}
+
+
+	# Force updates on a periodic basis
+	if (time() - $pushLast > $PUSH_TIMEOUT) {
+		# Not for the projector
+		#$update = 1;
+	}
+
+	# Die if we don't see regular updates
+	if (time() - $pullLast > $PULL_TIMEOUT) {
+		die('No update on state socket in past ' . $PULL_TIMEOUT . " seconds. Exiting...\n");
+	}
+
+	# Force updates on any state change
+	if ($stateLast ne $state) {
+		if ($DEBUG) {
+			print STDERR 'State change: ' . $stateLast . ' => ' . $state . "\n";
+		}
+		$update = 1;
+	}
+
+	# Update the projector
+	if ($update) {
+
+		# Extra debugging to record pushes
+		if ($DEBUG) {
+			print STDERR 'State: ' . $state . "\n";
+		}
+
+		# Send master power state
+		if ($state eq 'OFF' || $state eq 'ON') {
+			$proj->send($state)
+			  or die('Unable to write command to proj socket: ' . $state . ": ${!}\n");
+		}
+
+		# No output file
+
+		# Update the push time
+		$pushLast = time();
+
+		# Clear the update flag
+		$update = 0;
+	}
+
+
+	# Announce a pending shutdown every minute
+	if ($state eq 'COUNTDOWN') {
+		my $timeLeft = ($TIMEOUT + $COUNTDOWN) - $elapsed;
+		$timeLeft = ceil($timeLeft / 60);
+
+		if ($lastCount != $timeLeft) {
+			my $plural = 's';
+			if ($timeLeft == 1) {
+				$plural = '';
+			}
+			system('say', 'Projector powerdown in about ' . $timeLeft . ' minute' . $plural);
+			$lastCount = $timeLeft;
+		}
+	}
+}

+ 0 - 153
projector/projectorPower.pl

@@ -1,153 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-use IO::Socket::UNIX;
-use POSIX qw(ceil floor);
-
-# Prototypes
-sub mtime($);
-
-# Config
-my $TIMEOUT   = 900;
-my $COUNTDOWN = 300;
-
-# App config
-my $DELAY       = 60;
-my $CMD_TIMEOUT = 5;
-my $TEMP_DIR    = `getconf DARWIN_USER_TEMP_DIR`;
-chomp($TEMP_DIR);
-my $DATA_DIR = $TEMP_DIR . 'plexMonitor/';
-my $CMD_FILE = $DATA_DIR . 'PROJECTOR.socket';
-
-# Debug
-my $DEBUG = 0;
-if ($ENV{'DEBUG'}) {
-	$DEBUG = 1;
-}
-
-# Sanity check
-if (!-d $DATA_DIR || !-S $CMD_FILE) {
-	die("Bad config\n");
-}
-
-# Socket init
-my $sock = IO::Socket::UNIX->new(
-	'Peer'    => $CMD_FILE,
-	'Type'    => SOCK_DGRAM,
-	'Timeout' => $CMD_TIMEOUT
-) or die('Unable to open socket: ' . $CMD_FILE . ": ${@}\n");
-
-# State
-my $state      = 'INIT';
-my $stateLast  = $state;
-my $updateLast = time();
-my $projector  = 0;
-
-# Loop forever
-while (1) {
-
-	# Monitor the GUI and PLAYING files for changes only
-	{
-		my $mtime = mtime($DATA_DIR . 'PLAYING');
-		if ($mtime > $updateLast) {
-			$updateLast = $mtime;
-		}
-		$mtime = mtime($DATA_DIR . 'GUI');
-		if ($mtime > $updateLast) {
-			$updateLast = $mtime;
-		}
-	}
-
-	# Monitor the PROJECTOR file for state and changes
-	{
-		$projector = 0;
-		my $fh;
-		open($fh, $DATA_DIR . 'PROJECTOR')
-		  or die("Unable to open PROJECTOR\n");
-		my $text = <$fh>;
-		close($fh);
-		if ($text =~ /1/) {
-			$projector = 1;
-		}
-		if ($DEBUG) {
-			print STDERR 'Projector: ' . $projector . "\n";
-		}
-
-		my $mtime = mtime($DATA_DIR . 'PROJECTOR');
-		if ($mtime > $updateLast) {
-			$updateLast = $mtime;
-		}
-	}
-
-	# Calculate the new state
-	my $stateLast       = $state;
-	my $timeSinceUpdate = time() - $updateLast;
-	if ($DEBUG) {
-		print STDERR 'Time since update: ' . $timeSinceUpdate . "\n";
-	}
-	if ($state eq 'INIT') {
-		$state = 'COUNTDOWN';
-		if ($projector) {
-			$state = 'ON';
-		}
-	} elsif ($projector) {
-		if ($timeSinceUpdate > $TIMEOUT) {
-			$state = 'COUNTDOWN';
-			if ($timeSinceUpdate > $TIMEOUT + $COUNTDOWN) {
-				$state = 'OFF';
-			}
-		} else {
-			$state = 'ON';
-		}
-	} else {
-		if ($timeSinceUpdate < $TIMEOUT) {
-			$state = 'ON';
-		}
-	}
-
-	# If the state changed, do something about if
-	if ($state ne $stateLast) {
-		if ($DEBUG) {
-			print STDERR 'State change: ' . $stateLast . ' => ' . $state . "\n";
-		}
-		if ($state eq 'OFF') {
-
-			# Turn off the projector
-			$sock->send($state)
-			  or die('Unable to write command to socket: ' . $CMD_FILE . ': ' . $state . ": ${!}\n");
-		} elsif ($state eq 'ON') {
-
-			# Do nothing, at least for the moment
-		}
-
-	}
-
-	# Always announce a pending shutdown
-	if ($state eq 'COUNTDOWN') {
-		my $timeLeft = ($TIMEOUT + $COUNTDOWN) - $timeSinceUpdate;
-		$timeLeft = ceil($timeLeft / 60);
-
-		my $plural = 's';
-		if ($timeLeft == 1) {
-			$plural = '';
-		}
-		system('say', 'Projector powerdown in about ' . $timeLeft . ' minute' . $plural);
-	}
-
-	# Wait and loop
-	sleep($DELAY);
-}
-
-# Cleanup
-$sock->close();
-undef($sock);
-exit(0);
-
-sub mtime($) {
-	my ($file) = @_;
-	my $mtime = 0;
-	if (-r $file) {
-		(undef(), undef(), undef(), undef(), undef(), undef(), undef(), undef(), undef(), $mtime, undef(), undef(), undef()) = stat($file);
-	}
-	return $mtime;
-}