Z-Wave USB Stick Protokoll

Begonnen von Jochen0x90h, 24 Dezember 2017, 00:08:41

Vorheriges Thema - Nächstes Thema

Jochen0x90h

Hallo,

Gibt es eigentlich eine Dokumentation für die Kommunikation mit dem Z-Wave USB Stick? Der Code (10_ZWave.pm) ist ja leider nicht so gut dokumentiert, aber idealerweise gäbe es eine Doku im Wiki.

Folgendes habe ich bereits entschlüsselt (alle Werte in hex, Fragezeichen hinter Bytes mit unbekannter Bedeutung).

Frage 1: Was bedeuten die FLAGS? Wert 5 habe ich von http://www.digiwave.dk/en/programming/an-introduction-to-the-z-wave-protocol/

Frage 2: Warum kommt in der Variante mit callbackId nach der Response ein Request vom USB Stick, der die callbackId enthält und was bedeutet 00 00 02? Ich habe folgende Beobachtung gemacht: Sendet man einen weiteren Request (mit neuer callbackId) zum Stick bevor der Request vom Stick kommt, wird die callbackId überschrieben, d.h. beide Requests vom Stick, die dann kommen, enthalten die neue callbackId. Ich gehe also davon aus, dass ein weiterer Request an den Stick warten muss, bis er den Request mit der callbackId gesendet hat.
Fragt man einen Wert ab, kommt ein weiterer Request vom Stick, der den Wert enthält.

Messages
FRAME = SOF length TYPE FUNCTION data FLAGS callbackId checksum
   SOF = 01
   TYPE
      REQUEST = 00
      RESPONSE = 01
   FUNCTION
      DISCOVER_NODES = 02
      APPLICATION_COMMAND_HANDLER = 04
      SEND_DATA = 13
      GET_NODE_INFO = 41   
   FLAGS
   callbackId (only for SEND_DATA requests from PC)
   checksum = xor of frame bytes without first byte (negated)
ACK = 06
NACK = 15
CAN = 18

Each FRAME is acknowledged with an ACK if the CHECKSUM is ok and with a NACK if there is a checksum error. CAN means CANCEL and is sent when a next FRAME is sent while the other end expects an ACK.

Protocol
Without callbackId
send REQUEST
receive ACK
receive RESPONSE
send ACK

With callbackId
send REQUEST (with callbackId)
receive ACK
receive RESPONSE
send ACK
receive REQUEST (with callbackId)
send ACK
(Frage 2: senden eines neuen REQUEST erst jezt erlaubt?)

Example: Get BASIC value of node 4 (value is reported in an additional request)
send SOF length=09 REQUEST=00 SEND_DATA=13 node=04 length=02 BASIC=20 GET=02 FLAGS=05 callbackId=37
receive ACK
receive SOF length=04 RESPONSE=01 SEND_DATA=13 SENT=01
send ACK
receive SOF length=07 REQUEST=00 SEND_DATA=13 callbackId=37 00? 00? 02?
send ACK
receive SOF length=09 REQUEST=00 APP_HANDLER=04 00? node=04 length=03 BASIC=20 REPORT=03 value=01
send ACK

rudolfkoenig

ZitatGibt es eigentlich eine Dokumentation für die Kommunikation mit dem Z-Wave USB Stick?
Mir ist keine bekannt, vermutlich bekommt man sowas, wenn man die Mitgliedsgebuehren bei der Z-Wave Alliance entrichtet und ein NDA unterschreibt. Ich habe zwapi angeschaut (Vorgaenger von z-way), viel geraten und probiert.

ZitatDer Code (10_ZWave.pm) ist ja leider nicht so gut dokumentiert
Das klingt wie ein Vorwurf. Ich bin bis heute nicht sicher, dass die Kommunikation in FHEM nach der Spezifikation implementiert ist, ich kann hoechstens meine Beobachtungen dokumentieren, und das ist in etlichen Diksussionen hier in Forum nachzulesen. Ich will der Allianz keine Konkurrenz mit einer auf Vermutungen basierenden Doku machen.

ZitatWas bedeuten die FLAGS? Wert 5 habe ich von http://www.digiwave.dk/en/programming/an-introduction-to-the-z-wave-protocol/
Ich frage mich, warum du die Frage hier stellst, und nicht da.
Ich kann nur sagen, dass mit 25 ExplorerFrames zugelassen werden, mit 05 nicht.

