Addon for Phidget devices

Hi!
I’m trying to build an add-on to connect to Phidget devices
Thanks to the examples provided I managed to connect to the device, but now I’m facing my lack of computer science knowledge since the function provided in the framework to retrieve the data is totally out of my scope.
It is the last function listed here. I really don’t get the second parameter. Any advice??

Here is my cpp, so far:

#include "ofxPhidgetSpatial.h"

int CCONV CAttachHandler(CPhidgetHandle spatial, void *userptr)
{
	((ofxPhidgetSpatial *)userptr)->AttachHandler(spatial);
	return 0;
}
int CCONV CDetachHandler(CPhidgetHandle spatial, void *userptr)
{
	((ofxPhidgetSpatial *)userptr)->DetachHandler(spatial);
	return 0;
}

int CCONV CErrorHandler(CPhidgetHandle spatial, void *userptr, int ErrorCode, const char *unknown)
{
	((ofxPhidgetSpatial *)userptr)->ErrorHandler(spatial,ErrorCode,unknown);
	return 0;
}

int CCONV CSpatialDataHandler(CPhidgetHandle spatial, void *userptr, CPhidgetSpatial_SpatialEventDataHandle *data, int count)
{
    ((ofxPhidgetSpatial *)userptr)->SpatialDataHandler(spatial, data, count);
    return 0;
}

void ofxPhidgetSpatial::start(int dataRate)
{
	CPhidgetSpatial_create(&spatial);
	CPhidget_set_OnAttach_Handler((CPhidgetHandle)spatial, CAttachHandler, this);
	CPhidget_set_OnDetach_Handler((CPhidgetHandle)spatial, CDetachHandler, this);
	CPhidget_set_OnError_Handler((CPhidgetHandle)spatial, CErrorHandler, this);
	CPhidget_open((CPhidgetHandle)spatial, -1);
    CPhidgetSpatial_setDataRate(spatial, dataRate);
}

void ofxPhidgetSpatial::read()
{
    
    //CPhidgetSpatial_set_OnSpatialData_Handler((CPhidgetHandle)spatial, CSpatialDataHandler, this);
    CPhidgetSpatial_set_OnSpatialData_Handler((CPhidgetSpatialHandle)spatial, CSpatialDataHandler, NULL);
    
}

void ofxPhidgetSpatial::stop()
{
    CPhidget_close((CPhidgetHandle) spatial);
    CPhidget_delete((CPhidgetHandle) spatial);
}

int ofxPhidgetSpatial::AttachHandler(CPhidgetHandle spatial)
{
	int serialNo;
	
	CPhidget_getSerialNumber(spatial, &serialNo);
    
	printf("Spatial %10d attached!\n", serialNo);
    
	return 0;
}

int ofxPhidgetSpatial::DetachHandler(CPhidgetHandle spatial)
{
	int serialNo;
	
	CPhidget_getSerialNumber(spatial, &serialNo);
    
	printf("Spatial %10d detached!\n", serialNo);
    
	return 0;
}

int ofxPhidgetSpatial::ErrorHandler(CPhidgetHandle spatial, int ErrorCode, const char *unknown)
{
	printf("Error handled. %d - %s", ErrorCode, unknown);
    
	return 0;
}

int ofxPhidgetSpatial::SpatialDataHandler(CPhidgetHandle spatial, CPhidgetSpatial_SpatialEventDataHandle *data, int count)
{
	int i;
	printf("Number of Data Packets in this event: %d\n", count);
	for(i = 0; i < count; i++)
	{
		printf("=== Data Set: %d ===\n", i);
		printf("Acceleration> x: %6f  y: %6f  x: %6f\n", data[i]->acceleration[0], data[i]->acceleration[1], data[i]->acceleration[2]);
		printf("Angular Rate> x: %6f  y: %6f  x: %6f\n", data[i]->angularRate[0], data[i]->angularRate[1], data[i]->angularRate[2]);
		printf("Magnetic Field> x: %6f  y: %6f  x: %6f\n", data[i]->magneticField[0], data[i]->magneticField[1], data[i]->magneticField[2]);
		printf("Timestamp> seconds: %d -- microseconds: %d\n", data[i]->timestamp.seconds, data[i]->timestamp.microseconds);
	}
    
	printf("---------------------------------------------\n");
    
	return 0;
}

The problem is inside the read() function, the second parameter is somehow not correct.

Thanks in advance!

It is looking for a function to use as a callback with this format

	int(*)(CPhidgetSpatialHandle phid, void *userPtr, CPhidgetSpatial_SpatialEventDataHandle *data, int dataCount)

so put this in your cpp (at the top)

int onSpatialData(CPhidgetSpatialHandle phid, void *userPtr, CPhidgetSpatial_SpatialEventDataHandle *data, int dataCount)
{

ofLogVerbose() << "CALLED!";
 return 0;
}

And then in ofxPhidgetSpatial::read()

CPhidgetSpatial_set_OnSpatialData_Handler((CPhidgetSpatialHandle)spatial, &onSpatialData, (void *) this);

