stefandreyer / CODESYS-MQTT

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

noTLS example does not work #8

Closed bmshine closed 5 years ago

bmshine commented 5 years ago

Hallo Stefan,

ich habe mal deinen MQTT Baustein geladen und den Beispielprogramm ausprobiert. Leider funktioniert nur die TLS Variante. Die ohneTLS Variante verbindet sich weder auf test.mosquitto.org noch meinen lokalen MQTT server. Muss ich bestimmte Versionen von den LIB's laden oder funktioniert es auch mit den neusten? Aktuell verwende ich Codesys 3.5 SP13 Patch2.

Gruss Markus

Tommilein commented 5 years ago

...Hast du die Oscat Basic lib aus meinem Profil?...

Das ist die Frage, wie ich Deine "scharf" schalte. Ich habe ja mehrere solche " Oscat Basic lib"s im Bibliotheksverwalter. (Alleine schon von vor der zeit von MQTT).

Tommilein commented 5 years ago

Das meine ich: die Bibliothek ist zweimal enthalten. Wenn ich die obere "selbständige" lösche, kommen sofort Syntaxfehler. cmperrors_32bit_6

Mit solchen Bibliotheksfeinheiten bin ich nicht vertraut - eher erledigt...

Tommilein commented 5 years ago

Heureka, wenn ich die obere BASIC-Lib rausnehme und nochmal DEINE ins Repository bringen und dann hinzufüge, läuft der "Codesys Control Win 3" durch: 0 Fehler !! Und das, obwohl alles die gleiche Version ausweist - ziemlich riskant.

Den Raspberry muss ich morgen weiterüben - der wird wohl dann auch gehen... (ich habe aus Versehen das Programm beendet und nicht gesichert. Das ist eben die Arbeitsdauer ...)

Vielen Dank für Deine Hilfe. Morgen fasse ich mal meine Probleme zusammen. Das ist nämlich erst dann ein echter Test, wenn es jemand anderes testet als der Entwickler - der weiß ja immer schon alles. Ich muss mir erst alles tapfer erkämpfen. Aber zuwas macht man sowas sonst ?

Viele Grüße Thomas

Tommilein commented 5 years ago

Hallo Stefan, das gröbste ist geschafft, Dein Beispielprogramm läuft und sendet Telegramme in die Welt (nachgewiesen über MQTT.fx). Auch empfangen tuts.

Das das recht holprig ging, liegt wahrscheinlich an meinen geringen Codesys-Kenntnissen. Aber manches ist auch recht kompliziert: Beispiele:

"Mal eine neues Projekt mit dem Raspberry machen..." . Das geht schon , aber... man muss wissen wie man dynamischen Speicher anlegt.

Ich weiss immer noch nicht, wo der Anfang der Topics definiert ist, also das "Device/Application/..." . Ich möchte andere Pfade nutzen.

Das Problem mit einer erweiterten "BASIC"-Lib (Oscat) ist nicht schön, wenn man im Codesys selbst nicht feststellen kann, ob man nun die neuere Bibliothek geladen hat oder nicht. Nach vielem Suchen kann ich anhand des Änderungsdatums in etwa mitbekommen, welche Lib ich nun habe, welche nicht. Die Oscat-Lib ist von Dir erweitert worden ??

Dasselbe trifft auf Deine MQTT-Lib zu. Da sie die gleiche Versionsnummer usw. hat wie die vorherige, muss ich nun solange die Libs bei den verschiedenen Projekten rein und rausnehmen, bis ich "nach" bin mit dem Einbauen der neuen MQTT-Lib. Wie schön wäre es gewesen, wenn es eine Abwärtskompatibilität gäbe - einfach die neue Lib rein und die alten Projekte wären gelaufen - für Dich bestimmt kein Problem. Es gibt schon Nutzer, die Deine Lib nicht nur testen , sondern auch in größeren Projekten nutzen !!!

Du hast Dir sehr viel Mühe gegeben, das Beispiel nahe an die aktuellen Geräte zu bringen (ich nehme mal an, sowas wie Sonoff o.ä.). Ich will aber einfach einen String übertragen - wie geht das denn einfach ? Mit "Methoden" habe ich noch nie gearbeitet, aber mein Hinterkopf sagt mir, das genau in der Methode "PublishRecive" das Text-Übertragen verborgen ist.

Eine kleine Visualisierung hätte das testen für solche Geister wie mich alles etwas anschaulicher gemacht. Ich hatte zu tun, irgendwie eine Variable zum Togglen zu finden, die die Lampe enfdlich mal geschaltet hat. Vorteil war, ich musste mich intensiv mit den Programmen beschäftigen - da lernt man kräftig!!.

cmperrors_32bit_7

Jetzt will ich aber mal aufhören, mich zu beschweren. Das sollen ja auch nur Hinweise sein, was mir aufgefallen ist, jemandem, der nun nicht zu den Codesys-Gurus zählt. Soweit erst mal bis hierher. Vielen Dank dafür, das Du so eine Lib überhaupt ins Netz stellst.

