Zachary Kotlarek 14 лет назад
Родитель
Сommit
3b0c51d575
2 измененных файлов с 192 добавлено и 0 удалено
  1. 161 0
      dmx/fan.pl
  2. 31 0
      dmx/launchd/com.uberzach.ola.fan.plist

+ 161 - 0
dmx/fan.pl

@@ -0,0 +1,161 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use IO::Socket;
+use Time::HiRes qw( usleep );
+use File::Temp qw( tempfile );
+
+# Prototypes
+sub dim($$$);
+
+# Channels:
+#	0  => All channels
+#	1  => Couch-side hidden
+#	2  => Couch-side exposed
+#	3  => Stairs
+#	4  => <Unused>
+#	5  => Bar-side hidden
+#	6  => Bar-side bar-shelves
+#	7  => Bar-side exposed
+#	8  => Bar-side ceiling
+#	9  => <Unused>
+#	10 => <Unused>
+#	11 => Fan
+#	12 => Bias Light
+
+# User config
+my %DIM = (
+	'OFF'    => [
+		{ 'channel' => 11, 'value' => 0,   'time' => 0 }
+	],
+	'ON'    => [
+		{ 'channel' => 11, 'value' => 255, 'time' => 0 }
+	],
+);
+my $TIMEOUT = 180;
+
+# App config
+my $SOCK_TIMEOUT = 5;
+my $TEMP_DIR     = `getconf DARWIN_USER_TEMP_DIR`;
+chomp($TEMP_DIR);
+my $DATA_DIR = $TEMP_DIR . 'plexMonitor/';
+my $CMD_FILE = $DATA_DIR . 'DMX.socket';
+
+# Debug
+my $DEBUG = 0;
+if ($ENV{'DEBUG'}) {
+	$DEBUG = 1;
+}
+
+# Command-line arguments
+my ($DELAY) = @ARGV;
+if (!$DELAY) {
+	$DELAY = 0.5;
+}
+$DELAY *= 1000000;    # Microseconds;
+
+# 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' => $SOCK_TIMEOUT
+) or die('Unable to open socket: ' . $CMD_FILE . ": ${@}\n");
+
+# State
+my $state      = 'INIT';
+my $stateLast  = $state;
+my $fan        = 0;
+my $projector  = 0;
+
+# Always force lights out at launch
+dim(11, 0, 0);
+
+# Loop forever
+while (1) {
+
+	# Monitor the PROJECTOR file for state
+	{
+		$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";
+		}
+	}
+
+	# Monitor the FAN_CMD file for presence
+	{
+		# Clear the flag when the projector is off
+		if ($fan && !$projector) {
+			unlink($DATA_DIR . 'FAN_CMD');
+		}
+
+		$fan = 0;
+		if (-e $DATA_DIR . 'FAN_CMD') {
+			$fan = 1;
+		}
+		if ($DEBUG) {
+			print STDERR 'Fan: ' . $fan . "\n";
+		}
+	}
+
+	# Calculate the new state
+	$stateLast = $state;
+	if ($fan) {
+		if ($projector) {
+			$state = 'ON';
+		} else {
+			$state = 'OFF';
+		}
+	} else {
+		$state = 'OFF';
+	}
+	if ($state eq 'INIT') {
+		$state = 'OFF';
+	}
+
+	# Update the fan state
+	if ($stateLast ne $state) {
+		if ($DEBUG) {
+			print STDERR 'State: ' . $stateLast . ' => ' . $state . "\n";
+			foreach my $data (@{ $DIM{$state} }) {
+				print STDERR "\t" . $data->{'channel'} . ' => ' . $data->{'value'} . ' @ ' . $data->{'time'} . "\n";
+			}
+		}
+
+		# Send the dim command
+		my @values = ();
+		foreach my $data (@{ $DIM{$state} }) {
+			dim($data->{'channel'}, $data->{'time'}, $data->{'value'});
+			push(@values, $data->{'channel'} . ' => ' . $data->{'value'} . ' @ ' . $data->{'time'});
+		}
+
+		# Save the state and value to disk
+		my ($fh, $tmp) = tempfile($DATA_DIR . 'FAN.XXXXXXXX', 'UNLINK' => 0);
+		print $fh 'State: ' . $state . "\n" . join("\n", @values) . "\n";
+		close($fh);
+		rename($tmp, $DATA_DIR . 'FAN');
+	}
+
+	# Wait and loop
+	usleep($DELAY);
+}
+
+# Send the command
+sub dim($$$) {
+	my ($channel, $duration, $intensity) = @_;
+	my $cmd = join(':', $channel, $duration, $intensity);
+	$sock->send($cmd)
+	  or die('Unable to write command to socket: ' . $CMD_FILE . ': ' . $cmd . ": ${!}\n");
+}

+ 31 - 0
dmx/launchd/com.uberzach.ola.fan.plist

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>UserName</key>
+	<string>tv</string>
+	<key>LimitLoadToHosts</key>
+	<array>
+		<string>heady.uberzach.com</string>
+	</array>
+	<key>RunAtLoad</key>
+	<true/>
+	<key>Label</key>
+	<string>com.uberzach.ola.fan</string>
+	<key>KeepAlive</key>
+	<dict>
+		<key>OtherJobEnabled</key>
+		<dict>
+			<key>com.uberzach.ola.dmx</key>
+			<true/>
+			<key>com.uberzach.projector</key>
+			<true/>
+		</dict>
+	</dict>
+	<key>ProgramArguments</key>
+	<array>
+		<string>/Users/tv/bin/video/dmx/fan.pl</string>
+		<string>1</string>
+	</array>
+</dict>
+</plist>