Unbekannte Funkprotokolle

Aus FHEMWiki

Es gibt jede Menge offiziell in FHEM unterstützte Devices und Funkprotokolle. Solange das Device Ross und Reiter benennt (Homematic, Z-Wave, Intertechno etc.), ist es einfach, dieses in FHEM einzubinden. Was aber, wenn selbst mit hinreichend gut aktualisierter Installation nichts erkannt wird und es ein No-Name Produkt ist, bei dem man nur die Hoffnung hat, dass es im Innern etwas Bekanntes beherbergt?

Dieser Wiki-Artikel soll jenen helfen, die Geräte mit einem unbekannten Funkprotokoll an FHEM anbinden bzw. mit FHEM steuern wollen.

Wenn hier drin irgendetwas unverständlich sein sollte (und wenn es nur deswegen sein sollte, weil es hinreichend bescheuert beschrieben ist :)), dann --> MELDEN!, vielleicht via BenutzerSeite (oder natürlich einfach direkt verbessern) - die Usability dieses Projekts sollte sehr gut werden...

Dieser Artikel soll eine möglichst gut chronologische Sortierung haben, also:

Einführung ... erste Schritte ... Tests ... Analyse ... stabiler Betrieb ... Verfeinerung / letzte Schritte (Expertise-Details).

Basics

Hardware

Neben den bekannten Hardware-Dongles gibt es Selbstbaulösungen in Form eines SIGNALduino, CUL oder JeeLink.

Diese unterscheiden sich in verschiedener Hinsicht:

  • Sendemodul (SIGNALduino/CUL -> CC1101; JeeLink -> RF12B) [1]
  • Modulationsverfahren (OOK, ASK/FSK)
  • Frequenzband (433 MHz, 868 MHz)

(bei SIGNALduino / CUL kann manche Hardware - z.B. nanoCUL - da hardware-kompatibel, mit Projektaktivitäten von CUL oder SIGNALduino betrieben/firmware-geflasht werden; evt. ist es sogar außerdem empfehlenswert, mehrere baugleiche Geräte zu haben, um Support für SIGNALduino und CUL gleichzeitig verfügbar zu haben - evt. auch weitere Geräte mit unterschiedlichen Frequenzen: 433/868)

Frequenzbereich

Für die funkbasierte Heimautomation kommen im Wesentlichen zwei Frequenzbänder in Frage: 433 und 868 MHz. Die meisten Geräte haben auf der Rückseite ein Typenschild, auf dem das Frequenzband ausgewiesen ist.

Dann gibt es noch 2,4 GHz (WLAN, Bluetooth, Funkmaus-Chipsätze...) und 5GHz (WLAN...), diese Frequenzbänder werden in diesem Artikel aber nicht betrachtet.

Modulationsverfahren

So, wie vom Rundfunk (AM/FM) her bekannt, kennt man auch bei 433/868 MHz verschiedene Modulationsverfahren.

Das Signal des Senders wird auf der angegebenen Frequenz ein-/ausgeschaltet um die Dateninformationen zu übermitteln.
Der Sender überträgt den Datenstrom indem, ausgehend von der Trägerfrequenz, zwischen Frequenzen (z.B. Frequenz-Frequenzhub, Frequenz+Frequenzhub) hin- und hergeschaltet wird. Dieses Verfahren kennt verschiedene Ausprägungen: 2-FSK, 4-FSK, GFSK (Details siehe hier).

Encoding oder auch Leitungscode

Die Art und Weise wie dieses Signal interpretiert wird, hängt wiederum vom Encoding ab. Dazu sei auf die nachfolgenden Quellen verwiesen.

Je nach verwendetem Encoding wird ggf. mehr als 1 Übertragungs-Bit für ein Datenbit benötigt. Der Empfänger erwartet z.B. einen Bitwechsel zu einem bestimmten Zeitpunkt. Eine Abfolge

  • 100 (short high, long low) wird als 0
  • 110 (long high, short low) wird als 1

interpretiert.

Im FHEM-Forum gibt es viele freundliche Helfer, die Euch bei Bedarf den richtigen Weg weisen.

Signalstruktur

Ein typischer Aufbau einer Signalstruktur sieht z.B. so aus

| Pause | Sync | Pause | Daten |

  • eine größere Pause zur Trennung der Sequenzen
  • ein Sync-Block mit dem sich der Empfänger auf den Sender einstellt
  • eine Pause um Sync und Daten zu trennen
  • die eigentlichen, zu übertragenden Daten.

Es müssen nicht immer alle Bestandteile in der übertragenen Signalstruktur vorkommen (Details siehe auch Datenpräambel oder auch Syncword).

Die Sequenz wird ggf. mehrfach wiederholt

| Pause | Sync | Pause | Daten | Pause | Sync | Pause | Daten | Pause | Sync | Pause | Daten | ...

Protokoll

Das ist der herstellerspezifische Teil des Signalstroms - die Daten. Hersteller haben i.d.R. ihre eigene Definition der übertragenen Datenströme. Teils werden feste Code-Sequenzen übertragen, es gibt aber auch rollierende Codes (Engl.: Rolling Codes) bei denen sich die Daten bei jeder Übertragung ändern (Fremd-Manipulations-Sicherheit).

Mit etwas Glück erkennt z.B. SIGNALduino bereits das Protokoll, damit den Hersteller und legt automatisch ein passendes Device in FHEM an. Manchmal gibt es auch Fehlinterpretationen und das vermeintlich bekannte Device entpuppt sich als etwas anderes (Statement aus dem Forum: "Lösung war, wo Dooya drauf steht muss nicht immer Dooya drin stecken.").

Wie fange ich an?

Recherche

