Ankündigung

Einklappen
Keine Ankündigung bisher.

DMX Plugin für DMX512a USB devices

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    DMX Plugin für DMX512a USB devices

    Hallo,

    ich bin gerade dran das dmx Modul anzupassen, dass auch mein DMX Adapter (DMXKing DMX512a) funktioniert.

    Der verwendet ein völlig anderes Protokoll als die nanodmx dinger.

    Zu meinem Problem: Im DMX512a Protokoll gibt es leider keine Möglichkeit einzelne Kanäle zu modifizieren. Es müssen immer die Kompletten 512 Kanäle (oder zumindest von Kanal 1 bis x durchgehend) geschickt werden. Der integrierte Microcontroller refresht dann automatisch (wie auch beim NanoDMX).

    Da man keine einzelnen Kanäle aktualisieren kann, brauche ich ein Array dass während der Laufzeit von smarthome.py erhalten bleibt. Soweit ich das nachvollziehen kann, wird das Plugin ausgeführt und danach wieder beendet (was ja auch logisch ist).

    Nachdem ich absolut keine python Erfahrung habe: Weiss jemand Rat ?

    Hier noch der Code:

    PS: ich bin auch für Tipps/Feedback jeglicher Art empfänglich

    Code:
    #!/usr/bin/env python
    # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
    #########################################################################
    # Copyright 2011 KNX-User-Forum e.V.            https://knx-user-forum.de/
    #########################################################################
    #  This file is part of SmartHome.py.   http://smarthome.sourceforge.net/
    #
    #  SmartHome.py 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 3 of the License, or
    #  (at your option) any later version.
    #
    #  SmartHome.py 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 SmartHome.py. If not, see <http://www.gnu.org/licenses/>.
    #########################################################################
    
    import logging
    import threading
    import serial
    
    logger = logging.getLogger('')
    
    
    class DMX():
        # _dim = 10^((n-1)/(253/3)-1) by JNK from KNX UF
        #_dim = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, 26, 26, 27, 28, 29, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 50, 51, 52, 54, 55, 57, 58, 60, 62, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 86, 88, 90, 93, 95, 98, 101, 104, 106, 109, 112, 115, 119, 122, 125, 129, 132, 136, 140, 144, 148, 152, 156, 160, 165, 169, 174, 179, 184, 189, 194, 199, 205, 211, 216, 222, 228, 235, 241, 248, 255 ]
    
        self._dmxdata=[chr(0)]*513
    
        def __init__(self, smarthome, tty, adapter):
            self._sh = smarthome
            self._adapter = adapter
            self._is_connected = False
            self._lock = threading.Lock()
    
            try:
                self._port = serial.Serial(tty, 38400, timeout=1)
            except:
                logger.error("Could not open %s." % tty)
                return
            else:
                self._is_connected = True
            if not self._send_nanodmx("C?") and adapter == "nanodmx":
                logger.warning("Could not communicate with dmx adapter.")
                self._is_connected = False
            if adapter == "dmx512a":
                self._dmxopen=chr(126)
                self._dmxclose=chr(231)
                self._dmxinit1=chr(03)+chr(02)+chr(0)+chr(0)+chr(0)
                self._dmxinit2=chr(10)+chr(02)+chr(0)+chr(0)+chr(0)
                self._dmxintensity=chr(6)+chr(1)+chr(2)
                self._port.write(self._dmxopen+self._dmxinit1+self._dmxclose)
                self._port.write(self._dmxopen+self._dmxinit2+self._dmxclose)
    
        def _send_dmx512a(self, data):
            if not self._is_connected:
                return False
            self._lock.acquire()
            self._port.write(data)
            self._lock.release()
            return True
    
        def _send_nanodmx(self, data):
            if not self._is_connected:
                return False
            self._lock.acquire()
            try:
                self._port.write(data)
                ret = self._port.read(1)
            except:
                logger.warning("Problem sending data to dmx adapter.")
                ret = 'F'
            self._lock.release()
            if ret == 'G':
                return True
            else:
                return False
    
        def run(self):
            self.alive = True
    
        def stop(self):
            self._port.close()
            self.alive = False
    
        def send(self, channel, value):
            logger.debug("update dmx channel {0:03d} {1:03d}".format(channel, int(value)))
    	if self._adapter == "nanodmx":
                 self._send_nanodmx("C{0:03d}L{1:03d}".format(int(channel), int(value)))
    	if self._adapter == "dmx512a":
    	     self._dmxdata[channel]=chr(value)
    	     sdata=''.join(self._dmxdata)
    	     self._send_dmx512a(self._dmxopen+self._dmxintensity+sdata+self._dmxclose)
    
        def parse_item(self, item):
            if 'dmx_ch' in item.conf:
                channels = item.conf['dmx_ch']
                if isinstance(channels, str):
                    channels = [channels, ]
                channels = map(int, channels)
                item.conf['dmx_ch'] = channels
                return self.update_item
            else:
                return None
    
        def update_item(self, item, caller=None, source=None, dest=None):
            #logger.debug("update dmx channel {0:03d}".format(item.dmx_ch))
            for channel in item.conf['dmx_ch']:
                self.send(channel, item())

    #2
    Hi,

    es sollte normalerweise so sein, dass das USB/DMX Modul die DMX Daten empfängt, speichert und auf den Bus ausgibt, bis zur nächsten Änderung, dann wird aber nur der Kanal geädert, der sich verändert hat. Dazu ist das Modul nur da, gleichzeitig entlastet es die USB Schnittstelle (Typ 1.1) und den Rechner. Eine komplette Datenübertragung auf dem DMX Bus mit allen 512 Kanälen dauert 4 Millisekunden, ist also schön schnell.
    Die Datenübertragung auf den DMX Bus erfolgt kontinuierlich, bis zum Abschalten.
    Nicht alle USB/DMX Adapter sind gleich. Man sollte nur die Adapter verwenden, die geprüft wurden, und somit Kompatibel sind. Das trifft nicht auf alle Adapter zu. Es könnte sonst schon mal Probleme bei der Hilfe geben. Hier mal im Forum nachfragen.

    Wichtiger Hinweis ! Nie den Kanal 0 für ein Gerät verwenden, dieser Kanal ist das Start Byte auf dem DMX Bus. Das ist eine beliebte Fehlerquelle und sollte bei der Programmierung abgefangen werden.

    LG
    Martin
    Angehängte Dateien
    Wer zu Hause eine Show abziehen will nutzt DMX, wer nicht, auch.

    Kommentar


      #3
      DMX Plugin für DMX512a USB devices

      Zitat von fmeister Beitrag anzeigen
      Da man keine einzelnen Kanäle aktualisieren kann, brauche ich ein Array dass während der Laufzeit von smarthome.py erhalten bleibt. Soweit ich das nachvollziehen kann, wird das Plugin ausgeführt und danach wieder beendet (was ja auch logisch ist).
      Nein, das Plugin selber bleibt als Instanz im Speicher. Jede Variable die mit self.variablenname angelegt wird ist eine Instanzvariable und somit über die komplette Laufzeit von sh.py verfügbar.
      Mit freundlichen Grüßen
      Niko Will

      Logiken und Schnittstelle zu anderen Systemen: smarthome.py - Visualisierung: smartVISU
      - Gira TS3 - iPhone & iPad - Mobotix T24 - ekey - Denon 2313 - Russound C5 (RIO over TCP Plugin) -

      Kommentar


        #4
        Zitat von vietgilles Beitrag anzeigen
        es sollte normalerweise so sein, dass das USB/DMX Modul die DMX Daten empfängt, speichert und auf den Bus ausgibt, bis zur nächsten Änderung, dann wird aber nur der Kanal geädert, der sich verändert hat.
        Danke für die Info, mein USB DMX Adapter macht das genau so. Der einzige Unterschied ist das Protokoll. Beim nanoDMX kann man einzelne Kanäle gezielt ändern. Bei meinem muss ich das komplette Array pushen (einmal) - die Wiederholung passiert dann automatisch.

        Kommentar


          #5
          Zitat von 2ndsky Beitrag anzeigen
          Nein, das Plugin selber bleibt als Instanz im Speicher. Jede Variable die mit self.variablenname angelegt wird ist eine Instanzvariable und somit über die komplette Laufzeit von sh.py verfügbar.
          Okay dann wohl ein Fehler im script, danke für die Info!

          Kommentar


            #6
            Plugin soweit fertig

            für die die es Interessiert:

            Code:
            #########################################################################
            # Copyright 2011 KNX-User-Forum e.V.            https://knx-user-forum.de/
            #########################################################################
            #  This file is part of SmartHome.py.   http://smarthome.sourceforge.net/
            #
            #  SmartHome.py 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 3 of the License, or
            #  (at your option) any later version.
            #
            #  SmartHome.py 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 SmartHome.py. If not, see <http://www.gnu.org/licenses/>.
            #########################################################################
            
            import logging
            import threading
            import serial
            
            logger = logging.getLogger('')
            
            DMXOPEN=chr(126)
            DMXCLOSE=chr(231)
            DMXINIT1=chr(03)+chr(02)+chr(0)+chr(0)+chr(0)
            DMXINIT2=chr(10)+chr(02)+chr(0)+chr(0)+chr(0)
            DMXINTENSITY=chr(6)+chr(1)+chr(2)
            
            class DMX():
                # _dim = 10^((n-1)/(253/3)-1) by JNK from KNX UF
                #_dim = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, 26, 26, 27, 28, 29, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 48, 50, 51, 52, 54, 55, 57, 58, 60, 62, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 86, 88, 90, 93, 95, 98, 101, 104, 106, 109, 112, 115, 119, 122, 125, 129, 132, 136, 140, 144, 148, 152, 156, 160, 165, 169, 174, 179, 184, 189, 194, 199, 205, 211, 216, 222, 228, 235, 241, 248, 255 ]
            
            
                def __init__(self, smarthome, tty, adapter):
                    logger.debug("Init DMX...")
                    self._dmxdata=[chr(0)]*513
                    self._sh = smarthome
                    self._adapter = adapter
                    self._is_connected = False
                    self._lock = threading.Lock()
            
                    try:
                        self._port = serial.Serial(tty, 38400, timeout=1)
                    except:
                        logger.error("Could not open %s." % tty)
                        return
                    else:
                        self._is_connected = True
                    if not self._send_nanodmx("C?") and adapter == "nanodmx":
                        logger.warning("Could not communicate with dmx adapter.")
                        self._is_connected = False
                    if adapter == "dmx512a":
                        self._port.write(DMXOPEN+DMXINIT1+DMXCLOSE)
                        self._port.write(DMXOPEN+DMXINIT2+DMXCLOSE)
            
                def _send_dmx512a(self, data):
                    lst = list(data)
                    debug = ""
                    for element in lst:
                        debug += str(ord(element))
                        debug += ", "
                    logger.debug("_send_dmx512a: %s", debug)
                    if not self._is_connected:
                        return False
                    self._lock.acquire()
                    self._port.write(data)
                    self._lock.release()
                    return True
            
                def _send_nanodmx(self, data):
                    if not self._is_connected:
                        return False
                    self._lock.acquire()
                    try:
                        self._port.write(data)
                        ret = self._port.read(1)
                    except:
                        logger.warning("Problem sending data to dmx adapter.")
                        ret = 'F'
                    self._lock.release()
                    if ret == 'G':
                        return True
                    else:
                        return False
            
                def run(self):
                    self.alive = True
            
                def stop(self):
                    self._port.close()
                    self.alive = False
            
                def send(self, channel, value):
                    logger.debug("update dmx channel {0:03d} {1:03d}".format(channel, int(value)))
            	if self._adapter == "nanodmx":
                         logger.debug("%s", self._adapter)
                         self._send_nanodmx("C{0:03d}L{1:03d}".format(int(channel), int(value)))
            	if self._adapter == "dmx512a":
                         logger.debug("%s", self._adapter)
            	     self._dmxdata[channel]=chr(value)
                         debug = ""
                         for element in self._dmxdata:
                             debug += str(ord(element))
                             debug += ", "
                         logger.debug("send: %s", debug)
            	     sdata=''.join(self._dmxdata)
                         logger.debug("%s", sdata)
            	     self._send_dmx512a(DMXOPEN+DMXINTENSITY+sdata+DMXCLOSE)
            
                def parse_item(self, item):
                    if 'dmx_ch' in item.conf:
                        channels = item.conf['dmx_ch']
                        if isinstance(channels, str):
                            channels = [channels, ]
                        channels = map(int, channels)
                        item.conf['dmx_ch'] = channels
                        return self.update_item
                    else:
                        return None
            
                def update_item(self, item, caller=None, source=None, dest=None):
                    #logger.debug("update dmx channel {0:03d}".format(item.dmx_ch))
                    for channel in item.conf['dmx_ch']:
                        self.send(channel, item())

            Kommentar

            Lädt...
            X