You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
uhr/uhr.py

265 lines
8.9 KiB
Python

#!/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()