0
Under review

DeviceConnectivity for late joiners?

Bradford Needham 10 years ago updated by Jeff Plourde 10 years ago 6
I'm (still) writing an ICE app that detects when devices turn on and off.

So far, the app Subscribes to HeartBeat and DeviceIdentity.

We've found this doesn't seem to be sufficient to detect whether the device is on or off.

Now I've added a subscription to DeviceConnectivity, and am planning to consider a device "on" only if the app has received a DeviceIdentity (to know about the device), and DeviceConnectivity (to know when the device is in the Connected state).

It seems that DeviceIdentity is emitted by a device adapter only when its connection state changes. Given that, it seems that a late joiner app cannot know the DeviceConnectivity state (without provoking the Device Adapter in a way I don't yet know).

This leads me to ask two questions:
1) is there a simple method that I've missed, for detecting whether a given Medical Device is on or off?
2) (failing that) how should a late joiner app find whether the Devices it receives HeartBeat data from are on or off (connected or not connected)?

Thanks,
Brad
OpenICE demo-apps
P.S., and what is an MDSConnectivity data type used for? It seems related, yet when I wrote a listener for it, the Pulse Ox Simulator didn't seem to generate it.

Now we've really come to the basic question of How to infer/calculate whether a device is on or off.

Thanks,
Brad
Under review
1.) I posed this on the other thread as well but conceptually how would *you* detect that a device is off or on? I don't intend to be facetious but it can become a philosophical question. A future OpenICE aware medical device would publish its heartbeats to indicate it's presence on the network. To accommodate device adapter surrogates for legacy medical devices we created the DeviceConnectivity topic. (as an aside there is a gap here because nothing in HeartBeat or DeviceIdentity indicates whether the device is a surrogate and whether or not DeviceConnectivity should be expected. Currently all our devices and simulators publish DeviceConnectivity for consistency). In the existing apps and code a medical device is considered "on" the network if its HeartBeat instance is ALIVE AND its DeviceConnectivity is in the Connected state.

2.) Again I'd refer you to the DeviceListModelImpl and accessory classes thereof. In the Supervisory UI devices with live HeartBeats are admitted to the UI for display. If their DeviceConnectivity doesn't exist (so far unreported) or is NOT in the Connected state they are represented with a circle/slash indicating that the device is unavailable.

But this is a great discussion and we should continue to discuss the edge cases.

Thank you
Jeff
As a practical matter, I think detecting Connected state is sufficient for our needs: we want to know when a device is (roughly) ready to use vs. being asleep/off while the Device Adapter is on.

Thanks for the pointer to DeviceListModelImpl - I'll have a read. It's good to hear we're in the ballpark of the right way to detect what we want.

Thanks again,
Brad
Now that I've read a bit of DeviceListModelImpl and related classes, I think I'm missing something fundamental about classes to support liveness detection via InstanceModelImpl. Right now, I've written my own timer that checks a local cache of HeartBeat data every ~3 seconds to synthesize liveness; from reading the OpenICE code, it sounds like there's a component I should be using instead to automatically detect "ALIVE".

Can you say anything about how to detect "ALIVE" state of a Device's HeartBeat from an application? I'm unclear on which classes that DeviceListModelImpl depends on are part of the base OpenICE library vs. parts that are intended only for Device Adapters, or parts that were written solely for the OpenICE Supervisor. For example, I see TimeManager isn't part of the library available to HelloICE, but DeviceConnectivityInstanceModel is.

Peeling the onion,
Brad
I'm in the thick of it now. Related OpenICE classes are InstanceModelListener<DeviceIdentity, DeviceIdentityDataReader>, EventLoop, DeviceIdentityInstanceModelImpl, and DeviceConnectivityInstanceModelImpl. TimeManager plays an important part, but is not part of the base OpenICE library, so I'm looking to understand how to create that capability in an application rather than a Device Adapter. I see there are some fundamentals I don't yet know about DDS Subscribers vs. DataReaders, which should clear things up a bit.
Brad

It's not just the onion tears obscuring what's at work here. You are right that TimeManager is somewhat monolithic. It's a place where a lot of the magic lives to keep it safe. I'll try to explain some of the magic .. specifically how TimeManager tracks the liveliness of HeartBeat instances. But first to clarify Participants contain Subscribers (1:n) and Subscribers contain DataReaders (1:n). In DDS most of the "action" happens at the DataReader level. A Subscribers biggest job is to contain DataReaders. One other important job is that all the DataReaders inherit their "partition" from the containing Subscriber. There's a picture of it in RTI's documentation.

DDS tracks "liveliness" of data instances in accordance with the Liveliness QoS policy. Currently in OpenICE readers of the HeartBeat topic should use the "heartbeat" named QoS profile. In the code use of this profile looks like this:
hbReader = (HeartBeatDataReader) subscriber.create_datareader_with_profile(cfHbTopic, QosProfiles.ice_library, QosProfiles.heartbeat, null, StatusKind.STATUS_MASK_NONE);
and the profile specifies a 5 second lease duration (instances are marked "NOT ALIVE" when no new samples have arrived or the writer of the instance hasn't responded before the lease times out). The next line creates a ReadCondition which can be added to a WaitSet to get notified whenever an unread sample state exists in the reader.
hbReadCond = hbReader.create_readcondition(SampleStateKind.NOT_READ_SAMPLE_STATE, ViewStateKind.ANY_VIEW_STATE, InstanceStateKind.ANY_INSTANCE_STATE);
That condition is registered in the event loop with a handler.
eventLoop.addHandler(hbReadCond, hbReadHandler);
The handler then reads from the DataReader when the collection is active
hbReader.read(hb_seq, sa_seq, ResourceLimitsQosPolicy.LENGTH_UNLIMITED, SampleStateKind.NOT_READ_SAMPLE_STATE, ViewStateKind.ANY_VIEW_STATE, InstanceStateKind.ANY_INSTANCE_STATE);
and checks the SampleInfo.instance_state flag for the current liveliness state of an instance. So if the HeartBeat is no longer alive
if(0!=(InstanceStateKind.NOT_ALIVE_INSTANCE_STATE&sampleInfo.instance_state)) {
Or if the Heartbeat instance is alive
if(0!=(InstanceStateKind.ALIVE_INSTANCE_STATE&sampleInfo.instance_state)) {
different action can be taken.

In this way the current "live" and "not alive" instances of HeartBeat can be tracked. DDS is stateful so you could also do this without events periodically with calls to read_next_instance but somehow the API there gets even more obtuse.

Cheers!
Jeff Plourde