mofosyne / tagdrop

allows for reading datauris, and displaying the media as if it was html or text or sound etc...
GNU General Public License v3.0
13 stars 2 forks source link

Capability Container like binary header in QR code? #16

Open mofosyne opened 7 years ago

mofosyne commented 7 years ago

This has the danger of just being another standard. However the benefit of NDEF standard is how compact it is (since it is a binary format).

However, there may be merit to adapting the NDEF standard, but as a general independent format for any current or future 2d barcodes encoding. As for why? Because it would allow for consistent interpretation of binary content (e.g. is this tag an encryption key or a phone number).

A key point to note is that NDEF does not describe anything about the nature of it's container (e.g. split tag, size of tag). The way NFC tackles this is via the use of Capability Container as described in section 6.1 of NFC Forum document "Type 2 Tag Operation Specification" http://apps4android.org/nfc-specifications/NFCForum-TS-Type-2-Tag_1.1.pdf .

Capability Container of a NFC Forum Type 2 Tag

In a type 2 nfc tag, the capability container is structured like this


Barcode NDEF container

A barcode to an application is seen as an array of bytes. Where the 2d barcode NDEF content will be structured as:

[Capability Container][NDEF Content]

So if the NDEF Content is going to be used in the context of a barcode or set of barcodes then these are some considerations:

Requirements:

Assumption/Assertion of all 2d barcodes:

Structure Consideration of the capability container

So if the encoding of [NDEF CONTENT] is already defined in NFC Data Exchange Format (NDEF) Technical Specification NFCForum-TS-NDEF_1.0 then we only need to define the wrapper around it, which in this context is the barcode's Capability Container.

Due to the need to minimise size of barcode (for ease of scanning), the capability container should be as small as possible. If possible keeping it to a single byte would be the best, but growing as needed. So maybe the capability container is of variable length.

Inter-operating with existing URI barcodes

Since this needs to inter-operate with existing "ascii" URIs QRs in the field, this will need to avoid these symbols:

So what this mean is that ascii packed into an 8bit char has unprintable characters only in 0001xxxx or 1xxxxxxx.

So to distinguish between ascii encoded URI QR barcodes verses this NDEF binary encoding, we need a magic number or bit to distingush between the two. 0001xxxx will minimise collision with other binary encoding that are not ascii, but you only get 4 spare bits for flags. 1xxxxxxx will give you 7 potential flag bits.

Since I have not seen many other pure binary encoding in QR code. I think it should be safe to use a single magic bit. But feel free to inform me otherwise.

Capability Container Structure

The first byte should be treated as a recognition byte. It holds the container version and compression type. Thus the magic byte could be used in a simple switch case fashion.

Byte 0 : Magic Byte

Version Code can be updated max of 16 times with this layout (Avoid if possible):

CompressionID:

Byte 1 : Flag Bits?


Variable length unsigned integer...

So

essentially its based on max unsigned value = 2^(number of bits) -1 and how it can be split as ( 2^(7+7) ) -1 can be seen as ( 2^(7) * 2^(7) ) -1


How would an android program interpret such code?

It would first send the barcode to a decoder (from a camera app). It would then read the capability container, to work out how to handle/decompress the NDEF content. Once the NDEF content is extracted, the android app would just simple broadcast a 'fake nfc tag' intent to let the android OS handle the content as if it was an NFC tag.

This means the author of the program does not have to code in for every use case, and instead could just let the android OS handle the data instead based on the existing NFC NDEF standard.


Reference:

mofosyne commented 6 years ago

Portable Barcode Draft Proposal

The objective is to embed data everywhere in any kind of 2d barcodes. E.g. Size of TV, or clothing size, etc....

Just only need the barcode decoder to be able to read out binary data.

Tag Append Header

This simply focus on appending data as needed in sequence.

1st Byte (Magic)

2nd Byte (Append Sequence)

This allows for joining up to 16 tags (much like Structed Append in QR code). If each large qr tag can be 1kbytes, then that gets us 16kbytes in 16 tags.

3rd Byte (Optional. Use if Sequence Total is none zero)

Used to avoid scanning other sequences. Also simple check of scanning correctness. Parity is obtained from full content after all tag sequences is scanned.

Data Container

Once all tags is scanned, the content is joined together and has this structure.

| Content Structure Header | | Type Length (variable) | | Type ... (variable) | | Metadata Length (variable) | | Metadata ... (variable) | | Payload Length (variable) | | Payload ... (variable) |

Content Structure Settings

Total Overhead

For a single tag only holding a known type (e.g. UUID, or url) , the smallest the header can get is

2(tag header)+1(content struct header)+2(known type) = 5 bytes


2018-02-06 edit : CBOR style tagdrop semiportable container

Okay, I talked to the JAB guys, and I think their approach of just relying on file signature is sort of good enough. We can reasonably assume that anyone trying to read our barcode is using our tagdrop app... thus creating some file sig like tagdrop: or td: might be good enough...

After thinking though, I think I have a different idea how to tackle this concept... CBOR has been ratified and has significant growth as an internet standard. And is very suitable for this.

Also I noticed CoAP has blockwise transfer with principles than can apply here. E.g. being able to predefine the buffer size ahead of time.

Block Level

Each code in the sequence will show the block size (in power of 2) and the total blocks needed. This will allow for ahead of time buffer allocation. Payload exact size is define within the payload. This minimises overhead of each code. The file ID is simply to avoid collision. But we can define file ID zero, to be the directory list perhaps.

With this we can keep overhead to just 4 bytes per barcode (excluding the tagdrop signiture to be determined).

Max block of 256, is a reasonable upper limit of human patience... or storage in microfilms array.

[?:TagDrop Signature][[PayloadID, PayloadSize, BlockSize (2^n), BlockTotal, BlockPos][Binary Chunk]

Payload

Once all the blocks has been assembled, you can interpret this as a CBOR structure shown below. Error checking omitted as barcode typically has error checking built in already.

{0: Binary/CBOR payload, 1:mediatype, 2:filename, x: etc...}

or as an array

[Binary/CBOR payload, mediatype, filename]

Over time, tagdrop can add more fields etc... but the idea is that using CBOR, unknown fields can be easily ignored.