diff --git a/packets/__init__.py b/packets/__init__.py index c376ba4232a6c392a132dfe02ab3609c918a930c..ff00d3affe68f1e72ac4b20da10ac6ad50b45dff 100644 --- a/packets/__init__.py +++ b/packets/__init__.py @@ -81,11 +81,35 @@ class ArtNetPacket(object): physical = self.physical, ) + def _split_integer_to_byte(self, p_integer, p_length=2, p_bits=8): + """ + Splits a integer into a bytelist (not bytearray) of the given length. + Every chunk is p_bits bits long + """ + bitmask = (2 ** p_bits) - 1 + bytelist = [] + + for counter in range(p_length - 1, -1, -1): + shifted = p_integer >> counter * (p_bits) + bytelist.append(shifted & bitmask) + + return bytelist + + def _format_value(self, p_value, p_format): + if type(p_value) is str: + return p_value.encode() + if type(p_value) is int: + length = p_format / 8 + return self._split_integer_to_byte(p_value, length) + if type(p_value) is list: + return p_value + raise ValueError("Unknown type: %s" % str(type(p_value))) + def encode(self): """ Encodes a package into a bytearray. """ - fields = [] + packet = [] # Iterates through all entries of the schema for name, fmt in self.schema: # If there is a function to access the value, the function is called @@ -96,12 +120,18 @@ class ArtNetPacket(object): else: value = getattr(self, name) # Store values in array - fields.append([name, fmt, value]) + formated = self._format_value(value, fmt) + #fields.append([name, fmt, value]) + packet.append(formated) # Builds a bytearray to send as packet - fmt = ', '.join(['='.join([f,n]) for n,f,v in fields]) - data = dict([(n,v) for n,f,v in fields]) - return bitstring.pack(fmt, **data).tobytes() + #fmt = ', '.join(['='.join([f,n]) for n,f,v in fields]) + #data = dict([(n,v) for n,f,v in fields]) + #return bitstring.pack(fmt, **data).tobytes() + + return packet + + STANDARD_PORT = 6454 diff --git a/packets/ipprog_packet.py b/packets/ipprog_packet.py index 7b27192939835d02b1efc1b9011d119685abc049..78241d81bfeadbab0384bf316e925ac4a570ef0b 100644 --- a/packets/ipprog_packet.py +++ b/packets/ipprog_packet.py @@ -8,9 +8,93 @@ class IpProgPacket(ArtNetPacket): ('header', 'bytes:8'), ('opcode', 'int:16'), ('protocol_version', 'uintbe:16'), - ('filler1', 'bytes:8'), - ('filler2', 'bytes:8'), - ('command', 'bytes:8'), - ('filler4', 'bytes:8'), + ('filler1', 'int:8'), + ('filler2', 'int:8'), + ('command', 'int:8'), + ('filler4', 'int:8'), + ('progiphi', 'uint:8'), + ('progip2', 'uint:8'), + ('progip1', 'uint:8'), + ('progiplo', 'uint:8'), + ('progsmhi', 'uint:8'), + ('progsm2', 'uint:8'), + ('progsm1', 'uint:8'), + ('progsmlo', 'uint:8'), + ('progporthi', 'int:8'), # Deprecated + ('progportlo', 'int:8'), # Deprecated + # Spare + ('filler4', 'int:8'), # 1 + ('filler4', 'int:8'), # 2 + ('filler4', 'int:8'), # 3 + ('filler4', 'int:8'), # 4 + ('filler4', 'int:8'), # 5 + ('filler4', 'int:8'), # 6 + ('filler4', 'int:8'), # 7 + ('filler4', 'int:8'), # 8 + ) - ) \ No newline at end of file + def __init__(self, p_command=0, p_ip="127.0.0.1", p_netmask="255.255.255.0"): + self.command = p_command + self.ip = p_ip + self.netmask = p_netmask + self.progporthi = 0 + self.progportlo = 0 + + def __setattr__(self, p_name, p_value): + if p_name is "ip": + self.progiphi, self.progip2, self.progip1, self.progiplo = self._split_into_octets(p_value) + if p_name is "netmask": + self.progsmhi, self.progsm2, self.progsm1, self.progsmlo = self._split_into_octets(p_value) + + def _split_into_octets(self, p_ip): + """ + Splits a IP-like string into 4 int representing the octets + """ + type_p_ip = type(p_ip) + if type_p_ip is not str: + raise ValueError("String required, %s given" % type_p_ip + + splitted = p_ip.split(".") + if len(splitted) is not 4: + raise ValueError("Given IP does not consist of 4 octets: %s " % p_ip) + + ip_0 = int(splitted[0]) + ip_1 = int(splitted[1]) + ip_2 = int(splitted[2]) + ip_3 = int(splitted[3]) + + return (ip_0, ip_1, ip_2, ip_3) + +@ArtNetPacket.register +class IpProgReplyPacket(ArtNetPacket): + opcode = OPCODES['OpIpProgReply'] + schema = ( + ('header', 'bytes:8'), + ('opcode', 'int:16'), + ('protocol_version', 'uintbe:16'), + ('filler4', 'int:8'), + ('filler4', 'int:8'), + ('filler4', 'int:8'), + ('filler4', 'int:8'), + ('progiphi', 'uint:8'), + ('progip2', 'uint:8'), + ('progip1', 'uint:8'), + ('progiplo', 'uint:8'), + ('progsmhi', 'uint:8'), + ('progsm2', 'uint:8'), + ('progsm1', 'uint:8'), + ('progsmlo', 'uint:8'), + ('progporthi', 'int:8'), + ('status', 'int:8'), + ('filler4', 'int:8'), + ('filler4', 'int:8'), + ('filler4', 'int:8'), + ('filler4', 'int:8'), + ('filler4', 'int:8'), + ('filler4', 'int:8'), + ('filler4', 'int:8'), + ) + + def __init__(self): + self.progporthi = 0 + self.progportlo = 0 \ No newline at end of file diff --git a/packets/output_packet.py b/packets/output_packet.py index 8502ac92cac412bae240e659c98f276ac5fd1c4c..1cc5837690f633787a4effed37779df4695a7ee4 100644 --- a/packets/output_packet.py +++ b/packets/output_packet.py @@ -21,10 +21,9 @@ class DmxPacket(ArtNetPacket): super(DmxPacket, self).__init__(**kwargs) self.frame = frame - #@classmethod - #def parse_framedata(cls, b, fmt): - #from artnet import dmx - #return dmx.Frame([ord(x) for x in b.read('bytes:512')]) + @classmethod + def parse_framedata(cls, b, fmt): + return [ord(x) for x in b.read('bytes')] def format_length(self): return len(self.frame)