#!/usr/bin/env python # # dmx512.py - DMX512 class # Works with the following adapters: # - DMXKing ultraDMX Micro # # Copyright 2017 Todd Shadburn # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import serial #char 126 is 7E in hex. It's used to start all DMX512 commands DMXOPEN=chr(126) #char 231 is E7 in hex. It's used to close all DMX512 commands DMXCLOSE=chr(231) # Adapter initialization string #1 DMXINIT1= chr(03)+chr(02)+chr(0)+chr(0)+chr(0) # Adapter initialization string #2 DMXINIT2= chr(10)+chr(02)+chr(0)+chr(0)+chr(0) class DMX512(object): def __init__(self, device=None, maxchannels=512): self.device = device if maxchannels > 512: maxchannels = 512 self.maxchannels = maxchannels+1 # One extra byte needed self.dmxdata = [chr(0)] * (self.maxchannels) chh = int(self.maxchannels / 256) chl = int(self.maxchannels - (chh * 256)) print 'DEBUG maxchannels=%d chh=%d chl=%d' % (self.maxchannels, chh, chl) self.dmx_length = chr(6) + chr(chl) + chr(chh) self.sfd = serial.Serial(self.device) # Init DMX adapter self.sfd.write( DMXOPEN+DMXINIT1+DMXCLOSE) self.sfd.write( DMXOPEN+DMXINIT2+DMXCLOSE) return def close(self): self.sfd.close() return def set(self, channel, value): """ Change the value for a single channel (Does not push the change to the adapter) """ if channel < 1 or channel > 512: raise ValueError('DMX channel must be between 1 and 512') self.dmxdata[channel] = chr(value) return def update(self): """ Push the current channel settings to the adapater """ sdata = ''.join(self.dmxdata) self.sfd.write(DMXOPEN+self.dmx_length+sdata+DMXCLOSE) return