-
Notifications
You must be signed in to change notification settings - Fork 3
/
rpi-matrix-acn-e1-31.py
182 lines (156 loc) · 6.35 KB
/
rpi-matrix-acn-e1-31.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# Art-Net protocol for rpi-rgb-led-matrix
# https://github.com/hzeller/rpi-rgb-led-matrix
# License: MIT oder so....
# TO DO:
# - Buffer check (sind alle Packete aus dem Netzwerk angekommen)
# - Frame per Sekunde steuern
# - Frame Laenge aus dem E1.31 Paket auslesen und verarbeiten
# -
from twisted.internet import protocol, endpoints
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
from struct import pack, unpack
from PIL import Image
from PIL import ImageDraw
from rgbmatrix import RGBMatrix, RGBMatrixOptions
from operator import itemgetter
from collections import deque
from array import array
### Variabeln
# RGBMatrix Panel Variabeln
number_of_rows_per_panel = 32
number_of_columns_per_panel = 32
number_of_panels = 2
parallel = 2
# Art-Net Variabeln
display_size_x = 64
display_size_y = 64
universum_start = 1
universum_count = 25
channel_per_univers = 510
# FrameBuffer
frameBuffer = None
frameBufferCounter = 0
rgbframeLength = 0
# Wie viele Sequencen sollen im Buffer gespeichert werden min. 4
seqBufferSize = 6 # Buffer Min. 4
seqBufferOffset = 2
lastSequence = 0
frameArray = [[0, 0, 0, [0]]]
### RGBMatrixSetting
def rgbmatrix_options():
options = RGBMatrixOptions()
options.multiplexing = 6
options.row_address_type = 0
options.brightness = 80
options.rows = number_of_rows_per_panel
options.cols = number_of_columns_per_panel
options.chain_length = number_of_panels
options.parallel = parallel
options.hardware_mapping = 'regular'
options.inverse_colors = False
options.led_rgb_sequence = "BGR"
options.gpio_slowdown = 1
options.pwm_lsb_nanoseconds = 130
options.show_refresh_rate = 0
options.disable_hardware_pulsing = False
options.scan_mode = 0
options.pwm_bits = 11
options.daemon = 0
options.drop_privileges = 0
return options;
options = rgbmatrix_options()
display = RGBMatrix(options=options)
class sACN_E1_31(DatagramProtocol):
# def __init__(self):
# self.frameBuffer = None
# def __str__(self):
# return ("sACN_E1-31 package:\n - op_code: {0}").format(self.frameBuffer)
def addToFrameBufferArray(self, sequence, universe, rgb_length, data):
global frameArray
if (sequence > -1):
# Die Sequence Nummer wird aus dem Array gelesen
frameSequenceInt = int(float(str(frameArray [0][0])))
# Ist die Sequence Nummer 0, so wurde der Initial Array String erkannt
# nach dem befuellen muss der Initail Array entfernt werden
if (frameSequenceInt == 0):
frameArray.append([sequence, universe, rgb_length, data])
frameArray.pop(0)
else:
frameArray.append([sequence, universe, rgb_length, data])
# Loescht den Buffer der bestehenden Sequenz und aller vergangenen Sequenzen
def cleanUpFrameBuffer(self, sequenceNr):
global frameArray
bufferCounter = 0
bufferSize = seqBufferSize * universum_count
while(bufferCounter < bufferSize):
if (bufferCounter < len(frameArray)):
if (sequenceNr >= int(float(str(frameArray [bufferCounter][0])))):
frameArray.pop(bufferCounter)
bufferCounter += 1
# Diese Funktion gibt eine gesamte Sequenz auch alle Universum in einem Array zusammengezogen
def getSequenceFromFrameBuffer(self, sequenceNr):
global frameArray
finalFrameArray = []
rgbframeLength = 0
#Sequence korrektur da es nur Sequenzen zwischen 1 und 255 geben darf
if (sequenceNr == -1 or sequenceNr == -2):
sequenceNr = sequenceNr + 255
if (sequenceNr > -1):
# Sortieren des Array nach Sequence
frameArray = sorted(frameArray,key=itemgetter(1))
bufferCounter = 0
# der Frame Counter zaehlt die Datenpakete (Universum Pakete) in einer Sequenc
# ist ein Datenpaket verleren gegangen wird die gesamte Sequenz verworfen.
frameCounter = 1
bufferSize = seqBufferSize * universum_count
while(bufferCounter < bufferSize):
if (bufferCounter < len(frameArray)):
if (sequenceNr == int(float(str(frameArray [bufferCounter][0])))):
if (frameCounter == int(float(str(frameArray [bufferCounter][1])))):
frameCounter += 1
else:
self.cleanUpFrameBuffer(sequenceNr)
# Wenn daten im FrameBuffer fehlen, wird ein leerer Buffer zurueck gegeben
finalFrameArray = []
return (finalFrameArray, 0)
finalFrameArray = finalFrameArray + frameArray [bufferCounter][3]
rgbframeLength = rgbframeLength + int(float(str(frameArray [bufferCounter][2])))
frameArray.pop(bufferCounter)
bufferCounter += 1
if (len(frameArray) > bufferSize):
frameArray = [[0, 0, 0, [0]]]
return (finalFrameArray, rgbframeLength)
def datagramReceived(self, data, (host, port)):
global lastSequence
if ((len(data) > 18) and (data[4:16] == "ASC-E1.17\x00\x00\x00")):
rawbytes = map(ord, data)
if (len(data) > 18):
sequence = rawbytes[111]
universe = rawbytes[114]
rgb_length = (rawbytes[115] << 8) + rawbytes[116]
rgb_length = 510
rgbdata = rawbytes[126:(rgb_length+126)]
self.addToFrameBufferArray(sequence,universe,rgb_length,rgbdata)
if(lastSequence != sequence):
frameBuffer, rgbframeLength = self.getSequenceFromFrameBuffer(sequence - seqBufferOffset)
self.showDisplay(display_size_x,display_size_y,frameBuffer,rgbframeLength)
lastSequence = sequence
def showDisplay(self, display_size_x, display_size_y, datastream, rgb_length):
idx = 0
x = 0
y = 0
while ((idx < (rgb_length)) and (y < (display_size_y - 1))):
r = datastream[idx]
idx += 1
g = datastream[idx]
idx += 1
b = datastream[idx]
idx += 1
display.SetPixel(x, y, r, g, b)
x += 1
if (x > (display_size_x - 1)):
x = 0
y += 1
reactor.listenUDP(5568, sACN_E1_31())
reactor.run()