Compare commits

..

No commits in common. 'master' and 'change_neopixel_modul' have entirely different histories.

@ -1,10 +0,0 @@
# Uhr
## Benötigte Software
apt install iputils-arping python3-systemd
Pythonmodule
sudo pip3 install toml gpiozero adafruit-circuitpython-neopixel

@ -1,81 +0,0 @@
#!/usr/bin/python3
"""
Beschreibung:
Hilfskript zum Erstellen einer logging Instanz in Abhängigkeit, ob das Skript manuell gestartet worden ist oder
ob das Skript per Service Unit gestartet wurde
Abhängig dessen wird entweder die Logging Instanz mit einem JournalHandler erstellt (Service Unit)
oder mit einem StreamHandler (manuell)
Author: Hofei
Datum: 03.08.2018
Version: 0.1
"""
import logging
import os
import shlex
import subprocess
from systemd import journal
def __setup_logging(loglevel, frm, startmethode, unitname):
"""
Erstellt die Logger Instanz für das Skript
"""
logger = logging.getLogger()
logger.setLevel(loglevel)
logger.handlers = []
if startmethode == "auto":
log_handler = journal.JournalHandler(SYSLOG_IDENTIFIER=unitname)
else:
log_handler = logging.StreamHandler()
log_handler.setLevel(loglevel)
log_handler.setFormatter(frm)
logger.addHandler(log_handler)
return logger
def __get_service_unit_pid(unitname):
"""Ermittelt ob das ausführende Skript mit einer Service Unit gestartet worden ist, wenn ja so ist das
Ergebnis (pid_service_unit) != 0"""
cmd = "systemctl show -p MainPID {}".format(unitname)
cmd = shlex.split(cmd)
antwort = subprocess.run(cmd, stdout=subprocess.PIPE)
ausgabe = antwort.stdout
# strip entfernt \n, split teilt am = in eine Liste und [1] weißt die Zahl in die Variable zu
pid_service_unit = int(ausgabe.decode().strip().split("=")[1])
return pid_service_unit
def __get_startmethode(unitname):
"""Verglicht die PID vom skript mit der pid Service Unit Prüfung
wenn die Nummern gleich sind wird auf auto gestellt, wenn nicht auf manuell"""
pid_service_unit = __get_service_unit_pid(unitname)
pid_skript = os.getpid()
if pid_service_unit == pid_skript:
startmethode = "auto"
else:
startmethode = "manuell"
return startmethode
def __set_loggerformat(startmethode):
"""Stellt die passende Formattierung ein"""
if startmethode == "auto":
frm = logging.Formatter("%(levelname)s: %(message)s", "%d.%m.%Y %H:%M:%S")
else:
frm = logging.Formatter("%(asctime)s %(levelname)s: %(message)s", "%d.%m.%Y %H:%M:%S")
return frm
def create_logger(unitname, loglevel):
"""Dies ist die aufzurufende Funktion bei der Verwendung des Moduls von außen
Liefert die fertige Logging Instanz zurück"""
startmethode = __get_startmethode(unitname)
frm = __set_loggerformat(startmethode)
return __setup_logging(loglevel, frm, startmethode, unitname)
if __name__ == "__main__":
logger = create_logger("testunit", 10)
logger.debug("Testnachricht")

366
uhr.py

