Page 1 of 1
Closing a channel deletes it from manager
Posted: Mon Jul 27, 2020 11:49 pm
by sgeiger
I want to create a devices+channels tree (like in the Phidgets Control Panel), in which the user can select and re-select a channel to open.
I retain each channel's handle found by the manager.
When a channel is selected to be opened, its handle is assigned event handlers and it is opened.
If another channel is selected, I close the channel, but then it's made inaccessible by the manager (I cannot release it, and I cannot re-open it, if it's later selected again).
I can think of 2 (not so nice) solutions:
1. Each time a channel is deselected, delete all channels, reload the manager and recreate the list.
2. When opening a channel - not using the handle from the manager but creating a new channel of the correct class and use addressing properties from manager handler for opening it. (I did try doing that and the channels didn't open. maybe because they were retained?)
Is there a correct way of doing that? Can you say how it is done in the control panel?
And anyway - would be helpful if the "HelloWorld" example demonstrates how to use a channel gained by the manager...
Thanks.
Re: Closing a channel deletes it from manager
Posted: Tue Jul 28, 2020 10:07 am
by Patrick
Hi,
Once you retain a channel from the manager - this is now your channel. The manager releases it's own reference to the channel right after the attach or detach event returns. Also, keep in mind that attach and detach events from the manager for the same channel are not going to give you the same handle - these channels are created as needed for attach/detach events - so if you want to keep a list of attached channels, you can't just compare pointers when a detach event comes in.
Once you retain a channel, you can open/close/open, etc. however many times you like. Once you call Phidget_release() or Phidget_delete(), the channel is freed and you can't use it any longer.
I'm able to retain a channel from a manger attach event and open / close / open / close / etc. as many times as I like. When you say "If another channel is selected, I close the channel, but then it's made inaccessible by the manager (I cannot release it, and I cannot re-open it, if it's later selected again)." - I'm not sure what this means, can you elaborate.
Some simple example code:
Code: Select all
#include "stdlib.h"
#include "stdio.h"
#include "Windows.h"
//#include "unistd.h"
#include "phidget22.h"
PhidgetManagerHandle man;
int cnt;
#define PRINT_RES(func) do { \
char error[4096]; \
size_t errLen = sizeof(error); \
const char *errorDesc; \
PhidgetReturnCode res; \
if ((func) != EPHIDGET_OK) { \
Phidget_getLastError(&res, &errorDesc, error, &errLen); \
printf("================================================================\n"); \
printf("FAIL: " #func "\n%s (0x%02x)\n%s\n", errorDesc, res, error); \
printf("================================================================\n"); \
} else { \
printf("SUCCESS: " #func "\n"); \
} \
} while (0)
#define MAXCHANNELS 2000
PhidgetHandle managerChannels[MAXCHANNELS] = { 0 };
void CCONV attach(PhidgetManagerHandle phid, void *ctx, PhidgetHandle Channel) {
const char *name;
PRINT_RES(Phidget_getChannelName(Channel, &name));
printf("Attach: %s (%d)\n", name, cnt);
PRINT_RES(Phidget_retain(Channel));
managerChannels[cnt] = Channel;
cnt++;
}
int main() {
PhidgetDigitalOutputHandle d = NULL;
PhidgetReturnCode res1;
int i;
PRINT_RES(PhidgetLog_enable(PHIDGET_LOG_DEBUG, "test.log"));
PRINT_RES(PhidgetManager_create(&man));
PRINT_RES(PhidgetManager_setOnAttachHandler(man, attach, NULL));
PRINT_RES(PhidgetManager_open(man));
// Wait for the manager to pick up channels
Sleep(5000);
// Look for a paricular channel in the retained channels
i = 0;
while (managerChannels[i]) {
PhidgetHandle ch = managerChannels[i++];
int32_t deviceSerialNumber;
int channel;
Phidget_ChannelClass channelClass;
PRINT_RES(Phidget_getDeviceSerialNumber(ch, &deviceSerialNumber));
PRINT_RES(Phidget_getChannel(ch, &channel));
PRINT_RES(Phidget_getChannelClass(ch, &channelClass));
if (deviceSerialNumber == 611346 && channel == 0 && channelClass == PHIDCHCLASS_DIGITALOUTPUT) {
d = (PhidgetDigitalOutputHandle)ch;
break;
}
}
if (d != NULL) {
printf("Found interesting channel\n");
while (1) {
PRINT_RES(res1 = Phidget_openWaitForAttachment((PhidgetHandle)d, 5000));
if (res1 == EPHIDGET_OK) {
PRINT_RES(PhidgetDigitalOutput_setState(d, 1));
Sleep(1000);
PRINT_RES(Phidget_close((PhidgetHandle)d));
}
Sleep(1000);
}
}
PRINT_RES(PhidgetManager_delete(&man));
return 0;
}
The PRINT_RES macro is just there as a convenience, you could remove that.
-Patrick
Re: Closing a channel deletes it from manager
Posted: Wed Aug 05, 2020 11:44 pm
by sgeiger
OK, That seems to work fine, with one little question:
when closing an opened channel, the thread that reads it ("Phidget22 USB Read Thread...") exits with code 4. Is that normal? (I can only see this on the debugger - it doesn't interrupt anything).
I have another relevant problem though, concerning dismounting a device:
I no channel is opened, there are no problems - I get a "manager detach event" for every channel of the dismounted device, the I loop the list of retained channels and compare the channel number, device serial number etc. for getting the correct channel handler, and the I release it.
But after opening a channel, this doesn't work - I can't get any information from the retained channels. When I try reading it, I get a return code 0x34 (Device not Attached). It doesn't matter whether I close the opened channel or not.
Hope I missed a simple solution again
Thanks.
Re: Closing a channel deletes it from manager
Posted: Thu Aug 06, 2020 10:03 am
by Patrick
Hi,
The thread exit is normal.
As the your channel objects - yes, this is true. Once you have retained and called open on them, they are no longer referring to a particular device, but rather are the same as if you had created a channel handle yourself, and set the matching parameters - serial, channel, hubport, etc... however, these properties can still be read out after a detach, and should be sufficient for matching uniquely.
You can always read out:
DeviceSerialNumber
IsRemote
IsLocal
DeviceLabel
ServerName
Channel
HubPort
IsHubPortDevice
ChannelClass
ChannelClassName
You can uniquely identify a channel by combining (serial, channel, hubport, ishubportdeivice and channelclass), plus isremote if you're using the network server.
-Patrick