Jump to content

Angeschlossene Bricks und Bricklets identifizieren


CChris

Recommended Posts

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?

Link zu diesem Kommentar
Share on other sites

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.

Link zu diesem Kommentar
Share on other sites

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...^^

Link zu diesem Kommentar
Share on other sites

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 ^^)

Link zu diesem Kommentar
Share on other sites

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?

Link zu diesem Kommentar
Share on other sites

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

Link zu diesem Kommentar
Share on other sites

 

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". ;D

Link zu diesem Kommentar
Share on other sites

Was du mit dem Array meintest habe ich nicht verstanden...

Ich versuch mal den Erklärbär! ;D

 

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.

Link zu diesem Kommentar
Share on other sites

^^ 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?

tf_test.png.5abf37ecebb244168945e2a5d9c929bb.png

Link zu diesem Kommentar
Share on other sites

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();
    }

Link zu diesem Kommentar
Share on other sites

@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 :)

Link zu diesem Kommentar
Share on other sites

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.

Link zu diesem Kommentar
Share on other sites

Hi nochmal :)

 

so, die Test Bricks sind da, und es funktioniert fürs erste so, wie ich es mir vorgestellt hatte...  ;D

 

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!!

tf_test.thumb.png.6140b22e1140622e3efbcff418a54aab.png

Link zu diesem Kommentar
Share on other sites

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?

 

Link zu diesem Kommentar
Share on other sites

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

Link zu diesem Kommentar
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.

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...