e!Cockpit MQTT FbSubscribeMQTT

Zuviel Werbung?
-> Hier kostenlos registrieren
Zusätzlich habe ich jetzt noch ein Problem, wenn ich Werte sende kommen sie in MQTT.fx richtig an. Aber zum Teil werden sie in der Wago falsch dargestellt.Screenshot 2021-09-23 123451.jpg
Muss ich da noch ein Einstellung vornehmen?
 
Das scheint ein Kopierproblem mit unterschiedlichen Stringlängen zu sein. Lösche doch mal die Schreibvariable "sMessageDimmValue" vor dem MemCpy Aufruf. Also sMessageDimmValue:='';
 
Ich weiß ehrlich gesagt nicht, wie du das meinst?
Die Variable: sMessageLicht1DimValue, wird erst mit MemCpy aufgerufen.Screenshot 2021-09-24 081336.jpg


Screenshot 2021-09-24 082141.jpg
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

mit der SysMemCopy Funktion kopierst Du nur die Anzahl der empfangenen Zeichen in Deinen String. s. MIN(...) Abschnitt im Funktionsaufruf.

Wenn Dein neuer String also weniger Zeichen als Dein alter hat, dann werden nur die ersten Zeichen überschrieben, der Rest bleibt bestehen.

Z.B. erste Nachricht 10.3, zweite Nachricht 0 -> 00.3 bekommst Du dann als Ergebnis

Kann man auch an Deinen Daten sehen, Dein String ist zwei Zeichen lang '03', Du bekommst aber nru ein Zeichen übermittelt: dwRxNBytes = 1

Gruß
 
Genau das ist das Problem. Bitte den String vor dem Aufruf der SysMem.SysMemCpy() Funktion löschen! So wie ich es geschrieben habe.

IF ...xReceived THEN sMessageLicht1DimValue:=''; SysMem.SysMemCpy(...); END_IF
Zur Info: Ein STRING wird BYTE-technisch immer durch eine "0x0" abgeschlossen. Ist der neue Wert kürzer (weniger Zahlen/Zeichen) wird der alte Wert nur teilweise überschrieben und du bekommst diese komischen Zahlen. Im Übrigen würde ich keine STRING Variable als Wert nehmen, sondern REAL. Du müsstest eine temporäre Variable deklarieren und den DimWert in REAL umdeklarieren. Dein Code würde sich dann wie folgt ändern:

IF ...xReceived THEN tmpString:=''; SysMem.SysMemCpy(ADR(tmpString),...); rMessageLicht1DimValue:=TO_REAL(tmpString); END_IF
Ist etwas eleganter und mit REAL arbeitet es sich leichter ;)
 
Ok danke, das mit dem löschen habe ich jetzt verstanden.
Aber er zeigt mir immer noch die falschen Werte an, der String wird trotzdem nicht geleert.

Screenshot 2021-09-24 093820.jpg
 
Das setzen mit sMessageLicht1DimValue:=''; bringt gar nichts, weil damit nur das erste Byte auf 0 gesetzt wird. Es muss das erste Byte nach dem String auf 0 gesetzt werden, also abhängig von der empfangenen Länge.
 
Versuche es mal ohne SysMemCpy Funktion und kopiere die Bytes um.

Bitte folgende Variablen zusätzlich deklarieren:

ptSource: POINTER TO BYTE; // Quellpointer ptDestination: POINTER TO BYTE; // Zielpointer i: DWORD; // Laufvariable
Dann ersetzt du denen Code mit dem SysMemCpy durch folgendes:

IF Subscribe_LichtDimValue1.xDataReceived THEN ptSource:=ADR(aDatenMQTT_LichtDim1); ptDestination:=ADR(sMessageLicht1DimValue); FOR i:=1 TO MIN(subscriber.dwRxNBytes,SIZEOF(aDatenMQTT_LichtDim1)) DO ptDestination^:=ptSource^; ptSource:=ptSource+1; ptDestination:=ptDestination+1; END_FOR ptDestination^:=0; rMessageLicht1DimValue:=TO_REAL(sMessageLicht1DimValue); END_IF

