pamoja.lorawan.fragment

Fragmented data block transport, TS004-2.0.0, on port PORT.

A block too large for one frame goes across in pieces, followed by coded fragments that let a device solve for the ones it missed rather than asking for them again. A device sets aside its working memory once, sized by the losses it is willing to solve for rather than by the block.

>>> from pamoja.lorawan import fragment
>>> block = bytes(range(64))
>>> session = fragment.session(len(block), 16)
>>> receiver = fragment.Defragmenter(session.nb_frag, 16, 2)
>>> n = 0
>>> while not receiver.done:
...     n += 1
...     _ = receiver.fragment(n, fragment.fragment(block, 16, n))
>>> receiver.block[: len(block)] == block
True
 1"""Fragmented data block transport, TS004-2.0.0, on port :data:`PORT`.
 2
 3A block too large for one frame goes across in pieces, followed by coded fragments that let a
 4device solve for the ones it missed rather than asking for them again. A device sets aside its
 5working memory once, sized by the losses it is willing to solve for rather than by the block.
 6
 7>>> from pamoja.lorawan import fragment
 8>>> block = bytes(range(64))
 9>>> session = fragment.session(len(block), 16)
10>>> receiver = fragment.Defragmenter(session.nb_frag, 16, 2)
11>>> n = 0
12>>> while not receiver.done:
13...     n += 1
14...     _ = receiver.fragment(n, fragment.fragment(block, 16, n))
15>>> receiver.block[: len(block)] == block
16True
17"""
18
19from __future__ import annotations
20
21from pamoja._native import (
22    LORAWAN_FRAGMENT_PORT,
23    LORAWAN_MAX_FRAGMENTS,
24    LorawanBlockMic,
25    LorawanDefragmenter,
26    LorawanFragSession,
27)
28from pamoja._native import lorawan_data_block_int_key as data_block_int_key
29from pamoja._native import lorawan_frag_fragment as fragment
30from pamoja._native import lorawan_frag_parity_line as parity_line
31from pamoja._native import lorawan_frag_prbs23 as prbs23
32from pamoja._native import lorawan_frag_session as session
33
34__all__ = [
35    "MAX_FRAGMENTS",
36    "PORT",
37    "BlockMic",
38    "Defragmenter",
39    "Session",
40    "data_block_int_key",
41    "fragment",
42    "parity_line",
43    "prbs23",
44    "session",
45]
46
47#: The port this package is spoken on.
48PORT = LORAWAN_FRAGMENT_PORT
49
50#: The most fragments one session carries.
51MAX_FRAGMENTS = LORAWAN_MAX_FRAGMENTS
52
53#: How a block is cut into fragments.
54Session = LorawanFragSession
55
56#: A session being put back together from whatever arrives.
57Defragmenter = LorawanDefragmenter
58
59#: The code taken over a block as it arrives.
60BlockMic = LorawanBlockMic
MAX_FRAGMENTS = 16383
PORT = 201
BlockMic = <class 'builtins.LorawanBlockMic'>
Defragmenter = <class 'builtins.LorawanDefragmenter'>
Session = <class 'builtins.LorawanFragSession'>
def data_block_int_key(root_key):

Derives the key that signs a data block, TS004-2.0.0 section 3.3.

def fragment(block, frag_size, n):

Builds one fragment of a session out of a block held whole.

Up to nb_frag the fragment is a piece of the block; past that it is a coded fragment, the exclusive-or of a pseudo-random half of the pieces.

def parity_line(coded, nb_frag):

Lists the uncoded fragments a coded one is made of, appendix A.1.

coded counts from one past the uncoded fragments: a session's fragment nb_frag + 1 is coded fragment 1.

def prbs23(x):

Steps the pseudo-random sequence the parity matrix is drawn from, appendix A.1.

def session(block_len, frag_size):

Says how many fragments a block takes, and how much padding the last one needs.