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.
Nur Mut - der von Max schon verlinkte Code funktioniert und benötigt lediglich die Plugin-Schnittstelle und das Parsing der ankommenden Daten, wobei da auch alles offen liegt/spezifiziert ist. Wie aber dort geschrieben muss das jemand machen der Standard-konforme Geräte hat... Wenn mir einer ein/zwei sponsert... *g*
Das USB-Dongle ist ok. Hauptsache TCM310 - das ist das HF-Modul was ich auch auf dem Beaglebone Cape verbaue. Schnöder UART - also stell dich auf nen normalen CDC-ACM ein.
Schalter: Kein Plan - sieht günstig aus - hau rein.
Also die Taster liegen hier, dank des Ansatzes von Robert ist der Einstieg ja recht einfach.
Die Doku zum Protokoll ist auch ganz o.k. -> http://www.enocean.com/esp3/
Nun hab ich hier 4-fach Taster und frage mich was könnten die Hex/Dec-Werte bedeuten und gibts irgendwo ne ausführlichere Doku?
Die Taster senden RPS-Telegramme und identifizieren sich als Switch mit dec=246 / hex=0xf6.
Als "Nutzdaten kommt folgendes Dezimal beim Taster raus:
Code:
I--- 55 ---I
I 48 112 I
I I
I 16 80 I
I--- 21 ---I
Warum "eno" - "enocean" ist doch nun auch nicht soo lang. Die Leute schreiben ja auch "squeezebox_send" und murren nicht *g*.
Ein Blick auf die anderen EEP müsste die Reise vorbestimmen: Implementiert man ins Plugin verschiedene "rorg-Klassen"? Ein Dict mit den "rorg" wie bei dir angegeben und als value dann unterstützte "button" mit je einer Transformationsfunktion?
Dürfte so auch gut zu prüfen sein.
Aus diesem Grund würde ich nicht "enocean_button" sagen sondern "enocean_entity" und dann können da eben alle Wertefelder eingetragen werden, die zuvor in dem von "RORG" abhängigen dict gefunden wurden. Ich meine Ähnlich ist es auch im Onewire-Plugin, wo das "Entity-Set" von der Onewire-ID (und der unsäglichen Page.3) abhängig ist.
Wie gesagt, ich würde dann einen Transformator für jede Entität schreiben, der auf den Payload losgelassen wird. Dann kann man neue EEPs durch erweitern des Dictionaries bequem hinzufügen.
Grüße
Robert
Ach so, kurz erläutert:
x = {'F6_02':[('B0',<nimm Bit 2 als Funktion aber nur wenn nicht x>), ('A1',<nimm Bit 3 wenn...>)], 'F6_xx ...........}
Dann beim Parsen:
wenn "encoean_rorg" nicht in x -> Möööp
wenn "enocean_entity" nicht in x(enocean_rorg) -> Mööp
Bei Telegramm dann über "enocean_id" Item bestimmen und über x(rorg) alle Transformationen auf den Payload laufen lassen.
Vielleicht kann Marcus ja mit den Transformationen helfen. Würde das ähnlich den "eval" der Items machen!
Also das was ich ad hoc verstanden habe (75%) klingt sinnig. Davon irgendwelche Namen zu vergeben bin ich noch ein bisschen entfernt. aber meinetwegen auch enocean (ist aber son Fingerkiller).
RORG kommt ja aus dem Telegramm, FUNC und TYPE müsste man wissen, ist aus den "Unterlagen" zu meinen Jung Tastern aber auch nicht ersichtlich.
Mit meinen Worten:
Es gibt ein dict in dem steht die jeweilige Methode mit der payload bearbeitet wird. Ob wir das Telegramm überhaupt bearbeiten und mit welcher Methode entscheidet die SenderID zusammen mit der item.conf.
Gibts ein "Funktionsupdate" de Plugins kommt ein neue Methode und ein Eintrag im dict hinzu.
Weils nicht ganz offtopic ist:
Man könnte eine Übersicht gebrauchen über welche Methoden ein Plugin in sh.py verfügen sollte und eine timeline wie diese abgearbeitet werden ... brauch ich aber konkret für ein anderes Plugin.
Eine Frage taucht auf ... was ist effektiver/schneller/besser:
Code:
x=21
a = bitstring.BitArray(uint=x,length=8)
print(a[:3])
Code:
print((0x15 & 0xE0) >> 5)
Wobei ich das "a" von bitstring natürlich für weitere Operationen wieder verwenden kann. Die zweite Variante braucht dafür kein bitstring-Modul. Ich kann ja seit heute Bit-Schubsen .
@Robert:
Was hast Du denn an Sensoren für EnOcean rum zu liegen? Auch wenn das selbst gefertigte Dinge sind gehe ich doch davon aus dass Du Dich an das EnOcean Protokoll gehalten hast?
@all:
Ich sehe hier ne ziemlich komplexe Geschichte was die Config angeht.
Eigentlich gibt es mind. 3 große Filter.
1. Header auswerten und sehen um was für einen PacketType es sich handelt -> Packet Type.
An dieser Stelle kann ich noch nicht überblicken was man alles implementieren möchte/muss. RADIO scheint hier erstmal Standard(das wichtigste) zu sein.
Code:
0x00 --- Reserved
0x01 RADIO Radio telegram
0x02 RESPONSE Response to any packet
0x03 RADIO_SUB_TEL Radio subtelegram
0x04 EVENT Event message
0x05 COMMON_COMMAND Common command
0x06 SMART_ACK_COMMAND Smart Ack command
0x07 REMOTE_MAN_COMMAND Remote management command
0x08 --- Reserved for EnOcean
0x09 RADIO_MESSAGE Radio message
0x0A RADIO_ADVANCED Advanced protocol radio telegram
2. Abhängig vom Header/PacketType muss dann jeweils! der TelegramType ausgewertet werden -> Telegram Type
Code:
0XF6 RPS
0XD5 1BS
0xA5 4BS
0XD2 VLD
u.s.w.
3. Wiederum abhängig davon gibt es in jedem TelegramType teilweise unzählige Sub-Typen. Diese werden aber nicht! im Telegramm gesendet, die muss man dann wissen. Ausserdem hat jeder Telegramm-Type wieder unterschiedliche Objekte und Wertebereiche.
Seite 2: http://www.enocean.com/fileadmin/red...s_EEP_V2.5.pdf
Ich bekomme da nen Knoten im Kopf wie man das vernünftig strukturieren soll. Ich habe auch keine Lust anschließend 20 Seiten Doku zum Plugin zu schreiben um das verständlich zu machen. Gefühlt muss eigentlich auch nach 3 spezifischen Einträgen in der item.conf Schluss sein.
Ich hänge einfach mal den aktuellen Plugin-Stand an. Der macht aber nix weiter als print-Ausgaben im Debug Modus. Nicht alles was in der item.conf steht wird derzeit auch "verarbeitet".
Eine erste Idee wäre mit getattr und einer zusätzlichen class zu arbeiten.
items/item.conf
Code:
[A1]
type = bool
enforce_updates = true
enocean_id = 00:22:60:37
enocean_rorg = F6_02_02
enocean_rorg_id = A1 #Button-Name in Plugin
[A0]
type = bool
enforce_updates = true
enocean_id = 00:22:60:37
enocean_rorg = F6_02_02
enocean_rorg_id = A0 #Button-Name in Plugin
Klar, denke das sollte unbedingt jetzt schon ins develop. Je nach dem, wie produktiv du das nutzt und es magst, kann ich direkt versuchen mitzuhelfen oder zumindest testen.
Ich habe ein nur Evaluation Board mit integr. Programmer (EPK 350 - ENOCEAN - PROGRAMMER KIT, ESK300 UPGRADE | Farnell Deutschland) und eine handvoll zusätzliche TCM300. Ziel ist es, nur mit dem CC3000 (8051 Architektur) eine Ultraschallmessung zu realisieren (wie SR-04, aber ohne extra Controller - der SR-04 hat ja schon einen und dann noch einen dazwischen - neee) und das ganze per Solarenergie zu speisen. Braucht aber noch ein wenig. Ansonsten kann ich aber das ESK als 4-Button-Rocker parametrieren (bzw. wenn ich wollte auch alles andere, von x-fach Eingang bis x-fach Ausgang. Nur die Zeit.... Da ist ein "echter" Schalter angenehmer.
Nun zur Diskussion.
Gedanke vorweg: Mir schwante auch schon, dass sich die mannigfaltigen EEP Datenformate nur schwer abbilden lassen werden. Hier ist die Frage, ob man den Benutzer es möglicht einfach machen will, und er nur ein Minimum angeben muss (im Zweifel sogar ein konkretes Produkt), oder von ihm verlangt zumindest die korrekte RORG etc. zu kennen. Ersteres macht das Plugin möglicherweise unnötig unflexibel, letzteres verlangt vom Benutzer mehr Einsatz. Ich würde letzteres bevorzugen. So kapselt das squeezebox-Plugin ja auch nicht die Befehle sondern verlangt vom Benutzer die Befehle zu kennen. Nur benötigte Intelligenz welche durch das Protokoll nicht einfach möglich sind (start/stop/pause oder die Mute-Sachen) erfahren eine Extrabehandlung. Aber so konnten sich andere Nutzer einfach Funktionen zurechtdengeln, die ich gar nicht auf dem Schirm hatte.
Konkreter: Genau wie du es aufgeschlüsselt hast sehe ich es auch. Der Telegrammtyp muss halt verarbeitet werden. Sicher werden die für die unmittelbare Funktion interessanten Telegramme immer den gleichen Typ haben. Der RORG und die Adresse werden dann überprüft und falls nicht passend ein Fehler ausgegeben. Da ist über den Vergleich die erste Sicherheitsebene vorhanden.
Also:
Adresse prüfen ob in einem Dict unserer "Items" (also einfach {Addr:Item-Ref, Addr2, Item2-Ref})
Telegrammtyp ermitteln und gucken ob Datenpaket (andere später!)
Über Item-Ref von oben prüfen, ob erster Teil des "enocean_rorg" Attribut mit der RORG im Paket übereinstimmt.
Basierend auf der "enocean_rorg" in einem ZWEITEN Dict wie oben beschrieben a) die zulässigen "rorg_id" (heißt das wirklich so?) mit dem Attribut vergleichen. b) Dann mit der hinterlegten Transformationsfunktion (aus dem DICT!) konvertieren.
Vorteil:
Ein Dict was durch "parse_items" gefüllt wird und nur Referenzen auf die Items beinhaltet. Dessen "enocean..."-Attribute werden dann bei Bedarf gelesen. Machen ja einige Plugins so.
Ein Dict, wo wenn jemand ein "neues" Gerät hat die entsprechenden RORG, "RORG-ID" und Transformationsfunktionen nachgeplfegt werden können, ohne neue Abfragen/Handler im eigentlichen Code zu schreiben.
Ein wenig habe ich das im SMA-Plugin realisiert, wo aber keine Transformationsfunktionen benutzt werden müssen sondern nur Speicheradresse abhängig vom Feld gelesen werden. Dadurch kann man diese Lesezugriffe auch noch Zusammenfassen.
Auf diese Weise kommst du auch mit 3 Attributen aus: MAC, RORG, ID (wobei ich das wirklich als "select", "entity" oder "func" bezeichnen würde um Verwechselungen zu vermeiden). Diese können dann ja wie oben beschreiben sequentiell abgeprüft werden (MAC-Match (in dict1), RORG-Match (in Item-Attr), ID-Match (in dict2).
Klar, denke das sollte unbedingt jetzt schon ins develop. Je nach dem, wie produktiv du das nutzt und es magst, kann ich direkt versuchen mitzuhelfen oder zumindest testen.
Nein produktiv ist das nicht, es kann ja noch nix wirklich...da sind einfach noch zu viele Fragezeichen bzgl. der Struktur.
Hier ist die Frage, ob man den Benutzer es möglicht einfach machen will, und er nur ein Minimum angeben muss (im Zweifel sogar ein konkretes Produkt), oder von ihm verlangt zumindest die korrekte RORG etc. zu kennen. Ersteres macht das Plugin möglicherweise unnötig unflexibel, letzteres verlangt vom Benutzer mehr Einsatz. Ich würde letzteres bevorzugen. So kapselt das squeezebox-Plugin ja auch nicht die Befehle sondern verlangt vom Benutzer die Befehle zu kennen. Nur benötigte Intelligenz welche durch das Protokoll nicht einfach möglich sind (start/stop/pause oder die Mute-Sachen) erfahren eine Extrabehandlung. Aber so konnten sich andere Nutzer einfach Funktionen zurechtdengeln, die ich gar nicht auf dem Schirm hatte.
Ich denke man sollte vom Nutzer schon wenigstens die Konkrete RORG-ID verlangen können. Ohne jetzt tausend Datenblätter zu durchwühlen ... einen Tod muss man sterben. Rocker sind ja recht easy und kann man im Zweifel ausprobieren, Sensoren haben Datenblätter. Ansonsten muss der Support des Herstellers ran. Gute Übersicht für den "Standard" bietet Batterielose Funksensormodule, Funkempfangs- und Transceivermodule sowie Zubehör in 868 MH | EnOcean - Produkte.
Ich bin ehrlich: Ich habe keine Lust hier hunderte Stunden zu versenken.
Konkreter: Genau wie du es aufgeschlüsselt hast sehe ich es auch. Der Telegrammtyp muss halt verarbeitet werden. Sicher werden die für die unmittelbare Funktion interessanten Telegramme immer den gleichen Typ haben. Der RORG und die Adresse werden dann überprüft und falls nicht passend ein Fehler ausgegeben. Da ist über den Vergleich die erste Sicherheitsebene vorhanden.
Adresse prüfen ob in einem Dict unserer "Items" (also einfach {Addr:Item-Ref, Addr2, Item2-Ref})
Telegrammtyp ermitteln und gucken ob Datenpaket (andere später!)
Über Item-Ref von oben prüfen, ob erster Teil des "enocean_rorg" Attribut mit der RORG im Paket übereinstimmt.
Das ist in dem ersten Beispiel ja schon teilweise so - RORG hatte ich icht eingebaut da die Gesamtstruktur noch zu unklar ist. Jetzt kommt der Punkt den ich nicht ganz verstehe:
Basierend auf der "enocean_rorg" in einem ZWEITEN Dict wie oben beschrieben a) die zulässigen "rorg_id" (heißt das wirklich so?) mit dem Attribut vergleichen. b) Dann mit der hinterlegten Transformationsfunktion (aus dem DICT!) konvertieren.
Vorteil:
Ein Dict was durch "parse_items" gefüllt wird und nur Referenzen auf die Items beinhaltet. Dessen "enocean..."-Attribute werden dann bei Bedarf gelesen. Machen ja einige Plugins so.
Ein Dict, wo wenn jemand ein "neues" Gerät hat die entsprechenden RORG, "RORG-ID" und Transformationsfunktionen nachgeplfegt werden können, ohne neue Abfragen/Handler im eigentlichen Code zu schreiben.
Wie soll das realisiert werden? Bleiben wir beim Schalter, wie die Info zum gedrückten Schalter sich zusammenbaut steht ja im Code. Da braucht es aber neue Hilfsvariablen/Items ... nenn es wie Du willst. Um eindeutig zu identifizieren welcher Taster gedrückt wurde könnte man das:
a) über feste Werte machen (16,48,80,112,21,55)
b) über die entsprechenden Bits im Datenbyte + Plugin-Logik machen (So ist jetzt mal umgesetzt)
a) ist einfach eingebaut, aber nicht auf alles zu übertragen
Was ich immer noch nicht verstanden habe ist wie der Transformator aussehen soll? Das Transformationsdict liegt dann im Plugin?
Kannst Du das kurz mal zu diesem Beispiel angeben wenn wir davon ausgeben dass wir die items A1,A0,B1,B0,A1B1,A0B0 haben? Es geht nicht um den konkreten Code eg sondern eher was da konkret in welchem dict steht und wie die item.conf aussehen soll.
Was ich immer noch nicht verstanden habe ist wie der Transformator aussehen soll? Das Transformationsdict liegt dann im Plugin?
Kannst Du das kurz mal zu diesem Beispiel angeben wenn wir davon ausgeben dass wir die items A1,A0,B1,B0,A1B1,A0B0 haben?
PHP-Code:
my_items = {'mac_as_str_or_bytes':[item-ref], '2nd mac':[item2-ref, item3-ref]} my_dict = {'F6_02_02':{'A1':'pl & (1<<4) == (1<<4)','A0':'pl & (1<<5) == (1<<5)'}, 'F6_02_03':{'foo':'foo_transform'}} # in my_dict können natürlich auch komplexere Operation zum finden des Wertes gemacht werden! auch ein 'foo if bla else None' ginge...
# example frame received - yes, mac is too short i know frame = bytes([0xDE, 0xAD, 0xBE, 0xEF, 0xF6, (1<<5)])
#iterate over all items having this MAC if not frame[1:4] in my_items: print('unknown MAC') return
for item in my_items[frame[1:4]]:
# match rorg with item: if not item.conf['enocean_rorg'][3] == frame[5]: print('wrong RORG') continue
if (item.conf['enocean_rorg'] in my_dict) and (item.conf['enocean_id'] in my_dict[item.conf['enocean_rorg']]): pl = frame[4:] # for id = 'A0' this will be 'True' but for 'A1' this will be evaluated as 'False' value = eval(my_dict[item.conf['enocean_rorg']][item.conf['enocean_id']]) # allow "None" to enable "eval" to decide not to update item! if value is not None: item(value,'cooles Plugin')
Ganz bewusst habe ich die Attribute immer wieder neu referenziert - da würde man sonst sich was kürzeres zuweisen...
Hinweis: Dass die 'enocean_rorg' in my_dict und "enocean_id" in my_dict['enocean_rorg'] vorhanden ist, könnte bereits einmalig zu Beginn bei 'parse_items' sichergestellt werden. Item, für deren rorg/id-Attribut keine Transform-Vorschrift existiert würde so gar nicht erst aufgenommen und somit würden derlei Pakete auch keine MAC matchen -> Problem gelöst.
Aso: und man könnte noch ein direktes "enocean_eval"-Attribut einführen: Dann wird nur "enocean_rorg" als 1-Byte-Wert angegeben und man schreibt die Transformationsfunktion als Attribut. Würde dann ermöglichen neue Funktionen erst mal ohne Modifikation des Plugins zu testen.
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