#!/usr/bin/python3 from datetime import datetime from datetime import timedelta import sys import time import shlex import subprocess import toml import os import threading import gpiozero import signal sys.path.append("/home/pi/rpi_ws281x") from neopixel import * # # # # # # # # # # # LED strip configuration: # # # # # # # # # # LED_COUNT = 60 # Number of LED pixels. LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) LED_DMA = 5 # DMA channel to use for generating signal (try 5) LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) LED_BRIGHTNESS = 4 # Set to 0 for darkest and 255 for brightest LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53 LED_STRIP = ws.WS2811_STRIP_GRB # Strip type and colour ordering standard_helligkeit = LED_BRIGHTNESS # Zahl stellt den Wert in Minuten dar, wie lange kein Gerät erreichbar sein darf dass die Uhr "abgeschalten" wird ABSCHALTWERT = 4 # LED Mapping std0 = [0, 1, 59] std1 = [4, 5, 6] std2 = [9, 10, 11] std3 = [14, 15, 16] std4 = [19, 20, 21] std5 = [24, 25, 26] std6 = [29, 30, 31] std7 = [34, 35, 36] std8 = [39, 40, 41] std9 = [44, 45, 46] std10 = [49, 50, 51] std11 = [54, 55, 56] stdliste = [std0, std1, std2, std3, std4, std5, std6, std7, std8, std9, std10, std11] # # # # # # # # # # # GPIO: # # # # # # # # # # I_MODE_TASTER = 3 I_PLUS_TASTER = 4 I_MINUS_TASTER = 14 # # # # # # # # # # # Funktionen # # # # # # # # # # # Farbkonfiguration def rgb_standard(): rgb_leer = [0, 0, 0] rgb_s = [0, 180, 0] rgb_min = [32, 178, 170] rgb_std = [255, 0, 255] rgbconf = {"rgb_leer": rgb_leer, "rgb_s": rgb_s, "rgb_min": rgb_min, "rgb_std": rgb_std} return rgbconf def alle_led(r, g, b, strip): for pos in range(strip.numPixels()): strip.setPixelColorRGB(pos, r, g, b) strip.show() def led_calc(zeit, stdliste, rgbdict, led_gesetzt, strip): if zeit.hour > 11: index = zeit.hour - 12 else: index = zeit.hour hour = stdliste[index] minute = zeit.minute second = zeit.second # Schnittfarben berechnen falls "Zeiger" übereinander liegen # Stunde mit Minute vergleichen if bool(set(hour) & {minute}): for counter in range(0, 3): rgbdict["rgb_min"][counter] = int((rgbdict["rgb_std"][counter] + rgbdict["rgb_min"][counter]) / 2) # Stunde mit Sekunde vergleichen if set(hour) & {second}: for counter in range(0, 3): rgbdict["rgb_s"][counter] = int((rgbdict["rgb_std"][counter] + rgbdict["rgb_s"][counter]) / 2) # Minute mit Sekunde vergleichen if {minute} & {second}: for counter in range(0, 3): rgbdict["rgb_s"][counter] = int((rgbdict["rgb_min"][counter] + rgbdict["rgb_s"][counter]) / 2) led_gesetzt = led_setzen(hour, minute, second, rgbdict, led_gesetzt, strip) return zeit.second, led_gesetzt def led_setzen(hour, minute, second, rgbdict, led_gesetzt, strip): if not isinstance(led_gesetzt, list): led_gesetzt = [led_gesetzt] # Stunden setzen for stunde in hour: strip.setPixelColorRGB(stunde, rgbdict["rgb_std"][0], rgbdict["rgb_std"][1], rgbdict["rgb_std"][2]) # print("Stunden setzen") # print(stunde, rgbdict["rgb_std"][0], rgbdict["rgb_std"][1], rgbdict["rgb_std"][2]) # Minute setzen strip.setPixelColorRGB(minute, rgbdict["rgb_min"][0], rgbdict["rgb_min"][1], rgbdict["rgb_min"][2]) # print("Minute setzen") # print(minute, rgbdict["rgb_min"][0], rgbdict["rgb_min"][1], rgbdict["rgb_min"][2]) # Sekunde setzen strip.setPixelColorRGB(second, rgbdict["rgb_s"][0], rgbdict["rgb_s"][1], rgbdict["rgb_s"][2]) # print("Sekunde setzen") # print(second, rgbdict["rgb_s"][0], rgbdict["rgb_s"][1], rgbdict["rgb_s"][2]) # Neue Leere LED berechnen led_gesetzt_neu = set(hour) | {minute} | {second} leerliste = list(set(led_gesetzt) - led_gesetzt_neu) for leer in leerliste: strip.setPixelColorRGB(leer, rgbdict["rgb_leer"][0], rgbdict["rgb_leer"][1], rgbdict["rgb_leer"][2]), # print("Leer setzen") # print(leer, rgbdict["rgb_leer"][0], rgbdict["rgb_leer"][1], rgbdict["rgb_leer"][2]) strip.show() return list(led_gesetzt_neu) def taster_callback(button): start = datetime.now() ende = datetime.now() while button.is_pressed: ende = datetime.now() dauer = ende - start dauer = dauer + timedelta(seconds=0.3) pin_num = check_taster(button) if pin_num == I_MODE_TASTER: handler_mode_taster(dauer) def check_taster(button): pin_num = "" for i in str(button.pin): if i.isdigit(): pin_num = pin_num + str(i) pin_num = int(pin_num) return pin_num def handler_mode_taster(dauer): if dauer > timedelta(seconds=3): shutdown() def shutdown(): cmd = "sudo shutdown now" cmd = shlex.split(cmd) subprocess.call(cmd) # # # # # # # # # # # Threads # # # # # # # # # # def check_anwesenheit(strip): """Funktion, welche als eigener Thread laeuft, um selbststaendig in einem gewissenen Intervall alle Geraete in der Toml Liste zu pingen arg: Objekt des neopixel LED Ringes toml File: status "anwesend", ist kein Geraet von "anwesend" oder "dimmen" erreichbar, LED Helligkeit auf 0 sobald eine Adresse von status "dimmen" erreichbar ist, wird die Helligkeit verringert""" def ping_wlan(ip): """pingt die IP 2x an return (0 | !0) 0 wenn erreichbar""" befehl = "ping -c2 -W1 {}".format(ip) cmd = shlex.split(befehl) return subprocess.call(cmd) def ping_bt(bt): """pingt die IP 2x an return (0 | !0) 0 wenn erreichbar""" befehl = "sudo /usr/bin/l2ping -c1 -t1 {}".format(bt) cmd = shlex.split(befehl) return subprocess.call(cmd) # Tomlfile mit den IP Adressen einlesen pfad = os.path.abspath(os.path.dirname(__file__)) configfile = os.path.join(pfad, "bt_wlan.toml") with open(configfile) as conffile: wlanliste = toml.loads(conffile.read()) status_anwesend_liste = [] delta = timedelta(seconds=301) last = datetime.now() status = {} global standard_helligkeit while True: now = datetime.now() # Status der IP Adressen ermitteln if delta.seconds > 300: for key_status in wlanliste.keys(): for key_funkart in wlanliste[key_status].keys(): for ip in wlanliste[key_status][key_funkart]: if key_funkart == "wlan": status_return = ping_wlan(ip) elif key_funkart == "bt": status_return = ping_bt(ip) else: status_return = False if not status_return: status[key_status] = True break else: status[key_status] = False if status["anwesend"]: status_anwesend_liste = [] # Geraet von anwesend erreichbar helligkeit = standard_helligkeit elif not status["anwesend"] and not status["dimmen"]: # Wenn kein Geraet erreichbar ist if len(status_anwesend_liste) < ABSCHALTWERT + 1: status_anwesend_liste.append(status["anwesend"]) print("Nichts los daheim die ", len(status_anwesend_liste), ".") if len(status_anwesend_liste) > ABSCHALTWERT: helligkeit = 0 if status["dimmen"]: helligkeit = standard_helligkeit * 0.5 if now.hour < 5 and not status["dimmen"]: helligkeit = 0 strip.setBrightness(int(helligkeit)) last = datetime.now() delta = now - last time.sleep(30) def main(): mode_taster = gpiozero.Button(I_MODE_TASTER, hold_time=0.3) mode_taster.when_pressed = taster_callback lastsecond = None led_gesetzt = 0 rgbconf = rgb_standard() strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP) strip.begin() strip.setBrightness(255) thread_check_wlan = threading.Thread(target=check_anwesenheit, args=(strip,)) thread_check_wlan.start() alle_led(rgbconf["rgb_leer"][0], rgbconf["rgb_leer"][1], rgbconf["rgb_leer"][2], strip) while True: try: rgbconf = rgb_standard() now = datetime.now() if lastsecond != now.second: lastsecond, led_gesetzt = led_calc(now, stdliste, rgbconf, led_gesetzt, strip) time.sleep(0.2) except KeyboardInterrupt: print("KeyboardInterrupt") strip.setBrightness(0) alle_led(0, 0, 0, strip) sys.exit() if __name__ == "__main__": main()