Viele Grüße Thomas

stefandreyer commented 5 years ago

Hallo Thomas, schön das es bei vorrangig geht. Zum Thema dynamischen Speicher: das steht auf der Start Seite der Bibliothek und es gab auch schon ein issue dazu. Ich kann mir vorstellen das der einstieg so aus der kalten ins codesys und diese Bibliothek nicht einfach ist. Aber ich kann und will hier nicht noch ein codesys Tutorial platzieren. Das machen schon andere prima. Gerne aber beantwortet ich Fragen im Kontext der Bibliothek. Im GreatExampleOfAdvanteges wird das Topic aus den Namen der Applikation und FB Instanzen generiert. Bringt den Vorteil das man auch  Instanzen einfach in ein anders Topic verschieben kann oder einfach umbenennt und die folgenden einfach mit. Einfach einen string senden machst du mit dem FB MQTT publish(oder so änlich, bin nicht am pc). Mit Methoden wirst du dich in dem Zusammenhang auch beschäftigen müssen. Gehört zu codesys V3 halt dazu. Sind nur Funktionen einer "Klasse". Ich glaub ich habe nix an der Oscar lib gemacht. Nur den letzten stand von v2.3 nach V3 portiert. Warum die jetzt unterschiedlich sind ???? Aber ich lobe Besserung bei meinen Bibliotheks Versionen. Github zusammen mit codesys macht es einem da nur nicht so einfach. Glaub ich ;) Und, klingt so als wenn du eine visu für mein Beispiel bauen willst ;) besser kann man nicht lernen... Viel Spaß noch und lass ruhig mal hören wies bei dir klappt. Grüße Stefan

Tommilein commented 5 years ago

Hallo Stefan, vielen Dank für die Antwort. Wenn Du wieder mal am PC bist, schau mal, was ich alles vor einem "publish" machen muss. Da gibt es (leider für mich) eine Menge Abhängigkeiten. Topic und Payload kann man ja direkt vorgeben, aber innerhalb der Lib benötige ich noch Daten wie MQTT_IN_OUT .BROKER_CONNECTED werden irgendwie "aussenrum" übergeben. Aber ohne dieses Flag geht nichts los... Wie wird MQTT_IN_OUT vernünftig übergeben?

Vielen Dank Thomas

stefandreyer commented 5 years ago

Hallo Thomas,

schau mal in die anderen Github Beispiele, die sollten recht schmal sein.

Grüße Stefan

Tommilein commented 5 years ago

Hallo Stefan, hast recht, die anderen Beispiele sind viel schneller zu begreifen - aber !!

In Deiner alten Bibliothek gab es ein Flag "subscribe.Recived" zum Zeiche, daß etwas empfangen wurde. Dieses Flag gibt es nun nicht mehr und ich probierte es mit "subscribe.SubscribeDone" aus. Ich glaube aber nicht mehr, das dies das richtige "Empfangsflag" ist - es bewegt sich nicht:

subscribeDone_1

Mit welchem Signal kann ich denn nun bestimmen, das etwas subscribed wurde ??

Vielen Dank Thomas

stefandreyer commented 5 years ago

Hallo Thomas,

hmmm, ich interpretiere mal. Eigentlich willst du wissen ob was auf die Subscription empfangen wurden. Das bit SubscriptionDone singaliesiert, das die angeforderte subscription vom broker akzeptiert und eingerichtet wurde.

Was du wissen willst ist der empfang eines publish vom Broker. Diese Konzept habe ich aus diversen Gründen umgestellt. Wenn nun etwas passendes zur subscription empfangen wurde wird der am Eingang Callback hinterlegte FB aufgerufen. Das nennt sich callback. Diese FB kann nun eine einzelne Variable auswerten und beschrieben oder eine ganze sammlung(collection). Im konkreten Beispiel kümmert sich der FB StringCallback darum und schreibt die empfangenen Daten an die gewünschte Position.

Wenn du noch Fragen hast, frag ruhig.

Grüße Stefan

Tommilein commented 5 years ago

Hallo Stefan, erstmal vielen Dank, daß Du selbst zu nachschlafender Zeit mir noch antwortest. Ich find's toll.

Ich habe jetzt ein Programm so umgestellt, das ich Texte zum Broker hin schicken kann und sie wieder lesen kann. Ich habe dabei die größten Probleme. Deine Programmiermethoden lassen nicht zu, das ich einzelne Teile "herauskopiere" und zu einem einfacheren Programm zusammensetze. Du verwendest innerhalb Deiner Funktionen sowas wie globale Variable (nicht echte, aber irgendwie übergeordnete Variable). Hier ein Auszug aus einem abgewandleten **"LampBase":

VAR //für extra publish publish:SD_MQTT.MQTTPublish; QoS:SD_MQTT.QoS; send: BOOL:=False;; SendDone:BOOL; RetainMqtt: BOOL; end_var

... ...

IF SwitchTrigger.Q THEN send:=TRUE; END_IF

