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

Socket-based, multi-timer DMX dimmer/mixer

Zachary Kotlarek 14 лет назад
Родитель
Сommit
276be9cebd
3 измененных файлов с 69 добавлено и 12 удалено
  1. 1 0
      dmx/cmd.pl
  2. 43 12
      dmx/dmx.pl
  3. 25 0
      dmx/launchd/com.uberzach.ola.dmx.plist

+ 1 - 0
dmx/cmd.pl

@@ -0,0 +1 @@
+../serial/cmd.pl

+ 43 - 12
dmx/dmx.pl

@@ -2,6 +2,7 @@
 import os
 import sys
 import array
+import select
 import socket
 import string
 import subprocess
@@ -10,10 +11,18 @@ from ola.ClientWrapper import ClientWrapper
 # ====================================
 # Globals
 # ====================================
+max_channels = 512
 wrapper = None
-state = [ 0 ]
-cmds = { 'value' : [ 0 ], 'ticks' : [ 0 ] }
+state = [ 0 ] * max_channels
+cmds = { 'value' : [ 0 ] * max_channels, 'ticks' : [ 0 ] * max_channels }
 sock = None
+max_mesg_len = 1024
+
+# ====================================
+# Defaults
+# ====================================
+interval = 50
+universe = 0
 
 # ====================================
 # Wrapper callback -- exit on errors
@@ -29,35 +38,57 @@ def DmxSent(state):
 def SendDMXFrame():
   # Re-schedule ourselves in interval ms (do this first to keep the timing consistent)
   wrapper.AddEvent(interval, SendDMXFrame)
-
+  
   # Check for new commands
-  global sock
+  
+  ready = select.select([sock], [], [], interval / 2000)[0]
+  for fh in ready:
+    cmd = fh.recvfrom(max_mesg_len)[0]
+    channel, duration, intensity = string.split(cmd, ':')
+    try:
+      channel = int(channel)
+      duration = int(duration)
+      intensity = int(intensity)
+    except ValueError:
+      print 'Invalid command:', cmd
+      channel = -1
+    if (channel >= 0 and channel <= 512 and intensity >= 0 and intensity <= 255 and duration >= 0 and duration <= 60000):
+      if (channel > 0):
+        cmds['value'][channel - 1] = intensity
+        cmds['ticks'][channel - 1] = duration / interval
+      else:
+        for i in range(len(state)):
+          cmds['value'][i] = intensity
+          cmds['ticks'][i] = duration / interval
+    else:
+      print 'Invalid command parameters:', channel, duration, intensity
   
   # Update values for each channel
   for i in range(len(cmds['value'])):
     if (cmds['value'][i] != state[i]):
       diff = cmds['value'][i] - state[i]
-      delta = float(diff) / float(cmds['ticks'][i])
+      if (cmds['ticks'][i] < 1):
+        delta = diff
+      else:
+        delta = float(diff) / float(cmds['ticks'][i])
       state[i] += int(delta)
-      cmd['ticks'][i] -= 1
-  
+      cmds['ticks'][i] -= 1
+    
   # Send all DMX channels
   data = array.array('B')
   for i in range(len(state)):
-	data.append(state[i])
+    data.append(state[i])
   wrapper.Client().SendDmx(universe, data, DmxSent)
 
 # ====================================
 # Main
 # ====================================
 
-# Pick a universe (0, or as specified in the environment)
-universe = 0
+# Pick a universe (default from above, or as specified in the environment)
 if 'UNIVERSE' in os.environ:
   universe = int(os.environ['UNIVERSE'])
 
-# Pick a tick interval (50ms, or as specified in the environment)
-interval = 50
+# Pick a tick interval (default from above, or as specified in the environment)
 if 'INTERVAL' in os.environ:
   universe = int(os.environ['INTERVAL'])
 

+ 25 - 0
dmx/launchd/com.uberzach.ola.dmx.plist

@@ -0,0 +1,25 @@
+<?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.dmx</string>
+	<key>KeepAlive</key>
+	<dict>
+		<key>NetworkState</key>
+		<true/>
+	</dict>
+	<key>ProgramArguments</key>
+	<array>
+		<string>/Users/tv/bin/video/dmx/dmx.pl</string>
+	</array>
+</dict>
+</plist>