Sucht im Internet nach Informationen zu dem fraglichen Device. Zu bekannten Devices sollten sich Informationen finden lassen, die einem weiter helfen. Solltet Ihr fündig werden, verfolgt die Hinweise, wie diese Devices in FHEM eingebunden werden können.

Evt. haben auch konkrete verwandte Projekte bereits Protokoll-Informationen über das Gerät, z.B.:

Wenn sich nichts Verwertbares finden lässt, geht's mit dem nächsten Abschnitt weiter.

Ansatz 1 - Versuchen

Einfach probieren: Bau Dir einen SIGNALduino für das passende Frequenzband (die 433 oder 868 MHz-Variante des CC1101). Stelle im SIGNALduino-Setting die Frequenz auf die genannte ein (durch den Befehl cc1101_freq = 433.000 oder 868.000) und die Bandbreite auf das Maximum (cc1101_bWidth = 325 kHz bzw. 650 kHz). Jetzt noch das Attribut verbose auf 5 setzen und dann das FHEM-log (tail -f fhem-yyyy-mm.log) beobachten.

Ist ein Gerät in Reichweite, das regelmäßig etwas sendet (z.B. ein Funkthermometer), sollte hin und wieder etwas empfangen werden. Wenn autocreate aktiv ist, werden auf Basis der erkannten, bekannten Funkprotokolle automatisch neue Devices angelegt (dabei können auch diverse Funkthermometer der Nachbarschaft auftauchen).

Ist es ein Gerät, das sich über eine Fernbedienung steuern lässt: Eine Taste betätigen und hoffen, dass sich im FHEM-Log etwas tut. Auch hier gilt: Handelt es sich um ein bekanntes Funkprotokoll, wird automatisch ein Device angelegt, allerdings nur eines für die Gerätefamilie. Bei Baumarkt-Funksteckdosen z.B. nur das erste gefundene. Die anderen müsst Ihr manuell anlegen und die entsprechenden Codes zur Identifikation der einzelnen Steckdosen anpassen (schaut z.B. hier nach: Intertechno_Code_Berechnung).

Solltet Ihr mit diesem Ansatz Erfolg haben, ist das schon mal gut - Euer Gerät sendet ein bekanntes Protokoll und wird unterstützt.

Solltet Ihr etwas empfangen (MC, MS, MU), aber keine neuen Devices sehen, wird Euer Gerät möglicherweise noch nicht unterstützt. Jetzt gibt es zwei Varianten

  • es handelt sich um ein neues, noch nicht bekanntes Protokoll -> postet einen Log-Ausschnitt auf github wie im SIGNALduino-Wiki vorgeschlagen)
  • es handelt sich um etwas proprietäres, altes oder ähnlich kompliziertes (nicht aufgeben, weiterlesen)

Ansatz 2 - Aufschrauben

Fernbedienung aufschrauben, schauen welcher Chip dort verbaut ist. Endgerät/Device aufschrauben, schauen welcher Chip dort verbaut ist.

Das Teil ist zu klein? Folgende Möglichkeiten:

  • so im Winkel gegen ein Lampenlicht halten, dass man die Schrift besonders gut lesen kann
  • abfotografieren und das Foto vergrößern bis Ihr den Aufdruck lesen könnt

Danach folgt dann Internet-Suchmaschine und das Studium der zugehörigen Data Sheets der Chips.

Das gibt Euch weitere Anhaltspunkte zum Modulationsverfahren, den Frequenzen und Optionen welche diese Chips unterstützen.

Wenn die Grundsatzfrage geklärt ist, ergeben sich die ersten Handlungsoptionen

Die Devices senden/empfangen nicht notwendigerweise auf 433 oder 868 MHz, sondern auf Frequenzen "knapp daneben", das kann z.B. bis zu 870 MHz hochgehen. Darüber, welche Frequenz es genau ist, gibt möglicherweise der verbaute Quarz Auskunft. Meist klein, silber mit einer Gravur wie z.B. 6,70 MHz versehen. Mit Hilfe der Spezifikationen (Frequenzteiler, ...) im Datenblatt des daneben verbauten Chips lässt sich dann die tatsächliche Sende- bzw. Empfangsfrequenz errechnen.

Ansatz 3 - Messen

