stefandreyer / CODESYS-MQTT

MQTT client library for CODESYS, supporting all QoS
MIT License
113 stars 26 forks source link

Wo kommen am Ende die Daten wirklich nach einem Subscribe #51

Closed jontubs closed 3 years ago

jontubs commented 3 years ago

Hallo Stefan,

erstmal vielen Dank für die gute Arbeit. Ich habe dein Beispiel TestMQTTGithubInterfaceExampleTopicAndPayloadRaspberry zum laufen gebracht und bekomme auch eine Verbindung hin. Allerdings habe ich das mit dem Subscribe noch nicht verstanden. In Meinem Beispiel will ich einfachen Integer aus "home/messwerte" abonieren und in CODESYS abspeichern. Aber ich erhalte nirgendwo einen Integer, der meinem MQTTExplorer Wert entspricht.

Wo finde ich finde ich ankommende Daten?

2021-01-25 13_40_34-TestMQTTGithubInterfaceExampleTopicAndPayloadRaspberry_v03 project - CODESYS

2021-01-25 13_43_45-MQTT Explorer

stefandreyer commented 3 years ago

Hi,

also, wenn du subscription passt werden die PublishReceived methoden des collectors aufgerufen. Der wiederrum ruft die PublishReceived methode vom z.b. ReceiveValue auf. Dieser speichert es dan je nach Config in den entsprechenden Tatentyp in seinem Ausgang MQTTReceived.X

in dem Bespiel selber musst du in den FullReceiver schauen. Da geht das so:

//how to get to your vars...

myWord := VarWord.MQTTValue.MQTTReceived.WORD_T;

ganz am ende.

dem ReceiveValue musst du die Passende Topic und den erwarteten Datentyp mitgebeb und per put an den collector anhängen. da klappt das.

Grüße

jontubs commented 3 years ago

Hm, ich kenne mich eigentlich schon echt gut aus mit Codesys, aber deinem Beispielprojekt kann ich so noch nicht folgen. Es gibt kein Beispiel, wo am Ende wirklich mal ein nutzbarer Wert rausfällt. Die Integration der Library ist nicht sehr intuitiv. Aber lass uns mal Stück für Stück dadurch gehen.

Als Basis habe ich einen laufenden MQTT Broker unter der lokalen IP 192.168.1.5 Darunter gibt es folgendes topic home/bms/1/AliceCounter. Das läuft erstmal alles so

In Codesys verwende ich nun dein Beispiel "TestMQTTGithubInterfaceExampleTopicAndPayloadRaspberry"

Darin habe ich den Code wie folgt angepasst

IF NOT init THEN
    init := TRUE;
    //collect all callbacks...
    Collector.put(instance:= TestReceiver);
    //now Collector can be passed do a subscription FB
    myTime := TICKS.GetTick(xDummy:= TRUE)-5 ;
    ClientID := 'CodesysMqtt';
    MQTT_IN_OUT.ClientID := ClientID;
    subscriber.SetMqttInOut(MQTT_IN_OUT:= ADR(MQTT_IN_OUT));

END_IF

Client(
    url:= '192.168.1.5', 
    enable:= TRUE, 
    tls:= FALSE,
    MQTT_IN_OUT :=  MQTT_IN_OUT);

subscriber(
    Subscribe:= TRUE, 
    Topic:= ADR('home/bms/1/AliveCounter'), 
    QoSSubscribe:= SD_MQTT.QoS.ExactlyOnce, 
    ExpectingString:= TRUE, 
    Callback:= Collector,
    );

//here call of your FBs implementing the interface...

//now call instances of your reciver...
TestReceiver();         //FB StringReciver
connected := client.connected;

Das ganze lässt sich einloggen und starten und der FB Client (HANDLE_MQTT) zeigt an, dass der Spaß verbunden ist.

grafik

Der Subscriber sagt, dass das Topic so okay ist

grafik

Der TestReceiver enthält aber nur komische Sachen. Nichts davon sind meine Nutzdaten.

grafik

In allen Beschreibungen fehlen am Ende die letzten Meter, was aus diesem komplexen Haufen von Methoden noch gemacht werden muss, damit die Daten vorhanden sind. Auch die Variable myWord := VarWord.MQTTValue.MQTTReceived.WORD_T von "FullReceiver" ist 0 wenn ich den verwende.

Hast du eventuell ein vollständiges Beispiel wo einmal eine Subscription von irgendwas bis wieder zur Nutzvariable lauffähig ist? Ich habe mir dazu bereits das Beispiel Interaction HowTo geladen. Aber dieses enhält irgendwie nicht alles.

stefandreyer commented 3 years ago

Hi,

naja, ich muss zugeben, das Konzept für das empfangen ist vielleicht das ganze Gegenteil von Intuitiv. Schau dir vielleicht nochmal das Integration HowTo an. Der Letzte Meter fehlt in den Beispielen, weil es diesen quasi nicht in der Anwendung macht wenn man meine Empfangs FBs benutzt werden. Von diesen wir die PublishReceived Methode aufgerufen und diese schreibt den Wert. Das Passiert aber in dem Aufruf vom HANDLEMQTT.

Das ganze hat den Vorteil, das man sich FBs schreiben kann die sich dann selber beim collector registrieren.

METHOD FB_Init : BOOL
VAR_INPUT
    bInitRetains :BOOL;
    bInCopyCode :BOOL;
    ValueTyp:IBaseLibrary.TypeClass;
END_VAR
MyTopicRecive := AppendCmdToStringTopic(in:= InstanceName.GetInstanceTopic(), TopicLevel:= 1);
initAsFindTopic(compString:= ADR(MyTopicRecive), ValueTyp:= ValueTyp, returnHit:= TRUE);
LAN_Stuff.CollectorApplication.put(THIS^);

Ich errarbeite mal noch was und will eh die nächste Version releasen.

Du höhrst von mir

Grüße

stefandreyer commented 3 years ago

Hi,

ich habe mal ein Projekt fertig gemacht GitHubSimpelstReceiver.

Schau dir das mal an für das Verständnis. Solte auch was von test.mosquitto.org einfangen.

Wenn du noch Fragen hast, einfach melden.

Grüße

jontubs commented 3 years ago

alles klar. ich schau es mir gleich mal an. Danke für die Arbeit :)

jontubs commented 3 years ago

Jaa, jetzt läuft der Spaß

2021-02-11 21_07_38-MQTT_läuft_v02 project_ - CODESYS

Also für alle die sich genau so dumm anstellen wie ich.

Mit dem Beispiel GitHubSimpelstReceiver könnt ihr sehr einfach mal was zum laufen bringen. Die Payload landet also über einen Pointer in einem String, den ihr zuvor mit einer Initialisierungsmethode registrieren müsst.

Vielen Dank , stefandreyer