ソースを参照

Handler for the rope light

Zachary Kotlarek 14 年 前
親
コミット
eadd08ee72
2 ファイル変更、168 行追加、6 行削除
  1. 90 0
      dmx/rope.sh
  2. 78 6
      dmx/setChannels.py

+ 90 - 0
dmx/rope.sh

@@ -0,0 +1,90 @@
+#!/bin/bash
+
+# Config
+DIM_OFF=0
+DIM_OFF_TIME=10000
+DIM_PLAY=64
+DIM_PLAY_TIME=250
+DIM_PAUSE=192
+DIM_PAUSE_TIME=1000
+OFF_TIMEOUT=600
+DELAY=0.25
+
+# App Config
+TEMP_DIR="`getconf DARWIN_USER_TEMP_DIR`"
+EXEC_DIR="${HOME}/bin/video/dmx"
+
+cleanup() {
+	exit 0
+}
+trap cleanup SIGINT
+
+checkForUpdates() {
+	UPDATE=0
+	if [ -r "${1}" ]; then
+		UPDATE="`cat "${1}"`"
+	fi
+	if [ -z "${UPDATE}" ]; then
+		UPDATE=0
+	fi
+	UPDATE=$(( $UPDATE + 0 ))
+	echo $UPDATE
+}
+
+# Sanity check
+if [ ! -d "${EXEC_DIR}" ] || [ ! -d "${TEMP_DIR}" ]; then
+	echo "Bad config" 1>&2
+	exit 1
+fi
+
+# Move into position
+cd "${TEMP_DIR}/plexMonitor"
+
+# State
+STATE="PLAYING"
+DIM_LAST=$DIM_PLAY
+PLAYING=0
+LAST_UPDATE=0
+LAST_PLAYING=0
+
+# Loop forever
+while [ 1 ]; do
+	# Reset
+	CHANGED=0
+
+	# Monitor the playing file for changes
+	UPDATE=$(checkForUpdates PLAY_STATUS.lastUpdate)
+	if [ $UPDATE -gt $LAST_UPDATE ]; then
+		LAST_UPDATE=$UPDATE
+		CHANGED=1
+	fi
+
+	# Grab the new play state
+	LAST_PLAYING=$PLAYING
+	if [ $CHANGED -gt 0 ]; then
+		PLAYING="`cat PLAY_STATUS`"
+		PLAYING=$(( $PLAYING + 0 ))
+	fi
+
+	# Turn off when we reach the timeout
+	if [ $PLAYING -lt 1 ] && [ "${STATE}" != "OFF" ] && [ $(( LAST_UPDATE + $OFF_TIMEOUT )) -lt `date '+%s'` ]; then
+		STATE="OFF"
+		"${EXEC_DIR}/dimChannels.py" $DIM_OFF_TIME $DIM_LAST $DIM_OFF
+		DIM_LAST=$DIM_OFF
+
+	# If something has changed, check the actual play state
+	elif [ $PLAYING -ne $LAST_PLAYING ]; then
+		if [ $PLAYING -gt 0 ]; then
+			STATE="PLAYING"
+			"${EXEC_DIR}/dimChannels.py" $DIM_PLAY_TIME $DIM_LAST $DIM_PLAY
+			DIM_LAST=$DIM_PLAY
+		else
+			STATE="PAUSED"
+			"${EXEC_DIR}/dimChannels.py" $DIM_PAUSE_TIME $DIM_LAST $DIM_PAUSE
+			DIM_LAST=$DIM_PAUSE
+		fi
+	fi
+
+	# Delay
+	sleep $DELAY
+done

+ 78 - 6
dmx/setChannels.py

@@ -1,16 +1,88 @@
 #!/usr/bin/python
 #!/usr/bin/python
+import os
 import sys
 import sys
 import array
 import array
+import string
 from ola.ClientWrapper import ClientWrapper
 from ola.ClientWrapper import ClientWrapper
 
 
+wrapper = None
+dim = False
+dimTick = 0
+dimTime = 0
+numTicks = 0
+
+# Wrapper callback
 def DmxSent(state):
 def DmxSent(state):
-  wrapper.Stop()
+  # Stop on errors
+  if not state.Succeeded():
+    wrapper.Stop()
+  
+  # Only run one command if we're setting
+  if not dim:
+    wrapper.Stop()
+  
+  # Stop when we're done dimming
+  if dim and dimTick >= numTicks:
+    wrapper.Stop()
 
 
+# Pick a universe (0, or as specified in the environment)
 universe = 0
 universe = 0
-data = array.array('B')
-for i in range(1, len(sys.argv)):
-   data.append(int(sys.argv[i]))
+if 'UNIVERSE' in os.environ:
+  universe = int(os.environ['UNIVERSE'])
+
+# Pick a tick interval (50ms, or as specified in the environment)
+interval = 50
+if 'INTERVAL' in os.environ:
+  universe = int(os.environ['INTERVAL'])
+
+# Choose direct-set or dimming
+dim = False
+if 'dim' in string.lower(sys.argv[0]):
+  dim = True
+
+# If we are dimming, parse the command line into 3-part blocks
+# Otherwise just collect the intensities directly
+cmdData = [];
+if dim:
+  dimTime = int(sys.argv[1])
+  numTicks = dimTime / interval
+
+  for i in range(2, len(sys.argv), 2):
+      dimData = array.array('I')
+      dimData.append(int(sys.argv[i]))
+      dimData.append(int(sys.argv[i + 1]))
+      cmdData.append(dimData)
+else:
+  for i in range(1, len(sys.argv)):
+    cmdData.append(int(sys.argv[i]))
+
+def SendDMXFrame():
+  # Re-schedule ourselves in interval ms (do this first to keep the timing consistent)
+  if dim:
+    wrapper.AddEvent(interval, SendDMXFrame)
+  
+  # Eventually we need an array of intesnty bytes for each channel
+  data = array.array('B')
+
+  # Calculate intensities
+  if dim:
+    global dimTick
+    dimTick += 1
+    
+    for i in cmdData:
+      totalRange = i[1] - i[0]
+      delta = float(totalRange) / float(numTicks) * float(dimTick)
+      data.append(int(i[0] + delta))
+
+  else:
+    # Copy each intensity level from the command line
+    for i in cmdData:
+      data.append(i)
+  
+  # Send
+  wrapper.Client().SendDmx(universe, data, DmxSent)
+
+# Send the DMX command
 wrapper = ClientWrapper()
 wrapper = ClientWrapper()
-client = wrapper.Client()
-client.SendDmx(universe, data, DmxSent)
+wrapper.AddEvent(interval, SendDMXFrame)
 wrapper.Run()
 wrapper.Run()