// SendState(); // SendState() will ich ablösen, um einfach los senden zu können // und nicht via getoggeltem Status was rauszusenden.

// ab hier jetzt eigenes publish -- und das funktioniert nun nicht... publish( Topic:= ADR(MyTopicSend), PayloadString:= ADR(TextSend), PublishAsString:= TRUE, QoSIn:=SD_MQTT.QoS.ExactlyOnce, MRetain:= RetainMqtt, send:= Send, done=> SendDone);

IF SendDone THEN send:=FALSE; END_IF ... ...

Hier liegt irgendwas in der Umgebung von "publish" NICHT vor. Jedenfalls bewegt sich so nichts, obwohl das mehr oder weniger äquivalent zum Inhalt von SendState() ist.

Viel schlimmer ist aber noch, das ich keine 2 Clients einrichten kann. Mit Deiner alten Lib.-Version habe ich einfach 2x MQTT instanziert. Hier bezweifle ich, das ich sowas hinbringe, da doch wahrscheinlich das hier dem entgegensteht: VAR_GLOBAL MQTT_IN_OUT:SD_MQTT.MQTT_IN_OUT; END_VAR

Wie sollen hier die beiden Clients unterschieden werden. Ich glaube auch, das alles Funktionen sich auf EINEN Client beziehen, da ja nichts übergeben wird. Jedenfalls verstehe ich es nicht besser.

Um es zusammenzufassen:

Ich bauche Hinweise für eine richtige Umgebung für die Lib-Aufrufe und wie ich 2 Clients erzeuge und anspreche.

Viele Grüße Thomas

PS: Ich stamme noch aus einer Zeit, da man Wert darauf legte, das eine Funtion nur dann"sauber" programmiert war, wenn sie unabhängig "von aussen" funktionierte - also nix global... Das war aus heutiger Sicht eben schön altmodisch - nix objektorientiert. Alle Parameter wurden mitgegeben und alle Ergenisse standen als Funktionwert oder Ausgabevariable zur Verfügung. Sowas ließ sich noch debuggen und wenn man die Quelle hatte, auch leicht lesen.

Jetzt stelle Dir mal vor, was das für eine Arbeit für einen wie mich ist, wenn nun Funktionen gar nicht mehr erkenntlich aufgerufen werden und trotzdem dann online benutzt werden (PublishRecieve).

Zum Glück hatte ich auf der Arduino-Strecke mal die Callback-Funktion im Fokus. Aber da gab es einen Parameter mit einem Aufruf einer Funktion, die 5 Zeilen weiter unten auch zu finden war.

Bloß das Du verstehst, warum ich hier so rumeiere...

stefandreyer commented 5 years ago

Hallo Thomas,

es ist wieder abends...

Scheint so als wenn du gerade voll in die OOP mit meiner Bibliothek reinschlitterst ;) Du wirst noch viel Freunde haben.

Ich kenne auch noch eine Zeit mit SPS Programmen in STEP 5 von 1989. Und die waren sauber programmiert, haben dich aber dank indirekter Programmierung zum Wahnsinn getrieben... Soll heißen: jede Programiersprache kann man versauen, aber einige Ansätze sind sehr hilfreich und unerlässlich. Und mitlerweile kann ich CODESYS ganz gut debuggen, dir fehlt hier warscheinlich noch das Handling, aber das wird noch.

Ich habe auch eigentlich alles gut gekapselt und versucht in FB's zu verstauen. Globaler Kontext ist da sehr gering. Sicherlich vorhanden, aber für Fixwerte hauptsächlich.

Das Variablen aus dem nichts beschrieben werden war auch vorher schon möglich und auch sinvoll.

Die von dir angesprochene "Globale variable" ist warscheinlich ein Objekt das ich angelegt habe, damit alle Instanzen mit der Instanz des Cliente Sprechen können. Das geht auch in OOP nicht besser, Irgendein immer verfügbares objekt brauchst du immer, und sei es das du es dir mit einer get Methode holst.

Bei deinem publish kann es sein das du die Init Methode noch nicht aufgerufen hast. Da bekommt die Instanz einen Zeiger auf die globale variable um mit dem Client zu reden. Und ohne diesen Init macht publish einfach nix... Da werde ich auch nochmal ansetzten, das die Intialisierung beri der deklaration mitgegeben wird, da kann man das dann nicht vergessen.

Zum Thema 2 clienten Ich habe eigentlich nix Programmiert was dem entgegen steht. Ich weiß jetzt nicht wie genau du deine 2 Clienten und Variablen bei der Bibliothek versorgt hast aber mit der aktuellen ist das auch möglich. Das:

VAR_GLOBAL MQTT_IN_OUT:SD_MQTT.MQTT_IN_OUT; END_VAR

schränkt dich da nicht ein. Das kann dazu werden:

VAR_GLOBAL MQTT_IN_OUT_CLIENT1:SD_MQTT.MQTT_IN_OUT; MQTT_IN_OUT_CLIENT2:SD_MQTT.MQTT_IN_OUT; END_V

