[web-nfc] TNEP research/explainer (#567)

kenchris has just created a new issue for https://github.com/w3c/web-nfc:

== TNEP research/explainer ==
TNEP - Tag NDEF Exchange Protocol
===

TNEP is a protocol based on top of NDEF. It extends NDEF with 3 new record types, one for the reader device (e.g. phone) and two for the tag device.

A tag device would be a smart device (active, powered) that emulates a tag type (Type 2, 3, 4, 5 are supported) which is able to expose NDEF when read and change the data exposed given some timing constraints.

The three record types are

* Service Parameter records (sent by tag device to show services available)
* Status record (sent as a response to any Select record, or when errors occur during service specific operation modes)
* Select record (used to select a service, or deselect current service)

NDEF implementations like our `NDEFReader` that does not support TNEP should ignore these records.

The Service Parameter records, in addition to the service name and operation mode (single return, or service specific) includes a bit of extra data which is very implementation specific, like max size of NDEFMessage it will return, protocol version, the minimum time to prepare a response as well as time extensions for slower operations.

As NDEF is polling based, it means that the poller should not read (or need to poll) before a certain minimum time. But as some operations might take long on a device (like doing some calculations) the device can also set a maximum extension value (repetitions version minimum time) before timing out a response.

The Android API doesn't have fine-grained control over the polling, to my knowledge, but as it seems that new values might be exposed as a new read, making single return works seems doable on top of what we have.

"single response" operation mode
---
This could work like with the current implementation without relying on the exact time to read.

select record => start timer for timeout => read new records (data + status) => stop timer.

"service specific" operation mode
---
This might be harder to implement correctly as it is a way to create custom protocols, like for instance a service that returns a new temperature reading every second until being deselected.

This operation mode also always first response with a status message and potential other data records.

When a status message with error is returned at some other point, the service should still not be deselected automatically.

Questions:
- is timeout (max extensions * min time) per message or just the initial response?
- Is record deselected if error on first response (error messages at later seems not to be)

API shape
---

Something like the below seems to make sense for the single return case.

```js
TNEPReader extends NDEFReader {
  Promise<sequence<NDEFRecord>> select(service);
  deselect();

  attribute EventHandler onservicefound;
}
```

Unfortunately, the service specific mode, would require our existing write() and onmessage event handler, which makes it a bit weird that the first response data is returned as part of `select()`.

An alternative option would be to just let `select()` return a `Promise<void>` when successful and a rejected promise with the error code when not. From there on you would have to read and handle the data yourself. This means moving the FrozenArray<NDEFRecord> from the event argument onto the TNEPReader (makes sense to do for NDEFReader as well then) in alignment with Generic Sensors, thus:

```js
TNEPReader extends NDEFReader {
  Promise<void> select(service);
  deselect();

  attribute FrozenArray<NDEFRecord> records; // inherited

  attribute EventHandler onservicefound;
  attribute EventHandler onerror; // inherited
  attribute EventHandler onreading; // inherited
}
```

The service records would basically just need to expose service name url and communication mode and the implementation should take care of the rest.

```js
TNEPService {
   readonly attribute USVString name;
   readonly attribute TNEPCommMode communicationMode;
}
```

If we need to expose more in the future that is totally doable, but it doesn't seem useful at this point.

```js
TNEPService {
   readonly attribute USVString name;
   readonly attribute TNEPCommMode communicationMode;
   readonly attribute octet tnepVersionMajor;
   readonly attribute octet tnepVersionMinor;
   readonly attribute long minWaitTime;
   readonly attribute long maxWaitExtensions;
   readonly attribute long maxMessageSize; 
}

```




Please view or discuss this issue at https://github.com/w3c/web-nfc/issues/567 using your GitHub account

Received on Tuesday, 28 April 2020 11:58:36 UTC