ZitatWarum kommt in der Variante mit callbackId nach der Response ein Request vom USB Stick, der die callbackId enthält
Das ist doch Sinn einer Callbackid: damit man die Antworten auf die Anfragen zuordnen kann. Ist nur in seltenen Faellen sinnvoll, es ist naemlich nicht erlaubt, mehrere ausstehende Anfragen an dem Controller zu stellen. FHEM kam lange ohne Callbackid aus, man hat mich nur ueberredet es zu verwenden :)

krikan

Zitat von: Jochen0x90h am 24 Dezember 2017, 00:08:41
[..] aber idealerweise gäbe es eine Doku im Wiki.
Kannst Du gerne machen; ich sehe aber die Notwendigkeit nicht, da das die wenigsten FHEM-Anwender interessieren wird. Zudem findet sich vieles in den Weiten des WWW und Hinweise darauf auch verlinkt aus unserem Wiki. Ok, man muss suchen.  :)

ZitatFrage 1: Was bedeuten die FLAGS? Wert 5 habe ich von http://www.digiwave.dk/en/programming/an-introduction-to-the-z-wave-protocol/
https://github.com/yepher/RaZBerry/tree/master/docs
http://dz.prosyst.com/pdoc/mBS_SH_SDK_8.1/modules/zwave/api/driver/index.html
http://zwavepublic.com/downloads

ZitatFrage 2: Warum kommt in der Variante mit callbackId nach der Response ein Request vom USB Stick, der die callbackId enthält und was bedeutet 00 00 02?
Ergibt sich hinsichtlich 1. Teil auch aus den Links. Die in neueren SDKs kommenden laengeren Rückgabewerte, die im Modul nicht ausgewertet werden, habe ich noch nirgends dokumentiert gefunden. Falls Du die Bedeutung findest, würde mich eine Info freuen.

Gruß, Christian

throbin

Hi,

der Stick arbeitet mit dem Sigma Controller (ZWave Plus). Auf der Homepage gibt es einige Links zu Dokumentationen, vielleicht hilft's.

https://z-wave.sigmadesigns.com/design-z-wave/z-wave-public-specification/

LG

Jochen0x90h

#4
Vielen Dank für die Infos schonmal. Also ich könnte anbieten im Wiki ein paar grundlegende Infos konzentriert zusammenzutragen und für die Details dann auf die offiziellen Dokumente zu verweisen. Falls ihr die Idee gut findet, würde ich einen Account beantragen. Am besten sagt ihr mir noch wo genau im Wiki das hin soll.
Folgende Infos würde ich da eintragen:

  • Messagetypen (Frame, ACK/NACK)
  • Kommunikationsprotokoll (Request/Response, callbackId)
  • Inklusion und Node-Info abfragen wie unterstützte Command-Classes und Bezeichnung
  • Commands, jedoch nur am Beispiel von BASIC und max. 1-2 weiteren
  • Batteriebetriebene Geräte

Es fehlt mir erstmal nur noch das Abfragen der unterstützten Command-Classes und Device-Name (z.B. FGR-222). Im Dokument Z-Wave Application Command Class Specification in Sektion 3.4 steht zwar was zum Node Information Frame (NIF), aber nicht wie das in ein FRAME eingebettet ist und wie man Nodes dazu bewegt, ein solches Frame (außerhalb der Inklusion) mal zu senden ("A NIF will be sent to the controller when a node is to be included in the network, excluded from the
network or upon request" -> wie geht "upon request"?)

Zum Protokoll:
ZitatDas ist doch Sinn einer Callbackid: damit man die Antworten auf die Anfragen zuordnen kann. Ist nur in seltenen Faellen sinnvoll, es ist naemlich nicht erlaubt, mehrere ausstehende Anfragen an dem Controller zu stellen. FHEM kam lange ohne Callbackid aus, man hat mich nur ueberredet es zu verwenden :)
Das heißt ja dass Callbackid eigentlich keinen Sinn macht :), auch ist die Frage warum das nicht Teil der Response ist sondern ein extra Request kommt. Aber das muss man wohl einfach als gegeben akzeptieren, oder weiß jemand warum diese Design-Entscheidung von den Z-Wave Erfindern getroffen wurde?