Das sollte nun funktionieren.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen vielen Dank. es hat beides funktioniert:
Code:
IF Subscribe_LichtDimValue1.xDataReceived THEN
   ptSource:=ADR(aDatenMQTT_LichtDim1);
   ptDestination:=ADR(sMessageLicht1DimValue);
   FOR i:=1 TO MIN(subscriber.dwRxNBytes,SIZEOF(aDatenMQTT_LichtDim1)) DO
       ptDestination^:=ptSource^;
       ptSource:=ptSource+1;
       ptDestination:=ptDestination+1;
   END_FOR
   ptDestination^:=0;
   rMessageLicht1DimValue:=TO_REAL(sMessageLicht1DimValue);
END_IF

Code:
IF Subscribe_LichtDimValue1.xDataReceived THEN
    
    sMessageLicht1DimValue:='0';
    
    WagoSysPlainMem.SysMem.SysMemCpy(ADR(sMessageLicht1DimValue),ADR(aLicht1DimValue),MIN(Subscribe_LichtDimValue1.dwRxNBytes,SIZEOF(sMessageLicht1DimValue)));
    rMessageLicht1DimValue:=TO_REAL(sMessageLicht1DimValue);
    
END_IF
 
Vielen vielen Dank. es hat beides funktioniert:
Das hier:
sMessageLicht1DimValue:='0';

funktioniert aber nur für den Fall, dass der empfangene String genau 1 Byte lang ist, und das auch nicht wegen dem Text "0", welcher einem Bytewert von 48 entspricht, sondern geschuldet der Tatsache, dass dann das zweite Byte den Wert 0 erhält weil der String eine Länge 1 von hat.
 
Also, der Code:
Code:
IF Subscribe_LichtDimValue1.xDataReceived THEN
   ptSource:=ADR(aDatenMQTT_LichtDim1);
   ptDestination:=ADR(sMessageLicht1DimValue);
   FOR i:=1 TO MIN(subscriber.dwRxNBytes,SIZEOF(aDatenMQTT_LichtDim1)) DO
       ptDestination^:=ptSource^;
       ptSource:=ptSource+1;
       ptDestination:=ptDestination+1;
   END_FOR
   ptDestination^:=0;
   rMessageLicht1DimValue:=TO_REAL(sMessageLicht1DimValue);
END_IF

funktioniert am besten. Danke nochmal für die Solide Lösung.
 
Zur Zeit meldest du dich mit je einem Baustein an ein Topic an, also zum Beispiel an deinen Dimmwert 1. Da brauchst du das nicht auszuwerten, da es 1:1 auf deine für Dimmwert 1 verwendete Variable kopiert wird.
Wenn du aber einen Subscribe-Baustein für das ganze Wohnzimmer nimmst und dich auf "Wago/Wohnzimmer/#" subscribst, bekommst du vom Dimmer 1, 2, .. und allen anderen Geräten vom Wohnzimmer Nachrichten. Dann müsstest du das empfangene Topic stringtechnisch verarbeiten, also quasi den Sender "rausschneiden". In diesem Fall also "Licht1_Dimmer". Anschließend kannst du dann den empfangenen Wert via IF-Anweisung deiner Zielvariablen zuordnen. Dadurch würdest du die FB-Instanzen und Speicher sparen.
 
Alles klar, das habe ich jetzt verstanden.

Wenn ich aber das Topic mit Case abfragen will, bekomme ich eine Fehlermeldung: Unerwartetes Token "+/Licht1/command" gefunden.


Code:
Subscribe_TopicZimmer(
    xSubscribe:= TRUE,
    sTopic :=in_sTopicSubscribe,
    eQoS:=eQualityOfService.QoS0,
    aPayloadData:= aDaten,
sReceivedTopic=> sTopciSubscribeRevceived);
    
CASE sTopciSubscribeRevceived OF
    '+/Licht1/command' : rdimValue1:= TO_REAL (sMessage);
END_CASE;

habe ich die Abfrage falsch strukuriert?
 
Das sollte freilich funktionieren. Du musst nur das Topic vor dem Senden mit "xTrigger" neu zusammenbauen.
Schlussendlich wäre eine Art Auftragsliste denkbar, die über einen FbPublishMQTT_2 abgearbeitet wird.
 
Zurück
Oben