commit cf82fddbcbaab13602b4f9798f39937218e6dd2b Author: Hofei Date: Fri Dec 27 13:46:04 2019 +0100 Initial Commit diff --git a/uhr.py b/uhr.py new file mode 100644 index 0000000..d77c080 --- /dev/null +++ b/uhr.py @@ -0,0 +1,264 @@ +#!/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()