Jump to content

Perl binding brick.pm


Recommended Posts

habe eine brick.pm gebastelt um den Spass auf in Perl zu benutzen.

Braucht Math::Int64.

Alle Funtionen der Bricks und Bricklets sind aus der TCP - Doku entnommen.

Die Callbacks werden mit der Funktion brick::wait(timeout,brick1, .. , brickn)

verarbeitet. Jeder Brick(let) hat seine eigene Socket zum brickd.

Doku fehlt noch kommt später. Würde mich über feedback freuen.

Habe zum testen eine Stepper, Servo, Master, LCD20x4, Poti, IO4, light und distance Brick(let).

Habe meine Test-Programm t.pl auch drangehängt.

 

Viel Spass beim basteln.

 

Armin

brick.pm

t.pl

Link to comment
Share on other sites

Das sieht viel besser aus als die Perl Bindings die hier letzten vorgestellt wurden, die mit XS aus den C Bindings gewrappt wurden :)

 

Zwei Verbesserungsvorschläge hab ich allerdings für Dinge bei denen du vom allgemeinen Konzept der bisherigen Bindings abgewichen bist:

 

1) Du verwendest pro Brick(let) eine eigenen Socket. Mit dem jetzigen brickd funktioniert das, da der mehrere TCP/IP Verbindungen verwenden kann. Die WIFI Extension wird aber wahrscheinlich nur eine einzige TCP/IP Verbindungen unterstützen. Dann funktionieren deine Bindings nur noch für einen Brick im Stack.

 

Unsere bisherigen Bindings haben eine IPConnection, die einen Socket hat den sich alle Brick(let)s teilen.

 

2) Du pollst die Callbacks mit brick::wait. Ja, die PHP Bindings tun das auch, aber nur weil es in PHP keine Threads gibt.

 

Die übliche Vorgehensweise ist es, dass die IPConnection zwei Threads hat. Einen der eingehende Daten vom Socket ließt und einen der sich um die Ausführung von Callbacks kümmert. Dadurch passiert das ganze im Hintergrund und der Benutzer muss sich nicht explizit darum kümmern.

 

Oder hast du spezielle Gründe für diese Abweichungen, die mir entgangen sind?

Link to comment
Share on other sites

Also zu 2)

ich habe in Perl noch nicht mit Threads gearbeitet deswegen ohne.

Die Callbacks werden nicht gepollt, sondern mit IO::Select wird auf eine Antwort vom brickd gewartet. Die Schnittstelle brick::wait gestattet, daß nur auf bestimmte Brick(let)s gewartet wird.

zu 1)

Deshalb hat auch jeder Brick(let) seine eigene Socket. Außerdem kann man mit meinem Konzept, Brick(let)s von verschieden Rechner ansprechen.

 

Wenn ihr nun das brickd-Konzept ändert, muß ich natürlich meine Schnittstellen anpassen. Aber diese Änderung wäre eine deutliche Einschränkung der Funktionalität.

Dann könnte ich nicht mehr mehrere Programme auf einem Rechner paralell starten und ein Programm könnte nicht Brick(let)s von verschiednen Rechner kontrollieren.

Das jetzige Konzept ist optimal geeignet, für die Lehre, zur Übung von IPC und verteiltem Rechen.

Ich hoffe also das ihr das alte Konzept beibehaltet.

 

mfg

 

Armin

 

Link to comment
Share on other sites

Also zu 2)

ich habe in Perl noch nicht mit Threads gearbeitet deswegen ohne.

Die Callbacks werden nicht gepollt, sondern mit IO::Select wird auf eine Antwort vom brickd gewartet. Die Schnittstelle brick::wait gestattet, daß nur auf bestimmte Brick(let)s gewartet wird.

 

Auch select ist eine Art poll :)

 

Auf Getter Aufrufe muss eh explizit gewartet werden. Was du da tust ist im Prinzip das was in ich PHP getan habe. Ist also legitim, wenn man keine Threads hat oder verwenden will. Allerdings sehe ich das ausgewählte Warten von brick::wait nicht als nützlich an, da dies nicht der Normalfall sondern ein Sonderfall ist.

 

zu 1)

Deshalb hat auch jeder Brick(let) seine eigene Socket. Außerdem kann man mit meinem Konzept, Brick(let)s von verschieden Rechner ansprechen.

 

Dazu kann man mehrere IPConnection Objekte verwenden.

 

Wenn ihr nun das brickd-Konzept ändert, muß ich natürlich meine Schnittstellen anpassen. Aber diese Änderung wäre eine deutliche Einschränkung der Funktionalität.

Dann könnte ich nicht mehr mehrere Programme auf einem Rechner paralell starten und ein Programm könnte nicht Brick(let)s von verschiednen Rechner kontrollieren.

Das jetzige Konzept ist optimal geeignet, für die Lehre, zur Übung von IPC und verteiltem Rechen.

Ich hoffe also das ihr das alte Konzept beibehaltet.

 