Wie du das dann danach verteilt hast würde mich auch interessieren.

Hau rein ;)

Grüße Stefan

Tommilein commented 5 years ago

Hallo Stefan, ich bin wieder weiter: 3 Clients funktionieren. mehrere_clients_4

Ich habe alles 3x angelegt (GVL) Aber nur eine MQTT_STUFF , da drin liegt auch alles Erforderliche drei mal. So funktioniert das dann:

mehrere_clients_2

Ich habe aber kein gutes Gefühl, weil noch sowas auftritt:

mehrere_clients_3

ich habe hier ganz schnell "Senden" geklickert. In dem Moment geht ein Empfangstelegramm verloren - die Nr. 12. Da gehen auch manchmal noch mehr verloren. Es aknn aber auch an mir liegen.

Wahrscheinlich liegt es am Senden, denn am Broker kommen auch nicht alle Telegramme an.

Ich habe auch noch das "publish" - Problem. Es gibt ja wohl kein MQTTPublish.Init . Wo oder wie muss denn dann das MQTTPublish initialisiert werden. Aus der originalen Funktion sendstate() kann man keine besonderen Initialisierungen erkennen (ich wenigstens nicht). Das "SendState.Init" ist in jedem Falle drin.

Kann Du mir nochmal einen Hinweis diesbezüglich geben ??

Vielen Dank für deine Mitwirkung

Viele Grüße Thomas

stefandreyer commented 5 years ago

Hallo Thomas,

schaut ja schon gut aus.

Wir bekommen noch die Kuh vom Eis und das Kind noch geschauckelt.

Die Init Methode die ich meinte heißt SetMqttInOut.

Wie hast du die Broker getrennt? Ich würde dir pro Broker einen Client FB und eine MQTT_IN_OUT Struktur sowie pro Variable , einen publish FB, eine und einen subscription FB empfehlen. Unter dem Subscription FB können natürlich mehrere Topics bearbeitet werden.

Den callback FB kannst du jedoch für alle Broker nutzen. Das passt soweit.

Wie hast du das aktuell organsisiert? Vielleich bekomme ich so raus, warum da was untergeht.

Wenn du sendState nicht mehr brauchst kannst du die instance und alle Aufrufe dazu wegwerfen.

Das du alles in MQTT_STUFF packst passt schon.

Und schön das du die verschiedene broker unterstrichen und dann verpixelt hast ;)

Grüße Stefan

SvenJoedicke commented 5 years ago

Hallo,

bezüglich des Themas dynamischer Speicher habe ich eine Frage. Sie meinten man müsste diesen in der Appplikation festlegen, da die Libs dynamisch allokieren.

Dürfte ich fragen wo sie das tun???? Ich habe nämlich nirgends den Operator __NEW(); und das Attribute {attribute 'enable_dynamic_creation'} bei Ihnen im Quellcode finden können.

Nutzen sie eine andere Arte der dynamischen Allokation???

Mit freundlichen Grüßen Sven Jödicke

Gesendet von Mail für Windows 10

Von: stefandreyer Gesendet: Samstag, 13. Juli 2019 13:06 An: stefandreyer/CODESYS-MQTT Cc: Subscribed Betreff: Re: [stefandreyer/CODESYS-MQTT] noTLS example does not work (#8)

Hallo Thomas, schön das es bei vorrangig geht. Zum Thema dynamischen Speicher: das steht auf der Start Seite der Bibliothek und es gab auch schon ein issue dazu. Ich kann mir vorstellen das der einstieg so aus der kalten ins codesys und diese Bibliothek nicht einfach ist. Aber ich kann und will hier nicht noch ein codesys Tutorial platzieren. Das machen schon andere prima. Gerne aber beantwortet ich Fragen im Kontext der Bibliothek. Im GreatExampleOfAdvanteges wird das Topic aus den Namen der Applikation und FB Instanzen generiert. Bringt den Vorteil das man auch  Instanzen einfach in ein anders Topic verschieben kann oder einfach umbenennt und die folgenden einfach mit. Einfach einen string senden machst du mit dem FB MQTT publish(oder so änlich, bin nicht am pc). Mit Methoden wirst du dich in dem Zusammenhang auch beschäftigen müssen. Gehört zu codesys V3 halt dazu. Sind nur Funktionen einer "Klasse". Ich glaub ich habe nix an der Oscar lib gemacht. Nur den letzten stand von v2.3 nach V3 portiert. Warum die jetzt unterschiedlich sind ???? Aber ich lobe Besserung bei meinen Bibliotheks Versionen. Github zusammen mit codesys macht es einem da nur nicht so einfach. Glaub ich ;) Und, klingt so als wenn du eine visu für mein Beispiel bauen willst ;) besser kann man nicht lernen... Viel Spaß noch und lass ruhig mal hören wies bei dir klappt. Grüße Stefan

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

Tommilein commented 5 years ago

Hallo Stefan,

ca. 8:54 las ich die Info von Dir über SetMqttInOut und 9:08 ging der reine "publish"-Verkehr - toll.

