edgexfoundry / device-sdk-go

Owner: Device WG
Apache License 2.0
89 stars 126 forks source link

Option to create multiple events with readings #574

Open jpwhitemn opened 4 years ago

jpwhitemn commented 4 years ago

Using the current SDK, on AutoEvent schedule, the HandleReadCommands method gets called to create and add reading objects to an event. This, however presupposes that at the appointed schedule, only one event is to be created.

Some devices/sensors, when polled, return the data for multiple events/readings. For example, in some RFID devices, when the RFID reader is pulled, multiple RFID tag events are returned. Each tag event contains what tag was read, the signal strength, reader id, etc.

The SDK should allow for creation of multiple events as well as multiple readings on a single event.

iain-anderson commented 4 years ago

This could be done by sending all except the most recent Event via the async channel? Proposals for better ways of handling the use case are invited - for consideration for Ireland release

cloudxxx8 commented 3 years ago

@iain-anderson since this issue is tagged ireland but in icebox, should we implement this ?

jpwhitemn commented 3 years ago

Per Device Service WG meeting today, here are more details about my requirement:

My device has a REST endpoint that when I call, it gives me a collection of RFID alerts. Each alert (which would equate to an event in EdgeX language) is for a product it is seeing via RFID. On each read, it provides a lot of details (what we would call device resources) to include:
tagnumb tagname zone subzone signal strength readername UTC time when tag was read.

The device profile for this device is here: https://github.com/jpwhitemn/device-rest-rfrain/blob/master/cmd/res/device.rfrain.yaml (under older Hanoi schema)

After making the REST call to get the multiple RFID alerts with multiple data points, I'd like the device resource (through SDK) to be able to create multiple events (one for each RFID alert tag) with all the above device resources.

cloudxxx8 commented 3 years ago

We still need to define which event include which reading clearly in the Device Profile, because Event contains SourceName now. I thought the solution is to allow a composite Device Command.

In addition to resourceOperations, add another field called something like chainedCommand

ChainedCommand []string `json:"chainedCommand,omitempty" yaml:"chainedCommand,omitempty"`

It could trigger other Device Commands to send out additional events

iain-anderson commented 3 years ago

this? https://github.com/edgexfoundry/device-sdk-c/issues/3 field was originally called resource and subsequently renamed to deviceCommand but never implemented

tonyespy commented 3 years ago

There are three ways a device service produces EdgeX Events:

  1. An external client makes a REST call (either directly or via Core Command) to the command endpoint.
  2. An AutoEvent is triggered; this in fact similar to the first case, although AutoEvents are read-only
  3. The ProtocolDriver instance of a device service generates an Event asynchronously by writing one or more Readings to the internal async go channel.

In the first two cases, the client or AutoEvent are required to specify a deviceResource or deviceCommand (used to aggregate reads or writes for more than one deviceResource), in the third case the device service can push readings for any of the deviceResources defined in the current device profile.

It's not possible to use an AutoEvent to query for all available data, as AutoEvents use the same internal logic as calls to a device service's command endpoint (i.e. the AutoEvent needs to specify a deviceResource or deviceCommand).

In our device services meeting today, I thought what you were asking for was just a way to tell a device service to send all of it's queued Readings on-demand. In effect a way to trigger the service to send all of it's current reading via the async channel. We discussed adding a new deviceResource that could be used to trigger this behavior, but it was pointed out that AutoEvents don't support writes, only reads. @iain-anderson suggested that you could use Support Scheduler for this however. We could also explore allowing writes via AutoEvents.

tonyespy commented 3 years ago

After re-reading @jpwhitemn's comment from after last week's meeting, I don't think my previous comment captures what's really being asked for...

I think the issue here is that the EdgeX data model doesn't map simply to the RFID data model. To simplify it, let's say an RFID has three attributes:

Each RFID event is composed of the three attributes but it doesn't make sense to read them individually as they're constantly changing. You could create a deviceCommand which reads all three at once, but if these are discrete values that are constantly changing as tags appear and disappear, if you don't query the device service at a high enough sample rate, you'll lose data.

So what do you do? You could:

  1. Make the device service always use the asynchronous channel and always write the three readings together, which means they'd be packaged as a single event. You would only see events when the device service decided to send them.

  2. You could also create a single device resource with a string type, and generate a JSON-based report of all the tags seen and send it using the async channel. This is in fact how the the LLRP RFID service works. You configure the reader by writing ROSpecs and AccessSpecs and then the device service generates ROAccessReport readings via the async channel. The rate at which these reports are generated depends on the number and configuration of the various ROSpecs and AccessSpecs sent to the reader.

  3. As mentioned in the previous comment, you could also define a deviceResource which acts as a trigger to flush the accumulated readings being held at the protocol layer.

cloudxxx8 commented 9 months ago

@jpwhitemn May we use async channel to produce multiple events to fulfill this requirement?