Ihr nutzt einen Spektrumanalysator. Es gibt verschiedene preisgünstige Ansätze.

  • Zum einen könnt Ihr den nrfmon-Ansatz verfolgen (siehe hier). Tipp: bestellt Euch direkt genug Material um zwei zu bauen, denn die RF12demo kann als Sender und Empfänger genutzt werden. Damit lässt sich direkt verifizieren, dass Euer RFM12B-Device wirklich sendet/empfängt.
  • Der andere Ansatz nutzt einen DVB-T-Stick (siehe z.B. hier. Es gibt aber viele Internet-Suchmaschine-Treffer unter dem Stichwort SDR. Außerdem ein konkretes Projekt: rtl_433.
  • Mein persönlicher Favorit ist der Universal Radio Hacker. Mit dem war ich in der Lage, mittels RTL-SDR-Stick nicht nur Sequenzen mitzuschneiden sondern auch direkt zu analysieren.

Wieso überhaupt so kompliziert? OOK nutzt nur eine Frequenz, FSK zwei, vier, je nach Variante. Es kann auch vorkommen (so wie bei mir), dass ein FSK-Device auf einen OOK-Sender anspricht. Der Grund dafür sind Oberwellen die mit dem Ein-/Auschalten der Frequenz einher gehen.

Die Spektrumanalyse gibt Aufschluss über

  • das Modulationsverfahren (OOK vs. FSK) sowie
  • die relevante(n) Frequenz(en)

SIGNALduino - OOK

Dieses Kapitel geht davon aus, dass ihr einen SIGNALduino für alle weiteren Schritte nutzt.

Log-Meldungen

Der SIGNALduino empfängt die Rohdaten, ermittelt identische Zeitscheiben und ordnet diese den Zahlen 0-7 zu (P0...P7). Ein negativer Zahlenwert bedeutet "kein Empfang" und ein positiver "Signal empfangen". Damit lässt sich der Datenstrom analysieren und für das Senden auch wieder generieren.

Die folgenden Pulslängen-Zahlen stehen für Mikrosekunden.

P0=-13020;P1=15916;P2=-398;P3=415;P4=4008;P5=-794;P6=812;D=01232323232323232323232324532653265353532653262653265326 26262626265353532653265326532653535326265353535353265353532653262653265353265353535353535353265326;

Was bedeutet D=012323...?

0 -> P0=-13020 => 13.020 Mikrosekunden Pause
1 -> P1=15916 => 15.916 Mikrosekunden Signal
2 -> P2=-398 => 398 Mikrosekunden Pause
3 -> P3=415 => 415 Mikrosekunden Signal
2 -> P2=-398 => 398 Mikrosekunden Pause
3 -> P3=415 => 415 Mikrosekunden Signal
...


Tip: um hier schnell zu einem guten Analyse-Ergebnis zu kommen, sind einige verfügbare Beispiel-Zeilen sinnvoll - hier könnte folgendes hilfreich sein: Bei Geräten, die nicht on-demand (Knopfdruck) Funk-Aktivität generieren können: Nicht langwierig auf das jeweils nächste verzögerte Intervall der Funk-Aktivität des Geräts warten, sondern stattdessen mehrfach die Geräte-Batterien erneut wieder einsetzen, so dass (hoffentlich) das Gerät immer eine erste Funk-Aktivität sendet, die:

  • Log-Zeitstempelmäßig genau erkennbar ist
  • hoffentlich immer gleich/ähnlich ist --> gute Analyse-Grundlage

Damit dürfte die Funk-Aktivität hinsichtlich Empfangsstärke, Trägerfrequenz etc. leichter festnagelbar sein.

Frequenz ermitteln

Das folgende Beispiel geht davon aus, dass Ihr im 868 MHz-Band unterwegs seid. Bei 433 MHz könnt Ihr in gleicher Weise vorgehen.

Fangt damit an, dass Ihr den CC101 mittels set-Command cc1101_freq auf 868.000, cc1101_bWidth auf 650 und cc11=1_sens auf 8 einstellt. Kontrollieren könnt Ihr das durch get ccconf. Die Bandbreite bWidth gibt an wie groß der Empfangsbereich ist. Bei 650 kHz sind das z.B. +/- 325 kHz, also der Bereich von 867.675 bis 868.325 MHz.

Wenn ihr etwas empfangt ist das ein Ansatzpunkt. Anderfalls könnt Ihr die cc1101_freq in 200 kHz-Schritten (868.200, 868.400 ...) erhöhen und das Frequenzband auf diese Art und Weise absuchen. Ein Hinweis an der Stelle: Im FHEM-Log folgt bei den SIGNALduino-Einträgen nach dem Datenteil D= die Empfangsstärke R=. Damit könnt Ihr feststellen, ob Ihr Euch der Sendefrequenz nähert oder entfernt.

Wenn Ihr nun Frequenzen gefunden habt bei denen Ihr etwas empfangt, dann könnt Ihr die bWidth jeweils halbieren und den Bereich, in dem etwas empfangen wurde, mit halbierter Frequenz-Schrittweite weiter durchforsten. Das macht Ihr so lange, bis bWidth bei 58 kHz angekommen ist. Damit sollte sich die gesuchte Trägerfrequenz herauskristallisieren.

Eingrenzung - Selektiver Empfang

Am sichersten geht man selektiv vor - einen Message-Typ nach dem anderen testen. Im SIGNALduino kann man über das set-Command disableMessagetype die Interpretation als MC, MS und MU selektiv ausschalten. Man kann mit MC beginnen und danach beobachten, ob es bei aktivem MS + MU Dekoder jeweils nur eine Art von Nachrichten gibt.

Sobald man sieht, dass die Meldungen im FHEM-Log wechseln, die Message-Typen MS, MU bzw. MC mit nur einem aktiven Dekoder aufzeichnen.

Das sollte Anhaltspunkte geben worauf der S'duino am Besten reagiert.

Eingrenzung - Log-Analyse via regex

Wenn man schon ziemlich genau weiß, wie das Message-Pattern des relevanten Geräts aussieht, dann kann man sich folgendermaßen sehr elegant und schnell viele weitere zu diesem Gerät gehörige Aktivitäten aus dem Log fischen, ohne sehr störenden Traffic von anderen Geräten mit dabei zu haben: z.B.:

tail -f log/fhem-2018-11.log|grep "sduino.*msg READ: .*=-4...;"

um sich alle Pattern eines Geräts rauszufischen, bei dem man weiß, dass dessen Sende-Traffic das hinreichend charakteristische Merkmal besitzt, einen Low-Puls mit +- 4000us Länge zu haben:

sduino433/msg READ: MU;P0=-956;P1=450;P2=-1987;P3=-4212;P4=96;P6=-304;D=01212121212121312131212131312121213131312131313431316;CP=1;R=224;

Anmerkung: dies ist natürlich mit einem On-Demand-beherrschbaren Gerät (z.B. Fernbedienung, oder Batterie-basiertes Außerbetriebsetzen) kein Problem: hier kann man direkt live (aktueller Zeitpunkt!) nachvollziehen, ob die aktuelle Regex-Filterung tatsächlich Geräte-Aktivität richtig herausfischt (oder eben dummerweise nicht!). Jedoch bei nicht so leicht kontrollierbaren Geräten (intervall-mäßiges Senden, z.B. Klima-Sensoren, oder noch blöder, nur vereinzeltes Senden, z.B. Schwellwert-Sensoren, oder nicht direkt zugängliche Geräte) muss man natürlich den Regex möglichst wenig strikt formulieren, um sicherzustellen, dass man keine im Log abgelegte Aktivität dieses Geräts fälschlicherweise total übersieht/ignoriert.

Variationen

Solltet Ihr verschiedene Fernbedienungen für die Produktfamilie besitzen oder so wie ich eine die 8 Rolllädenmotoren bedienen kann, könnt Ihr bei nicht dokumentierten Protokollen trotzdem die Funktion der einzelnen Bytes herausarbeiten.

Spielt jede Tastenkombination durch, extrahiert die Meldungen aus dem FHEM-Log und legt sie in separaten Dateien ab die ihr z.B. mit Motor, Richtung, Fernbedienung kennzeichnet.

Signal analysieren

Habt Ihr nun den Punkt erreicht an dem Ihr reproduzierbar (hinreichend stabil erfasste) (Teil-)Code-Sequenzen (oft in mehrfacher, identischer Wiederholung) im FHEM-Log seht, geht es ans Entschlüsseln. Auch hier wieder der einfache Fall: SIGNALduino kennt den Hersteller bzw. Device-Typ schon und legt automatisch ein FHEM-Device an (da das aber öfter nicht der Fall sein wird, muss man hier weiterarbeiten).

Wenn ein Signal demoduliert wurde ist man den Bits und Bytes schon einen Schritt näher gekommen.

Gehen wir wieder von unserem Beispiel aus:

P0=-13020;P1=15916;P2=-398;P3=415;P4=4008;P5=-794;P6=812;D=01232323232323232323232324532653265353532653262653265326 26262626265353532653265326532653535326265353535353265353532653262653265353265353535353535353265326;

Wie ist diese Sequenz zu interpretieren?

Anhand der anfänglich gelisteten Puls-Beschreibungen Px= (Aktiv-Indikator/Dauer):

  • Es startet mit einer Pause D=0123232323232
  • gefolgt von einem Signal D=0123232323232 in der Länge von ca. 16 ms (15916 µs).
  • danach folgt ein Sync-Block D=0123232323232... bei dem jeweils Pärchen von 400 µs Pause/400 µs Signal wiederholt werden.
  • Sync- und Datenteil sind durch einen Puls von 4 ms [P4=4008] getrennt D=0123232323232323232323232453265
  • gefolgt vom Datenteil D=0123232323232323232323232453265....

Beim Datenteil wird es etwas komplizierter. Hier sind immer ein kurzer (2 oder 3) und ein langer (5 oder 6) Wert kombiniert. Folglich muss man bei der Interpretation zwischen Aktiv-Indikator (Vorzeichen) und Dauer differenzieren. Ein Pärchen ist immer 1.200 µs lang. In der Mitte dieser Zeitscheibe kann der übertragene Wert folglich eine Pause oder ein Signal sein.

Beispiel: Den Vorspann P0=-32001;P1=15874;P2=-364;P3=447;P4=4060;P5=-762;P6=853;D=01232323232323232323232324 (bestehend aus Puls-Beschreibungen und initialer Puls-Aktivität) lassen wir mal außen vor und konzentrieren uns auf den nachfolgenden echten Nutz-Daten-Teil (hinsichtlich dessen logischer Protokoll-Umformung hin zur finalen Nutz-Datenwort-Sequenz):

53265326535326535326265353262653265353535326265353265326262653265326265353535353532653535353262653265353265353535353535353532626 (rohe Abfolge der Puls-Typen)

lSsLlSsLlSlSsLlSlSsLsLlSlSsLsLlSsLlSlSlSlSsLsLlSlSsLlSsLsLsLlSsLlSsLsLlSlSlSlSlSlSsLlSlSlSlSsLsLlSsLlSlSsLlSlSlSlSlSlSlSlSlSsLsL (als sSlL-Notation)

1 0 1 0 1 1 0 1 1 0 0 1 1 0 0 1 0 1 1 1 1 0 0 1 1 0 1 0 0 0 1 0 1 0 0 1 1 1 1 1 1 0 1 1 1 1 0 0 1 0 1 1 0 1 1 1 1 1 1 1 1 1 0 0 (als Bitfolge)

10101101 10011001 01111001 10100010 10011111 10111100 10110111 11111100 (Gruppierung auf Bit-Datenworte)

AD99 79A2 9FBC B7FC (als Hex-Datenworte)

Die Analyse basiert auf folgenden Annahmen (mit Beispiels-Werten)

  • Mapping von Puls-Werten auf logische Zustände: wenn 800-ter Pulse: Wert kleiner 0 (z.B. -800) ist ein l (long low), größer 0 ist L (long high), wenn 400-ter Pulse: analog, gemapped auf sS (short low/high) - "sSlL-Notation"...
  • Weiter angenommen es werden immer 2 Frequenzen/Zustände verglichen (lS => 1 und sL => 0) (ein Gerät hat ja salopp gesagt nicht mehr zu tun als nur 2 Zustände - 0er und 1er Daten-Bits - robust codiert über Funk zu vermitteln - aus diesen Bits ergibt sich dann zusammengefügt ein gesamtes Geräte-Datenwort, welches anschließend in Bit-Bereiche wie Temperatur, Feuchte, Wind zerlegungs-analysiert werden muss, anhand charakteristischer Werte-Veränderungen, die man idealerweise auch direkt in z.B. einem Sensor-LCD-Display erkennen kann)

Abseits-Bemerkung: Sollte man mit dem SIGNALduino ein FSK-Signal empfangen/interpretieren (im Gegensatz zu "normaleren" ASK, OOK), so hängt die Bewertung davon ab, ob man die Sendefrequenz+Frequenzhub oder Sendefrequenz-Frequenzhub empfängt. Die Bedeutung von 0/1 wird dann negiert. FIXME diese Beschreibung ist (mir) zu unklar, eine Verbesserung sollte erarbeitet werden.

Weitere wichtige Tips:

  • es ist wohl sinnvoll, zu versuchen, sich evt. an einem längsten Puls (das ist nämlich evt. eine Sync-Pause) zu orientieren, um nachfolgende Bereiche evt. als startendes Bit-Datenpaket identifizieren zu können
  • man sollte die Pulsfolge per Textsuche analysieren, in einem Editor/Reader, der Such-Texte in einer Zeile mehrfach farbig markieren kann (less, ...) - bei markiertem Suchtreffer kann man dann Teil-Folgen identifizieren, welche sich deterministisch wiederholen - diese sind dann wohl offensichtlich codierte Bit-Daten, welche es passend zu entschlüsseln gilt
  • die identifizierten Merkmale sind dann als ein neues Protokoll (falls kein bereits existierendes Protokoll zu unpräzise formuliert sein sollte!) in FHEM/lib/signalduino_protocols.hash hinzuzufügen (Angabe präziser Durchschnittswerte von Basis-Takt, Gesamt-Patternlänge, Puls-Pause-Verhältnisse, ... - Details dieses Protokolls siehe Header dieser Datei), und dann muss ein reload 00_SIGNALduino gemacht werden, um dies zu testen (hier: beim sduino-Device temporär(!! - hoher Platzbedarf...) Attribute verbose 5 und debug 1 setzen!)
  • für Beispiele einer Protokoll-Implementierung sollte man sich wohl auch die History (entsprechende Commits) im RFFHEM git repository ansehen
  • es ist evt. sinnvoll, sich die Verarbeitungskette anhand von Empfang/Senden bereits funktionsfähiger Protokolle / Geräte zu verdeutlichen, bevor man selber loslegt, neue Geräte (Protokolle) zu unterstützen
  • richtige Verarbeitung von empfangenen Funk-Pattern (oder in leicht abgeänderter Form derselben) kann man wohl besonders effizient debuggen, indem man sich einen Dummy-SIGNALduino anlegt:

define sduino_dummy SIGNALduino none

In diesen kann man dann die gewünschten zu unterstützenden Pattern einimpfen:

get sduino_dummy raw MC;;LL=-653;;LH=665;;SL=-317;;SH=348;;D=D55B58;;C=330;;L=21;;

Alle Strichpunkte (Semikolon) müssen hierbei jeweils escaped werden (durch Wiederholung), vermutlich da sie in FHEM's Perl-Code-Umgebung sonst als normale sequence points interpretiert würden.

Weitere für einen Test verwendbare Beispiel-Pattern siehe RFFHEM git repository, in Datei: FHEM/14_SD_BELL.pm.

Wenn alles richtig läuft (weil man es richtig implementiert hat), dann sollte die gesamte Kette von Pattern-Fingerprinting bis hin zu Dispatch an Datenwort-Modul und dortige Verarbeitung bis hin zu einem entsprechend sichtbaren Auftauchen der Device-Aktivitäten/-Autocreate in FHEMWEB Event Monitor page und/oder Log durchlaufen werden.

Steuern

Die empfangenen, im Log ausgewiesenen Sequenzen könnt Ihr als Basis für das Senden verwenden. Relevant sind dabei Puls-Beschreibungen P0...P7 sowie D (Data). Die RSSI-Empfangsstärke wird beim Empfang als R= ausgewiesen. Beim Senden steht R jedoch für die Anzahl der Wiederholungen. Entnehmt die Details und Möglichkeiten bitte der Dokumentation Commands.

Signal-Protokoll-Beschreibung verfeinern

Sobald man bei einem Gerät initial erfolgreich empfangen / dekodieren (/ senden?) konnte, sollte man folgendes noch beachten:

Es ist recht wichtig, dass jede Protokoll-Beschreibung eines Geräte-Signals möglichst präzise Geräte-konforme Werte aufführt:

wenn mehrere Protokoll-Beschreibungen aufgrund von zu ungenauen Werten jeweils als passend betrachtet werden, dann landet das Signal-Pattern (auch) bei falschen Protokoll-Beschreibungen - die weitere Zuordnung (dies ist eine Routing-Entscheidung!) hin zu spezifischen Geräte-Datenwort-FHEM-Modulen ist also gefährdet / sinnlos:

  • evt. ganz fehlgeschlagen aufgrund von Falsch-Zuordnung
  • viel sinnlose Noise im Log, weil gleich mehrere Pfade angeblich passen und dann "noch nicht supported"-Fehlermeldungen werfen

Mit stark steigender Anzahl von bekannten Protokoll-Beschreibungen dürfte dieses Problem immer schlimmer werden.

Daher sollte man folgendes beachten:

  • sicherstellen, dass nicht eine andere - also bereits existierende! - Protokoll-Beschreibung eigentlich die richtige gewesen wäre, welche nur aufgrund von Impräzisionen das aktuelle völlig Protokoll-gleiche Gerät NICHT erkannt hat (zudem: "ähnlich" aussehende Protokolle, die allerdings von klar unterschiedlichen Geräte-Familien erzeugt werden, sollten NICHT in der gleichen Protokoll-Beschreibung zusammengemischt werden, und man sollte diese Abgrenzung dort auch klarstellen: durch Referenz-Hinweise auf entsprechende fast gleiche Protokoll-Beschreibungen dort)
  • length_min , length_max möglichst passend restriktiv spezifizieren (also z.B. 12 , 12)
  • clockabs-Basistakt-Mittelwert möglichst präzise ermitteln
  • ((die Perl-Demodulations-Implementierung - in 00_SIGNALduino.pm etc. - ebenfalls auf möglichst restriktive Checks / Wertebereiche trimmen))

Ermittlung eines präzisen clockabs-Basistakt-Mittelwerts dürfte folgendermaßen gut machbar sein:

  • einige Geräte-Pattern aus dem Log fischen
  • dort die clockabs-Werte suchen (CP=x verweist darauf)
  • aus diesen dann einen Mittelwert bilden, damit man die größte Präzision erreicht
  • evt. sogar längere (Sync-)Pulse (z.B.: 15x clockabs Low, 1x clockabs High) heranziehen, um durch Mittelung (+ Teilung) über viele dieser z.B. 15x wiederholten Pulslängen einen daraus resultierend maximal präzisen clockabs-Basistakt-Mittelwert zu ermitteln
  • evt. ist es auch hilfreich, den im Gerät verbauten Quarz zu berücksichtigen - u.U. lässt sich hieraus (falls eine solche Verarbeitung im Gerät tatsächlich Timer-mäßig relevant sein sollte!) ein sehr präziser da "mechanisch" passender Puls-Takt-Wert ermitteln (Pseudo-Beispiel:

(1 / 8MHz) * 2048 [digitaler Teiler] = 0.256ms == 256us ); wobei der mechanische Gerätetakt evt. doch erstaunlich anders sein könnte als die von SIGNALduino erfassten Werte (inwiefern das dann hinsichtlich Rx-/Tx-Präzision relevant ist - wer weiß...)

Development / patch submission

Es ist evt. empfehlenswert, auf github einen eigenen Fork des RFFHEM-Upstream-Repositories zu erstellen - dann kann man dort seine Entwicklung durchführen:

  • Änderungen durchführen (im korrekten Branch)
  • alles committen
  • controls_signalduino.txt updaten (wird via github actions automatisch aktualisiert), sonst kann nicht über den update Befehl installiert werden!
  • mit dem üblichen FHEM-Befehl (update all ..., aber eben sinnigerweise unter Angabe der URL seines eigenen Repositories!) seine eigenen Änderungen jeweils korrekt verwaltend und updatend austesten
  • evt. hier jeweils reload BEARBEITETES_MODUL nötig
  • wenn das alles passt, hat man bereits seinen eigenen Fork fix und fertig (und authentisch getestet) und kann somit direkt - evt. nach einem bereinigenden git rebase -i @{u} - einen Pull Request daraus machen (anders ausgedrückt: "direkt kontext-integrierte Entwicklung", "am Puls der Zeit", "mit voller Tool-Unterstützung"). Dies am besten vollständig Automatisierungs-gekapselt durch ein Shell-Script (FIXME: am besten hier einfach direkt hier präsentieren?), welches an FHEM den update all ... request schickt (über telnet, Port 7072) und den reload BEARBEITETES_MODUL durchführt.

SIGNALduino - FSK

Dieses Kapitel geht davon aus, dass ihr einen SIGNALduino für alle weiteren Schritte nutzt.

Aktuell laufen Bestrebungen, den SIGNALduino FSK-fähig zu machen: siehe FSK mit SIGNALduino (vormals https://forum.fhem.de/index.php/topic,82379.0.html)

Die Summary der CC1101-Settings findet ihr hier.

FSK Senden

Die ersten Bits des CC1101-Register 12 MDMCFG2 bestimmen die Übertragungsweise: 000 = 2-FSK 001 = GFSK 011 = ASK/OOK 100 = 4-FSK

Schaut Euch den aktuellen Registerinhalt an, bevor Ihr ihn ändert. Am einfachsten geht das über get <mysduino> ccreg 99 Ihr müsst beim angezeigten Wert die ersten drei Bits entsprechend abändern, also z.B. aus 0x30 dann 0x10 für GFSK statt OOK machen. Das Register wird über set <mysduino> raw W1410 abgeändert (bitte beachtet das Offset von 0x02 für das Beschreiben eines Registers, 14 adressiert Register 12).

Nun könnt Ihr FSK senden. Das im URH angezeigte Spektrum sollte nun zwei Spitzen aufweisen. Ihr seht daneben vermutlich auch weitere kleine links und rechts daneben. Das liegt daran, dass es Oberwellen gibt. Bei 2-FSK sind dies mehr als bei dem geglätteten GFSK.

Sendefrequenz und Frequenzhub

FSK, Trägerfrequenz minus Hub
FSK, Trägerfrequenz plus Hub

Bei OOK wird das Funksignal ein- und ausgeschaltet, um die bits als 0 und 1 darzustellen. Bei FSK sieht das anders aus. Zur Übertragung wird ein permanentes Signal ausgestrahlt; die Darstellung der bits 0 und 1 erfolgt durch Erniedrigung bzw. Erhöhung der Frequenz. Folglich gilt es sowohl die Trägerfrequenz als auch den Frequenzhub zu ermitteln. Das bit 0 wird i.d.R. durch Trägerfrequenz minus Hub, das bit 1 durch Trägerfrequenz plus Hub dargestellt.

In diesem Beispielspektrum eines FSK-Signals ist ersichtlich, dass die untere Frequenz bei ca. 868,233 Mhz und die obere bei ca. 868,281 Mhz liegt. Die Trägerfrequenz liegt folglich in der Mitte bei 868,257 MHz und der Frequenzhub beträgt ca. 24 kHz.

Ermittlung der Frequenzen

Wie im OOK-Kapitel bereits angesprochen, ist eine Messung mit Hilfe eines SDR-Sticks hilfreich. Doch Vorsicht - diese Sticks sind oftmals nicht geeicht und die angezeigte Frequenz wird "relativ" genau gemessen. Was aber hilft ist ein Vergleich Original/Kopie. Messt mit dem SDR-Stick unter Nutzung eines Programms wie URH die Frequenzen, sendet mit dem SDUINO ebenfalls ein Signal auf einer von Euch vorgegebenen Frequenz. Nehmt als Basis für den Ver- bzw. Abgleich die von Euch im SDUINO vorgegebene Frequenz. Die ist für die weiteren Aktivitäten relevant. Die Abweichung könnt Ihr in der URH-Software zur Frequenzkorrektur vorgeben, dann werden identische Werte angezeigt.

Hub

Da hilft Euch das RF Studio für den CC1101. Der darin ermittelte Wert ist in das Register 15 DEVIATN zu übertragen. Bei 25 kHz Hub ist das der Wert 40, der mittels set <mysduino> raw W1740 an den CC1101 des SDUINO übermittelt wird.

Wenn Ihr soweit seid, sollten die Funksignale der Original-Fernbedienung und Eures SDUINO ähneln.

Spektrum Original-Fernbedienung
Spektrum SDUINO GFSK

Baudrate

Beim SDUINO übernimmt der CC1101 die Funktion eines Modems. Die Signalaufbereitung bzw. -erzeugung erfolgt im Arduino. Das können wir auch für das Senden von FSK Signalen nutzen. Der CC1101 bietet eine Fülle weiterer Optionen (Sync, FIFO etc.), die aber eher für Spezialisten geeignet sind.

Welche Baudrate soll/muss ich angeben? Zunächst mal gilt es folgende Teilstrecken zu unterscheiden: FHEM <-> Arduino <-> CC1101 <-> Sendesignal

Die Baudrate zwischen FHEM und dem Arduino wird in FHEM vorgegeben. Die für den CC1101 angegebene und mittels get <myduino> ccconf ausgegebene Baudrate ist die zwischen dem Arduino und dem CC1101. Mit dieser Baudrate wird das Funksignal gesampled.

Beim Empfang interpretiert der Arduino den Signalpegel und erkennt die Übergänge zwischen 0 und 1. Es wird die Dauer des jeweiligen Signals ermittelt und einem Parameter (Puls?) 0-7 zugeordnet. Auf diese Weise wird die gesamte empfangene Codesequenz beschrieben.

RIO-Signal decodiert

Die Baudrate lässt sich im CC1101 nur bedingt präzise einstellen, da dafür nur ein Byte zur Verfügung steht.

Ich habe bei der obigen Sequenz die Baudrate bzw. SCLK aus dem Vorspann (Preamble) ermittelt und bin auf 2.482 Baud gekommen. Für die Übertragung habe ich aber die 10fache Rate verwendet, um die Steuerung des Zustandes 0/1 dem Arduino und nicht dem CC1101 zu überlassen. Statt einer 0 werden dann halt 10x 0 übertragen. Auf Sendeseite ändert sich dadurch nichts. Die Software URH arbeitet ähnlich. Das Signal wird z.B. mit 1 MHz gesampled. Um auf die ermittelte Baudrate und eine reale Darstellung zu kommen, gebe ich 402 Samples/Symbol (Symbol=bit) ein.

Das Ergebnis:

Vergleich RIO/SDUINO-Signale

Codesequenzen

Die Interpretaion des low- und high-Zustandes hängt von der Sende- und Empfangsfrequenz ab. Wenn Ihr im OOK-Modus Sequenzen mitgeschnitten habt werden die möglicherweise anders interpretiert als die mittels FSK empfangenen. Deshalb: Sequenzen mit der Original-Fernbedienung neu erzeugen und mitschneiden. Achtet dabei darauf, dass diese lang genug sind, um das komplette Steuerungssignal mitzuschneiden. Die Preamble ist recht auffällig (bei mir 01232323 ...). Die wiederholt sich nach dem eigentlichen Steuerungssignal. Ab hier könnt Ihr also abschneiden. Ferner empfiehlt sich, das mitgeschnittene Signal zu dekodieren und in Hex darzustellen. Dann erkennt Ihr, ob identische Inhalte/Sequenzen mitgeschnitten wurden. Das trennt die Spreu vom Weizen.

Damit konnte ich mein Problem meines unbekannten Funkprotokolls (RIO-Fernbedienung) letztendlich lösen.

Konfiguration

Last but not least meine Konfiguration: SDUINO Firmware war die Version v3.4.1_dev_21.12

Register-Settings:

  • Trägerfrequenz: 868.302 MHz
  • Deviation: 25 kHz
  • Bandwidth: 58 kHz
  • Baudrate: 24.795 kBaud
  • Modulation: GFSK
ccregAll: 

ccreg 00: 0D 2E 2D 47 D3 91 3D 04 32 00 00 06 00 21 65 6F
ccreg 10: F9 F4 18 23 B9 40 07 00 18 14 6C 07 00 91 87 6B
ccreg 20: F8 56 11 EF 2D 12 1F 41 00 59 7F 3F 88 31 0B 

Configuration Register Detail (address, name, value):
0x00 IOCFG2   - 0x0D
0x01 IOCFG1   - 0x2E
0x02 IOCFG0   - 0x2D
0x03 FIFOTHR  - 0x47
0x04 SYNC1    - 0xD3
0x05 SYNC0    - 0x91
0x06 PKTLEN   - 0x3D
0x07 PKTCTRL1 - 0x04
0x08 PKTCTRL0 - 0x32
0x09 ADDR     - 0x00
0x0A CHANNR   - 0x00
0x0B FSCTRL1  - 0x06
0x0C FSCTRL0  - 0x00
0x0D FREQ2    - 0x21
0x0E FREQ1    - 0x65
0x0F FREQ0    - 0x6F
0x10 MDMCFG4  - 0xF9
0x11 MDMCFG3  - 0xF4
0x12 MDMCFG2  - 0x18
0x13 MDMCFG1  - 0x23
0x14 MDMCFG0  - 0xB9
0x15 DEVIATN  - 0x40
0x16 MCSM2    - 0x07
0x17 MCSM1    - 0x00
0x18 MCSM0    - 0x18
0x19 FOCCFG   - 0x14
0x1A BSCFG    - 0x6C
0x1B AGCCTRL2 - 0x07
0x1C AGCCTRL1 - 0x00
0x1D AGCCTRL0 - 0x91
0x1E WOREVT1  - 0x87
0x1F WOREVT0  - 0x6B
0x20 WORCTRL  - 0xF8
0x21 FREND1   - 0x56
0x22 FREND0   - 0x11
0x23 FSCAL3   - 0xEF
0x24 FSCAL2   - 0x2D
0x25 FSCAL1   - 0x12
0x26 FSCAL0   - 0x1F
0x27 RCCTRL1  - 0x41
0x28 RCCTRL0  - 0x00
0x29 FSTEST   - 0x59
0x2A PTEST    - 0x7F
0x2B AGCTEST  - 0x3F
0x2C TEST2    - 0x88
0x2D TEST1    - 0x31
0x2E TEST0    - 0x0B

Finale

Nach Aktivierung der vormals ausgeschalteten Message-Typen im SIGNALduino werden nunmehr SD_Keeloq-Devices angelegt.

Der SIGNALduino erkennt

 2020.01.12 14:33:03 4: mySIGNALduino: Parse_MS, Decoded matched MS Protocol id 88 dmsg P88#74D21B18008B48058 length 68  RSSI = -32
 2020.01.12 14:33:03 5: mySIGNALduino: Dispatch, P88#74D21B18008B48058, test ungleich: disabled
 2020.01.12 14:33:03 5: mySIGNALduino: Dispatch, P88#74D21B18008B48058, -32 dB, dispatch
 2020.01.12 14:33:03 5: mySIGNALduino: dispatch P88#74D21B18008B48058
 2020.01.12 14:33:04 2: mySIGNALduino: SD_Keeloq_Parse Unknown device unknown with Code 012D100 detected, please define (rawdate=74D21B18008B48058)
 2020.01.12 14:33:04 2: autocreate: define SD_Keeloq_012D100 SD_Keeloq 012D100
 2020.01.12 14:33:04 2: autocreate: define FileLog_SD_Keeloq_012D100 FileLog ./log/SD_Keeloq_012D100-%Y.log SD_Keeloq_012D100
 2020.01.12 14:33:04 4: mySIGNALduino: Parse_MS, Matched MS Protocol id 91.1 -> Atlantic security
 2020.01.12 14:33:04 5: mySIGNALduino: Parse_MS, Starting demodulation at Position 3
 2020.01.12 14:33:04 4: mySIGNALduino: Parse_MS, last part pair=2 reconstructed, last bit=0
 2020.01.12 14:33:04 4: mySIGNALduino: Parse_MS, Matched MS Protocol id 87 -> JAROLIFT
 2020.01.12 14:33:04 5: mySIGNALduino: Parse_MS, Starting demodulation at Position 2
 2020.01.12 14:33:04 4: mySIGNALduino: Parse_MS, last part pair=1 reconstructed, last bit=1
 2020.01.12 14:33:04 4: mySIGNALduino: Parse_MS, Matched MS Protocol id 88 -> HCS300/HCS301
 2020.01.12 14:33:04 5: mySIGNALduino: Parse_MS, Starting demodulation at Position 2

und routet die Requests an das Modul SD_Keeloq weiter. Der Hinweis auf HCS301 führt auf die richtige Spur. Das analysierte Protokoll KeeLoq ist im Data Sheet des Microchip HCS301 (KeeLoq Code Hopping Encoder) beschrieben. Somit wurde aus einem unbekannten Funkprotokoll letztlich ein bekanntes.

Mittlerweile ist das Protokoll als model enjoy_motors_HS in das Modul SD_Keeloq aufgenommen.

CUL - FSK und Co.

Dieses Kapitel geht davon aus, dass ihr einen CUL für alle weiteren Schritte nutzt.

Es befindet sich aber noch im Aufbau....

FAQ

Woran genau wird erkannt ob ein Signal ShortHigh, bzw ShortLow ist?

Diese Begriffe kommen nur bei der Manchester Codierung zum Einsatz.

Die Bestimmung short High / Low erfolgt einfach dadurch, ob gesendet wird oder ob gerade eine Pause eingelegt wird.

Short und Long wird einfach durch die Kalkulation der Dauer ermittelt.

Die Dauer eines short Intervalles ist in der Regel halb so lang wie die von einem long und entspricht der Taktrate. Bei der ganzen Berechnung müssen natürlich Toleranzen berücksichtigt werden.

Beispiel einer empfangenen Sequenz

P0=-32001;P1=15874;P2=-364;P3=447;P4=4060;P5=-762;P6=853;D=01232323232323232323232324

P0, P2 + P5 haben ein negatives Vorzeichen. Damit ist gemeint, dass für eine Zeit von 762µs (P5) kein Signal empfangen wurde (Low). Die positiven sind dann High.

Generell sind die absoluten, gemessenen low-Werte bei Signalduino kürzer als die high-Werte.

Wie bereits ausgeführt, werden für die Daten die Pulse P2, P3, P5 und P6 genutzt. Der Mittelwert [ (P2 + P3 + P5 + P6) / 6 ] der absoluten Werte ergibt 404µs für ein Short und 808µs ein Long (2xShort). Idealisiert werden 400µs angenommen.

Das Umwandeln der Pulse in den Daten in eine "sSlL-Notation" vereinfacht die Erkennung von Mustern (in mehreren Nachrichten variieren auch die Pulse). Dass ein lS=1 und sL=0 entspricht, ist nur eine willkürlich angenommene Arbeitshypothese, die bis dato ganz gute Ergebnisse produziert hat.

Links