So you may notice we didn’t use int onSpatialData::read and declare it in the header. This is because it is a C style function as opposed to a C++ class method. It’s a good example of what the difference between a function and a method is.

Also in C++ methods a hidden pointer to the class is passed around - you can always get to it using this. However int onSpatialData(... isn’t a C++ class method so it can’t access other class methods or members/variables. The way we get around this begins where we pass in this as a generic pointer

CPhidgetSpatial_set ... , (void *) this);

When onSpatialData gets called, this is passed into it via void *userPtr. We just have to cast it back so we can use it

int onSpatialData(CPhidgetSpatialHandle phid, void *userPtr, CPhidgetSpatial_SpatialEventDataHandle *data, int dataCount)
{
  //cast it back  
  ofxPhidgetSpatial* phidgetSpatial = (ofxPhidgetSpatial*) userPtr;
  //now you can call your class methods
  //phidgetSpatial->doSomething();

  ofLogVerbose() << "CALLED!";
  return 0;
}

I liked working with Phidgets though - a bit more expensive but awesome stuff

Thanks a lot!!
I found this on the topic of method vs member function: http://stackoverflow.com/questions/155609/what-is-the-difference-between-a-method-and-a-function
It is a very small add-on, nevertheless I’ll check the frameworks’ s license and try to publish it in github

Hello, I’d like to extend the functionalities of this addon, including Manager and RFID.
I forked the ofxPhidgets addon and added the code I have right now.
What I’m trying to do is call an ofApp function when the RFID handler function executes.

the RFID callback that handles a new Tag is:

static int CCONV TagHandler(CPhidgetRFIDHandle RFID, void *usrptr, char *TagVal, CPhidgetRFID_Protocol proto);

I am creating a new RFID object like this:

ofxPhidgetsRFID currRFID;

currRFID.init();

In init() function I’m adding the TagHandler:

CPhidgetRFID_set_OnTag2_Handler(rfid, TagHandler, ofAppPtr);

The third parameter can be a void pointer I can use inside the static function.
I’m trying to pass a reference of ofApp, to use it inside the callback function via the passed *usrptr.

How?

1 Like

Easy way to do this is

In ofApp.h

void doSomethingWithTagVal(char * TagVal);

In ofApp.cpp

//Forward declare variable to hold ofApp pointer
ofApp *myAppPointer = NULL;



int TagHandler(CPhidgetRFIDHandle RFID, void *usrptr, char *TagVal, CPhidgetRFID_Protocol proto)
{
	
	myAppPointer->doSomethingWithTag(TagVal);	
}

void ofApp::setup()
{
	ofxPhidgetsRFID currRFID;
	currRFID.init();
	
	//Set variable
	myAppPointer = this;
}


void ofApp::doSomethingWithTagVal(char * TagVal)
{
	ofLogVerbose() << "TagVal: " << ofToString(TagVal);
}

Hi, just to let you know, I originally wrote ofxPhidgets but I only used a stepper and apparently didn’t have chance to implement other features. I’m happy if you can pr to my repo when it’s working :slight_smile:

Hi jvcleave and micuat, and thanks for your answers. I’ll try the suggested approach today.
A full Phidgets addon would be superuseful, but I need some help since it’s my first addon attempt.
I have just some 125kHz 1024 RFIDs (for a limited time) so I cannot try all of the Phidgets C/C++ API.
I’ll post new questions about it here.
Thank you again and have a good day.

What you suggested worked, here is the code:

ofApp.h

 #pragma once

#include "ofMain.h"
#include <phidget21.h>

class ofApp : public ofBaseApp{

public:
	void setup();
	void update();
	void draw();

	void keyPressed(int key);
	void keyReleased(int key);
	void mouseMoved(int x, int y );
	void mouseDragged(int x, int y, int button);
	void mousePressed(int x, int y, int button);
	void mouseReleased(int x, int y, int button);
	void windowResized(int w, int h);
	void dragEvent(ofDragInfo dragInfo);
	void gotMessage(ofMessage msg);

//Display the properties of the attached phidget to the screen.  We will be displaying the name, serial number and version of the attached device.
//We will also display the number of available digital outputs
int display_properties(CPhidgetRFIDHandle phid);

void newTagVal(char * TagVal);
};

ofApp.cpp

#include "ofApp.h"

//Forward declare variable to hold ofApp pointer

ofApp *myAppPointer = NULL;


int CCONV AttachHandler(CPhidgetHandle RFID, void *userptr)
{
    int serialNo;
    const char *name;
    
    CPhidget_getDeviceName (RFID, &name);
    CPhidget_getSerialNumber(RFID, &serialNo);
    printf("%s %10d attached!\n", name, serialNo);
    
    return 0;
}

int CCONV DetachHandler(CPhidgetHandle RFID, void *userptr)
{
    int serialNo;
    const char *name;
    
    CPhidget_getDeviceName (RFID, &name);
    CPhidget_getSerialNumber(RFID, &serialNo);
    printf("%s %10d detached!\n", name, serialNo);
    
    return 0;
}

