% ble-mesh-matter-thread.tex — Bluetooth Mesh (managed flooding, relays, TTL, friend/LPN,
% provisioning, pub/sub + group addresses, keys, the iOS reality: proxy over GATT), Thread
% (IPv6 over 802.15.4, border router, roles, sleepy end devices), Matter (application layer
% over Thread/Wi-Fi/Ethernet, BLE commissioning, attestation, fabrics + multi-admin, data
% model), Apple's role.
% Sources: docs/memos/ble-mesh.md, docs/memos/iot-matter-thread.md.
% Build ONLY with: tools/print/print-sheet.py <this>.tex --dry-run
% @source: hiot monorepo, docs/school/sheets/ble/ble-mesh-matter-thread.tex — the SOURCE OF TRUTH; a copy anywhere else (e.g. artur.gurgul.pro) is regenerated from it, never edited
% @labels: area=ble kind=concept level=deep platform=general new=no round=missing-2026-09-25 topic=protocols,networking
% @tags: bluetooth-mesh, managed-flooding, friend-node, low-power-node, mesh-provisioning, thread, ieee-802-15-4, border-router, matter, matter-commissioning, matter-fabric, mattersupport
\documentclass[8pt]{extarticle}
\usepackage{printup-sheet}
\usepackage{array}
\usepackage{tabularx}

\tikzset{
  nd/.style={circle, draw=sheetBlue, fill=sheetBlue!8, thick, minimum size=5.5mm, inner sep=0pt, font=\tiny\bfseries},
  rl/.style={nd, draw=sheetOrange, fill=sheetOrange!12},
  lp/.style={nd, draw=sheetGrey, fill=sheetGrey!10, dashed},
  gw/.style={box, font=\tiny, inner sep=1.2pt, minimum height=4.5mm},
  ly/.style={box, font=\tiny, inner sep=1pt, minimum height=4.3mm, minimum width=50mm},
  adv/.style={->, draw=sheetOrange, thick},
  lk/.style={draw=sheetBlue!70, thick},
  poll/.style={<->, draw=sheetGrey, dashed},
  lbl/.style={font=\tiny, text=black!75, inner sep=0.8pt, align=center},
  hd/.style={font=\bfseries\scriptsize, anchor=west},
}
\newcolumntype{L}{>{\raggedright\arraybackslash}X}

\begin{document}

\sheettitle{Bluetooth Mesh · Thread · Matter}{ble · memo}

\oneliner{\textbf{Bluetooth Mesh} floods small messages over BLE \emph{advertising} (no
connections) with pub/sub group addresses; \textbf{Thread} is a \textbf{routed IPv6} mesh
on 802.15.4 reaching the LAN through a \textbf{border router}; \textbf{Matter} is the
\textbf{application layer} (data model + security + commissioning) that runs over Thread,
Wi-Fi or Ethernet — commissioned over BLE, local-first, multi-admin.}

