|
@@ -0,0 +1,192 @@
|
|
|
+
|
|
|
+import os
|
|
|
+import fcntl
|
|
|
+import time
|
|
|
+import socket
|
|
|
+import struct
|
|
|
+import random
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+import copy
|
|
|
+import _thread as thread
|
|
|
+
|
|
|
+import sys
|
|
|
+
|
|
|
+def unpack_art_dmx(data):
|
|
|
+ dmx = ["x"]*512
|
|
|
+ for i in range(len(data[18:]) ):
|
|
|
+ x=data[18+i]
|
|
|
+ #print("x",x)
|
|
|
+ #print( "data",b'!B', data[18+i])
|
|
|
+ #x=struct.unpack( b'!B',data[18+i])
|
|
|
+ #print( "data",b'!B', data[18+i],x)
|
|
|
+ #x=x[0]
|
|
|
+ dmx[i] = x
|
|
|
+ return dmx
|
|
|
+
|
|
|
+
|
|
|
+class Socket():
|
|
|
+ def __init__(self,bind='',port=6454,options_recive=""):
|
|
|
+ self.__port =port
|
|
|
+ self.__bind =bind
|
|
|
+ self.options_recive=options_recive
|
|
|
+ self.__poll = 0
|
|
|
+ self.__data = []
|
|
|
+ self.__addr = "NONE"
|
|
|
+ #self.__hosts = {"host":{"9":[0]*512}}
|
|
|
+ self.__hosts = {}
|
|
|
+ self.hosts = self.__hosts
|
|
|
+ self.open()
|
|
|
+ self._poll_clean_time = time.time()
|
|
|
+ self._poll_clean_count = 0
|
|
|
+ def open(self):
|
|
|
+ try:
|
|
|
+ print("connecting to ArtNet bind:",self.__bind,"Port",self.__port)
|
|
|
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
+
|
|
|
+ self.sock.bind((self.__bind, self.__port))
|
|
|
+ fcntl.fcntl(self.sock, fcntl.F_SETFL, os.O_NONBLOCK)
|
|
|
+ #self.sock.setblocking(0)
|
|
|
+
|
|
|
+ except socket.error as e:
|
|
|
+ print("Socket ",self.__bind,self.__port, "ERR: {0} ".format(e.args))
|
|
|
+ #raw_input()
|
|
|
+ #sys.exit()
|
|
|
+ def poll_clean(self):
|
|
|
+ if self._poll_clean_time+(1/25.) <= time.time():
|
|
|
+ self._poll_clean_time = time.time()
|
|
|
+ self._poll_clean()
|
|
|
+ x = self._poll_clean_count
|
|
|
+ self._poll_clean_count = 0
|
|
|
+ return x
|
|
|
+ def _poll_clean(self):
|
|
|
+ while 1:
|
|
|
+ try:
|
|
|
+ self.__data, self.__addr = self.sock.recvfrom(self.__port)
|
|
|
+ self._poll_clean_count += 1
|
|
|
+ #return 1
|
|
|
+ except socket.timeout as e:
|
|
|
+ err = e.args[0]
|
|
|
+ if err == 'timed out':
|
|
|
+ time.sleep(1)
|
|
|
+ print('recv timed out, retry later')
|
|
|
+ else:
|
|
|
+ print(e)
|
|
|
+ break
|
|
|
+ except socket.error as e:
|
|
|
+ break
|
|
|
+ def poll(self ):
|
|
|
+ if not self.__poll:
|
|
|
+ try:
|
|
|
+ self.__data, self.__addr = self.sock.recvfrom(self.__port)
|
|
|
+
|
|
|
+
|
|
|
+ data, addr = (self.__data,self.__addr)
|
|
|
+ self.host = addr[0]
|
|
|
+ head = data[:18]
|
|
|
+ rawdmx = data[18:]
|
|
|
+ #print([head],addr)
|
|
|
+ self.univ = -1
|
|
|
+ try:
|
|
|
+ self.head = struct.unpack("!8sHBBBBHBB" , head )
|
|
|
+ except Exception as e:
|
|
|
+ pass#print( "======E09823" , e)
|
|
|
+ univ = self.head[6]/255 # /512 # * 512
|
|
|
+ self.univ = int(univ)
|
|
|
+
|
|
|
+ if self.host.startswith("127."): #allways recive localhost on port
|
|
|
+ self.__poll = 1
|
|
|
+ return 1
|
|
|
+ elif not self.options_recive:
|
|
|
+ self.__poll = 1
|
|
|
+ return 1
|
|
|
+ elif self.host.startswith(self.options_recive):
|
|
|
+ self.__poll = 1
|
|
|
+ return 1
|
|
|
+ else:
|
|
|
+ self.__poll = 0
|
|
|
+
|
|
|
+ addr = str(addr)
|
|
|
+ univ = str(univ)
|
|
|
+ if self.__poll:
|
|
|
+ if addr not in self.__hosts:
|
|
|
+ self.__hosts[addr] = {}
|
|
|
+ if univ not in self.__hosts[addr]:
|
|
|
+ self.__hosts[addr][univ] = {}
|
|
|
+
|
|
|
+ self.__hosts[addr][univ] = {"head":head,"addr":addr,"univ":univ,"dmx":rawdmx}
|
|
|
+ self.hosts = self.__hosts
|
|
|
+
|
|
|
+ except socket.timeout as e:
|
|
|
+ err = e.args[0]
|
|
|
+ if err == 'timed out':
|
|
|
+ time.sleep(1)
|
|
|
+ print('recv timed out, retry later')
|
|
|
+ else:
|
|
|
+ print(e)
|
|
|
+ except socket.error as e:
|
|
|
+ pass
|
|
|
+
|
|
|
+ def recive(self):
|
|
|
+ if self.__poll:
|
|
|
+ self.__poll = 0
|
|
|
+
|
|
|
+ data, addr = (self.__data,self.__addr)
|
|
|
+ #print( self.univ,self.head)
|
|
|
+
|
|
|
+ self.dmx = unpack_art_dmx(data)
|
|
|
+
|
|
|
+ return { "host":self.host,"dmx":self.dmx,"univ":self.univ,"head":self.head,"data":data,"addr":addr}
|
|
|
+
|
|
|
+
|
|
|
+def get_value(sdata=[] ,univ=0,dmx=[1,121]):
|
|
|
+ data=[]
|
|
|
+ for k in sdata:
|
|
|
+ xx = sdata[k]
|
|
|
+ _univ = int(xx["head"][6] /256)
|
|
|
+ if xx["host"].startswith('2.0.0.') and _univ == univ:
|
|
|
+ for d in dmx:
|
|
|
+ y = xx["dmx"][d-1]
|
|
|
+ data.append(y)
|
|
|
+
|
|
|
+ return data
|
|
|
+
|
|
|
+class ArtNetRead():
|
|
|
+ def __init__(self):
|
|
|
+ self.sdata = {}
|
|
|
+ self.xsocket = Socket()
|
|
|
+ self.lock = thread.allocate_lock()
|
|
|
+ def loop(self):
|
|
|
+ sdata = {}
|
|
|
+ print("loop")
|
|
|
+ while 1:
|
|
|
+ flag = 0
|
|
|
+ while self.xsocket.poll():
|
|
|
+ xx = self.xsocket.recive()
|
|
|
+ k = xx["host"] +":"+ str(xx["head"][6])
|
|
|
+ sdata[k] = xx
|
|
|
+ flag = 1
|
|
|
+
|
|
|
+ if flag:
|
|
|
+ try:
|
|
|
+ self.lock.acquire()
|
|
|
+ self.sdata = copy.deepcopy(sdata)
|
|
|
+ finally:
|
|
|
+ self.lock.release()
|
|
|
+ time.sleep(0.001)
|
|
|
+ def get(self):
|
|
|
+
|
|
|
+ try:
|
|
|
+ self.lock.acquire()
|
|
|
+ x = self.sdata #= copy.deepcopy(asdata)
|
|
|
+ self.sdata = {}
|
|
|
+ return x
|
|
|
+ finally:
|
|
|
+ self.lock.release()
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ e = ArtNetRead()
|
|
|
+ thread.start_new_thread(e.loop,())
|