Wumpus Geschrieben April 25, 2012 at 13:24 Geschrieben April 25, 2012 at 13:24 Im Falle von mehreren IO16 Bricklets im Stack würde ich in der Callback-Funktion gerne die UID des auslösenden Bricklets auslesen. Gibt es dazu eine Möglichkeit (C-Bindings)? Zitieren
borg Geschrieben April 25, 2012 at 14:22 Geschrieben April 25, 2012 at 14:22 Das geht so direkt nicht. Du kannst aber ein callback_uid machen der aufgerufen wird von den unterschiedlichen callbacks. Also z.B. callback_uid(..., char *uid) { ... } callback1(...) { callback_uid(..., "uid1"); } callback2(...) { callback_uid(..., "uid2"); } ... Zitieren
Wumpus Geschrieben April 25, 2012 at 14:26 Autor Geschrieben April 25, 2012 at 14:26 Danke für die schnelle Antwort. Da ich die IO16 Bricklets aber automatisch erkenne und Callbacks anlege, ist das etwas ungünstig. Vielleicht ist es ja ein Vorschlag für eine API-Erweiterung... Zitieren
Wumpus Geschrieben May 10, 2012 at 11:01 Autor Geschrieben May 10, 2012 at 11:01 So würde das für mich tun: --- bricklet_io16.c.old 2012-05-09 22:22:28.000000000 +0200 +++ bricklet_io16.c.new 2012-05-10 08:48:08.000000000 +0200 @@ -20,7 +20,11 @@ #define TYPE_GET_PORT_INTERRUPT 8 #define TYPE_INTERRUPT 9 -typedef void (*interrupt_func_t)(char, uint8_t, uint8_t); +#ifndef MAX_BASE58_STR_SIZE + #define MAX_BASE58_STR_SIZE 13 +#endif + +typedef void (*interrupt_func_t)(char*, char, uint8_t, uint8_t); #ifdef _MSC_VER #pragma pack(push) @@ -353,8 +357,10 @@ } int io16_callback_interrupt(IO16 *io16, const unsigned char *buffer) { + char str_uid[MAX_BASE58_STR_SIZE]; + ipcon_base58encode(io16->uid, str_uid); InterruptCallback_ *ic = (InterruptCallback_ *)buffer; - ((interrupt_func_t)io16->callbacks[ic->type])(ic->port, ic->interrupt_mask, ic->value_mask); + ((interrupt_func_t)io16->callbacks[ic->type])(str_uid, ic->port, ic->interrupt_mask, ic->value_mask); return sizeof(InterruptCallback_); } Besteht Hoffnung, dass ihr das in die offiziellen C-Bindings übernehmen könnt? Zitieren
Nifty Geschrieben July 16, 2012 at 09:52 Geschrieben July 16, 2012 at 09:52 Da ich ein ähnliches Problem hatte.... Du könntest die Callbacks unter C++ innerhalb einer Klasse definieren und dann pro Instanz eine UID abarbeiten. Nötig wäre dafür ein Compiler der tr1 kann oder boost benutzen (bind wird dafür benötigt). Zitieren
FlyingDoc Geschrieben July 16, 2012 at 13:16 Geschrieben July 16, 2012 at 13:16 Ich wäre auch dafür bei der Callback Funktion die UID mit zu schicken. Dies lässt sich doch bestimmt einbauen. Die UID wird ja schon bei der Create Funktion mit übergeben. imu_create(IMU *imu, const char *uid) Diese brächte mann dann nur mit bei der Callbackfunktion mit zurückzugeben. Meine 2 AnlaogIn Bricklets kommen ja heute an. Diese müsste ich dann auch auseinanderhalten. Registrieren tu ich sie auch automatisch. Zitieren
Wumpus Geschrieben July 16, 2012 at 13:40 Autor Geschrieben July 16, 2012 at 13:40 Ich hab emir mittlerweile die Bindings umgeschrieben, so dass die UID immer beim Callback-Aufruf mit übergeben wird. Bei Interesse kann ich ja mal ein Diff zu den originalen C-Bindungs posten. Zitieren
FlyingDoc Geschrieben July 16, 2012 at 13:42 Geschrieben July 16, 2012 at 13:42 So. Hab es mal selber eingebaut. Folgende Änderungen sind notwendig. Bei ipconnection.h typedef struct Device_{ uint8_t stack_id; uint64_t uid; #ifdef _WIN32 CRITICAL_SECTION write_mutex; HANDLE response_semaphore; #else pthread_mutex_t write_mutex; pthread_cond_t response_cond; bool response_flag; pthread_mutex_t response_mutex; #endif const char *id; const char *expected_name; char name[MAX_LENGTH_NAME]; uint8_t firmware_version[3]; uint8_t binding_version[3]; DeviceResponse response; void *registered_callbacks[MAX_NUM_CALLBACKS]; device_callback_func_t callback_wrappers[MAX_NUM_CALLBACKS]; struct IPConnection_ *ipcon; } Device; bei der jeweiligen Create Funktion. Hier am Beispiel von IMU void imu_create(IMU *imu, const char *uid) { ipcon_device_create(imu, uid); imu->id = uid; imu->expected_name = "IMU Brick"; imu->binding_version[0] = 1; imu->binding_version[1] = 0; imu->binding_version[2] = 1; imu->callback_wrappers[iMU_CALLBACK_ACCELERATION] = imu_callback_wrapper_acceleration; imu->callback_wrappers[iMU_CALLBACK_MAGNETIC_FIELD] = imu_callback_wrapper_magnetic_field; imu->callback_wrappers[iMU_CALLBACK_ANGULAR_VELOCITY] = imu_callback_wrapper_angular_velocity; imu->callback_wrappers[iMU_CALLBACK_ALL_DATA] = imu_callback_wrapper_all_data; imu->callback_wrappers[iMU_CALLBACK_ORIENTATION] = imu_callback_wrapper_orientation; imu->callback_wrappers[iMU_CALLBACK_QUATERNION] = imu_callback_wrapper_quaternion; } an der Quaternion Funktion als Beispiel typedef void (*quaternion_func_t)(float, float, float, float,const char*); und dann bei der eigentlichen Callback Funktion zum verabeiten. void cb_quaternion(float x, float y, float z, float w,const char *uid) { uid enthällt dann die UID des Bricks oder Brickleds und kann verwendet werden. } Zitieren
Xenna Geschrieben July 16, 2012 at 17:27 Geschrieben July 16, 2012 at 17:27 I think the best way to solve this is with something like closures (missing in C). I've done it in Python like this: AN_UID = { "pp1":"PP1", "pp2":"PP2", "pp3":"PP3", "pc1":"PC1", "pc2":"PC2", "pc3":"PC3" } # Analog IN bricklet UIDs per button ( label:UID ) # Note that I've renamed my bricklets to pp1..pp3, pc1..pc3 (in my case 6x Analog In). def button_callback( source, floor ): # Called when voltage drops below 0.1V def handler(voltage): print "button_callback(%s,%d,%.3f)" % (source, floor, float(voltage/1000.0)) if destination() > 0: control( 0, 'doublepress@' + source + str(floor) ) else: control( floor, 'buttonpress@' + source + str(floor) ) return handler # And then: for b, uid in AN_UID.iteritems(): print "0000: Setting up analog in bricklet %s: %s" % (uid,b) ai[b] = AnalogIn( uid ) ipcon.add_device( ai[b] ) setup_analog_in( ai[b], button_callback( b[0:2], int(b[2]) ), monitor, BUTTON_THRESHOLD, BUTTON_DEBOUNCE ) The source and floor variables are available in the handler when the callback occurs. So I've basically created 6 handlers this way. 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.