Hier mein Wissensstand zu Commands:

Commands
Commands can be sent to a node in the data section of a FRAME where FUNCTION is SEND_DATA:
SOF length REQUEST SEND_DATA nodeId COMMAND FLAGS callbackId checksum
   nodeId = id of target node

COMMAND = length CLASS ID data
   length = length of COMMAND
   CLASS (command class 1 or 2 bytes)
      BASIC = 20
      CONFIGURATION = 70
      ...
   ID (class specific command id's)
      GET
      SET
      REPORT
      ...
   data = data of command

krikan

Zitat von: Jochen0x90h am 25 Dezember 2017, 21:46:32
Es fehlt mir erstmal nur noch das Abfragen der unterstützten Command-Classes und Device-Name (z.B. FGR-222). Im Dokument Z-Wave Application Command Class Specification in Sektion 3.4 steht zwar was zum Node Information Frame (NIF), aber nicht wie das in ein FRAME eingebettet ist und wie man Nodes dazu bewegt, ein solches Frame (außerhalb der Inklusion) mal zu senden ("A NIF will be sent to the controller when a node is to be included in the network, excluded from the
network or upon request" -> wie geht "upon request"?)
Schau Dir in 00_ZWDongle.pm den Befehl "createNode" unter set an.
Namen liefern Dir die Geraete nicht direkt, sondern nur eine modelId, die man in Klartext übersetzen muss. Mehr in 10_ZWave.pm beim Befehl "get <device> model". Befehl gehört zur Command Class MANUFACTURER_SPECIFIC.

Zitat
Zum Protokoll:Das heißt ja dass Callbackid eigentlich keinen Sinn macht :), auch ist die Frage warum das nicht Teil der Response ist sondern ein extra Request kommt. Aber das muss man wohl einfach als gegeben akzeptieren, oder weiß jemand warum diese Design-Entscheidung von den Z-Wave Erfindern getroffen wurde?
Doch das macht Sinn. Es garantiert Dir niemand, dass eine Funkantwort nicht mehrfach und mit erheblichen Zeitversatz  ankommt und das muss man erkennen können.
Jetzt haben wir mühevoll Rudi zur CallbackId überredet und jetzt streust Du hier Zweifel...   ;)

Zum Wiki: Bin da unentschieden, da ich Angst habe, dass wir Halbwissen dokumentieren und Pflege kaum zu gewaehrleisten ist. Letztlich ist das "Wissen" auch im Perl-Code festgehalten und immer aktuell.

Jochen0x90h

Zitat von: krikan am 25 Dezember 2017, 22:21:30
Zum Wiki: Bin da unentschieden, da ich Angst habe, dass wir Halbwissen dokumentieren und Pflege kaum zu gewaehrleisten ist. Letztlich ist das "Wissen" auch im Perl-Code festgehalten und immer aktuell.
Ich meine auch nicht viel mehr als ich jetzt schon hier gepostet habe, so quasi die Grundidee des Protokolls, und natürlich mit Deiner Begründung für die Callbackid ;) und alles getestet. Das kann ich momentan anbieten bei FHEM beizutragen.

Ich hab es geschafft meinem Device die unterstützten Command Classes zu entlocken:
send SOF length=05 REQUEST=00 REQUEST_NODE_INFO=60 nodeId=04 FLAGS=05
receive ACK
receive SOF length=04 RESPONSE=01 REQUEST_NODE_INFO=60 SENT=01
send ACK
receive SOF length=1c REQUEST=00 APPLICATION_UPDATE=49 RESULT=84 nodeId=04 16? 04? GENERIC=11 SPECIFIC=06 CLASSES=(CONFIGURATION=70 SWITCH_BINARY=25 ...) CONTROL=(MARK=ef SWITCH_BINARY=25 ...)
send ACK

Problem ist jedoch, dass das für den Controller selbst (Node 1) nicht funktioniert:
send SOF length=05 REQUEST=00 REQUEST_NODE_INFO=60 nodeId=01 FLAGS=05
receive ACK
receive SOF length=04 RESPONSE=01 REQUEST_NODE_INFO=60 SENT=01
send ACK
receive SOF length=06 REQUEST=00 APPLICATION_UPDATE=49 FAILED=81 00? 00?
send ACK

Hast Du eine Idee woran das liegen könnte?

krikan

