Jump to content
yuna

IPconnection how to reconnect

Recommended Posts

Hi,

ich habe 24 Bricklets angeschlossen an Servo, Master und IMU bricks.

wen nun mein Programm bereits läuft bevor ich den USB Stecker einstecke oder ich den usb Stecker raus und wieder rein stecke, dann kommen nur ca. 12 Bricklets/Brickets wieder.

 

Daraufhin habe ich mir gedacht das ich einfach bei Timeout ein ipconnection.disconnect und ipconnection.connect aufrufe, um wieder alle Bricks/Bricklets zu bekommen. Auch habe ich probiert enummeration wieder aufzurufen. Dadurch kommen alle 24 Bricklets wieder, doch verliert sekündlich ein Brick oder Bricklet dann plötzlich die connection.

Bei Neustart des Programms ist es dann wieder kein Problem. Es schaut für mich aus, als würde das disconnect nicht vollständig alle Verbindungen trennen. Bei einer kleineren Anzahl von bricklets (ca. 6) funktioniert alles problemlos.

Share this post


Link to post
Share on other sites

Hört sich etwas nach Thread-Dead-Locks an, wenn es nach Neustart des Programmes wieder normal geht.

- Nutzt Dein Client auch mehrere Threads (neben jenen der TF API)?

- Falls ja: wie synchronisieren die sich bei reconnect?

- alles in Java?

Share this post


Link to post
Share on other sites

Japp, nativ Java 8 mit Tinkerforge API 2.1.19

 

Am Anfang, um alles 100%tig zu verstehen, wollte ich noch keine Frameworks oder Threads nutzen, bevor ich freaky zeugs mache. Beim debugging komme ich immer zur IPConnectionBase Klasse, die mir die timeouts und andere events per Listener zusendet. Wäre nur gut wenn ich nicht gleich die API Debugger müsste, sondern irgendwo noch eine schraube drehen könnte, um ein reconnect zu forcen.

 

Ich versuche gerade meine Library für Kids/Hackerschool zu verbessern. Wäre da sehr cool wenn die Kids nicht das Programm Neustarten müssten wenn der USB neu connected

Share this post


Link to post
Share on other sites

Ich habe das Reconnect Szenario auch nie stabil mit der API zum Laufen bekommen (mit der C-API).

Ich habe mich dann dazu entschlossen das TCP/IP-Protokoll direkt zu verwenden.

Jetzt ist alles gut  :)

 

Share this post


Link to post
Share on other sites

oha, dann müsste man mal generell schauen woran es bei der API hängt um das zu fixen. Ich werd erstmal meine library fertig schreiben und dann die API als Kern auseinander nehmen... Würde es schon sinnvoll finden wenn die API gefixt werden könnte

Share this post


Link to post
Share on other sites

Ja, das hatte ich auch überlegt. Allerdings ist das TCP-Protokoll nun auch nicht soo kompliziert und man hat alles selbst in der Hand. Ich fand das einfacher, als die jeweiligen Libraries zu debuggen.

Share this post


Link to post
Share on other sites

kannst du Beispiel geben? z.B. Temperatur auslesen. ich verstehe das Konzept nicht wirklich wie ich das die callbacks nachbaue

Share this post


Link to post
Share on other sites

Sorry für die späte Antwort, der Thread ist mir wohl durch die Lappen gegangen.

 

Yuna, wenn du von USB sprichst, dann meinst du, dass der Stapel über USB angeschlossen ist? Du verwendest keine WIFI oder Ethernet Extension?

 

Tritt dieses Verhalten nur in deinem Programm auf, oder kannst du das auch in Brick Viewer nachstellen?

 

Was meinst du mit "doch verliert sekündlich ein Brick oder Bricklet dann plötzlich die connection."?

 

Die IPConnection stellt keine individuelle Verbindung zu jedem Brick und Bricklet her. Sondern die IPConnection verbindet sich mit dem Brick Daemon der auf deinem PC läuft an dem der Stapel per USB angeschlossen ist. Brick Daemon übersetzt dann die Anfragen und Antworten von TCP/IP nach USB und zurück.

 

Daher hilft ein disconnect/connect der IPConnection nicht, um die Bricks und Bricklets dazu zu bringen sich per Enumerate Callback zu melden. Dafür ist die enumerate Methode der IPConnection da. Diese fordert alle Bricks und Bricklets auf sich der Enumerate Callback zu melden.

 

Das übliche Vorgehen ist nach dem Verbindungsaufbau ein Enumerate anzufordern, um mitzubekommen was alles gerade angeschlossen ist.

 

Wenn du, während dein Programm läuft, einen Stapel von USB ab/ansteckst, dann bekommst du dafür automatisch entsprechend Enumerate Callbacks.

Share this post


Link to post
Share on other sites

Hi, danke für die Antwort!

 

Wenn du, während dein Programm läuft, einen Stapel von USB ab/ansteckst, dann bekommst du dafür automatisch entsprechend Enumerate Callbacks

 