Wir ändern das brickd Konzept nicht. Ich hatte mit da nicht ausführlich genug ausgedrückt. brickd als Programm auf dem PC bleibt wie es ist.

 

Es wird aber demnächst die WIFI Extension geben. Und bei der läuft brickd dann im Prinzip auf dem Master Brick. Dass heißt du stellst eine TCP/IP Verbindung direkt mit dem Master Brick her ohne einen brickd auf dem PC dazwischen. Dieser spezielle brickd auf dem Master wird bedingt durch Hardwarebeschräkungen wahrscheinlich nur eine TCP/IP Verbindung unterstützen.

 

Dies funktioniert mit unseren bisherigen Bindings, da sich hier Bricks eine TCP/IP Verbindungs teilen können. Mit deinen Perl Bindings könnte man pro Stack mit WIFI Extension nur einen Brick oder Bricklet ansprechen.

Link to comment
Share on other sites

Ich habe das anderswo aus ähnlichen Gründen schonmal vorgeschlagen:

Wenn der aktuelle brickd auch TCP-Devices (also andere "brickd"s) anbinden könnte, dann wäre das eine gute Lösung für folgende Probleme:

- Code der nur eine Verbindung für viele Devices nutzt

- mehrere Clients die den gleichen Stack nutzen wollen

 

Inzwischen hatte ich auch schon die Gelegenheit den Brickd-Code anzuschauen. Leider ist der etwas obfuskiert... Aber egal, ich denke es sollte grundsätzlich möglich sein den Brickd um diese Funktionalität zu erweitern.

Um es mal kurz zu umreißen:

- Das Management der routing-tabelle müsste aus dem USB-Device in das brick-protocol wandern (die tabelle selbst liegt eh dort und ist auch "logisch" dort zu hause)

- Das USB-Device müsste auf ein abstrakteres Konzept abgebildet werden (quasi neue super-class)

- Das brick-protocol kennt nur noch diese abstrakte Klasse

- Eine neue Klasse (TCP-Device?) kann diese neue Klasse ebenfalls implementieren

Link to comment
Share on other sites

  • 2 weeks later...

Hi so Urlaub ist zu Ende

 

habe die Schnittestelle jetzt angepasst.

Man kann new nun auf 3 Arten ansprechen

 

Class->new( host, port, uid )

Class->new( IO::Socket::INET, uid )

obj->new( Class, uid )

 

damit können jetzt alle Objekte die gleiche Socket benutzen.

Anbei wieder ein t1.pl was alle 3 Arten benutzt.

 

Die Doku kommt später.

 

mfg

 

Armin

brick.pm

t1.pl

Link to comment
Share on other sites

Hi,

 