Aus der Erinnerung (habe es aktuell nicht nachgelesen, deshalb kontrollieren und ggfs. korrigieren):
Zitatsend SOF length=05 REQUEST=00 REQUEST_NODE_INFO=60 nodeId=04 FLAGS=05
Flags ist eine Spezialität der Controllerfunktion ZW_SENDDATA und weniger anderer Funktionen. Bei 0x60 ist das mMn nicht gefordert. Schaue dazu mal in das Dokument INS*, das hier https://github.com/yepher/RaZBerry/tree/master/docs liegt.

ZitatProblem ist jedoch, dass das für den Controller selbst (Node 1) nicht funktioniert:
Sollte korrekt sein, solange man dem Controller nicht per setNIF etwas zugewiesen hat. Letztlich kann er alles empfangen/verschicken; nur die Software muss es interpretieren können.
Der Controller hat spezielle Controllerfunktionen, zu denen es aber afaik keine offiziell veröffentlichte aktuelle Doku gibt. Nur alte Doku aus dem WWW.

ZitatIch meine auch nicht viel mehr als ich jetzt schon hier gepostet habe, so quasi die Grundidee des Protokolls, und natürlich mit Deiner Begründung für die Callbackid ;) und alles getestet. Das kann ich momentan anbieten bei FHEM beizutragen.
Dann mach ruhig. Kannst Du in der Kategorie https://wiki.fhem.de/wiki/Kategorie:Z-Wave_Components als Artikel unterbringen.
Nur zur Info: Hier https://wiki.fhem.de/wiki/Z-Wave#Wie_ist_der_Aufbau_der_Z-Wave_Messages_bzw._wie_finde_ich_bei_einem_Sendefehler_die_NodeId_des_Empf.C3.A4ngers_heraus.3F hat schon jemand den Aufbau einer ZW_SENDDATA-Nachricht dokumentiert.

Jochen0x90h

So, erstmal ein frohes Neues und die Doku ist jetzt da: https://wiki.fhem.de/wiki/Z-Wave-ZME_UZB1_USB_Dongle hoffe Euch gefällt's ;)
Inzwischen funktioniert das alles ganz gut, habe das USB Dongle ja selber mit C++ und Asio angesprochen. Vielleicht lässt sich jetzt sogar noch aufklären warum es mir nicht gelungen ist, die aktuelle Position der Jalousie (Fibaro FGR-222) von FHEM über HTTP (curl) abzufragen. Ist es richtig, dass FHEM die aktuellen Werte selbst nicht speichert sondern bei einem get Kommando über ZWave abfragt? Vielleicht kann das HTTP Modul dann nicht warten bis die Antwort von ZWave zurückgekommen ist. Alternativer Design-Ansatz wäre ja alle Werte zu speichern und zu aktualisieren sobald eine Node ein Update sendet, dann wäre man immer "auskunftsfähig".

Ein bisschen "doof" an dem ZWave USB Dongle (Controller) finde ich aber dass man so viele Schritte braucht um alle Infos einer Node zusammenzutragen. Zunächst muss man ja mit SERIAL_API_GET_INIT_DATA (02) die Liste der Nodes abfragen. Jetzt müsste man eigentlich mit ZW_GET_NODE_PROTOCOL_INFO (41) die Typen der Nodes abfragen, denn ZW_REQUEST_NODE_INFO (60) funktioniert ja nicht für den Controller selbst oder man geht einfach davon aus, dass der Controller immer Node id 1 hat. Zum Schluss muss man noch mit Command MANUFACTURER_SPECIFIC (72) das konkrete Device abfragen um zu sehen ob es MANUFACTURER_PROPRIETARY (91) Commands hat (z.B. Fibaro FGR-222). Gibt es da eine Abkürzung oder ist das einfach so?

rudolfkoenig

ZitatIst es richtig, dass FHEM die aktuellen Werte selbst nicht speichert sondern bei einem get Kommando über ZWave abfragt?
Weiss nicht genau, was du meinst, ich rate: Beim Setzen eines Parameters (Association, Konfig, etc) wird das dazugehoerige Reading nicht aktualisiert, das passiert erst nach einem passenden get. Ausnahme davon ist status (on/off/etc).