Genau das funktioniert nicht wenn ich viele Bricklet anschließe. Ich bekomme die automatischen Callbacks aber von 28 erscheinen nur noch 24 wieder. Ohne ein genaues Verhalten zu erkennen, steigen dazu willkürlich 1-2 weitere Bricks oder Bricklets wieder aus und enden in ein disconnect / reconnect loop.

 

Mein Vorgehen war dann, dass ich bei Verlust eines Bricks oder Bricklets, einfach einen disconnect, connect und enumeration aufrufe. Doch der disconnect funktioniert nicht vollständig. Es bleiben Thread wie z.B. Callback-Processor offen. Nach einem zweiten Connect sind natürlich die Threads doppelt da. Meine Applikation kann leider keine fremden Threads schließen. Wenn ich jedoch mittels kill Befehl diese Threads stoppe, dann funktioniert alles wieder wunderbar.

 

WLAN ist dann wieder noch ein anderes Thema... Wenn ich da den Reconnect schaffe, was dort sauberer funktioniert, dann kann ich mit dieser Lösung nicht mehr mit USB die bricks ansteuern - aus dem oben geschilderten problem.

 

Es wäre sehr angenehm, wenn ich die Connection sauber schließen könnte. Dann ist ein reconnect viel einfacher für mich. @ttt hat scheinbar selbes Problem. Leider hat er nicht mehr die Lösung geschildert. Ich denk die Threads wurden etwas zu komplex aufgebaut. der CallbackThreadRestarter ist auch nicht gerade hilfreich wenn man disconnecten möchte.

 

Aufbau:

Ich habe alte Bricks (Master, Servo, IMU, IMU2) und sehr viele Bricklets alte sowie neuere. Es befinden sich keine MasterExtension oder RedBrick im Stapel

Share this post


Link to post
Share on other sites

Hi,

 

@yuna: Meine "Lösung" bestand daraus, dass ich mir eine zuverlässige Netzwerklibrary herausgesucht habe (in meinem Fall die libuv[1], wird auch in nodejs verwendet) und mich per ganz normalen TCP/IP zum Brick verbunden habe (über WLAN). Die Beschreibung zum TF-TCP Protokoll[2] ist glücklicherweise ausführlich.

War zwar eine Menge Arbeit, läuft jetzt aber seit Monaten stabil ohne Abstürze, Hänger oder Speicherfresser. Die libuv ist zwar nicht unbedingt einfach, aber zuverlässig und das wichtigste: Alles single-threaded (aus Programmierersicht).

 

[1] https://github.com/libuv/libuv

[2] https://www.tinkerforge.com/en/doc/Low_Level_Protocols/TCPIP.html

Share this post


Link to post
Share on other sites

Hi @ttt :)

 

vielen Dank! Ich kenne mich mit Netzwerk nicht mehr so gut aus. Ich schaue es mir mal an. Das finde ich an Tinkerforge genial, Alles ist dokumentiert und keine Blackboxen. Wäre nur schön wenn die Library an einer Stelle gefixed wird, statt jeder für sich. Wenn ich Zeit hab schaue ich mir die Lösung mal genauer an. Vielen vielen Dank!

@photron bitte sagt das ihr das fixt :D

Share this post


Link to post
Share on other sites

Ich bekomme die automatischen Callbacks aber von 28 erscheinen nur noch 24 wieder.

 

Okay, du bekommst nicht alle Enumerate Callbacks in deinem Programm. Kannst du das Problem in Brick Viewer oder mit dem Java Enumerate Beispiel auch erzeugen? Sprich, fehlen in Brick Viewer oder dem Beispiel auch Bricks und Bricklets, wenn du den Stapel an USB ansteckst? Oder tauchen dort immer alle Bricks und Bricklets auf?

 

Wenn es in Brick Viewer und dem Beispiel funktioniert, dann würde ich auf ein Problem in deiner Library tippen.

 

Ohne ein genaues Verhalten zu erkennen, steigen dazu willkürlich 1-2 weitere Bricks oder Bricklets wieder aus und enden in ein disconnect / reconnect loop.

 

Was meinst du mit "aussteigen"? Woran erkennst du das?

 

Den Disconnect/Reconnect Loop löst dann deine Library als Reaktion auf das "aussteigen" aus?

 

WLAN ist dann wieder noch ein anderes Thema... Wenn ich da den Reconnect schaffe, was dort sauberer funktioniert, dann kann ich mit dieser Lösung nicht mehr mit USB die bricks ansteuern - aus dem oben geschilderten problem.

 

Du kannst mit einem Stapel nicht gleichzeitig über WLAN und USB kommunizieren, genau dies kann zu fehlgeleiteten/verlorenen Callbacks führen.

 

Es wäre sehr angenehm, wenn ich die Connection sauber schließen könnte. Dann ist ein reconnect viel einfacher für mich. @ttt hat scheinbar selbes Problem. Leider hat er nicht mehr die Lösung geschildert. Ich denk die Threads wurden etwas zu komplex aufgebaut. der CallbackThreadRestarter ist auch nicht gerade hilfreich wenn man disconnecten möchte.

 