ich habe noch schnell den einen Generator gebastelt der die Bindings/*.py in brick.pm umschreibt. In Perl weil *.py kann ich nicht. Vorraussetzung ist im gleichen Verzeichnis sind die Bindings/*.py und brick_rumpf.pm. Dann einfach brick_gen.pl starten und er baut brick.pm.

Habe gesehen ihr baut ständig an den Schnittstellen rum deswegen doch der Generator. Dazu noch eine Frage was ist der Unterschied zwischen CHAR und STRING ? und wann gibt es wieder Stepper-Bricks ?

Anbei noch die neueste brick.pm.

 

mfg

 

Armin

brick_gen.pl

brick_rumpf.pm

brick.pm

Link to comment
Share on other sites

Hallo,

 

habe noch mal die Schnittstellen überarbeitet.

 

mit new kann ich auch gleich initiallisieren

 

new( [ (host,port)|IO::Socket::Inet],[GUID],[ini])

 

Ini ist ein Hash mit

[funktion|Para] => [ value | Arrayref ]

 

Beispiel für den Stepper

 

my $step = stepper->new( $host, $port, '9ekEFBE4X9N', {

debug => 1,

set_max_velocity => 500,

set_speed_ramping => [4000,4000],

set_step_mode => 8,

set_motor_current => 100,

set_current_position => 0,

set_minimum_voltage => 5000,

CALLBACK_POSITION_REACHED => sub(){ shift },

});

 

Fehler werden nur noch mit dem Para debug true ausgegeben.

 

 

so wait kann auch vom obj gerufen werden also

$step->wait(0);

 

wartet hier bis CALLBACK_POSITION_REACHED eingetreten ist. Außerdem können die Callbacks was returnieren.

Mit dem Parameter wait werden nicht verarbeitet CALLBACK´s auf dem STDERR gemeldet.

 

mfg

 

Armin

 

 

brick.pm

stepper.pl

brick_rumpf.pm

brick_gen.pl

Link to comment
Share on other sites

  • 3 weeks later...

Hallo,

 

die neuen Perl-Bindings.

Jetzt auch mit threads und die Schnittstelle zum brickd.

 

also 1. brickd connectieren

 

my $brickd = brickd->new('192.168.11.11' => 4223 );

 

dann die brick(let)s anmelden

 

my $step = stepper->new($brickd,'asdasdad');
my $joy = $brickd->new('joystick','asd',{debug => 0,wait => 0,calibrate=>undef});
my $lcd = $brickd->new('lcd_20x4','sdf');
my $master = $brickd->new('master','sdafsdf456ds');

 

ich habe mich auch noch mit den threads rumgeschlagen. Geht unter linux besser als unter Windoofs habe ich aber zum laufen bekommen.

anbei wieder Beispielprogramm und Bindings und Generator

brick.pm

brick_gen.pl

brick_rumpf.pm

t4.pl

Link to comment
Share on other sites

  • 2 weeks later...
  • 1 month later...
  • 2 weeks later...
  • 2 weeks later...

Threads in Perl sind einfach nur gruselig. Auch wenn es in Perl Threads gibt funktionieren sie in der Praxis einfach nicht. Das war auch der Grund warum ich damals meine Arbeit an einer Perl API eingestellt hatte.

 

Leider ist auch die XS Variante im CPAN nicht wirklich toll.

 

Was wäre denn nötig um eine offizielle Unterstützung für Perl zu bekommen? Ich denke man bräuchte eine funktionierende, stabile IPConnection in Perl sowie den Generator für die Brick(let) API in Python, richtig?

 

Hat sich schonmal jemand an einer Event-basierten (AnyEvent, o.ä.) Umsetzung der IPConnection gemacht?

Link to comment
Share on other sites

Was willst du uns sagen ?

Also diese Threads funktionieren ganz gut, in Linux besser als in Windows.

Aber da es ja nur über USB oder WLAN geht, ist die Geschwindigkeit mehr als ausreichend.

Was hast du denn in Perl schon versucht zu steuern und was hat nicht funktioniert ?

 

Armin

Link to comment
Share on other sites

Ich will damit sagen, dass man mit Threads in Perl ganz schnell auf die Nase fällt. Ich weiß nicht, was du mit diesem Code bis jetzt gemacht hast, aber die Thread Implementierung von Perl hat einige ganz fiese Bugs. Ich hatte mal ein größeres Projekt in Perl mit Threads aufgabaut bis mir irgendwann alles um die Ohren gefolgen ist.

 

Ich versuche mal das Problem mit deinem Code nachzustellen und ein Sample hier zu posten.

Link to comment
Share on other sites

  • 1 month later...
  • 2 months later...
  • 1 month later...

Hallo batti,

 

bin gerade bei 2.0 Implementation. :-[

Hab ihr aktuelle Doku z.B für

CALLBACK_ENUMERATE

    Funktions ID:

 

    253

    Antwort:

 

        uid – uint32

        connected_uid – uint32

        position – char (as ascii)

        hardware_version – uint8[3]

        firmware_version – uint8[3]

        device_identifier – uint8

        enumeration_type – uint8

 

die von der TCP/IP Doku ist auf jeden falsch!!!!!

 

ich rate mal

        uid – char[8]

        connected_uid – char[8]

        position – char (as ascii)

        hardware_version – uint8[3]

        firmware_version – uint8[3]

        device_identifier – uint8

        enumeration_type – uint8

kann das sein ? und wenn das richtig ist was soll das ???

 

hoffe auf Antwort.

 

mfg

 

Armin

 

Link to comment
Share on other sites

die von der TCP/IP Doku ist auf jeden falsch!!!!!

 

Nein, das ist richtig. Auf TCP/IP Ebene sind uid und connected_uid des Enumerate Callbacks uint32, genauso wie die UID im Header jedes Packets auch uint32 ist. Die Bindings machen dann die Umwandlung zwischen Base58 und uint32, damit die UIDs auf Benutzerebene immer Base58 sind.

 

Edit: Du hast recht, die Dokumentation passte nicht. Ich habe mich da an eine erste Version von Protokoll 2.0 erinnert, sorry.

 

Dokumentation ist jetzt korrigiert.

Link to comment
Share on other sites

Hallo,

also ich habe ein brickd 2.0.4.

mit einem Master 2.0.6

dann kommt im dump 2 * char[8] und nicht uint32

 

Ich habe zum Testen nur die IPConnection gemacht

mit syswrite ein enumerate pack("LCCCC",0,8,254,0x10,0) geschickt

und dann dumpe ich mir die Antwort vom brickd und die ist

auf keinen Fall uint32 sondern char[8].

Kannst du dir mit tcpdump gerne mal anschauen.

auf Windows 7 64bit Prof.

 

mfg

 

Armin

 

 

Link to comment
Share on other sites

Hallo :-\

 

ich habe noch mal die sourcen durchgeschaut

und Oh Wunder

in packet.h vom brickd

 

typedef struct {

PacketHeader header;

char uid[8];

char connected_uid[8];

char position;

uint8_t hardware_version[3];

uint8_t firmware_version[3];

uint16_t device_identifier;

uint8_t enumeration_type;

} ATTRIBUTE_PACKED EnumerateCallback;

 

also nicht immer was behaupten ohne es zu prüfen.

Könnt ihr bitte die Doku entsprechend ändern ?

 

mfg

 

Armin

Link to comment
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.

 Share

×
×
  • Create New...