Nun bin ich am Einbauen in die Anwendung (noch nicht fertig), aber ich wundere mich schon: schnelle Broker schicken schon die Antwort, ohne das die Sendung dort eingegangen ist? D.h. Ich bekomme das Signal über das Ende der Sendung (SendDone) nach(!!) dem Subscribe des gleichen Telegrammes. mehrere_clients_5

Ich sende ja das Telegramm an den gleichen Topic, den ich auch subscribe. ABer trotzdem müsste ja das Telegramm erst mal beim Broker verarbeitet werden - ehe ich was empfangen kann. Oder empfange ich schon am eigenen Rechner - so eine Art Kurzschluß ??

"Verloren" gehen Telegramme immer noch. Ich habe zwar erneut (war bei Dir schon drin) eine neue Sendung verboten, solange "send" noch aktiv ist. Trotzdem scheint hier was durcheinander zu gehen:

mehrere_clients_7

Das liegt bestimmt an mir.

Ab jetzt wird es immer besser - vom Grunde her funktionierts schon mal. Und die sich überholenden Telegramme habe ich in der Anwendung nicht - da müssen sie ja erst zum anderen Rechner und Sende- und Empfangstopic sind verschieden.

Jetzt habe ich ein Bierchen verdient...

Viele Grüße Thomas

stefandreyer commented 5 years ago

Hallo,

@Sven, vor der aktuellen Bilbiotheksversion habe ich sysMemAlloc genutzt. Das allokiert auch ohne das im Projekt dynamischer Speicher frei gegeben wurde. Das hatte aber glaub ich ein Problem mit 64bit. Und weil der Bibliothek Nutzer auch damit nicht mitbekommt das dynamsich allokiert wird, bin ich auf NEW und DELETE umgestiegen. In der aktuellen Biblitothek findet man das auch über suchen. Was ich aber zu meiner Schande noch erledigen muss ist, die Rückgabewerte von __NEW auf Plausibilität zu prüfen. Das werde ich noch einbauen. Sonnst habe ich das so angelegt, das die Dynamischen Aufgaben beim Startup abgearbeitet werden und während des Betriebs ruhig sind. Zu finden sind die Optionen für dynamischen Speicher unter: Rechts Klick auf Applikation --> Eigenschaften --> Optionen Applikationserzeugung --> Dynamische Speicherallozierung verwenden.

@Thomas

Schön das es weiter bei dir voran geht. Ich hoffe das Bier hat geschmeckt.

Ok, du hast natürlich das Problem, wenn du zur selben Topic subscribst du immer eine Kopie von deinem gesendetem zurück bekommst. Das ist nicht so sinvoll. Versuch mal das in send receiv oder cmd und stauts zu trennen. Das schafft sonnst unnötig traffic oder Probleme. Weiter kann es sein, das du ein publish als "retain" markiert hast. Dann sendet der Broker Sofort die Daten nach der sibscription an den clienten. Das bekommst du weg indem du ein publish zur Topic mit leerem Payload machst.

Und welches send done meinst du? Das vom Publish FB? Falls ja, senden geht immer unabhänig vom subscribe. Du kannst immer zu jeder Topic senden, egal ob subscription dazu oder nicht. Du musst das Publish zum broker zu dem von broker trennen!

Ist dein log ein fifo? oder sortiert der das nach der Zeit? nicht das das nur ein Auflösungsproblem der Anzeige ist.

Versuch doch mal eine Fangschaltung zu Programmieren ob das Empfangene wirklich vor dem senden kommt.

Warum Sachen verlohren gehen kann ich mir nicht erklären. Bis jetzt kenn ich von der aktuellen Version nur positive Rückmeldungen. Wäre schön wenn ich mir das Projekt mal anschauen kann.

Grüße Stefan

Tommilein commented 5 years ago

Hallo Stefan, mir ist klar, das es nicht besonders sinnvoll ist, wenn man sofort das gesendete wieder empfängt. Aber so habe ich im Testprogramm auch gleich eine Empfangsmöglichkit, die ich sonst händisch (z.B. mit mqtt.fx) machen müßte. Das ist mühevoll. In meiner Anwendung ist das natürlich nicht so. Da liegen immer größere Zeiten zwischen Senden und einer Antwort.


Mein LOG ist fifo, was die Satznummerierung am rechten Zeilenrand dokumentiert. Jeder Satz läuft in ein Array rein und wenn dies voll ist, wird ein 2. Array gefüllt und das erste via FTP rausgeschrieben. Die Loggerei läuft in einem extra Task mit 5x kürzerer Zykluszeit wie der MQTT-Task. Bis jetzt war die Nummerierung immer in der Reihenfolge.


Du musst das Publish zum broker zu dem von broker trennen!

Auch auf die Gefahr hin, das Du mich auslachst: ich kenne nur das publish "zum Broker" - eben "Senden". Wo ist denn da das "publish" "vom Broker" ?? Falls es sowas innerhalb Deiner Lib gibt, habe ich es bisher nicht erkannt.


