Closed mpetzold closed 3 years ago
Hi. This sounds similar in nature to #30, can you elaborate on what you have in mind? Perhaps a skeleton interface definition that would suit your project's needs?
Given the lack of activity I'm going to close this issue.
Hi Gary,
Once we started to work with hid4java
we have missed the feature suggested here.
The same way HidService
listen and trigger HidServiceEvents
due to attachments and detachments, would be great if there were some way to attach our components to some listener or queue to handle incoming messages from devices.
We have, somewhat, implemented a walkaround based on the Observer
pattern wrapping the hidDevice
instance we want to listen. It's a Runnable, running in a different thread which performs an endless loop around the statement
while (active) {
try {
observe();
//XXX CYV : Walkaround to avoid input messages to be read partialy due to interruptions
//XXX CYV : Thread sleeps as much time as device keeps the input buffer open for new messages
//XXX CYV : The lock and the sleep generates the innactivity period of readTimeoutx2
Thread.sleep(readTimeout);
}catch(InterruptedException ex) {
LOG.error("USBHIDDeviceObserver' sleep interrupted!",ex);
active = false;
}
}
And the observe
try {
List<byte[]> output = new LinkedList<byte[]>();
boolean hasMoreData = Boolean.TRUE;
do {
byte[] data = new byte[maxPackageSize];
// This method will now block for {readTimeout} ms or until data
// is read
int val = readDevice(data);
switch (val) {
case RUNTIME_ERROR:
case TRANSFER_ERROR:
listener.onTransferError(new USBHidDeviceEvent(hidDevice, hidDevice.getLastErrorMessage()));
hasMoreData = Boolean.FALSE;
break;
case END_OF_TRANSFER:
if (output.size() > 0) {
listener.onTransfer(
new USBHidDeviceEvent(hidDevice, new LinkedList<byte[]>(output)));
LOG.debug("observe() - " + output.size()+" packages ("+maxPackageSize+" length) were transfered from HidDevice " + hidDevice);
}
hasMoreData = Boolean.FALSE;
break;
default:
output.add(data);
break;
}
} while (hasMoreData);
} catch (Exception ex) {
LOG.warn("Error observing hid device data transfers. Cause: " + ex.getMessage(), ex);
listener.onTransferError(new USBHidDeviceEvent(hidDevice, ex.getMessage()));
}
The listener interface is
public interface USBHidDeviceListener {
/**
* Handles errors during the loading of data comming from the HID Device.
* {@link USBHidDeviceEvent} handled by {@code onTransferError} has no content nor error codes. Instead
* they provide with a {@code message} describing the error.
* @param usbHidDeviceEvent
*/
void onTransferError(USBHidDeviceEvent usbHidDeviceEvent);
/**
* Handles the latest {@code content} transfered by the HID Device to the host.
* {@link USBHidDeviceEvent} handled by {@code onTransfer} has no output message nor response codes, just content.
* @param usbHidDeviceEvent
*/
void onTransfer(USBHidDeviceEvent usbHidDeviceEvent);
}
The event
public class USBHidDeviceEvent {
//Null Object Pattern
private static final String EMPTY_MESSAGE = "";
private Optional<List<byte[]>> content;
private Optional<String> message;
private final HidDevice hidDevice;
public USBHidDeviceEvent(HidDevice hidDevice) {
this.hidDevice = hidDevice;
this.content = Optional.empty();
this.message = Optional.empty();
}
public USBHidDeviceEvent(HidDevice hidDevice, String message) {
this.hidDevice = hidDevice;
this.content = Optional.empty();
this.message = Optional.ofNullable(message);
}
public USBHidDeviceEvent(HidDevice hidDevice, List<byte[]> content) {
this.hidDevice = hidDevice;
this.content = Optional.ofNullable(content);
this.message = Optional.empty();
}
public String getMessage() {
return message.orElse(EMPTY_MESSAGE);
}
public List<byte[]> getContent() {
return content.orElse(Collections.emptyList());
}
@Override
public String toString() {
return getClass().getSimpleName() +
"[Hid ="+hidDevice+"]"
+"[Message="+getMessage()+"]";
}
}
I could have added getHidDevice()
to the event, but I didn't because I don't want everybody being aware of the hid4java lib since it's an implementation detail.
The Listener interface also could have been better named and get better names for the handlers, as for example onInputTransfer
to handle inputs from the device or onOutputTransfer()
to handle messages sent to the device. In our case, we only need to be aware of incoming messages.
Hope it helps!
Thanks for stepping up here @Laivindur. I've reopened the issue and I'll add in data read support as an event.
I've added some code to support this into the issue-95
branch. If you'd like to take an early look and offer up some feedback on its usefulness it would help greatly.
Hi Gary.
Unfortunately, we are kinda busy at the moment due to the release. We are performing several task forces to round some corners of the actual version. I will look at it as soon as I can.
No worries. I've still got a few extra items to add in but thought I'd let you know that work is underway.
Hi Gary, I didn't forget this "feature" I'm still striving to find a gap in my schedule to look at it with care and the due attention. We have stumbled upon more critical problems and we think hid4java is involved. I will open another issue and see what can we do.
Merged and closed.
I would suggest to add a HidDeviceListener interface so that it should be possible to listen to device events.