@ -4,146 +4,61 @@ import datetime
import os
import shlex
import subprocess
import sys
import threading
import time
from copy import deepcopy
import gpiozero
import toml
import neopixel
import board
import setup_logging
SKRIPTPFAD = os.path.abspath(os.path.dirname(__file__))
def load_config(pfad=SKRIPTPFAD):
configfile = os.path.join(pfad, "uhr_cfg.toml")
with open(configfile) as conffile:
config = toml.loads(conffile.read())
return config
CONFIG = load_config()
LOGGER = setup_logging.create_logger("uhr", CONFIG["loglevel"])
# LED strip configuration
LED_COUNT = 60 # Number of LED pixels.
LED_PIN = board.D18 # GPIO pin connected to the pixels (must support PWM!).
LED_PIXEL_ORDER = neopixel.GRB # Strip type and colour ordering
LED_COUNT = 60 # Number of LED pixels.
LED_PIN = board.D18 # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_PIXEL_ORDER = neopixel.GRB # Strip type and colour ordering
LED_BRIGHTNESS = 0.2
# Zahl stellt den Wert in Minuten dar, wie lange kein Gerät erreichbar sein darf dass die Uhr "abgeschalten" wird
ABSCHALTWERT = 4
class Uhr:
def __init__(self, pixels, mode):
self.helligkeit = pixels.brightness
self.pixels = pixels
self.helligkeit_geaendert = None
self.mode_geaendert = None
self.mode = mode
self._rgb_leer = None
self._rgb_sekunde = None
self._rgb_minute = None
self._rgb_stunde = None
self.led_gesetzt = 0
self.durchlauf_pause = datetime.timedelta(seconds=0)
self.sleep_time = 0
def mode_wechseln(self):
mode = int(self.mode)
mode_anzahl = len(CONFIG["mode"]) - 1
if mode_anzahl < 0:
mode_anzahl = 0
mode += 1
if mode > mode_anzahl:
mode = 0
self.mode = str(mode)
now = datetime.datetime.now()
self.mode_geaendert = now
alle_led(0, 0, 0, self.pixels)
self.mode_control(now)
LOGGER.info(f"Mode geändert auf: {self.mode} um {self.mode_geaendert}Uhr")
def set_helligkeit(self, helligkeit):
self.helligkeit = helligkeit
self.pixels.brightness = self.helligkeit
self.helligkeit_geaendert = datetime.datetime.now()
LOGGER.info(f"Helligkeit geändert auf: {self.helligkeit} um {self.helligkeit_geaendert}Uhr")
def helligkeit_erhoehen(self):
self.helligkeit += 0.05
if self.helligkeit > 1:
self.helligkeit = 0
self.set_helligkeit(self.helligkeit)
def helligkeit_verringern(self):
self.helligkeit -= 0.05
if self.helligkeit < 0:
self.helligkeit = 1
self.set_helligkeit(self.helligkeit)
def rgb_farben_lesen(self):
config = deepcopy(CONFIG)
self._rgb_leer = config["mode"][self.mode]["leer"]
self._rgb_sekunde = config["mode"][self.mode]["sekunde"]
self._rgb_minute = config["mode"][self.mode]["minute"]
self._rgb_stunde = config["mode"][self.mode]["stunde"]
rgbconf = {"rgb_leer": self._rgb_leer, "rgb_s": self._rgb_sekunde, "rgb_min": self._rgb_minute,
"rgb_std": self._rgb_stunde}
return rgbconf
def mode_control(self, zeit):
rgbconf = self.rgb_farben_lesen()
mode = int(self.mode)
if mode == 0:
stdliste = stunden_led_mapping_variante_0()
stunden_leds, minuten_leds, sekunden_leds, leer_leds, sonstige_leds, rgbdict, \
self.led_gesetzt = stunde_minute_sekunde_einfach_modus(zeit, stdliste, rgbconf, self.led_gesetzt)
self.durchlauf_pause = datetime.timedelta(seconds=1)
self.sleep_time = 0.2
elif mode == 1:
stdliste = stunden_led_mapping_variante_0()
stunden_leds, minuten_leds, sekunden_leds, leer_leds, sonstige_leds, \
rgbdict = stunde_minute_dauerhaft_modus(zeit, stdliste, rgbconf)
self.durchlauf_pause = datetime.timedelta(seconds=1)
self.sleep_time = 0.5
elif mode == 2:
stunden_leds, minuten_leds, sekunden_leds, leer_leds, sonstige_leds, \
rgbdict = uhr_aus_modus(rgbconf)
self.durchlauf_pause = datetime.timedelta(minutes=1)
self.sleep_time = 2
else:
stunden_leds = [0]
minuten_leds = [0]
sekunden_leds = [0]
sonstige_leds = [0]
leer_leds = [0]
rgbdict = self.rgb_farben_lesen()
LOGGER.debug(f"stunden_leds: {stunden_leds}\n"
f"minuten_leds: {minuten_leds}\n"
f"sekunden_leds: {sekunden_leds}\n"
f"leer_leds: {leer_leds}\n"
f"sonstige_leds: {sonstige_leds}\n"
f"rgbdict: {rgbdict}")
led_setzen(stunden_leds, minuten_leds, sekunden_leds, leer_leds, sonstige_leds, rgbdict, self.pixels)
# GPIO
# 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 = gpiozero.Button(3)
I_PLUS_TASTER = gpiozero.Button(4)
I_MINUS_TASTER = gpiozero.Button(17)
I_MINUS_TASTER = gpiozero.Button(14)
def config_schreiben(pfad=SKRIPTPFAD):
configfile = os.path.join(pfad, "uhr_cfg.toml")
with open(configfile, "w") as conffile:
conffile.write(toml.dumps(CONFIG))
LOGGER.info(f"Schreibe Config: {CONFIG}")
# # # # # # # # # #
# 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, pixels):
@ -151,119 +66,54 @@ def alle_led(r, g, b, pixels):
pixels.show()
def stunden_led_mapping_variante_0():
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]
return stdliste
def stunden_index_mapping_ermitteln(zeit):
def led_calc(zeit, stdliste, rgbdict, led_gesetzt, pixels):
if zeit.hour > 11:
index = zeit.hour - 12
else:
index = zeit.hour
return index
def stunde_minute_sekunde_einfach_modus(zeit, stdliste, rgbdict, led_gesetzt):
index = stunden_index_mapping_ermitteln(zeit)
stunden_leds = list(stdliste[index])
minuten_leds = [zeit.minute]
sekunden_leds = [zeit.second]
sonstige_leds = []
hour = stdliste[index]
minute = zeit.minute
second = zeit.second
# Schnittfarben berechnen falls "Zeiger" übereinander liegen
# Stunde mit Minute vergleichen
if bool(set(stunden_leds) & set(minuten_leds)):
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(stunden_leds) & set(sekunden_leds):
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 set(minuten_leds) & set(sekunden_leds):
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, pixels)
return zeit.second, led_gesetzt
# Neue Leere LED berechnen
led_gesetzt_neu = set(stunden_leds) | set(minuten_leds) | set(sekunden_leds)
if isinstance(led_gesetzt, (int, float)):
led_gesetzt = [led_gesetzt]
leer_leds = set(led_gesetzt) - set(led_gesetzt_neu)
return stunden_leds, minuten_leds, sekunden_leds, leer_leds, sonstige_leds, rgbdict, led_gesetzt_neu
def stunde_minute_dauerhaft_modus(zeit, stdliste, rgbdict):
sekunden_leds = []
index = stunden_index_mapping_ermitteln(zeit)
stunden_leds = list(stdliste[index])
minuten_leds = [minute for minute in range(0, zeit.minute + 1)]
if zeit.minute == 0:
leer_leds = list(set(range(0, 60)) - set(stunden_leds) - set(minuten_leds))
else:
leer_leds = []
if max(minuten_leds) < max(stunden_leds):
sonstige_leds = list(set(stunden_leds) & set(minuten_leds))
minuten_leds = list(set(minuten_leds) - set(sonstige_leds))
else:
sonstige_leds = []
minuten_leds = list(set(minuten_leds) - set(stunden_leds))
stunden_leds = list(set(stunden_leds) - set(sonstige_leds))
sonstige_leds = [(led, (0, 0, 255)) for led in sonstige_leds]
return stunden_leds, minuten_leds, sekunden_leds, leer_leds, sonstige_leds, rgbdict
def uhr_aus_modus(rgbdict):
sekunden_leds = []
minuten_leds = []
stunden_leds = []
sonstige_leds = []
leer_leds = [led for led in range(0, 60)]
return stunden_leds, minuten_leds, sekunden_leds, leer_leds, sonstige_leds, rgbdict
def led_setzen(stunden_leds, minuten_leds, sekunden_leds, leer_leds, sonstige_leds, rgbdict, pixels):
def led_setzen(hour, minute, second, rgbdict, led_gesetzt, pixels):
if not isinstance(led_gesetzt, list):
led_gesetzt = [led_gesetzt]
# Stunden setzen
for stunde_led in stunden_leds:
pixels[stunde_led] = rgbdict["rgb_std"][0], rgbdict["rgb_std"][1], rgbdict["rgb_std"][2]
for stunde in hour:
pixels[stunde] = rgbdict["rgb_std"][0], rgbdict["rgb_std"][1], rgbdict["rgb_std"][2]
# Minute setzen
for minute_led in minuten_leds:
pixels[minute_led] = rgbdict["rgb_min"][0], rgbdict["rgb_min"][1], rgbdict["rgb_min"][2]
pixels[minute] = rgbdict["rgb_min"][0], rgbdict["rgb_min"][1], rgbdict["rgb_min"][2]
# Sekunde setzen
for sekunde_led in sekunden_leds:
pixels[sekunde_led] = rgbdict["rgb_s"][0], rgbdict["rgb_s"][1], rgbdict["rgb_s"][2]
pixels[second] = rgbdict["rgb_s"][0], rgbdict["rgb_s"][1], rgbdict["rgb_s"][2]
# Leer setzen
for leer_led in leer_leds:
pixels[leer_led] = rgbdict["rgb_leer"][0], rgbdict["rgb_leer"][1], rgbdict["rgb_leer"][2]
# Neue Leere LED berechnen
led_gesetzt_neu = set(hour) | {minute} | {second}
leerliste = list(set(led_gesetzt) - led_gesetzt_neu)
for leer in leerliste:
pixels[leer] = rgbdict["rgb_leer"][0], rgbdict["rgb_leer"][1], rgbdict["rgb_leer"][2]
# Sonstige LEDs verarbeiten
# Aufbau -> [index_lednummer, (R, G, B)]
for led, rgb in sonstige_leds:
pixels[led] = rgb[0], rgb[1], rgb[2]
pixels.show()
return list(led_gesetzt_neu)
def shutdown():
@ -273,58 +123,46 @@ def shutdown():
# Threads
def check_anwesenheit(uhr, pixels):
def check_anwesenheit(pixels):
"""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_ping(ip):
def ping_wlan(ip):
"""pingt die IP 2x an
return (0 | !0) 0 wenn erreichbar"""
befehl = "ping -c2 -W1 {}".format(ip)
LOGGER.debug(f"Pinge: {befehl}")
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)
LOGGER.debug(f"Pinge: {befehl}")
cmd = shlex.split(befehl)
return subprocess.call(cmd)
def ping_arping(ip, interface):
"""pingt die IP 3x an
return (0 | !0) 0 wenn erreichbar
"""
befehl = "/usr/bin/arping -q -c 3 -w 10 -b -f -I {interface} {ip}".format(interface=interface, ip=ip)
LOGGER.debug(f"Pinge: {befehl}")
cmd = shlex.split(befehl)
return subprocess.call(cmd)
wlanliste = CONFIG["ping"]
interface = CONFIG["interface"]
status_anwesend_liste = []
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 = datetime.timedelta(seconds=301)
last = datetime.datetime.now()
status = {}
while True:
helligkeit = uhr.helligkeit
now = datetime.datetime.now()
# Status der Geräte ermitteln
# 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 == "ping":
status_return = ping_ping(ip)
if key_funkart == "wlan":
status_return = ping_wlan(ip)
elif key_funkart == "bt":
status_return = ping_bt(ip)
elif key_funkart == "arping":
status_return = ping_arping(ip, interface)
else:
status_return = False
if not status_return:
@ -334,15 +172,15 @@ def check_anwesenheit(uhr, pixels):
status[key_status] = False
if status["anwesend"]:
status_anwesend_liste = [] # Geraet von anwesend erreichbar
helligkeit = uhr.helligkeit
helligkeit = LED_BRIGHTNESS
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"])
LOGGER.debug(f"Nichts los daheim die {len(status_anwesend_liste)}.")
if len(status_anwesend_liste) > ABSCHALTWERT:
helligkeit = 0
print("Nichts los daheim die ", len(status_anwesend_liste), ".")
if len(status_anwesend_liste) > ABSCHALTWERT:
helligkeit = 0
if status["dimmen"]:
helligkeit = 0.03
helligkeit = LED_BRIGHTNESS * 0.5
if now.hour < 5 and not status["dimmen"]:
helligkeit = 0
pixels.brightness = helligkeit
@ -352,41 +190,27 @@ def check_anwesenheit(uhr, pixels):
def main():
letzter_durchlauf = datetime.datetime(1970, 1, 1)
pixels = neopixel.NeoPixel(LED_PIN, LED_COUNT, brightness=CONFIG["led_helligkeit"],
lastsecond = None
led_gesetzt = 0
rgbconf = rgb_standard()
pixels = neopixel.NeoPixel(LED_PIN, LED_COUNT, brightness=LED_BRIGHTNESS,
auto_write=False, pixel_order=LED_PIXEL_ORDER)
uhr = Uhr(pixels, CONFIG["mode_nummer"])
thread_check_wlan = threading.Thread(target=check_anwesenheit, args=(uhr, pixels))
thread_check_wlan.start()
rgbconf = uhr.rgb_farben_lesen()
thread_check_wlan = threading.Thread(target=check_anwesenheit, args=(pixels,))
thread_check_wlan.start()
alle_led(rgbconf["rgb_leer"][0], rgbconf["rgb_leer"][1], rgbconf["rgb_leer"][2], pixels)
I_PLUS_TASTER.when_pressed = uhr.helligkeit_erhoehen
I_MINUS_TASTER.when_pressed = uhr.helligkeit_verringern
I_MODE_TASTER.when_pressed = uhr.mode_wechseln
try:
while True:
while True:
try:
rgbconf = rgb_standard()
now = datetime.datetime.now()
if (now - letzter_durchlauf) > uhr.durchlauf_pause:
uhr.mode_control(now)
letzter_durchlauf = now
if uhr.helligkeit_geaendert is not None:
if (datetime.datetime.now() - uhr.helligkeit_geaendert) > datetime.timedelta(seconds=30):
CONFIG["led_helligkeit"] = uhr.helligkeit
config_schreiben()
uhr.helligkeit_geaendert = None
if uhr.mode_geaendert is not None:
if (datetime.datetime.now() - uhr.mode_geaendert) > datetime.timedelta(seconds=30):
CONFIG["mode_nummer"] = uhr.mode
config_schreiben()
uhr.mode_geaendert = None
time.sleep(uhr.sleep_time)
finally:
pixels.brightness = 0
alle_led(0, 0, 0, pixels)
if lastsecond != now.second:
lastsecond, led_gesetzt = led_calc(now, stdliste, rgbconf, led_gesetzt, pixels)
time.sleep(0.2)
except KeyboardInterrupt:
print("KeyboardInterrupt")
pixels.brightness = 0
alle_led(0, 0, 0, pixels)
sys.exit()
if __name__ == "__main__":

@ -1,10 +0,0 @@
# /etc/systemd/system/uhr.service
[Unit]
Description=Uhr starten
[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/pi/uhr/uhr.py
[Install]
WantedBy=multi-user.target

@ -1,43 +0,0 @@
interface = "wlan0"
led_helligkeit = 0.05
mode_nummer = "1"
loglevel = 10 # (10=Debug, 20=Info, 30=Warning, 40=Error, 50=Critical)
[mode]
# RGB Farben Definition in den Listen
# Index 0 = Rot
# Index 1 = Grün
# Index 2 = Blau
# Stunden Minuten und Sekundenzeiger einzeln
[mode.0]
leer = [0, 0, 0]
sekunde = [0, 180, 0]
minute = [32, 178, 170]
stunde = [255, 0, 255]
# Stunden und Minutenzeiger dauerhaft
[mode.1]
leer = [0, 0, 0]
sekunde = []
minute = [0, 255, 0]
stunde = [255, 0, 0]
# Uhr aus
[mode.2]
leer = [0, 0, 0]
sekunde = [0, 0, 0]
minute = [0, 0, 0]
stunde = [0, 0, 0]
[ping]
# Passende IP Adressen eintragen
[ping.anwesend]
ping = []
bt = []
arping = []
[ping.dimmen]
ping = []
bt = []
arping = []
Loading…
Cancel
Save