|
|
|
@ -15,7 +15,7 @@ import pytz
|
|
|
|
|
LED_COUNT = 48
|
|
|
|
|
LED_PIN = 18
|
|
|
|
|
LED_FREQ_HZ = 800000
|
|
|
|
|
LED_DMA = 5
|
|
|
|
|
LED_DMA = 10
|
|
|
|
|
LED_BRIGHTNESS = 255
|
|
|
|
|
LED_INVERT = False
|
|
|
|
|
|
|
|
|
@ -25,14 +25,19 @@ class Lightrix:
|
|
|
|
|
self.client = MatrixClient(config['homeserver_uri'])
|
|
|
|
|
self.token = self.client.login_with_password(username=config['username'],
|
|
|
|
|
password=config['password'])
|
|
|
|
|
self.rooms = {}
|
|
|
|
|
self.room_ids = []
|
|
|
|
|
self.join_room(room)
|
|
|
|
|
self.strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS)
|
|
|
|
|
self.strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ,
|
|
|
|
|
LED_DMA, LED_INVERT, LED_BRIGHTNESS)
|
|
|
|
|
self.strip.begin()
|
|
|
|
|
self.init_patterns()
|
|
|
|
|
self.rooms[room].send_text("Setting color to timebase.")
|
|
|
|
|
self.set_pattern(self.patterns['timebase'])
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def init_patterns():
|
|
|
|
|
def init_patterns(self):
|
|
|
|
|
def wheel(pos):
|
|
|
|
|
"""Generate rainbow colors across 0-255 positions."""
|
|
|
|
|
if pos < 85:
|
|
|
|
@ -44,7 +49,7 @@ class Lightrix:
|
|
|
|
|
pos -= 170
|
|
|
|
|
return Color(0, pos * 3, 255 - pos * 3)
|
|
|
|
|
|
|
|
|
|
def rainbowCycle(idx, wait_ms=20, iterations=5):
|
|
|
|
|
def rainbowCycle(idx, msg, wait_ms=20, iterations=5):
|
|
|
|
|
"""Draw rainbow that uniformly distributes itself across all pixels."""
|
|
|
|
|
for j in range(256*iterations):
|
|
|
|
|
for i in range(self.strip.numPixels()):
|
|
|
|
@ -53,8 +58,8 @@ class Lightrix:
|
|
|
|
|
time.sleep(wait_ms/1000.0)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
def timebased(idx):
|
|
|
|
|
time = datetime.datetime.now().astimezone(pytz.timezone('US/Pacific'))
|
|
|
|
|
def timebased(idx, msg):
|
|
|
|
|
time = datetime.datetime.now(tz=pytz.timezone('US/Pacific'))
|
|
|
|
|
m = time.minute
|
|
|
|
|
if time.hour < 7 and time.hour > 0: # low red at night
|
|
|
|
|
return Color(64, 0, 0)
|
|
|
|
@ -66,69 +71,100 @@ class Lightrix:
|
|
|
|
|
return Color(202 + m, 128 + m, 64 + m)
|
|
|
|
|
if time.hour > 9 and time.hour < 18: # off during the day
|
|
|
|
|
return Color(0, 0, 0)
|
|
|
|
|
if time.hour > 18 and time.hour < 22: # medium yellow-white in the evening
|
|
|
|
|
return Color(128, 128, 64)
|
|
|
|
|
if time.hour >= 18 and time.hour < 22: # medium yellow-white in the evening
|
|
|
|
|
return Color(255, 255, 128)
|
|
|
|
|
if time.hour == 22: # slowly fade to low red over the hour
|
|
|
|
|
return Color(128 + 60 - m, 128 + 60 - m, 0)
|
|
|
|
|
return Color(255 - m*2, 255 - m*2, 128 - m)
|
|
|
|
|
if time.hour == 23: # slowly fade to low red over the hour
|
|
|
|
|
return Color(64 + 60 - m, 64 + 60 - (m * 2), 0)
|
|
|
|
|
if time.hour == 24: # low red at night
|
|
|
|
|
return Color(64, 0, 0)
|
|
|
|
|
|
|
|
|
|
def wheelStrip(idx, msg):
|
|
|
|
|
val = int(msg.split(' ')[1])
|
|
|
|
|
return wheel(val)
|
|
|
|
|
|
|
|
|
|
np = self.strip.numPixels()
|
|
|
|
|
self.patterns = {}
|
|
|
|
|
self.patterns['red'] = [Color(255, 0, 0) for i in range(0, np)]
|
|
|
|
|
self.patterns['green'] = [Color(0, 255, 0) for i in range(0, np)]
|
|
|
|
|
self.patterns['blue'] = [Color(0, 0, 255) for i in range(0, np)]
|
|
|
|
|
self.patterns['yellow'] = [Color(255, 255, 0) for i in range(0, np)]
|
|
|
|
|
self.patterns['white'] = [Color(255, 255, 255) for i in range(0, np)]
|
|
|
|
|
self.patterns['off'] = [Color(0,0,0) for i in range(0, np)]
|
|
|
|
|
self.patterns['purple'] = [Color(255,0,255) for i in range(0, np)]
|
|
|
|
|
self.patterns['cyan'] = [Color(0,255,255) for i in range(0, np)]
|
|
|
|
|
self.patterns['rainbow'] = [wheel(255 * i / np) for i in range(0, np)]
|
|
|
|
|
self.patterns['cycle'] = rainbowCycle
|
|
|
|
|
self.patterns['timebase'] = timebased
|
|
|
|
|
self.patterns[u'red'] = [Color(255, 0, 0) for i in range(0, np)]
|
|
|
|
|
self.patterns[u'green'] = [Color(0, 255, 0) for i in range(0, np)]
|
|
|
|
|
self.patterns[u'blue'] = [Color(0, 0, 255) for i in range(0, np)]
|
|
|
|
|
self.patterns[u'yellow'] = [Color(255, 255, 0) for i in range(0, np)]
|
|
|
|
|
self.patterns[u'white'] = [Color(255, 255, 255) for i in range(0, np)]
|
|
|
|
|
self.patterns[u'off'] = [Color(0,0,0) for i in range(0, np)]
|
|
|
|
|
self.patterns[u'purple'] = [Color(255,0,255) for i in range(0, np)]
|
|
|
|
|
self.patterns[u'cyan'] = [Color(0,255,255) for i in range(0, np)]
|
|
|
|
|
self.patterns[u'rainbow'] = [wheel(int(255 * i / np)) for i in range(0, np)]
|
|
|
|
|
self.patterns[u'cycle'] = rainbowCycle
|
|
|
|
|
self.patterns[u'timebase'] = timebased
|
|
|
|
|
self.patterns[u'wheel'] = wheelStrip
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def join_room(self, room_id):
|
|
|
|
|
room = self.client.join_room(room_id)
|
|
|
|
|
self.rooms[room_id] = room
|
|
|
|
|
self.room_ids.append = room_id
|
|
|
|
|
self.room_ids.append(room_id)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_brightness(self, brightness):
|
|
|
|
|
if brightness > 255:
|
|
|
|
|
return
|
|
|
|
|
if brightness < 0:
|
|
|
|
|
return
|
|
|
|
|
self.strip.setBrightness(brightness)
|
|
|
|
|
self.strip.show()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def listen_and_glow(self):
|
|
|
|
|
self.idle_since = datetime.datetime.now()
|
|
|
|
|
def glow_from_message_maybe(chunk):
|
|
|
|
|
def maybe_idle():
|
|
|
|
|
tdel = datetime.datetime.now() - self.idle_since
|
|
|
|
|
if tdel.seconds > 5 * 60: # idle for five minutes
|
|
|
|
|
self.set_pattern(self.patterns['timebase'])
|
|
|
|
|
if chunk[u'type'] != u'm.message':
|
|
|
|
|
maybe_idle()
|
|
|
|
|
return
|
|
|
|
|
if not chunk[u'room_id'] in self.room_ids:
|
|
|
|
|
maybe_idle()
|
|
|
|
|
return
|
|
|
|
|
if not chunk[u'content'][u'body'] in self.patterns:
|
|
|
|
|
maybe_idle()
|
|
|
|
|
return
|
|
|
|
|
self.set_pattern(self.patterns[chunk[u'content'][u'body']])
|
|
|
|
|
try:
|
|
|
|
|
def maybe_idle():
|
|
|
|
|
tdel = datetime.datetime.now() - self.idle_since
|
|
|
|
|
if tdel.seconds > 5 * 60: # idle for five minutes
|
|
|
|
|
self.set_pattern(self.patterns['timebase'])
|
|
|
|
|
if chunk[u'type'] != u'm.room.message':
|
|
|
|
|
maybe_idle()
|
|
|
|
|
return
|
|
|
|
|
if not chunk[u'room_id'] in self.room_ids:
|
|
|
|
|
maybe_idle()
|
|
|
|
|
return
|
|
|
|
|
text = chunk[u'content'][u'body']
|
|
|
|
|
room = self.rooms[chunk[u'room_id']]
|
|
|
|
|
if text.startswith("!brightness"):
|
|
|
|
|
brightness = int(text.split(' ')[1])
|
|
|
|
|
room.send_text("Setting brightness to %s/255" % brightness)
|
|
|
|
|
self.set_brightness(int(text.split(' ')[1]))
|
|
|
|
|
return
|
|
|
|
|
if text.startswith("!wheel"):
|
|
|
|
|
self.set_pattern(self.patterns[u'wheel'], text)
|
|
|
|
|
return
|
|
|
|
|
if not text in self.patterns:
|
|
|
|
|
maybe_idle()
|
|
|
|
|
return
|
|
|
|
|
room.send_text("Setting color to %s" % text)
|
|
|
|
|
self.set_pattern(self.patterns[text])
|
|
|
|
|
except:
|
|
|
|
|
self.rooms[self.room_ids[0]].send_text("Error setting settings, try something else?")
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
self.client.add_listener(glow_from_message_maybe)
|
|
|
|
|
self.client.listen_forever()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_pattern(self, pattern):
|
|
|
|
|
def set_pattern(self, pattern, msg=None):
|
|
|
|
|
# XXX: Retcon this in to a single thing.
|
|
|
|
|
if type(pattern) == list:
|
|
|
|
|
for led_idx in range(0, self.strip.numPixels):
|
|
|
|
|
for led_idx in range(0, self.strip.numPixels()):
|
|
|
|
|
self.strip.setPixelColor(led_idx, pattern[led_idx])
|
|
|
|
|
elif type(pattern) == function:
|
|
|
|
|
for led_idx in range(0, self.strip.numPixels):
|
|
|
|
|
self.strip.setPixelColor(led_idx, pattern(led_idx))
|
|
|
|
|
else:
|
|
|
|
|
for led_idx in range(0, self.strip.numPixels()):
|
|
|
|
|
color = pattern(led_idx, msg)
|
|
|
|
|
self.strip.setPixelColor(led_idx, color)
|
|
|
|
|
self.strip.show()
|
|
|
|
|
self.idle_since = datetime.datetime.now()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|