Cleaned up some code

This commit is contained in:
Shy 2017-03-15 00:05:45 +01:00
parent a2692c8f14
commit 739f90a019

143
c4ctrl.py
View file

@ -106,7 +106,7 @@ class C4Interface():
class Dmx: class Dmx:
"""Abstraction of the 3 Channel LED Cans in the Club.""" """Abstraction of the 3 channel LED cans in the club."""
template = "000000" template = "000000"
@ -118,8 +118,9 @@ class Dmx:
return "<Dmx '{}: {}'>".format(self.topic, self.color) return "<Dmx '{}: {}'>".format(self.topic, self.color)
def _pad_color(self, color): def _pad_color(self, color):
"""Merge hex color value into hex template.""" """Merge hex color value into hex template.
# Expand shorthand hex codes (eg. #f0f) and pad with template
Expand shorthand hex codes (eg. #f0f) and pad with template."""
if len(color) > len(self.template): # Truncate if len(color) > len(self.template): # Truncate
print("Warning: truncating color value {} to {}".format( print("Warning: truncating color value {} to {}".format(
color, color[:len(self.template)])) color, color[:len(self.template)]))
@ -133,11 +134,11 @@ class Dmx:
expanded += c*2 expanded += c*2
color = expanded color = expanded
if len(color) == len(self.template): # Nothing to do if len(color) == len(self.template): # Nothing more to do
return color return color
# Add padding # Add padding
color = color + self.template[-(len(self.template) - len(color)):] color = color + self.template[len(color):]
return color return color
def set_color(self, color): def set_color(self, color):
@ -151,29 +152,30 @@ class Dmx:
class Dmx4(Dmx): class Dmx4(Dmx):
"""Abstraction of the 4 Channel LED Cans in the Club.""" """Abstraction of the 4 channel LED cans in the club."""
template = "000000ff" template = "000000ff"
def __repr__(self): def __repr__(self):
return "<Dmx4 '{}: {}'>".format(self.topic, self.color) return "<Dmx4 '{}: {}'>".format(self.topic, self.color)
class Dmx7(Dmx): class Dmx7(Dmx):
"""Abstraction of the 7 Channel LED Cans in the Club.""" """Abstraction of the 7 channel LED cans in the club."""
template = "000000000000ff" template = "000000000000ff"
def __repr__(self): def __repr__(self):
return "<Dmx7 '{}: {}'>".format(self.topic, self.color) return "<Dmx7 '{}: {}'>".format(self.topic, self.color)
class C4Room: class C4Room:
"""Base class for Club rooms.""" """Base class for club rooms."""
def interactive_switchctrl(self, userinput="NULL"): def __init__(self):
"""Switch lamps in this rooms on and off.""" self.c4 = C4Interface()
c4 = C4Interface()
if userinput == "NULL": def _interactive_light_switch(self):
# Interactively ask for input # Interactively ask for input
print("[{}]".format(self.name)) print("[{}]".format(self.name))
print("Please enter 0 or 1 for every lamp:") print("Please enter 0 or 1 for every lamp:")
@ -185,7 +187,7 @@ class C4Room:
req = [] req = []
for t in self.switches: for t in self.switches:
req.append(t[1]) req.append(t[1])
responce = c4.fetch(req) responce = self.c4.fetch(req)
for sw in self.switches: for sw in self.switches:
for r in responce: for r in responce:
if r.topic == sw[1]: if r.topic == sw[1]:
@ -197,7 +199,14 @@ class C4Room:
userinput = sys.stdin.readline().rstrip('\n') userinput = sys.stdin.readline().rstrip('\n')
except KeyboardInterrupt: except KeyboardInterrupt:
print("\rInterrupted by user.") print("\rInterrupted by user.")
return False return ""
return userinput
def light_switch(self, userinput=""):
"""Switch lamps in this rooms on and off."""
if not userinput:
userinput = self._interactive_light_switch()
if len(userinput) != len(self.switches): if len(userinput) != len(self.switches):
print("Error: wrong number of digits (expected {}, got {})!".format( print("Error: wrong number of digits (expected {}, got {})!".format(
@ -213,7 +222,8 @@ class C4Room:
"topic" : self.switches[si][1], "topic" : self.switches[si][1],
"payload" : bytearray([int(userinput[si])]) "payload" : bytearray([int(userinput[si])])
}) })
return c4.update(cmd)
return self.c4.update(cmd)
def set_colorscheme(self, colorscheme): def set_colorscheme(self, colorscheme):
"""Apply colorscheme to the LED Cans in this room.""" """Apply colorscheme to the LED Cans in this room."""
@ -226,8 +236,7 @@ class C4Room:
"payload" : light.payload "payload" : light.payload
}) })
c4 = C4Interface() return self.c4.update(cmd)
return c4.update(cmd)
class Wohnzimmer(C4Room): class Wohnzimmer(C4Room):
@ -312,6 +321,7 @@ class Keller(C4Room):
class Kitchenlight: class Kitchenlight:
"""The Kitchenlight.""" """The Kitchenlight."""
_END = "little" # Endianess
_available_modes = """ _available_modes = """
off turn off off turn off
checker[,DELAY[,COLOR_1[,COLOR_2]]] checker[,DELAY[,COLOR_1[,COLOR_2]]]
@ -377,13 +387,13 @@ class Kitchenlight:
return self.flood() return self.flood()
if mode == "clock": if mode == "clock":
return self.clock() return self.clock()
print('Error: unknown mode "' + mode + '"!') print("Error: unknown Kitchenlight mode {}!".format(mode))
return False return False
def empty(self): def empty(self):
"""Set to mode "empty" and turn off Kitchenlight.""" """Set to mode "empty" and turn off Kitchenlight."""
# Screen 0 # Screen 0
d = int(0).to_bytes(4, "little") d = int(0).to_bytes(4, self._END)
self._switch(d, poweroff=True) self._switch(d, poweroff=True)
def checker(self, delay=500, colA="0000ff", colB="00ff00"): def checker(self, delay=500, colA="0000ff", colB="00ff00"):
@ -394,17 +404,17 @@ class Kitchenlight:
d = bytearray(20) d = bytearray(20)
v = memoryview(d) v = memoryview(d)
# Screen 1 # Screen 1
v[0:4] = int(1).to_bytes(4, "little") v[0:4] = int(1).to_bytes(4, self._END)
# Delay # Delay
v[4:8] = int(delay).to_bytes(4, "little") v[4:8] = int(delay).to_bytes(4, self._END)
# ColorA R/G/B # ColorA R/G/B
v[8:10] = int(ca.color[0:2], base=16).to_bytes(2, "little") v[8:10] = int(ca.color[0:2], base=16).to_bytes(2, self._END)
v[10:12] = int(ca.color[2:4], base=16).to_bytes(2, "little") v[10:12] = int(ca.color[2:4], base=16).to_bytes(2, self._END)
v[12:14] = int(ca.color[4:6], base=16).to_bytes(2, "little") v[12:14] = int(ca.color[4:6], base=16).to_bytes(2, self._END)
# ColorB R/G/B # ColorB R/G/B
v[14:16] = int(cb.color[0:2], base=16).to_bytes(2, "little") v[14:16] = int(cb.color[0:2], base=16).to_bytes(2, self._END)
v[16:18] = int(cb.color[2:4], base=16).to_bytes(2, "little") v[16:18] = int(cb.color[2:4], base=16).to_bytes(2, self._END)
v[18:20] = int(cb.color[4:6], base=16).to_bytes(2, "little") v[18:20] = int(cb.color[4:6], base=16).to_bytes(2, self._END)
self._switch(d) self._switch(d)
def matrix(self, lines=8): def matrix(self, lines=8):
@ -413,8 +423,8 @@ class Kitchenlight:
d = bytearray(8) d = bytearray(8)
v = memoryview(d) v = memoryview(d)
# Screen 2 # Screen 2
v[0:4] = int(2).to_bytes(4, "little") v[0:4] = int(2).to_bytes(4, self._END)
v[4:8] = int(lines).to_bytes(4, "little") v[4:8] = int(lines).to_bytes(4, self._END)
self._switch(d) self._switch(d)
def moodlight(self, mode=1): def moodlight(self, mode=1):
@ -423,30 +433,30 @@ class Kitchenlight:
d = bytearray(19) d = bytearray(19)
v = memoryview(d) v = memoryview(d)
# Screen 3 # Screen 3
v[0:4] = int(3).to_bytes(4, "little") v[0:4] = int(3).to_bytes(4, self._END)
# Mode # Mode
v[4:5] = int(mode).to_bytes(1, "little") v[4:5] = int(mode).to_bytes(1, self._END)
# Step # Step
v[5:9] = int(1).to_bytes(4, "little") v[5:9] = int(1).to_bytes(4, self._END)
# Fade delay # Fade delay
v[9:13] = int(10).to_bytes(4, "little") v[9:13] = int(10).to_bytes(4, self._END)
# Pause # Pause
v[13:17] = int(10000).to_bytes(4, "little") v[13:17] = int(10000).to_bytes(4, self._END)
# Hue step # Hue step
v[17:19] = int(30).to_bytes(2, "little") v[17:19] = int(30).to_bytes(2, self._END)
else: # Mode "Random" else: # Mode "Random"
d = bytearray(17) d = bytearray(17)
v = memoryview(d) v = memoryview(d)
# Screen 3 # Screen 3
v[0:4] = int(3).to_bytes(4, "little") v[0:4] = int(3).to_bytes(4, self._END)
# Mode # Mode
v[4:5] = int(mode).to_bytes(1, "little") v[4:5] = int(mode).to_bytes(1, self._END)
# Step # Step
v[5:9] = int(1).to_bytes(4, "little") v[5:9] = int(1).to_bytes(4, self._END)
# Fade delay # Fade delay
v[9:13] = int(10).to_bytes(4, "little") v[9:13] = int(10).to_bytes(4, self._END)
# Pause # Pause
v[13:17] = int(10000).to_bytes(4, "little") v[13:17] = int(10000).to_bytes(4, self._END)
self._switch(d) self._switch(d)
def openchaos(self, delay=1000): def openchaos(self, delay=1000):
@ -454,20 +464,20 @@ class Kitchenlight:
d = bytearray(8) d = bytearray(8)
v = memoryview(d) v = memoryview(d)
# Screen 4 # Screen 4
v[0:4] = int(4).to_bytes(4, "little") v[0:4] = int(4).to_bytes(4, self._END)
v[4:8] = int(delay).to_bytes(4, "little") v[4:8] = int(delay).to_bytes(4, self._END)
self._switch(d) self._switch(d)
def pacman(self): def pacman(self):
"""Set to mode "pacman".""" """Set to mode "pacman"."""
# Screen 5 # Screen 5
d = int(5).to_bytes(4, "little") d = int(5).to_bytes(4, self._END)
self._switch(d) self._switch(d)
def sine(self): def sine(self):
"""Set to mode "sine".""" """Set to mode "sine"."""
# Screen 6 # Screen 6
d = int(6).to_bytes(4, "little") d = int(6).to_bytes(4, self._END)
self._switch(d) self._switch(d)
# Screen 7 is Strobo, which is disabled because it seems to do harm to # Screen 7 is Strobo, which is disabled because it seems to do harm to
@ -482,8 +492,8 @@ class Kitchenlight:
d = bytearray(8 + len(text) + 1) d = bytearray(8 + len(text) + 1)
v = memoryview(d) v = memoryview(d)
# Screen 8 # Screen 8
v[0:4] = int(8).to_bytes(4, "little") v[0:4] = int(8).to_bytes(4, self._END)
v[4:8] = int(delay).to_bytes(4, "little") v[4:8] = int(delay).to_bytes(4, self._END)
v[8:8 + len(text)] = text v[8:8 + len(text)] = text
v[len(d) - 1:len(d)] = bytes(1) v[len(d) - 1:len(d)] = bytes(1)
self._switch(d) self._switch(d)
@ -491,20 +501,20 @@ class Kitchenlight:
def flood(self): def flood(self):
"""Set to mode "flood".""" """Set to mode "flood"."""
# Screen 9 # Screen 9
d = int(9).to_bytes(4, "little") d = int(9).to_bytes(4, self._END)
self._switch(d) self._switch(d)
def clock(self): def clock(self):
"""Set to mode "clock".""" """Set to mode "clock"."""
# Screen 11 # Screen 11
d = int(11).to_bytes(4, "little") d = int(11).to_bytes(4, self._END)
self._switch(d) self._switch(d)
class ColorScheme: class ColorScheme:
"""Abstraction of a colorscheme.""" """Abstraction of a colorscheme."""
# Virtual presets # Names of virtual presets
_virtual_presets = ["off", "random"] _virtual_presets = ["off", "random"]
def __init__(self, autoinit=""): def __init__(self, autoinit=""):
@ -515,16 +525,15 @@ class ColorScheme:
if autoinit: if autoinit:
# Load or generate preset # Load or generate preset
if autoinit[0] == '#': if autoinit[0] == '#':
if '/' in autoinit:
return self.from_color(autoinit.split('/'))
else:
return self.from_color(autoinit) return self.from_color(autoinit)
elif self._expand_preset(autoinit) == "off": elif self._expand_preset(autoinit) == "off":
# Special case. Sets masters to #000000 # Virtual preset: set masters to #000000
return self.from_color("000000") return self.from_color("000000")
elif self._expand_preset(autoinit) == "random": elif self._expand_preset(autoinit) == "random":
# Virtual preset: return random color on every query
return self.from_random() return self.from_random()
else: else:
# Load preset file
return self.from_file(autoinit) return self.from_file(autoinit)
def __bool__(self): def __bool__(self):
@ -605,7 +614,7 @@ class ColorScheme:
return None return None
else: else:
return self._random_color() return self._random_color()
else: # Fallback
return None return None
def from_file(self, preset): def from_file(self, preset):
@ -946,16 +955,16 @@ if __name__ == "__main__":
group_sw = parser.add_argument_group(title="light switch control", group_sw = parser.add_argument_group(title="light switch control",
description="The optional DIGIT_CODE is a string of 0s or 1s for every light in the room. Works interactivly if missing.") description="The optional DIGIT_CODE is a string of 0s or 1s for every light in the room. Works interactivly if missing.")
group_sw.add_argument( group_sw.add_argument(
"-W", nargs='?', dest="w_switch", const="NULL", metavar="DIGIT_CODE", "-W", nargs='?', dest="w_switch", const="", metavar="DIGIT_CODE",
help="switch lights in Wohnzimmer on/off") help="switch lights in Wohnzimmer on/off")
group_sw.add_argument( group_sw.add_argument(
"-P", nargs='?', dest="p_switch", const="NULL", metavar="DIGIT_CODE", "-P", nargs='?', dest="p_switch", const="", metavar="DIGIT_CODE",
help="switch lights in Plenarsaal on/off") help="switch lights in Plenarsaal on/off")
group_sw.add_argument( group_sw.add_argument(
"-F", nargs='?', dest="f_switch", const="NULL", metavar="DIGIT_CODE", "-F", nargs='?', dest="f_switch", const="", metavar="DIGIT_CODE",
help="switch lights in Fnordcentter on/off") help="switch lights in Fnordcentter on/off")
group_sw.add_argument( group_sw.add_argument(
"-K", nargs='?', dest="k_switch", const="NULL", metavar="DIGIT_CODE", "-K", nargs='?', dest="k_switch", const="", metavar="DIGIT_CODE",
help="switch lights in Keller on/off") help="switch lights in Keller on/off")
args = parser.parse_args() args = parser.parse_args()
@ -1003,8 +1012,6 @@ if __name__ == "__main__":
if args.list_remote: if args.list_remote:
RemotePresets().list_available(args.list_remote.lower()) RemotePresets().list_available(args.list_remote.lower())
if args.remote_preset: if args.remote_preset:
# Lets try to preserve spaces
#remote_opts = ' '.join(args.remote_preset).split(':')
remote_opts = args.remote_preset.split(':') remote_opts = args.remote_preset.split(':')
if len(remote_opts) == 1: if len(remote_opts) == 1:
RemotePresets().apply_preset(remote_opts[0].strip()) RemotePresets().apply_preset(remote_opts[0].strip())
@ -1013,14 +1020,14 @@ if __name__ == "__main__":
remote_opts[1].lower().split(',')) remote_opts[1].lower().split(','))
# Light switches # Light switches
if args.w_switch: if args.w_switch != None:
Wohnzimmer().interactive_switchctrl(args.w_switch) Wohnzimmer().light_switch(args.w_switch)
if args.p_switch: if args.p_switch != None:
Plenarsaal().interactive_switchctrl(args.p_switch) Plenarsaal().light_switch(args.p_switch)
if args.f_switch: if args.f_switch != None:
Fnordcenter().interactive_switchctrl(args.f_switch) Fnordcenter().light_switch(args.f_switch)
if args.k_switch: if args.k_switch != None:
Keller().interactive_switchctrl(args.k_switch) Keller().light_switch(args.k_switch)
# No command line options or only debug? # No command line options or only debug?
if len(sys.argv) <= 1 or len(sys.argv) == 2 and args.debug: if len(sys.argv) <= 1 or len(sys.argv) == 2 and args.debug: