> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adsumnetworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# BLG20x first run, step by step

> A complete first run on the Fanstel BLG20x: from an unflashed board to a gateway sending its own readings to your platform, and a command travelling back. No prior knowledge of the board or of Adsum IoT Coder assumed.

<div className="adsum-mast">
  <div><span className="adsum-mast-k">How many steps?</span><span className="adsum-mast-v">Eight</span><span className="adsum-mast-n">Two of them wait on the unit's own radio cycle.</span></div>
  <div><span className="adsum-mast-k">What gets flashed?</span><span className="adsum-mast-v">Both halves</span><span className="adsum-mast-n">The Bluetooth half and the wide-area half, each from its own probe.</span></div>
  <div><span className="adsum-mast-k">Where do readings go?</span><span className="adsum-mast-v">Your platform</span><span className="adsum-mast-n">Your own tenant. Nothing of ours in the path.</span></div>
  <div><span className="adsum-mast-k">What do you need to know?</span><span className="adsum-mast-v">Nothing yet</span><span className="adsum-mast-n">No prior knowledge of the board or of Adsum IoT Coder.</span></div>
</div>

<div className="adsum-byline">
  <span>Gateway <b>Fanstel BLG20XE02C-V1</b></span>
  <span>Firmware <b>the BLG20x evaluation pair</b></span>
  <span>Captured by <b>Adsum Networks, 17 September 2026</b></span>
</div>

<Card title="New to the BLG20x?" icon="microchip" href="/supported-hardware/fanstel/blg20x" horizontal>
  The board, what the firmware does, and every way to have it.
</Card>

## What you are building

The BLG20x is a **gateway**. It listens for small Bluetooth sensors around it, keeps what they say, and forwards it over a mobile network to a platform you choose. Nothing you do here writes any of your data to Adsum.

### The hardware

The BLG20x is made and sold by [Fanstel](https://www.fanstel.com/blg20cbwg20c), as a desk- or wall-mount unit with the radios, antennas and power supply already in the box. This guide was captured on a **BLG20XE02C-V1**; the other models in the family run the same evaluation firmware.

| Part | What it is | What it does in this run |
| :- | :- | :- |
| Bluetooth module | Fanstel **BM20**, built on Nordic's **nRF54LM20B** (Bluetooth 6.0) | Hears your sensors, keeps what is worth keeping, and is what the commissioning page talks to |
| Cellular modem | Nordic **nRF9151**: LTE-M, NB-IoT and NB-NTN satellite | Attaches to the mobile network and sends the readings to your platform |
| Power | USB-C, adapter and 2 m cable included | Plug it in. No battery to charge |
| Enclosure | IP51, 90 × 65 × 28 mm | For indoor use: a bench, a shelf or a wall |

The family has five models, which differ in antenna, output power and extra radios: **BLG20BC**, **BLG20BF** (better antenna), **BLG20XE** (adds a power amplifier), **BWG20BF** (adds Wi-Fi 6) and **BLG2H20F02C** (Wi-Fi 6 and a CAN port). The firmware uses Wi-Fi where the module is fitted and a network is set; it does not use CAN. Datasheets, models and ordering are on [Fanstel's BLG20 page](https://www.fanstel.com/blg20cbwg20c).

The important thing to understand before you touch it: **this board is two computers, not one**, and almost every confusing moment in a first run comes from forgetting that.

<Frame caption="The two halves. The Bluetooth half hears your sensors and decides what is worth keeping. The wide-area half owns the modem and the schedule. They talk to each other over two wires, and each can only report what it knows itself, which is why, later, a message the sender logs is not proof the receiver got it.">
  <img className="block dark:hidden" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-1-light.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=de3d033a60980f3f9848424e3583b598" alt="Sensors advertise to the Bluetooth half, which passes digests over a two-wire link to the wide-area half, which sends them over the mobile network to your platform." width="800" height="300" data-path="images/guides/blg20x/diagram-1-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-1-dark.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=d7c180c346622ac13cb3db1f0e00caac" alt="Sensors advertise to the Bluetooth half, which passes digests over a two-wire link to the wide-area half, which sends them over the mobile network to your platform." width="800" height="300" data-path="images/guides/blg20x/diagram-1-dark.svg" />
</Frame>

### Adsum IoT Coder, in one paragraph

Adsum IoT Coder is a VS Code extension. For this run it does three jobs: it knows the procedure for this board, it fetches and verifies the firmware images, and it drives the programming commands with your approval. You can do every step by hand instead (the commands are in this guide), but the extension is what stops you flashing the wrong chip.

## What you need

*about 20 minutes to gather*

| You need | Why, and what to watch |
| :- | :- |
| **The BLG20x board** with **two debug probes**, one on each SWD header | Two chips, two probes. They are not interchangeable and the labels will not save you |
| A **SIM** in the board, on a plan that allows LTE-M or NB-IoT | The wide-area half needs a network to attach to |
| Nordic's **`nrfutil`** on your PATH | Everything that touches the chips goes through it |
| **VS Code** with the **Adsum IoT Coder** extension, signed in | The BLG20x card appears once your account has access to this board |
| **Chrome or Edge** on a desktop, or Chrome on Android | Commissioning uses Web Bluetooth. **No browser on iOS can do it** |
| A **ThingsBoard** account (free), or another device-data platform | See below. Get this **before** you start: it is the one prerequisite that interrupts the run |
| A **BLE sensor** within a few metres | Anything that advertises. You will need its address |

<Tabs>
  <Tab title="Front">
    <Frame caption="The BLG20x board face up, with the two development kits cabled to its debug headers.">
      <img src="https://mintcdn.com/adsumnetworks/OLHNJ4taZvy2JkCl/images/guides/blg20x/fig-wiring-front.png?fit=max&auto=format&n=OLHNJ4taZvy2JkCl&q=85&s=b1e95aaf3695141d670e8c3c4cdf92de" alt="The BLG20x board, component side, with an nRF54LM20 DK and an nRF52840 DK above it, each connected to the board by a 10-pin ribbon cable" style={{ maxWidth: "440px", margin: "0 auto" }} width="1000" height="1250" data-path="images/guides/blg20x/fig-wiring-front.png" />
    </Frame>
  </Tab>

  <Tab title="Back">
    <Frame caption="The same setup from the other side, where the two ribbon cables plug in.">
      <img src="https://mintcdn.com/adsumnetworks/OLHNJ4taZvy2JkCl/images/guides/blg20x/fig-wiring-back.png?fit=max&auto=format&n=OLHNJ4taZvy2JkCl&q=85&s=43eaa89f4af93e7850cebaf77529cc46" alt="The same setup from the other side of the BLG20x board, showing where the two ribbon cables plug into its debug headers" style={{ maxWidth: "440px", margin: "0 auto" }} width="1000" height="1250" data-path="images/guides/blg20x/fig-wiring-back.png" />
    </Frame>
  </Tab>
</Tabs>

**The two probes on the bench.** Each DK reaches one half of the gateway over a 10-pin ribbon cable to that half's debug header; USB-C powers the board. **A DK's name says nothing about which half it programs:** here the nRF54LM20 DK is cabled to the nRF9151 half and the nRF52840 DK to the nRF54LM20B half. That is why step 2 reads the silicon behind each probe before anything is written.

### ThingsBoard: what it is, and why you need it

**ThingsBoard** is an IoT platform: a service that devices send their readings to, and that stores them, charts them on dashboards, raises alarms on them and sends commands back. It is open source, and **ThingsBoard Cloud** is the same software run as a hosted service, so there is nothing to install.

The gateway needs one because it only *collects*. It keeps readings locally, but a gateway that only keeps them is a logger: it needs somewhere off-site to send them, a place to look at them, and a way to reach the unit when it is in the field. In this run ThingsBoard is where three things happen:

* **Step 6**: the unit's readings arrive, each with the device's own timestamp;
* **Step 7**: you send a command back to the unit from the device's page;
* the **device token** ThingsBoard issues is what the unit presents to prove it is yours.

**The account is yours, not ours.** The readings go from the gateway straight to your tenant. Adsum is not in that path and never sees your data.

### Where to create the account

| Your data should live in | Sign up at |
| :- | :- |
| North America | [thingsboard.cloud/signup](https://thingsboard.cloud/signup) (the one used in this guide) |
| Europe | [eu.thingsboard.cloud/signup](https://eu.thingsboard.cloud/signup) |

Pick the region when you sign up; your devices and data stay in it. The **Free** plan is enough to evaluate one gateway: 5 devices and 1 million data points a month, no card required. ThingsBoard's current plans are on its [pricing page](https://thingsboard.io/pricing/).

The firmware is set up for ThingsBoard, but it is not tied to it. The unit sends **CoAP with a protobuf payload**, so any platform that accepts those will do. If you use another one, what changes is the host, the port, and how you define the device on your side.

<Warning>
  **Create it now, not at step 6**

  You will need a tenant, a device profile, a device on that profile, and the **device token** it issues. Five minutes up front keeps the board work unbroken.
</Warning>

## The whole run at a glance

Eight steps. Two of them wait on the unit's own radio cycle, which is where most of the waiting is.

<Frame caption="Where the time goes. Steps 1–5 are as fast as you are. Steps 6 and 7 each wait for the unit to wake its radio. Nothing is wrong while they wait, and restarting the board only restarts the clock.">
  <img className="block dark:hidden" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-2-light.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=047f6481e70ffd28b0b1edccb73a6f27" alt="Eight steps: install, flash, commission, set class, admit a sensor, data plane, command back, done. Steps four and eight wait on a radio cycle." width="800" height="320" data-path="images/guides/blg20x/diagram-2-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-2-dark.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=efabf2ad92c5b2297a6a677b50505c94" alt="Eight steps: install, flash, commission, set class, admit a sensor, data plane, command back, done. Steps four and eight wait on a radio cycle." width="800" height="320" data-path="images/guides/blg20x/diagram-2-dark.svg" />
</Frame>

## Step 1a: Start the run

Open VS Code, open the Adsum IoT Coder panel, and open a folder for this project. The panel offers a few ways in; you want the one for this board.

<Frame caption="The panel. Suggested runs sit at the top, and cards for boards it recognises sit below them.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-a-cockpit.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=3fac7b588432deb9e9155af0c922c95e" alt="The Adsum IoT Coder panel listing suggested runs" width="1580" height="1399" data-path="images/guides/blg20x/fig-a-cockpit.png" />
</Frame>

<Frame caption="The BLG20x card. Two ways in: build the firmware yourself, or install the images we already built and verified. This guide takes the second: Install into this project.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-00-board-detected.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=de6ad52709f9411a5c537da04e747ec7" alt="The BLG20x card offering to build it yourself or use the licensed demo images" style={{ maxWidth: "460px", margin: "0 auto" }} width="1560" height="1790" data-path="images/guides/blg20x/fig-00-board-detected.png" />
</Frame>

<Note>
  **If you do not see the card**

  The card appears when your account has access to this board, or when a BLG20x is detected on a probe. If neither is true, ask for access from the panel; it names what you are asking for.
</Note>

## Step 1b: Install the images

*about 2 minutes*

The install lists what it will write, checks each file against a recorded hash **before** writing it, and states the firmware's limits before anything lands on disk.

<Frame caption="The limits, before the install rather than after. This capture is from September, when the satellite allowance was 50 KB a month; today's demo allows 10 KB, with ten devices, 10 MB a month over mobile and no time limit.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-02b-demo-limits.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=89efe5a965f9b6c6bcb1852bfd3464b6" alt="The three limits of the evaluation firmware stated before installing" width="1500" height="1380" data-path="images/guides/blg20x/fig-02b-demo-limits.png" />
</Frame>

<Frame caption="--list first, then --into. A truncated image programs happily and then never boots, which is why the hash check is not optional.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-02-install-command.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=bdd975a9c9ce507c35be49ca30d8d799" alt="The install command listing bundle members" width="1500" height="700" data-path="images/guides/blg20x/fig-02-install-command.png" />
</Frame>

<Frame caption="The files in your project: bm20/merged.hex, nrf9151/merged.hex and the licence.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-03-files-landed.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=1c8dd20f6dbd0ddbed62f5296a1f4dd2" alt="The two hex images and the licence file in the project explorer" width="1500" height="1280" data-path="images/guides/blg20x/fig-03-files-landed.png" />
</Frame>

<Frame caption="Three files: one image per half, plus the licence. Each image carries both a bootloader and an application, so a board straight from the box comes up from this pair alone. Nothing has been programmed yet.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-b-files-landed.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=fc4487ebc8407ec75fff50750054c467" alt="A table of the three installed files and their paths" width="1580" height="907" data-path="images/guides/blg20x/fig-b-files-landed.png" />
</Frame>

## Step 2: Flash both halves

*about 5 minutes*

Two chips, two images, and they must not be swapped. **Take the probe serial numbers from the tool's own list**, never from the kit's name or the header's label.

<Frame caption="Before any write, each probe is asked what it actually reaches.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-05-click-read-probes.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=ef51dcaae4916d344b96abbd11390946" alt="The agent asking to read both probes before programming anything" width="1500" height="680" data-path="images/guides/blg20x/fig-05-click-read-probes.png" />
</Frame>

<Frame caption="The mapping, confirmed against your board's wiring before a single byte is written. Note the third probe: present, but not part of this gateway.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-07-probe-mapping.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=a8b819aab95b9e50cf791046abec3a46" alt="A table mapping each probe serial number to the chip it reaches and the image it gets" style={{ maxWidth: "460px", margin: "0 auto" }} width="1500" height="1880" data-path="images/guides/blg20x/fig-07-probe-mapping.png" />
</Frame>

### The wide-area half: three commands, one session, nothing in between

<Warning>
  **Why the order matters more here than anywhere else**

  Erasing this chip clears the word that keeps its debug port open, and **on this part a cleared word means locked**. Neither the bootloader nor the application writes it back. So: program, write the word back, and only then reset.
</Warning>

<Frame caption="The one sequence to get right. Run all three in one session with nothing in between. If the write is refused once, run it again before anything else.">
  <img className="block dark:hidden" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-3-light.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=0e44ee14c4c488272a1a947f5751b8e0" alt="Program with no reset, then write the protection word back to unlocked, then reset. A reset before the write leaves the part locked." width="800" height="190" data-path="images/guides/blg20x/diagram-3-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-3-dark.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=88db4927e3a7126d3cb1326e2abc8bf1" alt="Program with no reset, then write the protection word back to unlocked, then reset. A reset before the write leaves the part locked." width="800" height="190" data-path="images/guides/blg20x/diagram-3-dark.svg" />
</Frame>

```bash theme={null}
nrfutil device program --firmware nrf9151/merged.hex \
  --serial-number <from the list> --options reset=RESET_NONE

nrfutil device x-write --address 0x00FF8000 --value 0x50FA50FA \
  --serial-number <same>

nrfutil device reset --reset-kind RESET_SYSTEM --serial-number <same>
```

**The Bluetooth half** is the same without the middle command: program with `reset=RESET_NONE`, then reset.

<Warning>
  **Never press the board's reset button**

  Both halves share one reset line. A reset the probes did not initiate takes down both debug ports until the probe boards are re-powered. Reset through `nrfutil` instead.
</Warning>

## Step 3: Commission the unit

*about 10 minutes*

Commissioning gives the unit its place, its name and key, its network, its platform and its sensors. It happens over Bluetooth, in one of two places: **Adsum IoT Coder**, at your desk, or **a browser**, on an installer's phone at the site. Both write the same settings with the same checks, and everything written is **read back from the unit's own account of itself**. Nothing is trusted because a button was pressed.

### From Adsum IoT Coder

From 0.5.1, the **Hardware** page in Adsum IoT Coder lists the units it hears under **Gateways in range** and takes each one through four steps: pair, claim it for this computer, check its firmware, commission it. **Commission it** opens a session. The agent reads what the unit already holds and asks one question at a time for what it cannot read: where the unit is, its name, the Wi-Fi, the mobile network and its class, the platform. It writes each setting, reads it back, starts the unit and checks that it is working, then goes on to the sensors the unit should admit.

<Frame caption="An LBG20x in range: paired, claimed by this computer, its firmware current, not commissioned yet. A BLG20x takes the same four steps.">
  <img src="https://mintcdn.com/adsumnetworks/OZLcvSxZlz2IQqUn/images/states/32-hardware-bluetooth-commission-it.png?fit=max&auto=format&n=OZLcvSxZlz2IQqUn&q=85&s=98ec011b27d8ac489a65b294d1a663d0" alt="Gateways in range: LBG20x AD50, window open and paired; 1 paired with its two firmware versions, 2 claimed by this computer, 3 up to date with Check again, 4 not commissioned with Commission it" style={{ maxWidth: "444px", margin: "0 auto" }} width="824" height="338" data-path="images/states/32-hardware-bluetooth-commission-it.png" />
</Frame>

* **The key is shown once.** The session also adds it to `adsum-fleet-register.csv` in your workspace, with the unit's name and identity. Keep that file: it is the only place the key exists.
* **The answers that repeat are kept.** A site profile, `adsum-site.json` in the workspace, holds the naming pattern, the network, the platform and the Wi-Fi name, so the next unit needs only its position, the Wi-Fi passphrase and the platform's token. It never holds a password, a token or a key; those are asked each time.
* **A commissioned unit says how it is doing.** The fourth step then reads commissioned with the unit's own verdict (working, not working yet, still checking), its (i) holds the position, how it sends and where, and **Change…** opens a session to change any of it.
* **A claimed unit is updated from this computer.** Claiming locks the unit's service port to this computer's key. The browser page still commissions it, and points here for its firmware.

<Frame caption="Commissioned, in the unit's own words: still checking its first send. The (i) holds the position, how it sends and where, and the commissioning window.">
  <img src="https://mintcdn.com/adsumnetworks/OZLcvSxZlz2IQqUn/images/states/33-hardware-bluetooth-commissioned.png?fit=max&auto=format&n=OZLcvSxZlz2IQqUn&q=85&s=2f273030e6c3f5978e5d5afa08aa1c0a" alt="The same unit commissioned: 4 commissioned, still checking, with Change" style={{ maxWidth: "444px", margin: "0 auto" }} width="824" height="338" data-path="images/states/33-hardware-bluetooth-commissioned.png" />
</Frame>

### From a browser

The NTN-GW Commissioner, at [commission.adsumnetworks.com/ntn-gw/](https://commission.adsumnetworks.com/ntn-gw/), does the same in Chrome over Web Bluetooth, for an installer with a phone or a laptop. Nothing is installed and nothing is served from your machine.

<Frame caption="The page at rest. Stand next to the unit. The QR code opens the same page on an Android phone.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-24-commissioner-page.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=cc72e6491ad34127fdc8ae05ef58c37f" alt="The commissioner page before connecting, with a QR code for opening it on a phone" style={{ maxWidth: "460px", margin: "0 auto" }} width="2400" height="3420" data-path="images/guides/blg20x/fig-24-commissioner-page.png" />
</Frame>

<Note>
  **The unit only listens for five minutes**

  A commissioned gateway advertises for five minutes after power-on and after each disconnect, then stops. If the chooser is empty, **hold DFU1 for 3–5 seconds** and press Connect again. Open the chooser *first*, then press the button if you need to.
</Note>

<Frame caption="The pairing dialog belongs to the operating system, not the browser, so it can open behind the window. The page shows the six digits first, so you always know which unit you are answering for.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-25-mac-passkey-dialog.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=b9e9fd3259239de3c0e7e088a477994b" alt="The operating system asking for the passkey shown on the page" style={{ maxWidth: "560px", margin: "0 auto" }} width="960" height="430" data-path="images/guides/blg20x/fig-25-mac-passkey-dialog.png" />
</Frame>

<Frame caption="Connected. What the unit says it is, before you change anything.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-29-unit-panel.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=16dbed56f15b9f39f218a46cef24b98f" alt="The unit panel showing identity, firmware and what the unit exposes" width="2400" height="880" data-path="images/guides/blg20x/fig-29-unit-panel.png" />
</Frame>

<Note>
  **A newer demo firmware, from the same page**

  When the unit runs an older demo release, the first line after Connect says a newer one is out from Adsum Networks. **Upgrade** installs it over Bluetooth, the Bluetooth half first, in about six minutes, and the unit keeps its settings. Keep the page open and the device near the unit until it says Upgraded. If it stops, nothing breaks: the unit keeps the firmware it runs, and Upgrade again continues.
</Note>

#### Position, name, credential

The board has **no GNSS receiver**, so the position is written here and is permanent until the unit is re-commissioned. Every method carries an uncertainty and the unit refuses a position without one: a coordinate that cannot say how wrong it might be is worth nothing later.

<Frame caption="Written, then read straight back. The coordinates are masked in this guide only; on your unit they appear in full.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-32-position-written.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=44257a6a344aa51bfc97924f3d934536" alt="A position written to the unit and read straight back, with coordinates masked" width="2400" height="1400" data-path="images/guides/blg20x/fig-32-position-written.png" />
</Frame>

<Frame caption="The credential is shown once. Add the unit to the fleet register before you disconnect: the register is the only place that key exists.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-33-commissioned.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=5f48b76d8871d164403f9046690f737d" alt="The credential shown once, and the commission button" width="2400" height="1400" data-path="images/guides/blg20x/fig-33-commissioned.png" />
</Frame>

<Frame caption="The gate for this step: every field read back and compared. Green is a match; anything else is the unit disagreeing, and the unit is right.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-35-read-back-matches.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=5b35fec3bee2d53eda4acfa6611cf653" alt="Every written field compared against the unit's read-back, all matching" width="2400" height="900" data-path="images/guides/blg20x/fig-35-read-back-matches.png" />
</Frame>

## Step 4: Set the deployment class

*about 5 minutes*

<Note>
  **From Adsum IoT Coder, this step is part of Step 3.** The session asks for the class with the mobile network (mobile only, mobile with satellite backup, or satellite only) and writes the policy and the class in the order the unit accepts. The panel below is the browser's.
</Note>

Commissioning does **not** set the class, and the build's default is the full ladder. The class fixes the transport and the encoding for the life of the record store, because a record written under one bearer has to be sendable, unchanged, under any bearer the unit might fall back to.

<Frame caption="The Deployment class panel, below Verify on the same page. Re-commissioning is not the way to change a class; this panel is.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-39-deployment-class-panel.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=3d491a5a10e6e820510d18397a9d0f43" alt="The deployment class panel with class, transport, encoding, endpoint host, port, APN and device token" width="2400" height="1640" data-path="images/guides/blg20x/fig-39-deployment-class-panel.png" />
</Frame>

<Warning>
  **Narrowing has an order, and the unit will refuse you**

  1. **Network policy**: untick satellite under *Allowed accesses* **and** clear it from the *Ladder* rungs. Unticking alone is not enough.
  2. Write the policy, and read it back.
  3. **Then** write the Deployment class.

  Widening is the reverse: class first, then policy.
</Warning>

<Frame caption="What the wrong order looks like. The unit refuses the write and names both the reason and what to do; nothing on the unit changed.">
  <img src="https://mintcdn.com/adsumnetworks/QVnwIKpQ2ObpvJjj/images/guides/blg20x/fig-40-class-refused.png?fit=max&auto=format&n=QVnwIKpQ2ObpvJjj&q=85&s=a6fd5010bb9596faff0bc00d26549697" alt="The unit refusing the class write and naming the rule" width="2400" height="493" data-path="images/guides/blg20x/fig-40-class-refused.png" />
</Frame>

<Frame caption="Written and read back in the right order.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-43-class-written-tn.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=a03839db5b45682b343903677cc42257" alt="The class written and read back as terrestrial only" style={{ maxWidth: "460px", margin: "0 auto" }} width="2400" height="2320" data-path="images/guides/blg20x/fig-43-class-written-tn.png" />
</Frame>

## Step 5: Admit your sensor

*about 5 minutes*

**A commissioned unit with no access list ingests nothing.** That is deliberate: on a metered link, admitting whatever happens to be nearby is a bill somebody else writes for you.

<Frame caption="Nothing is ingested by accident. Only an admitted advertisement gets a short id, a digest and a record in the store. Everything else is counted and forgotten, or held where you can look at it.">
  <img className="block dark:hidden" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-4-light.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=abc942f9d5f78b6726d29d1488246a79" alt="An advertisement is admitted only if the expected list or a rule names it; otherwise it is counted and dropped, or held in quarantine." width="800" height="220" data-path="images/guides/blg20x/diagram-4-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-4-dark.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=5cbc573d959f707cebd04e36378de30c" alt="An advertisement is admitted only if the expected list or a rule names it; otherwise it is counted and dropped, or held in quarantine." width="800" height="220" data-path="images/guides/blg20x/diagram-4-dark.svg" />
</Frame>

<Frame caption="The quarantine: what the unit has heard and deliberately not taken. Note the one marked rotating: its address changes every fifteen minutes.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-58-quarantine-panel.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=1f2a4ffb4e9a625596dacb23fc9da7ba" alt="The quarantine listing advertisers heard but not ingested, including a rotating one" width="2400" height="1900" data-path="images/guides/blg20x/fig-58-quarantine-panel.png" />
</Frame>

To admit one device you know, use the **expected list**, one entry per line:

```bash theme={null}
D2:14:97:21:15:C9, any, kitchen probe, 1
```

`ADDRESS, profile, label, short id`. Then **Write the expected list**, then **Read from the unit**. Three things that will otherwise surprise you:

* **Writing replaces the whole list.** It is not an append: send every entry you want kept, every time.
* **An entry admits its device on its own**, no rule needed, and fixes its short id by list order, so numbering is identical on every unit given the same list.
* **A rotating address is refused**, by line number. A reserved slot would point at something that stops existing.

<Warning>
  **Do not use "Admit what I see" for one device**

  It is the quarantine's bulk button and admits everything the unit has heard: on a bench, mostly strangers' phones. On the evaluation firmware that spends your ten-device allowance, the set survives restarts, and it can be cleared only five times in the unit's life.
</Warning>

<Frame caption="Written, then read back from the unit.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-60-expected-devices.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=6892b3c0746e841e58e032af58eb4d43" alt="The expected list written to the unit and read back" width="2400" height="900" data-path="images/guides/blg20x/fig-60-expected-devices.png" />
</Frame>

<Frame caption="The counters that matter. Expected devices: 1 of 1 heard, the expectation the unit is actually enforcing, matching reality. The large dropped count is the rest of the room, working as designed.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-61-access-counters.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=ad5d60043beef743b293c99465e33dc4" alt="The access counters showing one expected device, one heard, and over a million dropped" style={{ maxWidth: "460px", margin: "0 auto" }} width="333" height="389" data-path="images/guides/blg20x/fig-61-access-counters.png" />
</Frame>

<Frame caption="The modem's own account of itself. The effective ladder explains each rung: here satellite is excluded because the configuration excludes it, not because anything failed.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-63-network-live.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=0bd0e12356f9bb5eb10d3a99e7b85228" alt="The network block showing the rung, effective ladder, network, band and cell" style={{ maxWidth: "560px", margin: "0 auto" }} width="333" height="301" data-path="images/guides/blg20x/fig-63-network-live.png" />
</Frame>

## Step 6: Send readings to your platform

*about 10 minutes, plus one radio cycle*

<Frame caption="The whole path. The token is what makes the last hop yours; without it the unit has nowhere to send and its uplink stays at never.">
  <img className="block dark:hidden" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-5-light.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=17e12538968b519050cf9cd687c5f01c" alt="A reading travels from the sensor through both halves, over CoAP with a protobuf payload, to a device on your tenant identified by a token." width="800" height="168" data-path="images/guides/blg20x/diagram-5-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-5-dark.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=e3f23344c9d217dcb4af5ab980f49071" alt="A reading travels from the sensor through both halves, over CoAP with a protobuf payload, to a device on your tenant identified by a token." width="800" height="168" data-path="images/guides/blg20x/diagram-5-dark.svg" />
</Frame>

### On your tenant

<Frame caption="Transport CoAP, payload Protobuf. These two fields are the whole step: get either wrong and the readings silently never arrive.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/tb-07-profile-transport-coap.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=021c7bd12268ec86ac160641da3f6492" alt="A device profile with CoAP transport and protobuf payload highlighted" width="1460" height="880" data-path="images/guides/blg20x/tb-07-profile-transport-coap.png" />
</Frame>

<Frame caption="A device on that profile. The name is yours; it is how you will find it again.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/tb-15-ready-to-add.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=5f11324d21dc6b290a36ccbcfbfbf2ad" alt="Creating a device on the CoAP protobuf profile" width="1460" height="880" data-path="images/guides/blg20x/tb-15-ready-to-add.png" />
</Frame>

<Frame caption="The device's access token. Copy it: this is the one value the unit will never read back to you.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/tb-18-credentials-masked.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=70fc2d82c88ac12dd5c681d1e5b80162" alt="The device's access token, masked in this guide" width="1460" height="880" data-path="images/guides/blg20x/tb-18-credentials-masked.png" />
</Frame>

### On the unit

Back on the Deployment class panel: transport **CoAP / DTLS-CID**, encoding **protobuf**, your host and port, APN blank unless your SIM needs one, and the token pasted in.

<Frame caption="Written and read back. The token is deliberately excluded from the comparison: the unit never sends a credential back, so there is nothing to compare against. It is on test for three boots: if the unit fails its health gate under it, the previous one returns and the panel says so.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/comm-23-read-back.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=645c675e24bb0538be6859823107fb18" alt="The data plane written to the unit and read back, with the token excluded from the comparison" width="1460" height="880" data-path="images/guides/blg20x/comm-23-read-back.png" />
</Frame>

<Frame caption="The first record. Several intact keys, each carrying the device's own timestamp: that is what proves the profile is right. Had the payload type been wrong, the whole reading would have collapsed into one field named after the wrapper.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/tb-23-telemetry-arrived.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=021aec52b5c41ee873563b98ea293a1e" alt="Telemetry keys arriving on the platform, each with the device's own timestamp" width="1460" height="880" data-path="images/guides/blg20x/tb-23-telemetry-arrived.png" />
</Frame>

<Check>
  **Stop here and you have a working gateway**

  It hears your sensors, keeps their readings, and sends them to your own platform on its own schedule. The code to look for is `2.01`: the platform took the reading.
</Check>

<Frame caption="The unit's own account of its last uplink: the result code, how long ago, the datagram size, and when it will go again.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/fig-64-uplink-live.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=1303f34c8afe046e97e11aee4216f443" alt="The uplink block showing last result 2.01, when, datagram size and next cycle" style={{ maxWidth: "560px", margin: "0 auto" }} width="333" height="211" data-path="images/guides/blg20x/fig-64-uplink-live.png" />
</Frame>

## Step 7: Send a command back

*one radio cycle*

Everything so far travelled outwards. This step goes the other way, and it is the only step that proves you can reach into a deployed unit from your desk.

<Frame caption="Why only the far end counts. The sender saying &#x22;I sent it&#x22; proves nothing: in an earlier measured run one message in two was lost between the halves and both ends reported no drops, because neither was counting something it never knew about.">
  <img className="block dark:hidden" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-6-light.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=f7de936f3898900a982446773a29f3cc" alt="Outward, readings travel from the sensor to your platform. Inward, a command travels from your platform to the Bluetooth half, and only the Bluetooth half's log proves it arrived." width="800" height="200" data-path="images/guides/blg20x/diagram-6-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/diagram-6-dark.svg?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=82941a397398bed17be69c78d0626822" alt="Outward, readings travel from the sensor to your platform. Inward, a command travels from your platform to the Bluetooth half, and only the Bluetooth half's log proves it arrived." width="800" height="200" data-path="images/guides/blg20x/diagram-6-dark.svg" />
</Frame>

On your tenant, add a **shared attribute** to the device: key `cmd`, type string, value `clear_latch`.

<Frame caption="The shared scope, not server, not client. The wrong scope gives the unit a 4.04 when it polls.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/tb-29-value-typed.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=847f316cc31a2ec59c8268c694beba84" alt="Adding a shared attribute with key cmd and value clear_latch" width="1460" height="880" data-path="images/guides/blg20x/tb-29-value-typed.png" />
</Frame>

The unit reads its shared attributes on its next radio cycle: **up to about fifteen minutes, usually a few**. The status panel's `NEXT CYCLE` is your wait. Rebooting to hurry it only restarts the clock.

<Frame caption="This line is the pass, and only this line. It comes from the Bluetooth half, preceded by the frame arriving over the link. 0 latch(es) cleared is correct on a unit with no alert rules: we are proving the command arrives, not that it does something dramatic.">
  <img src="https://mintcdn.com/adsumnetworks/FHuIJBYuebMJDAfk/images/guides/blg20x/comm-31-clear-latch-line.png?fit=max&auto=format&n=FHuIJBYuebMJDAfk&q=85&s=4af5866c84d82b1cb0e830b914cd2528" alt="The Bluetooth half logging that it received the command and acted on it" width="1460" height="880" data-path="images/guides/blg20x/comm-31-clear-latch-line.png" />
</Frame>

**Delete the attribute afterwards.** The unit acts on a shared attribute at *every* cycle while it stays set.

## When something looks wrong

These are the ones that cost real time, with what they actually mean.

| What you see | What it usually is |
| :- | :- |
| **The Bluetooth chooser is empty** | The five-minute advertising window has closed. Hold DFU1 for 3–5 seconds and press Connect again. Only if it is *persistently* empty should you suspect the browser's Bluetooth permission. |
| **A log read returns nothing** | Not a dead chip. Both halves share one newest-first buffer and the Bluetooth half prints every ten seconds, so it crowds the other out within seconds. **Fetch the log immediately after the moment you care about.** Confirm a half is alive by something it cannot fake: its attach, its uploads, a command it acted on. |
| **A log line contradicts the page** | Check the line's timestamp against the time of your action. A line is evidence only if it is *after* the thing you are asking about. Where the page has read a value back from the unit, that read-back outranks any log. |
| **The log clock jumps back to zero** | It is a 32-bit microsecond counter and wraps every **71 minutes 35 seconds**. A wrap, not a restart. Take uptime from the status record. |
| **A configuration write is refused** | The unit is protecting itself and nothing changed on it. The message names the rule; for a class change the usual cause is a network policy still allowing something the class does not. |
| **Two different firmware versions** | Expected. The halves version independently and both numbers are right. The commissioner's `fw` badge is the Bluetooth half's. |
| **`strings` finds nothing in a `.hex`** | Intel HEX stores the payload as hexadecimal *text*. Decode to binary before searching it. |
| **The modem will not attach after several resets** | The modem bans attach for about half an hour after repeated resets without a clean shutdown, and the ban is invisible unless event reporting was armed first. Wait it out; resetting again restarts it. |
| **Readings never arrive, no error anywhere** | Almost always the profile: a CoAP device against an MQTT profile, or the wrong payload type. Check the two fields in the profile before anything else. |

## What this firmware will not do

<Note>
  **Evaluation firmware**

  It hears your sensors, keeps their readings, and sends them to your own platform, with the three limits below, and those limits are in this build only.

  **No device-management client:** this unit will not appear in a console and is not updated over the mobile network; that part is fitted per build. A newer demo release still installs over Bluetooth, from Adsum IoT Coder or the commissioning page.
</Note>

| Limit | What it means in practice |
| :- | :- |
| **Ten devices** | The first ten this gateway hears become its set. An eleventh is still scanned and still listed, it is simply not carried off site. The set survives a restart; you can clear it and start again five times in the unit's life. |
| **10 MB a month**, mobile | A gateway left running uses well under this. If it is ever reached, uplink waits for the next month and everything else keeps working. |
| **10 KB a month**, satellite | The whole satellite package. Only alerts and status go that way; firmware never does. |

**There is no time limit, and restarting the unit resets none of this.** Nothing here ever asks you to reboot, and you should not, because the modem blocks attach for about half an hour after repeated resets.

### Ways on from here

* **Our verified build** for the units you ship
* **The source of our firmware**, the Bluetooth half or both, with the advanced knowledge to build on it and customise it
* **We build it for you**

Ask for details on any of these from the Adsum panel and we reply within a business day.

***

Captured on a BLG20XE02C-V1 with the published evaluation pair, verified on macOS. Coordinates and credentials in the figures are masked for this page; on your own unit they appear in full.

<CardGroup cols={2}>
  <Card title="The BLG20x" icon="microchip" href="/supported-hardware/fanstel/blg20x">
    The board, the firmware, and every way to have it.
  </Card>

  <Card title="Satellite IoT: NB-NTN" icon="satellite" href="/satellite-ntn">
    What a satellite link is good for, and what it costs.
  </Card>

  <Card title="The NTN-GW Commissioner" icon="bluetooth" href="https://commission.adsumnetworks.com/ntn-gw/">
    Commission a BLG20x from Chrome, over Web Bluetooth.
  </Card>

  <Card title="Ask for more" icon="envelope" href="mailto:support@adsumnetworks.com?subject=BLG20x">
    A production licence, the source, or a build made for you.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.