Trotz intensiver Anstrengung bringe ich die Reihenfolge nicht hin. Bei 2 Brokern (1+2) kommt erst die Empfangsbestätigung - dann die Bestätigung, das das Signal überhaupt raus ist. Beim Broker 3 geht alles wie gehabt.

Ich denke - und kann das schlecht beweisen - das die Bestätigung , das "publish" etwas rausgeschickt hat, länger braucht, als der Empfang dauert. Publish und Subscribe laufen so unabhängig, das die Ablaufdauer der beiden Funktionen eben so lange ist, wie sie ist.

Der langsame Broker 3 macht nämlich alles wie er soll.

Versuch doch mal eine Fangschaltung zu Programmieren ob das Empfangene wirklich vor dem senden kommt. Da habe ich keine Ahnung, wie ich das machen soll, da ich den Ablauf nicht weiß (vor allem von der Callback-Funktion und deren Aufrufen) .


Verloren geht immer noch was. Ich habe die telegrammnr.-Erhöhung an eine Stelle gesetzt, die nur durchlaufen wird, wenn der Broker eigentlich nicht "Active" ist. Dann müsste er auch das nächste Telegramm annehmen.

Das Flag "gl_mqtt_send_broker_1" löst "publish" aus:

IF MQTT_Sende_Flanke_B1.Q AND NOT M_a_Taskprogramm.M_b_TextSendRecieve.Text_B1.SendActive THEN
    telegrammnr:=telegrammnr+1;
    gl_SendeText_1:=concat(concat('Telegrammnr: ',WORD_TO_STRING(telegrammnr)),  '  Hallo Broker 1');       
    gl_mqtt_send_broker_1:=TRUE;
END_IF
IF MQTT_Sende_Flanke_B2.Q AND NOT M_a_Taskprogramm.M_b_TextSendRecieve.Text_B2.SendActive THEN
 .........

Das Flag "gl_mqtt_send_broker_1" wird hier zurückgesetzt:

VAR
    MQTT:MQTT_STUFF;
    Text_B1: M_c_MQTT_PublishRecieve;   
        ..........
END_VAR

MQTT();

Text_B1(Broker_Nr:=1,SwitchIn:= GVL_MQTT.gl_mqtt_send_broker_1,TextIn:=gl_SendeText_1,  MQTT_IN_OUT_PT:=ADR(GVL_MQTT.MQTT_IN_OUT_1));

IF GVL_MQTT.gl_mqtt_send_broker_1 AND NOT Text_B1.SendActive  THEN
    GVL_MQTT.gl_mqtt_send_broker_1:=FALSE;
END_IF
..........

Ich habe extra "SendActive" zurückgeben lassen aus "MQTT_PublishRecieve" , trotzdem geht ab und zu ein Telegrammpaar verloren. Ich nehme an, das das Sende-Flag im ungünstigsten Falle im gleichen Zyklus runter und gleich wieder hochgesetzt wird. Telegramm_fehlt

Ich übe weiter daran. Eigentlich sollte das nichts mit dem "MQTT_PublishRecieve" zu tun haben.


Ich kann Dir gerne das Testprogramm zuschicken. Nur will ich Dir gar nicht zumuten, das Du auch noch mein Kauderwelsch untersuchen sollst. Ich hab keine Ahnung wie ich hier was reingeben soll, damit es bei Dir landet. Vielleicht geht es über eine Mail (Mailanhang) besser ...

Viele Grüße Thomas

stefandreyer commented 5 years ago

Hallo Thomas,

kurz schmuzeln musste ich schon.... OK. publish bedeutet immer eine Übertragung von Topic und Payload. Ziel und Quelle können je Broker und Client sein. D.h. eine subscription teilt dem broker die Topics mit die er gern von ihm hätte und der broker schickt die per publis paket zum clienten.

Zum Thema Pakete aus der Zukunft. Wie du das skizziert hast kann das schon sein. Bei QoS 2 gehen insgesamt 4 Pakete über die Leitung ehe das für den Sender erledigt ist. Nun kann ein Empfänger das erhaltene publish paket sofort nach dem erhalt auswerten. So mach ich das auch. D.h. der broker kann nach erhalt des publish die Quittung und das publish zurück in einem TCP Paket versenden. Dann bekommst du das paket zurück bevor es komplett abgearbeitet ist. Raus bekommst du das z.B. mit dem Wireshark und einem Testprogramm auf windows. Ist für mich aber sehr plausibel.

Das dein log Task schneller läuft wie dein MQTT Task machts schwierig. Hast du das Thread safe Programmiert? Wenn dir das nichts sagt dann versuch mal alles in einen Task zu packen, oder mal mit MQTT.FX zu lauschen.

Weiter nehme bitte für das publish erledigt das done bit von dem publish FB. das ist genau dafür gemacht. Setzte damit deine Sendeanforderung zurück, und nur damit.

