Wumpus Posted April 25, 2012 at 01:24 PM Share Posted April 25, 2012 at 01:24 PM 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)? Quote Link to comment Share on other sites More sharing options...
borg Posted April 25, 2012 at 02:22 PM Share Posted April 25, 2012 at 02:22 PM 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"); } ... Quote Link to comment Share on other sites More sharing options...
Wumpus Posted April 25, 2012 at 02:26 PM Author Share Posted April 25, 2012 at 02:26 PM 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... Quote Link to comment Share on other sites More sharing options...
Wumpus Posted May 10, 2012 at 11:01 AM Author Share Posted May 10, 2012 at 11:01 AM 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? Quote Link to comment Share on other sites More sharing options...
Nifty Posted July 16, 2012 at 09:52 AM Share Posted July 16, 2012 at 09:52 AM 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). Quote Link to comment Share on other sites More sharing options...
FlyingDoc Posted July 16, 2012 at 01:16 PM Share Posted July 16, 2012 at 01:16 PM 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. Quote Link to comment Share on other sites More sharing options...
Wumpus Posted July 16, 2012 at 01:40 PM Author Share Posted July 16, 2012 at 01:40 PM 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. Quote Link to comment Share on other sites More sharing options...
FlyingDoc Posted July 16, 2012 at 01:42 PM Share Posted July 16, 2012 at 01:42 PM 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. } Quote Link to comment Share on other sites More sharing options...
Xenna Posted July 16, 2012 at 05:27 PM Share Posted July 16, 2012 at 05:27 PM 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. 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.