BST Posted October 24, 2018 at 10:08 AM Share Posted October 24, 2018 at 10:08 AM Servus, in einem unserer Projekte (Python) nutzen wir einen Master Brick mit WiFi Extension 2.0 und einen mit WiFi Extension (alte Version). Für beide wird ein CALLBACK_CONNECTED registriert. Das funktioniert auch bei dem Master Brick mit dem alten WiFi-Modul hervorragend: Die als CALLBACK gesetzte Funktion wird immer augerufen, wenn die WLAN-Verbindung neu augebaut wird - egal, ob zum ersten Mal per .connect() Befehl oder nach einem Abrruch der Verbindung, z.B. weil das Brick Stromausfall hatte. Anders bei dem Brick mit WiFi Extension 2.0: Beim ersten Verbindungsaufbau per .connect() Befehl wird der Callback korrekt ausgelöst, wenn dann aber die WiFi-Verbindung unterbrochen wird und wieder aufgebaut ist, wird der Callback NICHT ausgelöst. Kennt jemand dieses Verhalten, ist das bekannt oder ein Bug? Machen wir etwas falsch? Code im Anhang. LG Johannes #!/usr/bin/python3 #---------------- Library -------------------------- from tinkerforge.ip_connection import IPConnection from tinkerforge.bricklet_sound_pressure_level import BrickletSoundPressureLevel from tinkerforge.bricklet_oled_64x48 import BrickletOLED64x48 from tinkerforge.bricklet_dual_relay import BrickletDualRelay import time import datetime # -------------- Implementation --------------------- class rugged: HOST1 = "brickie" HOST2 = "brickie2" PORT = 4223 def __init__(self): self.oled1 = None self.dr1 = None self.spl1 = None self.oled2 = None self.dr2 = None self.spl2 = None self.ipcon1 = IPConnection() self.ipcon2 = IPConnection() self.ipcon1.register_callback(IPConnection.CALLBACK_ENUMERATE,self.cb_enumerate1) self.ipcon1.register_callback(IPConnection.CALLBACK_CONNECTED,self.cb_connected1) self.ipcon2.register_callback(IPConnection.CALLBACK_ENUMERATE,self.cb_enumerate2) self.ipcon2.register_callback(IPConnection.CALLBACK_CONNECTED,self.cb_connected2) isConnected1 = False isConnected2 = False while not (isConnected1 and isConnected2): if not isConnected1: try: print('Connecting to Brick 1...') self.ipcon1.connect(rugged.HOST1, rugged.PORT) isConnected1 = True print('Connected to Brick 1!') except OSError: print('Could not connect to Brick1. Will retry in 5 seconds...') time.sleep(5) if not isConnected2: try: print('Connecting to Brick 2...') self.ipcon2.connect(rugged.HOST2, rugged.PORT) isConnected2 = True print('Connected to Brick 2!') except OSError: print('Could not connect to Brick2. Will retry in 5 seconds...') time.sleep(5) self.ipcon1.enumerate() self.ipcon2.enumerate() def cb_dB1(self, decibel): #This part should not matter def cb_enumerate1(self, uid, connected_uid, position, hardware_version, firmware_version, device_identifier, enumeration_type): if enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED or \ enumeration_type == IPConnection.ENUMERATION_TYPE_AVAILABLE: if device_identifier == BrickletSoundPressureLevel.DEVICE_IDENTIFIER: self.spl1 = BrickletSoundPressureLevel(uid, self.ipcon1) self.spl1.set_decibel_callback_configuration(100,False,"x",0,0) self.spl1.register_callback(self.spl1.CALLBACK_DECIBEL,self.cb_dB1) if device_identifier == BrickletOLED64x48.DEVICE_IDENTIFIER: self.oled1 = BrickletOLED64x48(uid, self.ipcon1) self.oled1.clear_display() if device_identifier == BrickletDualRelay.DEVICE_IDENTIFIER: self.dr1 = BrickletDualRelay(uid, self.ipcon1) def cb_connected1(self, connected_reason): self.ipcon1.enumerate() def cb_dB2(self, decibel): #This part should not matter def cb_enumerate2(self, uid, connected_uid, position, hardware_version, firmware_version, device_identifier, enumeration_type): if enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED or \ enumeration_type == IPConnection.ENUMERATION_TYPE_AVAILABLE: if device_identifier == BrickletSoundPressureLevel.DEVICE_IDENTIFIER: self.spl2 = BrickletSoundPressureLevel(uid, self.ipcon2) self.spl2.set_decibel_callback_configuration(100,False,"x",0,0) self.spl2.register_callback(self.spl2.CALLBACK_DECIBEL,self.cb_dB2) if device_identifier == BrickletOLED64x48.DEVICE_IDENTIFIER: self.oled2 = BrickletOLED64x48(uid, self.ipcon2) self.oled2.clear_display() if device_identifier == BrickletDualRelay.DEVICE_IDENTIFIER: self.dr2 = BrickletDualRelay(uid, self.ipcon2) def cb_connected2(self, connected_reason): self.ipcon2.enumerate() if __name__ == "__main__": temp=rugged() input('Program is running. Press enter to exit.') temp.ipcon1.disconnect() temp.ipcon2.disconnect() Quote Link to comment Share on other sites More sharing options...
borg Posted October 26, 2018 at 11:57 AM Share Posted October 26, 2018 at 11:57 AM Grundsätzlich kann sich die WIFI Extension (1 oder 2) nach einem neustart nicht selbst wieder mit dem Programm verbinden. Der Verbindungsaufbau findet immer durch die IPConnection auf PC-Seite statt. Wenn die Verbindung zur WIFI Extension abbricht, sorgt das auto-reconnect Feature der IPConnection dafür das die Verbindung wieder hergestellt wird. Dadurch wird dann auch ein neuer CALLBACK_CONNECTED erzeugt. Das funktioniert mit beiden Extensions, hab ich getestet. Das Problem hier ist die Erkennung des Abbruchs der TCP/IP Verbindung. Wann eine TCP/IP Verbindung als abgebrochen erkannt wird hängt von der Implementierung des TCP/IP Stacks, des Betriebssystems, den Einstellungen im Betriebssystem etc ab. Da haben wir im Zweifelsfall keinen Einfluss drauf. Warum sich das jetzt bei euch zwischen WIFI Extension V1 und V2 unterscheidet weiß ich nicht. Als Workaround könntet ihr folgendes probieren: Oben bei den Imports: import struct import socket Nach dem self.ipconX.connect: sec = 15 usec = 0 timeval = struct.pack('ll', sec, usec) self.ipconX.socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval) Mit dieser Socket Option wird die Verbindung nach 15 Sekunden ohne Datenaustausch geschlossen und das auto-reconnect greift auf jeden Fall. Nur wird die Verbindung damit natürlich auch geschlossen und wieder hergestellt wenn für 15 Sekunden einfach keine Daten übertragen wurden. Am besten wäre es wenn das Tinkerforge Protokoll eine Art Alive-Ping-Pong-Message hätte die zwischen Brick Daemon und Bindings hin und hergeschickt wird. Auf diese Nachricht könnte man dann einen Timeout haben der automatisch das auto-reconnect startet, auch wenn die TCP/IP-Verbindung noch offen ist. Das steht auch schon auf der TODO-Liste, gibt es allerdings im Moment noch nicht im Protokoll. Quote Link to comment Share on other sites More sharing options...
BST Posted October 26, 2018 at 12:38 PM Author Share Posted October 26, 2018 at 12:38 PM Vielen Dank, Workaround läuft. Interessant wäre natürlich noch, warum die TCP/IP-Verbindungen zu den versch. Master Extensions unterschiedlich behandelt werden... MfG Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.