ZitatVielleicht kann das HTTP Modul dann nicht warten bis die Antwort von ZWave zurückgekommen ist.
Get laeuft in ZWave Modul asynchron ab, damit das monothreaded FHEM nicht blockiert wird. Das Ergebnis wird asynchron zum Client gesendet (mit asyncOutput), fuer HTTP muss longpoll aktiviert sein.

Jochen0x90h

Zitat von: rudolfkoenig am 02 Januar 2018, 10:21:06
Weiss nicht genau, was du meinst, ich rate: Beim Setzen eines Parameters (Association, Konfig, etc) wird das dazugehoerige Reading nicht aktualisiert, das passiert erst nach einem passenden get. Ausnahme davon ist status (on/off/etc).
Wenn man die Jalousie mit dem Schalter an der Wand verstellt, versendet das Fibaro FGR-222 den neuen Zustand. Dieser wird von FHEM also nicht "mitgeschnitten" und gespeichert sondern erst, wenn man explizit einen get Befehl auslöst?


Zitat von: rudolfkoenig am 02 Januar 2018, 10:21:06
Get laeuft in ZWave Modul asynchron ab, damit das monothreaded FHEM nicht blockiert wird. Das Ergebnis wird asynchron zum Client gesendet (mit asyncOutput), fuer HTTP muss longpoll aktiviert sein.
Ich vermute mit "asynchron" ist "in einem separaten Thread" gemeint? Im Wiki steht zu longpoll: "fhem sendet eine Nachricht per longPoll sobald sich ein Status ändert" - Frage ist wie "sendet" zu verstehen ist, da HTTP ja nur Abfragen kennt, außer vielleicht mit Websockets. Wenn man mit curl einen HTTP request mit einem get Befehl an FHEM sendet ist die Frage ob der aktuelle Wert schon in der HTTP Response enthalten ist oder später irgendwie übermittelt werden muss.

rudolfkoenig

ZitatWenn man die Jalousie mit dem Schalter an der Wand verstellt, versendet das Fibaro FGR-222 den neuen Zustand. Dieser wird von FHEM also nicht "mitgeschnitten" und gespeichert sondern erst, wenn man explizit einen get Befehl auslöst?
Alles was das Geraet sendet wird in einem Reading gespeichert, es ist kein get notwendig.
Nur das, was man an dem Geraet sendet, wird nicht gespeichert, bis auf on/off/etc.

ZitatIch vermute mit "asynchron" ist "in einem separaten Thread" gemeint?
Nein. FHEM versendet die Anfrage, und wartet nicht. Wenn die Antwort eintrifft, wird der Client benachrichtigt.

ZitatFrage ist wie "sendet" zu verstehen ist, da HTTP ja nur Abfragen kennt, außer vielleicht mit Websockets.
Wenn schon Wiki, dann auch longpoll nachlesen. Ist ein bisschen Betrug: der Server schliesst nicht Verbindung, und sagt nie, er waere mit den Senden fertig, ich habe es aber nicht erfunden. Aber FHEMWEB kann auch websockets (attr WEB longpoll websocket)

ZitatWenn man mit curl einen HTTP request mit einem get Befehl an FHEM sendet ist die Frage ob der aktuelle Wert schon in der HTTP Response enthalten ist oder später irgendwie übermittelt werden muss.
Mit curl/wget kann man mW die Antwort auf einem FHEM-ZWave-get nicht bekommen, da die Antwort auf einem separaten Kanal kommt. Ueber telnet (d.h. plain TCP/IP) geht das, da hier die Antowrt auf dem gleichen Kanal kommt.

Jochen0x90h

Zitat von: rudolfkoenig am 02 Januar 2018, 12:44:25
Alles was das Geraet sendet wird in einem Reading gespeichert, es ist kein get notwendig.
Die Lösung für mein "Problem" wäre doch dann über HTTP mit curl das Reading abzufragen statt einen get Befehl zu senden. Geht das?

rudolfkoenig

Beispiel:
% curl 'http://localhost:8083/fhem?cmd=\{ReadingsVal("Comet","day-temp","")\}&fwcsrf=csrf_233210241989884&XHR=1'
22.0 C
%

csrfToken sollte man fuer solche Abfragen auf einen festen Wert setzen, per Voreinstellung wird beim FHEM-Start eins generiert.
\{ \} ist curl spezial, sonst baut curl bei sowas wie {a,b,c} mehrere URL-Requests.