\noindent\begin{tikzpicture}[sheet]
  % ================= Bluetooth Mesh =================
  \node[hd] at (-0.2,3.05) {BT Mesh — flooding};
  \node[nd] (sw) at (0.2,1.9) {SW};
  \node[rl] (r1) at (1.45,2.45) {R};
  \node[rl] (r2) at (1.45,1.25) {R};
  \node[nd] (l1) at (2.8,2.55) {L1};
  \node[rl] (r3) at (2.8,1.65) {R};
  \node[nd] (l2) at (4.1,1.95) {L2};
  \node[nd, draw=sheetGreen, fill=sheetGreen!12] (fr) at (4.1,0.95) {F};
  \node[lp] (lpn) at (5.2,0.95) {LPN};
  \node[nd, draw=sheetGreen, fill=sheetGreen!12] (px) at (0.2,0.55) {P};
  \node[gw] (ph) at (1.6,0.2) {iPhone};
  \draw[adv] (sw) -- node[lbl, above left]{TTL 3} (r1);
  \draw[adv] (sw) -- (r2);
  \draw[adv] (r1) -- (l1); \draw[adv] (r1) -- node[lbl, right]{2} (r3);
  \draw[adv] (r2) -- (r3);
  \draw[adv] (r3) -- node[lbl, above]{1} (l2); \draw[adv] (r3) -- (fr);
  \draw[poll] (fr) -- node[lbl, above]{poll} (lpn);
  \draw[lk] (px) -- node[lbl, below left]{GATT} (ph);
  \draw[adv, dashed] (r2) -- (px);
  \node[lbl, text=sheetRed] at (2.7,0.85) {2nd copy: in msg cache\\$\to$ dropped};
  \node[lbl, text=sheetBlue] at (3.9,3.05) {SW publishes to group \texttt{0xC001};\\L1, L2 subscribe};
  \node[lbl, text=sheetBrown, align=left, anchor=west] at (2.4,0.2) {R relay · P proxy · F friend\\stores for the sleeping LPN};
  % ================= Thread =================
  \node[hd] at (5.8,3.05) {Thread — routed IPv6 mesh};
  \node[gw, draw=sheetGreen, fill=sheetGreen!10] (br) at (6.7,2.45) {Border router};
  \node[gw, draw=sheetGrey, fill=sheetGrey!8] (lan) at (6.7,0.35) {Wi-Fi / Ethernet LAN};
  \node[rl, minimum size=6.5mm] (ld) at (8.2,2.05) {Lead};
  \node[rl] (t1) at (9.6,2.5) {R};
  \node[rl] (t2) at (9.6,1.35) {R};
  \node[nd] (re) at (8.0,0.95) {REED};
  \node[nd] (me) at (10.8,2.3) {MED};
  \node[lp] (se) at (10.8,1.0) {SED};
  \draw[lk] (br) -- (ld); \draw[lk] (ld) -- (t1); \draw[lk] (ld) -- (t2); \draw[lk] (t1) -- (t2);
  \draw[lk] (br) -- (t2); \draw[lk, sheetGrey] (re) -- (t2);
  \draw[lk, sheetGrey] (me) -- (t1); \draw[poll] (se) -- node[lbl, above, sloped]{polls} (t2);
  \draw[flow, <->, draw=sheetGreen] (br) -- node[lbl, left]{IPv6 routing} (lan);
  \node[lbl, text=sheetBrown] at (9.6,0.3) {802.15.4 · 2.4 GHz · 250 kbps\\6LoWPAN · $\leq$32 routers};
  % ================= Matter stack =================
  \node[hd] at (11.3,3.05) {Matter — layers};
  \node[ly, draw=sheetGreen, fill=sheetGreen!10] at (14.0,2.6) {\textbf{Data model}: node · endpoint · cluster · attribute/command/event};
  \node[ly] at (14.0,2.12) {\textbf{Interaction model}: Read · Write · Invoke · Subscribe};
  \node[ly] at (14.0,1.64) {\textbf{Secure channel}: PASE (commission) · CASE (operate)};
  \node[ly] at (14.0,1.16) {Messages over UDP (+MRP retries) or TCP · IPv6};
  \node[ly, draw=sheetOrange, fill=sheetOrange!10, minimum width=16mm] at (12.25,0.62) {Thread};
  \node[ly, draw=sheetOrange, fill=sheetOrange!10, minimum width=16mm] at (14.0,0.62) {Wi-Fi};
  \node[ly, draw=sheetOrange, fill=sheetOrange!10, minimum width=16mm] at (15.75,0.62) {Ethernet};
  \node[lbl, text=sheetBlue] at (14.0,0.1) {BLE (BTP) only to \emph{commission}: PASE + hand over network credentials};
\end{tikzpicture}

\begin{multicols}{2}