int CCONV ErrorHandler(CPhidgetHandle RFID, void *userptr, int ErrorCode, const char *unknown)
{
    printf("Error handled. %d - %s\n", ErrorCode, unknown);
    return 0;
}

int CCONV OutputChangeHandler(CPhidgetRFIDHandle RFID, void *usrptr, int Index, int State)
{
    if(Index == 0 || Index == 1)
    {
        printf("Output: %d > State: %d\n", Index, State);
    }
    return 0;
}

int CCONV TagHandler(CPhidgetRFIDHandle RFID, void *usrptr, char *TagVal, CPhidgetRFID_Protocol proto)
{
    //turn on the Onboard LED
    CPhidgetRFID_setLEDOn(RFID, 1);
    myAppPointer->newTagVal(TagVal);
    
    printf("Tag Read: %s\n", TagVal);
    return 0;
}

int CCONV TagLostHandler(CPhidgetRFIDHandle RFID, void *usrptr, char *TagVal, CPhidgetRFID_Protocol proto)
{
    //turn off the Onboard LED
    CPhidgetRFID_setLEDOn(RFID, 0);
    
    printf("Tag Lost: %s\n", TagVal);
    return 0;
}



     //Display the properties of the attached phidget to the screen.  We will be displaying the name, serial number and version of the attached device.
    //We will also display the nu,mber of available digital outputs
    int ofApp::display_properties(CPhidgetRFIDHandle phid)
    {
        int serialNo, version, numOutputs, antennaOn, LEDOn;
        const char* ptr;
    
    CPhidget_getDeviceType((CPhidgetHandle)phid, &ptr);
    CPhidget_getSerialNumber((CPhidgetHandle)phid, &serialNo);
    CPhidget_getDeviceVersion((CPhidgetHandle)phid, &version);
    
    CPhidgetRFID_getOutputCount (phid, &numOutputs);
    CPhidgetRFID_getAntennaOn (phid, &antennaOn);
    CPhidgetRFID_getLEDOn (phid, &LEDOn);
    
    
    printf("\n%s\n", ptr);
    printf("Serial Number: %10d\nVersion: %8d\n", serialNo, version);
    printf("# Outputs: %d\n\n", numOutputs);
    printf("Antenna Status: %d\nOnboard LED Status: %d\n", antennaOn, LEDOn);
    
    return 0;
}

//--------------------------------------------------------------
void ofApp::setup(){
    
    int result;
    const char *err;
    
    //Declare an RFID handle
    CPhidgetRFIDHandle rfid = 0;
    
    //create the RFID object
    CPhidgetRFID_create(&rfid);
    
    //Set the handlers to be run when the device is plugged in or opened from software, unplugged or closed from software, or generates an error.
    CPhidget_set_OnAttach_Handler((CPhidgetHandle)rfid, AttachHandler, myAppPointer);// NULL);
    CPhidget_set_OnDetach_Handler((CPhidgetHandle)rfid, DetachHandler, myAppPointer);
    CPhidget_set_OnError_Handler((CPhidgetHandle)rfid, ErrorHandler, myAppPointer);
    
    //Registers a callback that will run if an output changes.
    //Requires the handle for the Phidget, the function that will be called, and an arbitrary pointer that will be supplied to the callback function (may be NULL).
    CPhidgetRFID_set_OnOutputChange_Handler(rfid, OutputChangeHandler, myAppPointer);
    
    //Registers a callback that will run when a Tag is read.
    //Requires the handle for the PhidgetRFID, the function that will be called, and an arbitrary pointer that will be supplied to the callback function (may be NULL).
    CPhidgetRFID_set_OnTag2_Handler(rfid, TagHandler, myAppPointer);
    
    //Registers a callback that will run when a Tag is lost (removed from antenna read range).
    //Requires the handle for the PhidgetRFID, the function that will be called, and an arbitrary pointer that will be supplied to the callback function (may be NULL).
    CPhidgetRFID_set_OnTagLost2_Handler(rfid, TagLostHandler, myAppPointer);
    
    //open the RFID for device connections
    CPhidget_open((CPhidgetHandle)rfid, -1);
    
    //get the program to wait for an RFID device to be attached
    printf("Waiting for RFID to be attached....\n\n");
    if((result = CPhidget_waitForAttachment((CPhidgetHandle)rfid, 10000)))
    {
        CPhidget_getErrorDescription(result, &err);
        printf("Problem waiting for attachment: %s\n", err);
        return 0;
    }
    
    //Display the properties of the attached RFID device
    display_properties(rfid);
    
    CPhidgetRFID_setAntennaOn(rfid, 1);
    
    //read RFID event data
    printf("Reading.....\n");
    
    //Set variable
    myAppPointer = this;
}

void ofApp::newTagVal(char *TagVal){
    printf ("NEW TagVal: %s\n", TagVal );
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){

}

I will look into the addon as soon as I have my current job done.
Thank you again!