Anschauen würd ich mir schon mal dein Programm, versuchs doch mal hier rein zu kopieren. Bei Bildern geht das ja auch. Ansonnsten muss ich mir mal ne wegwerf mail besorgen zu der du mir deine Mailadresse schickst. Oder hast du eine die du hier nennen kannst?

Unterschiedliche Tasks sind wirklich gefährlich.... Warum hast du das so gemacht?

Grüße Stefan

Tommilein commented 5 years ago

Hallo Stefan, die verlorenen Telegramme haben sich wieder angefunden. Auf meine Fehlerhaftigkeit ist Verlass!!

Es ist so, das bei schneller Sendeaufforderung in meinem Programm das "Send"-Flag auf TRUE stehen blieb. Damit konnte in "publish" keine Sendeflanke gebildet werden.

--- Senden aus Visu steht an

//  gl_mqtt_send_broker_1   wurde im letzten Zyklus gerade auf FALSE gesetzt 
//  mit SendDone hinter letztem publish-Aufruf).

// nächster Zyklus
MQTT_Sende_Flanke_B1(CLK:=send_broker_1);   // send_broker_x  wird in  Visualisierung getastet

//   Sendeflanke trifft auf ersten Zyklus mit gl_mqtt_send_broker_1=FALSE
IF MQTT_Sende_Flanke_B1.Q AND NOT gl_mqtt_send_broker_1 THEN                    
    gl_mqtt_send_broker_1:=TRUE;  // und hier wird sofort wieder auf TRUE gesetzt
    telegrammnr:=telegrammnr+1;
    gl_SendeText_1:=concat(concat('Telegrammnr: ',WORD_TO_STRING(telegrammnr)),  '  Hallo Broker 1');       

//  gl_mqtt_send_broker_1   ist schon wieder TRUE wenn es zum
//  nächsten publish-Aufruf kommt.

Mit der Tast-Flanke genau den Zyklus zu treffen, wo das Sendeflag rückgesetzt wurde ist schon toll, konnte ich aber relativ häufig provozieren.

Der eigentliche Fehler liegt darin, das ich das Sendeflag zu 2 Zwecken nutzen will:

// Auslösen der Sendevorgänge #####

// Das ist die Lösung !! 
// Nutzen des "SendActive"-Flags aus "Publish" zum verhindern eines neuen Sendeanstoßes.
IF MQTT_Sende_Flanke_B1.Q AND NOT M_a_Taskprogramm.M_b_TextSendRecieve.Text_B1.SendActive THEN                  
    gl_MQTT_SendeTopic_B1:='tl_cinema/testdata';
    telegrammnr:=telegrammnr+1;
    gl_SendeText_1:=concat(concat('Telegrammnr: ',WORD_TO_STRING(telegrammnr)),  '  Hallo Broker 1');       
    gl_mqtt_send_broker_1:=TRUE;    
END_IF

// hier publish-Aufruf
// und sofort Sendeflag rücksetzen

gl_mqtt_send_broker_1:=FALSE;

Damit ist sichergestellt, das das Sendeflag wenigstens 1 Zyklus lang FALSE bleibt. Das ist aber wahrlich kein MQTT-Problem. Das sind meine eigenen Eingriffe...


Das "Überholproblem" lege ich mal zu den Akten. Ich denke das liegt an dem unsinnigen senden und rückholen vom gleichen Topic und an der Arbeitsweise der Broker. Denn offensichtlich warten die Broker 1+2 nicht aufs Ende der Sendung, während iot.eclipse.org erst seinen Empfang komplett macht, ehe er was zum abschicken freigibt. Denke ich mir mal so.

Viele Grüße Thomas

SvenJoedicke commented 5 years ago

Hallo,

@sven, vor der aktuellen Bilbiotheksversion habe ich sysMemAlloc genutzt. Das allokiert auch ohne das im Projekt dynamischer Speicher frei gegeben wurde. Das hatte aber glaub ich ein Problem mit 64bit. Und weil der Bibliothek Nutzer auch damit nicht mitbekommt das dynamsich allokiert wird, bin ich auf NEW und DELETE umgestiegen. In der aktuellen Biblitothek findet man das auch über suchen. Was ich aber zu meiner Schande noch erledigen muss ist, die Rückgabewerte von __NEW auf Plausibilität zu prüfen. Das werde ich noch einbauen. Sonnst habe ich das so angelegt, das die Dynamischen Aufgaben beim Startup abgearbeitet werden und während des Betriebs ruhig sind. Zu finden sind die Optionen für dynamischen Speicher unter: Rechts Klick auf Applikation --> Eigenschaften --> Optionen Applikationserzeugung --> Dynamische Speicherallozierung verwenden.

@thomas

Schön das es weiter bei dir voran geht. Ich hoffe das Bier hat geschmeckt.

Ok, du hast natürlich das Problem, wenn du zur selben Topic subscribst du immer eine Kopie von deinem gesendetem zurück bekommst. Das ist nicht so sinvoll. Versuch mal das in send receiv oder cmd und stauts zu trennen. Das schafft sonnst unnötig traffic oder Probleme. Weiter kann es sein, das du ein publish als "retain" markiert hast. Dann sendet der Broker Sofort die Daten nach der sibscription an den clienten. Das bekommst du weg indem du ein publish zur Topic mit leerem Payload machst.

