CChris Geschrieben May 15, 2013 at 12:02 Geschrieben May 15, 2013 at 12:02 Hallo Zusammen, ist es Möglich über Programmcode von allen an einen Masterbrick angeschlossenen Extensions und Bricklets die UID und den Typ zu ermitteln? Ich vermute mal mit dem EnumerationCallback() für den Masterbrick... oder?? Falls du keine UID kennst, dann bleibt dir nur der Enumerate Callback mit Timeout. Wenn es ein "TinkerPing" gäbe würde das genau so funktionieren. Kann mir jemand dafür mal bitte ein kleinen Beispielcode schreiben? Zitieren
borg Geschrieben May 15, 2013 at 12:08 Geschrieben May 15, 2013 at 12:08 Beispiel dafür gibt es hier: http://www.tinkerforge.com/de/doc/Tutorials/Tutorial_Rugged/Tutorial.html Zitieren
FlyingDoc Geschrieben May 15, 2013 at 12:09 Geschrieben May 15, 2013 at 12:09 Der Beispielcode hängt von der Programmiersprache ab. Die Funktion ist schon richtig. Hier mal meine Funktion in c++ geschrieben. void cb_enumerate(const char *uid, const char *connected_uid, char position, uint8_t hardware_version[3], uint8_t firmware_version[3], uint16_t device_identifier, uint8_t enumeration_type, void *user_data) { /****************************************************************************/ /* Antwort auf Komponentenabfrage (Bricks,Bricklets) */ /****************************************************************************/ // printf("device_uid: %s\tdevice_name: %s\tdevice_stack_id: %d\t is_new: %d\n\n", device_uid, device_name, device_stack_id,is_new); /****************************************************************************/ /* Testen ob IMU Brick gefunden */ /****************************************************************************/ if(device_identifier==IMU_DEVICE_IDENTIFIER) { Create_IMU(uid,device_identifier, connected_uid, position,true); } if(device_identifier==MASTER_DEVICE_IDENTIFIER) { Create_Master(uid,device_identifier, connected_uid, position,true); } if(device_identifier==ANALOG_IN_DEVICE_IDENTIFIER) { Create_AnalogIn(uid,device_identifier, connected_uid, position,true); } if(device_identifier==ROTARY_POTI_DEVICE_IDENTIFIER) { Create_RotaryPoti(uid,device_identifier, connected_uid, position,true); } if(device_identifier==TEMPERATURE_DEVICE_IDENTIFIER) { Create_Temperature(uid,device_identifier, connected_uid, position,true); } if(device_identifier==BAROMETER_DEVICE_IDENTIFIER) { Create_Barometer(uid,device_identifier, connected_uid, position,true); } if(device_identifier==IO16_DEVICE_IDENTIFIER) { Create_IO16(uid,device_identifier, connected_uid, position,true); } if(device_identifier==GPS_DEVICE_IDENTIFIER) { Create_GPS(uid,device_identifier, connected_uid, position,true); } } Hier findest du auch eine Liste. Die device_identifier sind jeweils in der dazugehörigen .h Datei definiert. Zitieren
CChris Geschrieben May 15, 2013 at 15:19 Autor Geschrieben May 15, 2013 at 15:19 Hi, danke schon mal für den Ansatz Jetzt müsste ich das alles in einer ListView ausgeben... also z.B. BrickletTyp | UID | ConnectedUID Temperatur | abc | 1354dg Humidity | fge | 1354dg Temperatur | abc | 22568cs Humidity | flw | 22568cs ach ja, Programmiere im Moment in C#... oder ... ich versuch es zumindest...^^ Zitieren
AuronX Geschrieben May 15, 2013 at 17:34 Geschrieben May 15, 2013 at 17:34 Kommt jetzt noch ein bisschen drauf an, ob du WPF oder WinForms nutzt. Im Wesentlichen sind folgende Schritte zu erledigen: 1. Alle Daten die du anzeigen willst am besten in einer kleinen Klasse kapseln etwa: class MyModel { public string UID { get; private set; } //...mehr properties zum anzeigen... public MyModel(string uid, /* mehr parameter für mehr properties */) { UID = uid; //und der Rest } } 2. Im Callback aus den erhaltenen Informationen eine solche Klasse erstellen und zur ListView hinzufügen, dabei beachten, dass das ganze im GUI-Thread erfolgen muss, google stichworte dazu: WinForms Invoke oder WPF Invoke 3. Im ListView konfigurieren wie die Model-Elemente angezeigt werden sollen, auch hier ist das ganze WinForms/WPF-abhängig P.S.: Ein WPF-Beispiel für einen anderen Anwendungsfall findest du hier: https://github.com/NobodysNightmare/TwitchURLGrabber/tree/master/TwitchURLGrabber (hat nix mit TF zu tun, aber das ist meine erste in WPF realisierte ListView ^^) Zitieren
CChris Geschrieben May 15, 2013 at 18:46 Autor Geschrieben May 15, 2013 at 18:46 nutze WinForms... ist aber auch nur eine erste Software um ein bisschen zu testen und zu spielen ^^ Hauptsächlich geht es mir gerade darum, wie ich die Daten empfange... da ich die Bricks noch nicht geliefert bekommen habe, kann ich auch noch nicht wirklich testen... sodass ich gerade etwas "blind" Programmiere. habe jetzt: private void EnumerateCB(IPConnection sender, string UID, string connectedUID, char position, short[] hardwareVersion, short[]firmwareVersion, int deviceIdentifier, short enumerationType) { } Ich gehe mal davon aus, dass ich hier die jeweiligen Werte als Array zurück bekomme... oder? Zitieren
AuronX Geschrieben May 15, 2013 at 19:22 Geschrieben May 15, 2013 at 19:22 Im Anhang findest du ein Programm, dass für deine Tests ausreichen sollte ^^ Das simuliert einen Stack, du kannst es also nutzen bis deine echte Hardware da ist. Starten und dann auf localhost:4224 verbinden. Enumerate-Callback und einige Basis-Funktionen funktionieren. Was du mit dem Array meintest habe ich nicht verstanden...TFStackEmulator.zip Zitieren
FlyingDoc Geschrieben May 15, 2013 at 19:46 Geschrieben May 15, 2013 at 19:46 habe jetzt: private void EnumerateCB(IPConnection sender, string UID, string connectedUID, char position, short[] hardwareVersion, short[]firmwareVersion, int deviceIdentifier, short enumerationType) { } Ich gehe mal davon aus, dass ich hier die jeweiligen Werte als Array zurück bekomme... oder? Nein. Das sind keine Array. Jeder Brick oder Bricklet wird einzeln gemeldet. Also für jeden bekommst dun einen Callback Aufruf. Ins Array musst du sie schon selbst "reinklimpern". Zitieren
FlyingDoc Geschrieben May 15, 2013 at 19:55 Geschrieben May 15, 2013 at 19:55 Was du mit dem Array meintest habe ich nicht verstanden... Ich versuch mal den Erklärbär! Ein Array ist um es mal leicht vorstellbar zu erklären, eine Tabelle (Stapel) im Speicher wo in jeder "Zelle" ein Zeiger (die Adresse) zu einer Variable oder oder eine Struktur im Speicher steht. Das ganze ist dynamisch. Kann also seine Größe ändern. Er will sozusagen eine Struktur für jedes Brick oder Bricklet anlegen und in die Tabelle eintragen und dann in einer View anzeigen. Zum Testen. Zitieren
CChris Geschrieben May 15, 2013 at 20:26 Autor Geschrieben May 15, 2013 at 20:26 ^^ dachte, es kommt vlt. ein Array als Datensatz zurück... So, hab jetzt ein bisschen was Probiert - Danke auf jeden fall @AuronX - klappt soweit wunder bar! Bin zwar noch nicht sehr weit, aber immerhin... langsam wirds Allerdings: Ist es normal, dass ich die Daten doppelt zurück bekomme, wenn dein Programm im Hintergrund läuft? Zitieren
CChris Geschrieben May 15, 2013 at 20:33 Autor Geschrieben May 15, 2013 at 20:33 ok, hab den Grund gefunden... Im Codebeispiel von "Robuster Ansatz" ist: ipcon.EnumerateCallback += EnumerateCB; ipcon.Connected += ConnectedCB; und der ConnectedCB schickt wiederum ein Enumerate: static void ConnectedCB(IPConnection sender, short connectReason) { // Enumerate devices again. If we reconnected, the Bricks/Bricklets // may have been offline and the configuration may be lost. // In this case we don't care for the reason of the connection ipcon.Enumerate(); } Zitieren
AuronX Geschrieben May 16, 2013 at 07:10 Geschrieben May 16, 2013 at 07:10 @FlyingDoc: Danke für die Erklärung, aber so war das nicht gemeint ^^ Mir war nicht klar wo er ein Array erwartet ^^ Und noch als Ergänzung: In C# (und auch in allen anderen Sprachen die mir gerade einfallen) haben Arrays immer eine feste Größe. Für dynamisches Resizen gibt es dann üblicherweise verschiedene Klassen, die meist entweder auf Arrays aufbauen (und beim Vergrößern alles von einem ins nächste kopieren) oder als verkettete Listen arbeiten. @CChris: schön zu sehen, dass es geholfen hat und du schonmal anfangen konntest Zitieren
Nic Geschrieben May 16, 2013 at 11:58 Geschrieben May 16, 2013 at 11:58 Ich gehe mal davon aus, dass ich hier die jeweiligen Werte als Array zurück bekomme... oder? So ganz falsch liegst Du damit nicht, denn der EnumerateEvent-Handler in C# gibt die FW- und Hardware-Version hier jeweils als Array der festen Größe 3 vom Typ short zurück, Arrays erkennbar an den eckigen Klammern: ...short[] hardwareVersion, short[] firmwareVersion... Der Ursprung ist sehr schön zu sehen in der Methode DispatchPacket der IpConnection Class. Zitieren
CChris Geschrieben May 16, 2013 at 17:45 Autor Geschrieben May 16, 2013 at 17:45 Hi nochmal so, die Test Bricks sind da, und es funktioniert fürs erste so, wie ich es mir vorgestellt hatte... Allerdings... Kann mir jemand sagen, warum mir das DualRelayBricklet in meiner Liste nicht angezeigt wird? Ich habe: Masterbrick - Identifier 13, UID 6m9VR4 HumidityBricklet - Identifier 27, UID eGQ, ConnectedUID 6m9VR4 TemperatureBricklet - Identifier 216, UID dD5, ConnectedUID 6m9VR4 aber das DualRelay wird mir nicht angezeigt :-( Hängt an 6m9VR4 am Port "C"... Vielen Dank für die Hilfe bis hier hin!! Zitieren
AuronX Geschrieben May 17, 2013 at 06:59 Geschrieben May 17, 2013 at 06:59 Dem Durchstreichen entnehme ich, dass du das Problem mit deinem DualRelay schon selbst gelöst hast ^^ Möchtest du noch kurz mitteilen, woran es lag? (einfach, damit ich ein besseres Gefühl für "Standardprobleme" bekomme ) Zitieren
CChris Geschrieben May 17, 2013 at 07:20 Autor Geschrieben May 17, 2013 at 07:20 ja, das mit dem DualRelay hat sich geklärt... wurde auch im BrickViewer nicht angezeigt... bin dann mal testweise auf Update Firmware gegangen - plötzlich war das Bricklet zu sehen - und wie sich gezeigt hat noch mit einer 1.0 Firmware. Nach Update aller komponenten wird jetzt alles korrekt erkannt. Zitieren
CChris Geschrieben May 18, 2013 at 15:11 Autor Geschrieben May 18, 2013 at 15:11 Und weiter geht's... Derzeit hab ich noch ein kleines Problem mit dem Beispielcode aus der Dokumentation, bzw. mit einem Reconnect zu den Bricks... Im Beispielcode für C# wird die Sache mit den Callbacks wie folgt beschrieben: static void Main() { // Create IP Connection ipcon = new IPConnection(); // Register IP Connection callbacks ipcon.EnumerateCallback += EnumerateCB; ipcon.Connected += ConnectedCB; // Connect to brickd, will trigger cb_connected ipcon.Connect(HOST, PORT); ipcon.Enumerate(); System.Console.WriteLine("Press key to exit"); System.Console.ReadKey(); ipcon.Disconnect(); } static void EnumerateCB(IPConnection sender, string UID, string connectedUID, char position, short[] hardwareVersion, short[] firmwareVersion, int deviceIdentifier, short enumerationType) { if(enumerationType == IPConnection.ENUMERATION_TYPE_CONNECTED || enumerationType == IPConnection.ENUMERATION_TYPE_AVAILABLE) { ...... } } static void ConnectedCB(IPConnection sender, short connectReason) { // Enumerate devices again. If we reconnected, the Bricks/Bricklets // may have been offline and the configuration may be lost. // In this case we don't care for the reason of the connection ipcon.Enumerate(); } Ich habe den Code jetzt wie folgt übernommen: private void button2_Click(object sender, EventArgs e) { // Register IP Connection callbacks ipcon.EnumerateCallback += EnumerateCB; //ipcon.Connected += ConnectedCB; // Connect to brickd, will trigger cb_connected try { ipcon.Connect(TF_Bricklets.HOST, TF_Bricklets.PORT); } catch (Exception exceptionMsg) { MessageBox.Show(exceptionMsg.Message + "\n\nDas Programm wird beendet.", "Fehler!", MessageBoxButtons.OK, MessageBoxIcon.Error); this.Close(); } try { ipcon.Enumerate(); } catch (Exception exceptionMsg) { MessageBox.Show(exceptionMsg.Message, "Fehler!", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error); } //ipcon.Disconnect(); } private void EnumerateCB(IPConnection sender, string UID, string connectedUID, char position, short[] hardwareVersion, short[] firmwareVersion, int deviceIdentifier, short enumerationType) { if (enumerationType == IPConnection.ENUMERATION_TYPE_CONNECTED || enumerationType == IPConnection.ENUMERATION_TYPE_AVAILABLE) { // create the subitems to add to the list string[] myItems = new string[] { UID.ToString(), connectedUID.ToString() }; // insert all the items into the listview at the last available row listView1.Invoke(new Action(() => listView1.Items.Add(deviceIdentifier.ToString()).SubItems.AddRange(myItems))); private void ConnectedCB(IPConnection sender, short connectReason) { // Enumerate devices again. If we reconnected, the Bricks/Bricklets // may have been offline and the configuration may be lost. // In this case we don't care for the reason of the connection ipcon.Enumerate(); } Wenn ich ipcon.Connected += ConnectedCB; nicht auskommentiere, werden mir alle Verbundenen Bricks und Bricklets doppelt ausgegeben - ich vermute mal, durch den erneuten Aufruf von ipcon.Enumerate() in ConnectCB... ?! Desweiteren musste ich das ipcon.Disconnect() auskommentieren, da das Programm ansonsten hängen bleibt, bzw. in diesem Fall keine Verbindung aufbaut... Ich gehe davon aus, dass der Grund hierfür relativ einfach sein dürfte, aber ich komme leider nicht drauf... Vermutlich, weil der Code unter "Robuster Ansatz" als Consolenprogramm geschrieben ist, ich aber eine GUI nutze? Zusätzlich habe ich versucht, das ganze nochmal als WPF in C# zu machen... funktioniert auch einiger Maßen, allerdings habe ich hier ein kleines Problem mit dem Disconnect und der ListView... dazu aber ggf. später mehr ^^ Habt Ihr noch nen Tipp für mich? Zitieren
Ritchi210 Geschrieben May 18, 2013 at 18:31 Geschrieben May 18, 2013 at 18:31 Hi CChris, also die doppelte Ausgabe der Bricks und Bricklets ist das doppelte aufrufen der Methode ipcon.Enumerate(). Bei deinem zweiten Problem mit dem Ausklammern des disconnects frage ich mich gerade, ob du die IPConnection nach dem disconnecten noch benutzt? Wenn ja könnte das der Grund dafür sein. Viele grüße Ritchi Zitieren
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.