Zumindest in deinem AllStatusLed_Loop_Example.java steht sich da deine synchronized Stack.disconnect() Methode selber auf den Füßen, weil diese IPConnection.disconnect() aufruft und auch als Reaktion auf den IPConnection Disconnected Callback aufgerufen wird. Du solltest dieses Problem in deiner Library erstmal lösen.

 

Ich kann in meinen Tests keine Probleme mit sich nicht beendenden Threads außerhalb deiner Library erzeugen, daher kann ich da im Moment nichts fixen. Wenn es Fehler in den Java Bindings gibt werden wir diese natürlich beheben.

 

Welches Problem ttt da genau hat weiß ich nicht. Meines Wissens nach hat ttt es nirgendwo genau geschildert.

Share this post


Link to post
Share on other sites

Im BrickViewer habe ich tatsächlich das selbe Problem mit dem Reconnect über USB.

Das Bricks und Bricklets aussteigen erkenne ich ganz einfach per API das ständig diese einen Timeout bekommen und plötzlich wieder anmelden. Im Brickviewer sehe ich das anhand dessen, das einfach mal ein paar Bricks, Bricklets fehlen. Im Brickviewer pendelt sich das Problem automatisch ein. Ich schaffe das leider nicht nachzustellen das es sich einpendelt.

Keine Sorge, ich verbinde nur USB oder WLAN. Ich meinte nur das wenn ein Fix/Workaround für WLAN finde, das nicht mehr für USB funktioniert. Meine stack.disconnect(); Methode, die sich selbe auf die Füße tritt, war nur einer der Verzweifelten Versuche. Dies werde ich wieder auf die normale Methode ausbauen. Ich würde gern mehr Details geben, aber kann das Problem nicht ganz greifen. Ich weis nur das bei sehr vielen Bricklets, diese nicht alle wiederkommen. Es sei denn ich beende das gesamte Programm und starte es neu. Meine Erwartung wäre das ich den USB mal kurz abstecken kann und danach wieder anstecken sowie weiter arbeiten kann.

Share this post


Link to post
Share on other sites

Das hört sich nach starkem Nachrichtenverlust an. Es gehen Enumerate Callbacks verloren, dadurch bekommst du beim Anstecken an USB nicht alle Bricks und Bricklets mit. Es gehen Abfragen an die Bricks und Bricklets verloren, dadurch bekommst du die Timeouts.

 

Das du so starken Nachrichtenverlust über USB hast ist ungewöhlich. Da du das aber auch in Brick Viewer hast wird das höchstwahrscheinlich nichts mit deiner Software zu tun haben, sondern mit deinem speziellen Aufbau. Das passt dann auch dazu, dass es nur ab einer bestimmten Größe des Stapels auftritt.

 

Nur um sicher zu gehen, dass wir hier nicht alte Bugs suchen: Hast du auf allen Bricks und Bricklets die aktuelle Firmware laufen? Der aktuelle Brick Viewer Version 2.4.4 zeigt dir das auf dem Setup Tab an. Hast du die aktuelle Brick Daemon Version 2.3.2 installiert? Wenn das nicht der Fall ist, dann updatet bitte zuerst mal alles auf die aktuellen Versionen.

 

Beschreibe bitte mal den exakten Aufbau des Stapels (was ist wie wo mit welcher Kabellänge angeschlossen) der dir Probleme macht, damit ich das hier nachstellen kann.

 

Wenn du auf macOS oder Linux arbeitest dann häng mir auch bitte mal die Brick Daemon Logdatei (/var/log/brickd.log) an, oder schick sie mir per E-Mail. Vielleicht kann ich daraus sehen warum der Nachrichtenverlust auftritt.

Share this post


Link to post
Share on other sites

Sorry für die verspätete Antwort. Ich musste für einen Test meine Bricks und Bricklets aus den verschiedenen Hackerschool Büros holen.

 

Ich habe tatsächlich veraltete Firmware gehabt. Leider habe ich vorher geupdatet und kann das Problem nicht reproduzieren. Aus meiner Library ist nun mein Workaround raus gelöscht und nutze somit die neuste Tinkerforge API. mein Stack Objekt ist nun nur noch ein Wrapper von der IPConnection. Nur noch beim disconnect bleibt es ewig hängen solange ich listener aktiv habe. Könnt ihr eine "removeAllListener" Methode implementieren? Oder mache ich wieder etwas falsch?

Share this post


Link to post
Share on other sites

Ich hab mir die Library noch mal angesehen und der Deadlock mit der disconnect Methode ist noch da.

 

Wenn ich den beheben, dann bleibt noch das Problem, dass das AllStatusLed_Loop_Example Beispiel sich auch nach dem Ende der main Methode nicht direkt beendet, sondern noch ein Stück weiter läuft. Das liegt daran, wie du den ExecutorService verwendest. Der hält das Programm noch eine Weile offen.

 

Mir sind auch noch ein paar andere Kleinigkeiten aufgefallen. Ich habe die dazu auch GitHub mal einen Pull Request erstellt.

Share this post


Link to post
Share on other sites

Vielen vielen Dank!!!!!

 

habe den Pull Request gemerged :)

Manchmal sieht man allein den Wald vor lauter bäumen nicht mehr :)

Laut ersten Tests funktioniert alles Perfekt :)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...