Und welches send done meinst du? Das vom Publish FB? Falls ja, senden geht immer unabhänig vom subscribe. Du kannst immer zu jeder Topic senden, egal ob subscription dazu oder nicht. Du musst das Publish zum broker zu dem von broker trennen!

Ist dein log ein fifo? oder sortiert der das nach der Zeit? nicht das das nur ein Auflösungsproblem der Anzeige ist.

Versuch doch mal eine Fangschaltung zu Programmieren ob das Empfangene wirklich vor dem senden kommt.

Warum Sachen verlohren gehen kann ich mir nicht erklären. Bis jetzt kenn ich von der aktuellen Version nur positive Rückmeldungen. Wäre schön wenn ich mir das Projekt mal anschauen kann.

Grüße Stefan

Hallo Stefan,

ich kann beim besten Willen kein __NEW und kein sysMemAlloc finden, selbst wenn ich im "Gesamtes Projekt & nicht kompilierte Bibliotheken" suche. Wo soll denn das dynamische Allokieren denn sein???

MFG Sven

stefandreyer commented 5 years ago

Hallo, welche Biblitoheksversion nutzen sie? Ich kann mich dunkel an Zeiten erinnern wo noch nicht Dynamisch alloziert wurden, ich denke aber zu mindest im HandleSplitTopic habe ich das schon immer gemacht. In der Aktuellen Version in: HandleSplitTopic --> PushNewLevel Zeile 21HandleSplitTopic --> FullInit Zeile 20 und 30HandleSplitTopic --> LowInit Zeile 17 und 27

CallbackCollector --> put Zeile 13 HandleMQTT --> CASE step OF --> 00: Zeile 87 Ich hänge mal die meine Aktuellen Arbeitsstand mit an, aus dem habe ich die Zeilennummern. Achtung, noch nicht produktiv verwenden, ist aber schon mit allokationskontrolle ausgerüstet. MfG Dreyer Am Mittwoch, 24. Juli 2019, 19:55:53 MESZ hat SvenJoedicke notifications@github.com Folgendes geschrieben:

Hallo,

@sven, vor der aktuellen Bilbiotheksversion habe ich sysMemAlloc genutzt. Das allokiert auch ohne das im Projekt dynamischer Speicher frei gegeben wurde. Das hatte aber glaub ich ein Problem mit 64bit. Und weil der Bibliothek Nutzer auch damit nicht mitbekommt das dynamsich allokiert wird, bin ich auf NEW und DELETE umgestiegen. In der aktuellen Biblitothek findet man das auch über suchen. Was ich aber zu meiner Schande noch erledigen muss ist, die Rückgabewerte von __NEW auf Plausibilität zu prüfen. Das werde ich noch einbauen. Sonnst habe ich das so angelegt, das die Dynamischen Aufgaben beim Startup abgearbeitet werden und während des Betriebs ruhig sind. Zu finden sind die Optionen für dynamischen Speicher unter: Rechts Klick auf Applikation --> Eigenschaften --> Optionen Applikationserzeugung --> Dynamische Speicherallozierung verwenden.

@thomas

Schön das es weiter bei dir voran geht. Ich hoffe das Bier hat geschmeckt.

Ok, du hast natürlich das Problem, wenn du zur selben Topic subscribst du immer eine Kopie von deinem gesendetem zurück bekommst. Das ist nicht so sinvoll. Versuch mal das in send receiv oder cmd und stauts zu trennen. Das schafft sonnst unnötig traffic oder Probleme. Weiter kann es sein, das du ein publish als "retain" markiert hast. Dann sendet der Broker Sofort die Daten nach der sibscription an den clienten. Das bekommst du weg indem du ein publish zur Topic mit leerem Payload machst.

Und welches send done meinst du? Das vom Publish FB? Falls ja, senden geht immer unabhänig vom subscribe. Du kannst immer zu jeder Topic senden, egal ob subscription dazu oder nicht. Du musst das Publish zum broker zu dem von broker trennen!

Ist dein log ein fifo? oder sortiert der das nach der Zeit? nicht das das nur ein Auflösungsproblem der Anzeige ist.

Versuch doch mal eine Fangschaltung zu Programmieren ob das Empfangene wirklich vor dem senden kommt.

Warum Sachen verlohren gehen kann ich mir nicht erklären. Bis jetzt kenn ich von der aktuellen Version nur positive Rückmeldungen. Wäre schön wenn ich mir das Projekt mal anschauen kann.

Grüße Stefan

Hallo Stefan,

ich kann beim besten Willen kein __NEW und kein sysMemAlloc finden, selbst wenn ich im "Gesamtes Projekt & nicht kompilierte Bibliotheken" suche. Wo soll denn das dynamische Allokieren denn sein???

MFG Sven

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub, or mute the thread.