Wenn dies dein erster Besuch hier ist, lies bitte zuerst die Hilfe - Häufig gestellte Fragen durch. Du musst dich vermutlich registrieren, bevor du Beiträge verfassen kannst. Klicke oben auf 'Registrieren', um den Registrierungsprozess zu starten. Du kannst auch jetzt schon Beiträge lesen. Suche dir einfach das Forum aus, das dich am meisten interessiert.
Das Paket ist schon unterwegs, also nächste Woche kann ich berichten.
Hallo Rudi,
kannst Du schon berichten?
Ich habe vor die Woche das babtec duo SR auch bei Voltus zu bestellen.
Die eldoleds habe ich schon.
Hab mit den DMX Gateway noch gezögert da ich mich nicht zwischen babtec und arcus entscheiden konnte.
Gruß Michael
Meine Installation: VM Debian Buster SH NG 1.8.1, SmartVISU 3.0, KNX, DMX, 1-wire, Fortigate 30E IPS, VMware vSphere 6.7
Leider nicht. Morgen sollte es da sein. Das Arcus habe ich schon mal verbaut. Ist nicht schlecht aber es gibt nur 4 Sequenzen und das ist mir zu wenig.
Ich hab als Visu auch die Smartvisu auf nen sh.py in einer Debian VM am Laufen. Das USB-DMXnano GW habe ich hier, ist aber in der Produktivumgebung nicht die Lösung für mich.
Ich habe lange mit dem arcus eds geliebäugelt aber mit dem babtec sehe ich für die Zukunft mehr Möglichkeiten. Zwei Kanäle (z.Z. reicht mir einer) Send to KNX und IP Interface
Bei dem babtec ist mir die KNX Anbindung noch nicht klar. Auf der Hersteller Webseite findet man diesbezüglich auch nichts.
Hat das schon mal jemand integriert?
Gruß
Michael
Meine Installation: VM Debian Buster SH NG 1.8.1, SmartVISU 3.0, KNX, DMX, 1-wire, Fortigate 30E IPS, VMware vSphere 6.7
Da ich auch gerade einen parametrierbaren RGBW Fader implementiere und bisher einen anderen Ansatz verfolgt habe, eine Frage an die Programmier-Cracks:
Der im ersten Post beschriebene Ansatz verwendet die Fade-Funktion und lässt über den Scheduler gesteuert die Logik immer wieder triggern und die Werte anpassen.
Ich hatte es dagegen bisher so aufgesetzt, dass ich einmalig eine Schleife starte und diese erst durch Auftreten einer Abbruchbedingung (e.g. Cycler beenden) verlasse. Anstelle .fade() setze ich die Werte direkt und verwende für die Delays time.sleep().
Funktionieren tut's, aber welche Variante ist die zu bevorzugende und "sauberere" - gerade hinsichtlich RPi auch weniger Performance lastig?
Als Negativpunkt bei meinem Ansatz sehe ich auf jeden Fall, dass ich einen mehrfachen Start der Logik (Schleife) abfangen muss...
Hi zusammen!
Ich hab auf Basis des ersten Posts die Logik angepasst und optimiert. Jetzt gibt es ein paar try-Abfragen und mehrere Einstellungsmöglichkeiten. Kann das Ergebnis gerne hier posten, habe allerdings derzeit noch 2 Probleme:
a) Die FADE Funktion bricht ab, sobald der KNX bzw. DALI-Aktor einen Statuswert sendet. Das kann man natürlich beheben, indem das Item einfach nicht auf die Statusadresse hört. Habe ich derzeit auch so gelöst, ist aber nicht sonderlich komfortabel.
b) Die FADE Funktion scheint einen aktuellen Fade-Vorgang nicht zu aktualisieren. Heißt: Wenn die Leuchten am Ziel angekommen sind und dann erfolgt die nächste Stufe (Also zB rot wird wieder runtergedimmt und grün hoch), dann funktioniert alles perfekt. Wird der next_step aber ausgeführt, während ein Kanal noch dimmt, dimmt dieser fröhlich weiter auf die alte Destination. Ich hoffe, das ist verständlich Hier kurz der Logeintrag:
Code:
2015-07-30 13:07:23,313 DEBUG Sequencer_Wohnen Triggering wohnen.led_vorhang.R.dimmen - by: Logic source: None dest: None value: {'dest': 247.0, 'item': Item: wohnen.led
2015-07-30 13:07:43,244 DEBUG Main knx: 0.0.0 set 3/6/27 to 0c -- __init__.py:parse_telegram:189
2015-07-30 13:07:43,359 DEBUG Main knx: 1.1.3 set 3/6/28 to 0c -- __init__.py:parse_telegram:189
2015-07-30 13:07:43,519 INFO Sequencer_Wohnen {'dest': None, 'source': None, 'by': 'Scheduler', 'value': 2} -- sequencer.py:<module>:3
2015-07-30 13:07:43,614 DEBUG Sequencer_Wohnen Triggering wohnen.led_vorhang.R.dimmen - by: Logic source: None dest: None value: {'dest': 20.0, 'item': Item: wohnen.led
2015-07-30 13:08:03,286 DEBUG Main knx: 0.0.0 set 3/6/27 to 14 -- __init__.py:parse_telegram:189
2015-07-30 13:08:03,416 DEBUG Main knx: 1.1.3 set 3/6/28 to 14 -- __init__.py:parse_telegram:189
Hehe
Also kurz und knackig.. ist es möglich, einen bestehenden FADE noch während des Durchlaufens zu aktualisieren und wenn ja, wie?
Sprich: die Leuchte fadet zur Destination 255. Beim Wert 100 möchte ich sie jetzt aber mittels fade(0,1,1) wieder langsam ausschalten lassen. Irgendwie wird dieser zweite Befehl ignoriert. Die Leuchte fadet weiter bis 255. Wenn ich DANN fade (0,1,1) laufen lasse, klappt auch das sanfte Ausschalten, aber eben erst nach Beenden des ersten Fades.
ich hatte einmal bei Hue Plugin das Thema, dass ich kein fade Abbruch bekomme, wenn ich exakt den gleichen Wert des Items setze. Das war ausserhalb des IF Zweigs. Hattest Du das schon geändert ? Siehe Thread #10. Ich sehe im aktuellen develop keine Änderung (item.py ab Zeile ca. 362 in develop). Dort setzt Du fading auf false, wenn eine Änderung da war (value !=self._value). Ich muß im Plugin zum stoppen immer noch value +1 (oder value -1) setzen, damit fade() anhält !
Code:
_changed = False
if value != self._value:
_changed = True
self.__prev_value = self._value
self._value = value
self.__prev_change = self.__last_change
self.__last_change = self._sh.now()
self.__changed_by = "{0}:{1}".format(caller, source)
if caller != "fader":
self._fading = False
self._lock.notify_all()
Jup, das mit dem +1 hatte ich auch bemerkt.. Jetzt funktioniert soweit mal alles wie es soll. Am Code kann man sicher viel optimieren, vermutlich sind auch übertrieben viele try drin mit viel Debugcode, aber kann ja jeder säubern wie er will
Hier die Items:
Code:
['wohnen']
[['led_vorhang']]
type = foo
[[['R']]]
# nehm ich zum Schalten
[[[['dimmen']]]]
knx_send = 3/6/27
knx_dpt = 5
visu_acl = rw
type = num
#knx_init = 3/6/28
cache = True
enforce_updates = yes
[[['G']]]
# nehm ich zum Schalten
[[[['dimmen']]]]
knx_send = 3/6/31
knx_dpt = 5
visu_acl = rw
type = num
#knx_init = 3/6/32
cache = True
enforce_updates = yes
[[['B']]]
# nehm ich zum Schalten
[[[['dimmen']]]]
knx_send = 3/6/35
knx_dpt = 5
visu_acl = rw
type = num
#knx_init = 3/6/36
cache = True
enforce_updates = yes
[[['sequencer']]]
knx_listen = 3/6/94
knx_dpt = 1
visu_acl = rw
type = bool
cache = True
enforce_updates = yes
[[[['uzsu']]]]
type = dict
uzsu_item = wohnen.led_vorhang.sequencer
cache = True
visu_acl = rw
Hier die logic.conf:
Code:
[Sequencer_Wohnen]
filename = sequencer.py
watch_item = wohnen.led_vorhang.sequencer
stepping = 2 # OPTIONAL. Ohne Angabe nimmt die Logik 5 als Standardwert
timedelta = 10 # OPTIONAL. Ohne Angabe nimmt die Logik 1 als Standardwert
randomchanger = 35 # OPTIONAL. On und Off-Wert werden um diesen Wert randomisiert. Rand(off, off+randomchanger)
randomstart = 150 # OPTIONAL. G und B werden auf random +-50 diesen Wert gesetzt, um nicht immer mit nem dunklen Rot zu starten.
off_value = 0 # OPTIONAL. Standardwert 0
on_value = 255 # OPTIONAL. Standardwert 255
off_fade = 10 # OPTIONAL. Sanftes deaktivieren des Faders/Sequencers in Sekunden. Sonst wird direkt ausgeschaltet.
R = R.dimmen # Child-Item, das gefadet werden soll. Kann auch in der Logik angepasst werden.
G = G.dimmen
B = B.dimmen
Und hier die Logik. Optimierungshinweise herzlich willkommen
Code:
#!/usr/bin/env python
#
logger.info(trigger)
source_item = sh.return_item(trigger['source'])
logger.debug("Source Item for Sequencer Logic: {0}".format(source_item))
if sh.return_item(logic.watch_item[0])() : # Variablen werden nur gesetzt/gecheckt, wenn Sequencer eingeschaltet wird
step = trigger['value']
logger.debug("Step: {0}".format(step))
# Aus-Wert wird entweder als off in logic.conf definiert oder automatisch auf 0 gesetzt
try:
off = int(logic.off_value)
logger.debug("Off via Config = {0}".format(off))
except:
off = 0
logger.debug("Off via Standard = 0")
# Ein-Wert wird entweder als off in logic.conf definiert oder automatisch auf 255 gesetzt
try:
on = int(logic.on_value)
logger.debug("On via Config = {0}".format(on))
except:
on = 255
logger.debug("On via Standard = 255")
# Sollte Off groesser als On sein, werden die beiden Werte getauscht.
if off >= on:
realoff = on
realon = off
on = int(realon)
off = int(realoff)
logger.debug("Werte in Config verdreht. Off nach Korrektur = {0}, On nach Korrektur = {1}".format(off, on))
# Ist Randomchanger in der logic.conf angegeben, wird der dort angegebene Wert benutzt, um On und Off mit dem angegebenen Wert zufaellig abzuaendern.
try:
rand = logic.randomchanger
logger.debug("Random via Config = {0}".format(rand))
except:
rand = 'no'
# Wird Randomchanger ohne Wert deklariert, wird Standardwert 30 gesetzt.
if not isinstance(rand, int):
if rand.lower() in ['1', 'true', 'yes', 'on']:
rand = 30
logger.debug("Random ist aktiviert, aber kein Wert gesetzt. Off = zwischen {0} und {1}, On = zwischen {2} und {3}".format(off,off+30,on,on-30))
elif rand.lower() in ['0', 'false', 'no', 'off']:
logger.debug("Keine Zufallswerte gewuenscht. Off = {0}, On = {1}".format(off,on))
else:
rand = int(rand)
# On und Off werden anhand des Randomchanger-Wertes zufaellig abgeaendert.
if isinstance(rand, int):
random.seed()
upper = int(on-rand)
lower = int(off+rand)
on = random.randint(upper, on)
off = random.randint(off, lower)
logger.debug("Randomspanne = {0}, Obergrenze fuer off = {4}, Untergrenze fuer on = {3}, Sequencer Werte: off {1}, on {2}".format(rand,off,on, upper, lower))
# Ist Stepping nicht in der logic.conf definiert, wird der Wert auf 5 gesetzt.
try:
stepping = int(logic.stepping)
logger.debug("Stepping = {0}".format(stepping))
except:
stepping = 5
# Ist Timedelta nicht in der logic.conf definiert, wird der Wert auf 1 gesetzt.
try:
timedelta = int(logic.timedelta)
logger.debug("Timedelta = {0}".format(timedelta))
except:
timedelta = 1
# Randomstart ermoeglicht es, mit einer zufaelligen Farbe anstatt dunklem Rot zu starten.
try:
randomstart = logic.randomstart
except:
randomstart = False
# Wird Randomstart ohne Wert in der logic.conf aktiviert, wird 150 als Standardwert gesetzt.
try:
if randomstart.lower() in ['true', 'yes', 'on']:
randomstart = 150
elif randomstart.lower() in ['0', 'false', 'no', 'off']:
randomstart = 0
else:
randomstart = int(randomstart)
logger.debug("Random Start = {0}".format(randomstart))
except:
if not isinstance(randomstart, int):
logger.debug("Randomstart nicht oder falsch definiert")
else:
logger.debug("Randomstart wird berechnet...")
# Berechnen des zufaelligen Startwerts fuer Gruen und Blau.
if isinstance(randomstart, int) and randomstart > 0:
random.seed()
randomstartG = random.randint(randomstart-50, randomstart+50)
randomstartB = random.randint(randomstart-50, randomstart+50)
logger.debug("Random Start fuer gruen = {0}, fuer blau = {1}".format(randomstartG, randomstartB))
else:
logger.debug("Random Start ist ausgeschaltet. Wert = {0}".format(randomstart))
# Next_Step wird entweder in Sekunden in logic.conf definiert oder automatisch errechnet.
try:
next_step = int(logic.next_step)
logger.debug("Next Step via Config = {0}".format(next_step))
except:
next_step = int(on*timedelta/stepping)
logger.debug("Next Step via Calculation = {0}".format(next_step))
next_time = sh.now() + dateutil.relativedelta.relativedelta(seconds=next_step)
# Sind die anzusteuernden Children in logic.conf nicht definiert, wird der Standardname FARBE.dimmen angenommen. Sollte angepasst werden!
parent_item = sh.return_item(logic.watch_item[0]).return_parent()
try:
R = str(parent_item) + "." + str(logic.R)
G = str(parent_item) + "." + str(logic.G)
B = str(parent_item) + "." + str(logic.B)
logger.debug("Items via Config: Rot = {0}, Gruen = {1}, Blau = {2}".format(R,G,B))
except:
R = str(parent_item) + ".R.dimmen"
G = str(parent_item) + ".G.dimmen"
B = str(parent_item) + ".B.dimmen"
logger.debug("Items via Standard: Rot = {0}, Gruen = {1}, Blau = {2}".format(R,G,B))
id = logic.name
items = R, G, B
if sh.return_item(logic.watch_item[0])() : #wenn watch_item gesetzt ist startet Ablauf (1-2-3-4-2-3-4-2-3-4-.....)
if step == 1:
logger.debug("Sequencer Stufe 1")
if randomstart:
sh.return_item(items[0]).fade(on,stepping*2,timedelta)
sh.return_item(items[1]).fade(randomstartG,25,1)
sh.return_item(items[2]).fade(randomstartB,33,1)
else:
sh.return_item(items[0]).fade(on,stepping,timedelta)
step = 2
elif step == 2:
logger.debug("Sequencer Stufe 2")
aktuellR = sh.return_item(items[0])()
aktuellG = sh.return_item(items[1])()
logger.debug("R = {0}, G = {1}".format(aktuellR,aktuellG))
sh.return_item(items[0])(aktuellR+1)
sh.return_item(items[1])(aktuellG+1)
sh.return_item(items[1]).fade(on,stepping,timedelta)
sh.return_item(items[0]).fade(off,stepping,timedelta)
step = 3
elif step == 3:
logger.debug("Sequencer Stufe 3")
aktuellG = sh.return_item(items[1])()
aktuellB = sh.return_item(items[2])()
logger.debug("G = {0}, B = {1}".format(aktuellG,aktuellB))
sh.return_item(items[1])(aktuellG+1)
sh.return_item(items[2])(aktuellB+1)
sh.return_item(items[2]).fade(on,stepping,timedelta)
sh.return_item(items[1]).fade(off,stepping,timedelta)
step = 4
elif step == 4:
logger.debug("Sequencer Stufe 4")
aktuellR = sh.return_item(items[0])()
aktuellB = sh.return_item(items[2])()
logger.debug("R = {0}, B = {1}".format(aktuellR,aktuellB))
sh.return_item(items[0])(aktuellR+1)
sh.return_item(items[2])(aktuellB+1)
sh.return_item(items[0]).fade(on,stepping,timedelta)
sh.return_item(items[2]).fade(off,stepping,timedelta)
step = 2
else:
logger.warning("Kein Sequenzwert gesetzt")
exit()
sh.scheduler.change(id, next=next_time, value=step) #nächsten Aufruf setzen
else:
# Ist off_fade nicht in der logic.conf definiert, wird sofort ausgeschaltet statt in 10 Sekunden ausgefadet.
try:
off_fade = logic.off_fade
logger.debug("Ausschalten mit Fade")
except:
off_fade = 'no'
logger.debug("Ausschalten ohne Fade")
try:
if off_fade.lower() in ['1', 'true', 'yes', 'on']:
off_fade = 10
elif off_fade.lower() in ['0', 'false', 'no', 'off']:
off_fade = False
else:
off_fade = int(off_fade)
logger.debug("Ausschaltfade in Sekunden via Config = {0}".format(off_fade))
except:
if not isinstance(off_fade, int):
logger.debug("Ausschaltfade nicht oder falsch definiert")
else:
logger.debug("Ausschaltfade wird berechnet...{0}".format(off_fade))
for i in items:
if off_fade:
off_step = int(sh.return_item(i)()/off_fade)
off_delta = 1
if off_step == 0:
off_step = 1 # Waere ueber timedelta wohl nobler zu loesen, aber egal...
logger.debug("Offstep fuer {1} = {0}".format(off_step,sh.return_item(i)))
aktuell = sh.return_item(i)()
sh.return_item(i)(aktuell+1)
sh.return_item(i).fade(0,off_step,off_delta)
else:
sh.return_item(i)(0)
logger.debug("Sequencer deaktiviert fuer {0}".format(sh.return_item(i)))
exit()
@Dragonos2000
Könntest du hier mal deinen Ansatz posten bitte? Ich habe inzwischen am Plugin schon ein paar weitere Sachen implementiert und eigentlich bin ich mit dem obigen Ansatz was die Funktion anlangt zufrieden. Das Problem ist aber eben, dass mit dem Fade Befehl die Items so konfiguriert sein müssen, dass sie nicht auf die Status-GAs hören.
Insofern würde mich der andere Ansatz über die Schleife mal interessieren. Noch nobler könnte es übrigens sein, wenn man hier einen eigenen Scheduler nutzt, der immer wieder in einem bestimmten Zeitabstand neu aufgerufen wird. Noch cooler wäre natürlich, wenn die Fader Funktion entsprechend konfiguriert werden könnte, dass bestimmte GAs bezüglich des Abbruchs ignoriert werden oder so..
Hat sich hier noch irgendwer mit einem RGB Fader auseinander gesetzt? Überlege gerade, das Ganze in ein Plugin zu gießen. Bei mir hab ich zB eine Menge an Konfigurationskram, was sich durch ein Multi-Instancing Plugin noch ein bisschen nobler lösen ließe...
Ich hab nur mal ein bisschen mit einem HSV-RGB Konverter rumprobiert und dann im HSV die Farbwerte durchlaufen lassen. Hat auf dem PI aber zu viele Ressourcen gefressen, wenn ich mehrere Dimmer gleichzeitig so ansteuern wollte.
Ich mach es daher aktuell so (und das gehört zum vorangegangenen Post, den ich übersehen habe), dass ich per Variable Maximalwerte übergebe (im Endeffekt die max Helligkeit) und diese dann in verschachtelten Schleifen und Zeitglied dekrementiere/inkrementiere. Die Werte schreib ich dann direkt auf den DMX raus.
Ich hab dann 2-3 verschiedene Schleifen gebaut, um verschiedene Farbverläufe zu realisieren.
Wir verarbeiten personenbezogene Daten über die Nutzer unserer Website mithilfe von Cookies und anderen Technologien, um unsere Dienste bereitzustellen. Weitere Informationen findest Du in unserer Datenschutzerklärung.
Indem Du unten auf "ICH stimme zu" klickst, stimmst Du unserer Datenschutzerklärung und unseren persönlichen Datenverarbeitungs- und Cookie-Praktiken zu, wie darin beschrieben. Du erkennst außerdem an, dass dieses Forum möglicherweise außerhalb Deines Landes gehostet wird und bist damit einverstanden, dass Deine Daten in dem Land, in dem dieses Forum gehostet wird, gesammelt, gespeichert und verarbeitet werden.
Kommentar