\section{Bluetooth Mesh (SIG, not LE pairing)}
\begin{itemize}\raggedright
  \item \textbf{Advertising bearer}: non-connectable adverts (AD \texttt{0x2A} message ·
        \texttt{0x2B} beacon · \texttt{0x29} PB-ADV), nodes scan all the time. No
        central/peripheral, no per-link pairing.
  \item \textbf{Managed flooding}: relays rebroadcast; \textbf{TTL} (7 bit, 0 = not
        relayed) caps hops; a \textbf{message cache} drops repeats. No routing tables —
        robust, airtime-hungry; more relays = coverage, not speed.
  \item \textbf{Features}: relay · \textbf{proxy} (GATT $\leftrightarrow$ adv, for phones) ·
        \textbf{friend} (queues for its LPN) · \textbf{LPN} (radio mostly off, \emph{polls} its
        friend).
  \item \textbf{Addresses}: unicast \texttt{0x0001–0x7FFF} (per element) · virtual
        \texttt{0x8000–0xBFFF} (hashed 128-bit label) · group \texttt{0xC000–0xFEFF} ·
        fixed \texttt{0xFFFC} proxies, \texttt{FFFD} friends, \texttt{FFFE} relays,
        \texttt{FFFF} all.
  \item \textbf{Models}: node $\to$ elements $\to$ models (Generic OnOff server/client);
        a client \emph{publishes} to an address, servers \emph{subscribe} — bind by group,
        like MQTT topics.
  \item \textbf{Provisioning} (PB-ADV or PB-GATT): Invite $\to$ Capabilities $\to$ ECDH
        P-256 $\to$ OOB-authenticated Confirmation/Random $\to$ Data: NetKey, unicast
        address, IV index. Then configure with the DevKey: bind AppKeys, set pub/sub.
  \item \textbf{Keys}: \textbf{NetKey} (network layer — relays forward, can't read) ·
        \textbf{AppKey} (payload, per function: lights vs locks) · \textbf{DevKey} (config).
        Replay: 24-bit SEQ + 32-bit IV index; receivers keep a replay list — persist SEQ.
  \item Tiny: 11-byte access payload unsegmented, $\leq$ 384 B segmented — control, not
        bulk. Mesh 1.1 (2023) adds directed forwarding, remote provisioning, DFU.
\end{itemize}

\section{Thread}
\begin{itemize}\raggedright
  \item IEEE \textbf{802.15.4} (Zigbee's radio): channels 11–26, 250 kbps, 127-byte
        frames; \textbf{6LoWPAN} compresses IPv6 — every node has an IPv6 address.
  \item Roles: \textbf{Router} (always on, routes) · \textbf{Leader} (a router that
        assigns router ids, re-elected) · \textbf{REED} (can promote) · \textbf{MED}
        (radio on, not routing) · \textbf{SED} (sleeps, polls its parent) ·
        \textbf{Border router} (IPv6 to the LAN; none = isolated island). Self-healing.
\end{itemize}

\section{Pick one}
{\scriptsize
\noindent\begin{tabularx}{\linewidth}{@{}>{\bfseries}p{11mm}LLL@{}}
\toprule
 & \textbf{BT Mesh} & \textbf{Thread} & \textbf{Matter} \\
\midrule
Layer & full stack on BLE & network (IPv6) & application \\
Forward & flooding + TTL & routing & — (below) \\
IP & no & yes & needs IP \\
Phone & via proxy (GATT) & via border router & native in iOS/Android \\
Best at & lighting, many nodes, no infra & low-power IP sensors & cross-ecosystem home \\
\bottomrule
\end{tabularx}}

\section{Remember}
\emph{Mesh floods (TTL + cache), Thread routes (IPv6 + BR), Matter speaks (clusters),
BLE commissions.}

\columnbreak

\section{Matter}
\begin{itemize}\raggedright
  \item CSA standard (ex-Project CHIP), 1.0 in Oct 2022. \textbf{Not a radio}: Matter over
        Thread, Wi-Fi or Ethernet; Zigbee/Z-Wave only via a \textbf{bridge} (endpoints per
        bridged device). \textbf{Local-first}: control on the LAN, cloud only for remote.
  \item \textbf{Data model}: \textbf{node} (one operational identity) $\to$
        \textbf{endpoints} (0 = root: basic info, commissioning, credentials, ACL) $\to$
        \textbf{clusters} (OnOff \texttt{0x0006}, LevelControl \texttt{0x0008}) $\to$
        attributes, commands, events. Subscribe = min/max interval reports.
  \item \textbf{Commissioning}: QR (\texttt{MT:…}) / NFC / 11-digit code = passcode +
        discriminator $\to$ find the device (BLE adv or DNS-SD \texttt{\_matterc.\_udp})
        $\to$ \textbf{PASE} (SPAKE2+) $\to$ \textbf{attestation}: DAC $\to$ PAI $\to$ PAA
        root listed in the CSA's DCL, + Certification Declaration $\to$ Wi-Fi/Thread
        credentials $\to$ \textbf{NOC} installed $\to$ \textbf{CASE} on the IP network
        (\texttt{\_matter.\_tcp}).
  \item \textbf{Fabric} = root CA + fabric id; each admin (Apple, Google, Alexa) installs
        its own NOC — \textbf{multi-admin} via a new commissioning window.
\end{itemize}

\section{Apple's role}
\begin{itemize}\raggedright
  \item Home app / HomeKit commission Matter accessories (iOS 16.1+); a \textbf{home hub}
        (HomePod mini, HomePod 2nd gen, Apple TV 4K with Thread) = Thread border router +
        remote access + automations.
  \item \textbf{MatterSupport} framework: a third-party app commissions a device into
        \emph{its own} ecosystem (\texttt{MatterAddDeviceRequest}); ThreadNetwork shares
        Thread credentials.
  \item \textbf{No native Bluetooth Mesh} on iOS: the app implements the mesh stack
        (e.g. Nordic nRF Mesh) and talks to a \textbf{proxy node} over GATT
        (\texttt{0x1828}; provisioning \texttt{0x1827}); never a relay.
\end{itemize}

\section{Interview traps}
\begin{itemize}\raggedright
  \trap{``Mesh = GATT links'' — adverts; GATT only at the proxy.}
  \trap{``Matter = Thread'' — app layer vs one transport. No border router, no Internet.}
  \trap{Relay privacy: NetKey forwards, AppKey reads — separate on purpose.}
\end{itemize}

\section{Likely questions}
\begin{enumerate}\raggedright
  \item iOS app for a BLE mesh? — own stack over CoreBluetooth via a proxy node.
  \item How does a Matter device join Google \emph{and} Apple? — second fabric, own NOC.
  \item Why does an LPN need a friend? — flooding assumes listeners; the friend queues.
\end{enumerate}

\end{multicols}

\noindent{\footnotesize\color{sheetGrey}\textit{Related:} ble-radio-and-roles ·
ble-advertising-scanning · ble-security-pairing-privacy · corebluetooth-central-peripheral ·
mqtt-for-devices · coap-lwm2m}

\end{document}
