LIGHT FIGHTERGUIDES Resources
GUIDE // 01 DOLOS DEVICE

Dolos Device

A low-cost Raspberry Pi false-emitter for home-station EW and SIGINT training.

The Device
1.1

Overview

There are many ways which this device can be utilized besides its false emitter intent; including: retransmission, jammer, and DF kit. Utilizing a Raspberry Pi and some knowledge in coding, the possibilities are only limited by your imagination. In this configuration, the device and attached devices are unclassified and therefore pose a lower security risk if compromised. It is not recommended that this device hold any information that could be exploited if compromised. Full disk encryption could be used but it would only serve to protect the data at rest and would require the device be unlocked prior to any script execution (the device would not be fully functional when power is applied). Less complexity in design and program configuration allows anyone at the end user level to emplace the device.

1.2

Bill of Materials

The following is the parts list for the device.

Core

PartSpecNotes
Raspberry Pi Zero 2 WQuad-core, onboard 2.4 GHz Wi-Fi / BLE, ~0.4 W idleRuns the access point on its own radio. The GPIO header is unpopulated.
2×20 stacking GPIO headerExtended / stacking 40-pinSoldered to the Pi to seat the LTE Base HAT and keep the UART pins reachable for the optional BFoxCon serial link.
microSD card16 GB or larger, A1/A2Holds the OS and scripts.

Cellular & timing

PartSpecNotes
Sixfab 3G–4G/LTE Base HAT40-pin HAT, holds a mini-PCIe modemThe carrier board from the Sixfab LTE-M Cellular IoT Kit.
Telit ME910C1-WW modemLTE-M (Cat-M1) + NB-IoT, integrated GNSSCellular link and GPS timing in one mini-PCIe module.
LTE / GNSS dual u.FL antenna100 mmOne lead cellular, one GNSS.
Sixfab SIMLTE-M / NB-IoT dataShips with the kit. A 90° micro-USB cable carries the modem's data to the Pi's USB port.

Radio & emitter

PartSpecNotes
Baofeng UV-5RDual-band 2–8 W HT, Kenwood 2-pin SP/MIC jackThe transmitter. Cheap, common, 3 W or 6 W.
Byonics BFoxCon (v1.6)PIC16F1827 fox-hunt controller; +, −, G, R, P, T padsMounts on the radio's back. Keys PTT and plays the tone / Morse sequence; DTMF remote control; runs off the radio battery.
UV-5R earpiece / mic headsetSacrificial, ~$1Cut for its 2-pin SP/MIC plug and four wires, soldered to G/R/P/T (see the soldering section).

Power, enclosure & consumables

PartSpecNotes
PiSugar 3 (Zero)Li-ion UPS, pogo-pin mount, RTC, up to 3 APowers the Pi from the back contacts, so it never touches the 40-pin header. Its clock retains time.
Logic-level MOSFET / load switchsmall N-FET or load-switch ICA Pi GPIO switches the BFoxCon's power on J2 pin 3, so the Pi can power-cycle it.
Waterproof caseConduit box or Pelican-styleAntennas mount externally.
Mounting hardwareAssorted M2.5 standoffs, screws, nutsHolds the boards and keeps the insides from shifting.
Wire & heat-shrink22 AWG, various colorsFor the BFoxCon, headset, and power leads.
How the two halves connect

Two halves. BFoxCon + UV-5R is the emitter — battery-powered, DTMF-controlled, no Pi needed. The Pi Zero 2 W adds the LTE-M and Wi-Fi signatures and orchestration, optionally over the BFoxCon J2 header (1 GND / 2 Serial-In / 3 +3–5 V / 4 Serial-Out). On the Pi, the Base HAT uses GPIO 27/22/6/13/19/26 + UART; the PiSugar sits off-header on the back pogo pins.

Estimated cost

Approximate 2026 prices in USD, before shipping and tax. The Sixfab line is the LTE-M Cellular IoT Kit (Base HAT, Telit modem, antenna, and SIM together).

ItemApprox.
Raspberry Pi Zero 2 W$15
microSD card$8
Stacking header$3
Sixfab LTE-M Cellular IoT Kit$80
Baofeng UV-5R$30
Byonics BFoxCon (assembled)$63
Sacrificial headset$2
PiSugar 3$40
Case, hardware, wire$25
Total~$265
1.3

Tools and Supplies Required

  • Soldering Iron and associated kit
  • Wire strippers
  • Precision screwdriver set (attaching boards together and wires to terminals)
  • Shrink tubing
  • 22 AWG wire (various colors)
  • USB to micro USB cables (quantity will vary per components used)
  • Multimeter
Build
1.4

Radio Interface — BFoxCon + UV-5R

The BFoxCon ships assembled and pre-wired to the radio: the G/R/P/T pads are already wired to a 2-pin SP/MIC plug, and the +/− to a power lead for the BL-5L extended battery. You don't solder these. Mount the BFoxCon on the radio's back, plug the SP/MIC into the UV-5R, and plug the power lead into the BL-5L battery's charge jack.

Factory wiring (reference)

Plug contactFunctionBFoxCon pad
2.5 mm sleeveGroundG
2.5 mm tipReceive AudioR
3.5 mm sleevePush-To-TalkP
3.5 mm ringTransmit AudioT
Bare-PCB version

If you buy the unassembled PCB instead, you solder those four wires yourself: cut a UV-5R headset, ohm out the leads, and solder each to the top of its G/R/P/T pad. Most builders buy it assembled, so the work moves to the Pi side.

1.5

Pi → BFoxCon (J2 serial)

This is where the Pi takes control. The Pi connects to the BFoxCon's J2 serial header (the 1×4 header by RST) — nothing else. Wire the four J2 pins to the Pi's 40-pin GPIO header:

INTERACTIVE
Drag each J2 pin to its Raspberry Pi GPIO pin. Pinouts are to spec.
J2 pinFunctionRaspberry Pi pin
1 (square)GroundPin 6 (GND)
2Serial InPin 8 (GPIO14 / TXD)
3+3–5 VPin 1 (3V3), switched by a GPIO
4Serial OutPin 10 (GPIO15 / RXD)
Crossover

Serial is crossed: the BFoxCon's Serial-In takes the Pi's transmit (TXD → J2 pin 2), and the BFoxCon's Serial-Out feeds the Pi's receive (J2 pin 4 → RXD).

Two facts from the manual shape the control: configuration only works in the first three seconds after the BFoxCon powers up, and on a serial cable it will not run until it gets the first serial command. So the Pi powers the BFoxCon through J2 pin 3 — switched by a GPIO and a small MOSFET — and on each power-up sends the config and start command over UART inside that window. Power and serial, both through J2.

Power source

The BL-5L power lead (the factory +/− wiring) is only for running the BFoxCon standalone with no Pi. Under Pi control, power the BFoxCon from the Pi through J2 pin 3 instead.

1.6

Soldering

On the assembled build the BFoxCon is already wired, so the only soldering is the Pi's GPIO header — the Pi Zero 2 W ships with bare GPIO pads.

  • Solder a 2×20 stacking header to the Pi: seat it square, tack two opposite corners, check it sits flat, then solder all 40 pins.
  • Use a stacking (extended) header so the LTE Base HAT can seat and the UART pins (8 and 10) stay reachable for the J2 link.
  • Solder to clean, tinned pads; keep the iron on each pin about a second.
1.7

Dolos Build

INTERACTIVE
Add the parts in the right build order; the stack fills in as you go.

Mount the Raspberry Pi, power module, radio interface, and associated plugs and accessories in the waterproof case you intend to use. Set it in a way that prides easy access to any power switches and ports for recharging the battery, also set it in a way to prevent the insides from shifting about during deployment and potentially breaking connections. Antennas should be mounted externally and oriented to allow efficient and correct wave propagation. It is advised to test connectivity and functionality of the device prior to mounting inside the case. It is also advised to utilize an onboard time retention module or GPS timing module if it is your intent to utilize the device for “on time” effects.

Operation
1.8

Capabilities & Triggers

The finished device is triggered and controlled three ways. Each path can start, stop, and reconfigure the emitter; the two data paths also run commands on the Pi.

TriggerPathWhat it does
Radio (DTMF)UV-5R receive → BFoxConStart / stop / toggle transmit and change tones, timing, and the Morse ID over the air. No data link needed.
Wi-FiPi access pointJoin the AP and SSH to the Pi: full shell, swap audio and configs, drive the BFoxCon over its J2 serial.
Cellular (LTE-M)Telit modem → mesh VPNSSH and run commands from anywhere over the Headscale/Tailscale mesh; small data back.
One control surface

All three reach the same two things: the Pi (shell and scripts) and the BFoxCon (DTMF or J2 serial).

A fleet, and sensors

These deploy as a fleet. Build several, emplace them across an area, and a team hunts them like live SIGINT targets. Each Pi joins the mesh under its own hostname (dolos-1, dolos-2, …), so you command any node from one place.

The Pi has spare GPIO once the Base HAT and the J2 link are wired. Attach sensors — motion, door, vibration — and the dolos tool reads them and reports over the mesh. A sensor event can also trigger the emitter, so a node fires when something trips it.

1.9

Operating System

Raspberry Pi OS Lite (64-bit), Bookworm, flashed with Raspberry Pi Imager 2.0. The wizard sets everything for a headless first boot.

  1. Choose Device: Raspberry Pi Zero 2 W.
  2. Choose OS: Raspberry Pi OS Lite (64-bit).
  3. Choose Storage: the microSD.
  4. OS customization: hostname dolos; username user; enable SSH with your public key; set Wi-Fi for first boot; set locale.
  5. Write, boot, then ssh [email protected] and sudo apt update && sudo apt full-upgrade -y.
1.10

Access Point

Bookworm uses NetworkManager. hostapd and dnsmasq are not used and will conflict if installed. One command stands up the AP on the onboard radio.

nmcli device wifi hotspot ifname wlan0 ssid dolos password CHANGEME
nmcli connection modify Hotspot connection.autoconnect yes ipv4.method shared
One radio, one role

wlan0 serves the AP, so it is not also a Wi-Fi client. Field updates come over the cellular link instead.

1.11

Cellular Link (LTE-M)

The Telit ME910C1 on the Base HAT connects to the Pi by USB. On Bookworm, ModemManager manages the modem and NetworkManager brings up the connection — no ttyS0, minicom, or PPP scripts.

  1. Insert the SIM, connect the LTE/GNSS antenna, and seat the Base HAT; run the 90° micro-USB lead to the Pi's USB port.
  2. Confirm the modem is seen: mmcli -L.
  3. Create the connection: nmcli con add type gsm ifname '*' con-name dolos-lte apn YOUR_APN connection.autoconnect yes.
  4. Verify: mmcli -m 0 and ip addr show wwan0.
Bandwidth

LTE-M is low-bandwidth and sits behind carrier NAT — right for command and control, not streaming. APN and Telit specifics: Sixfab Base HAT docs.

1.12

Boot & Autostart

rc.local is removed in Bookworm. NetworkManager autostarts the AP and the cellular link; run any orchestration script as a systemd service.

# /etc/systemd/system/dolos.service
[Unit]
Description=Dolos orchestration
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/home/user/dolos.sh
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl enable --now dolos.service
journalctl -u dolos -f
1.13

Software — the dolos tool

The network services (access point, LTE-M, mesh) run from config and autostart. One thin Python tool, dolos, is the control surface; run it over SSH from the Wi-Fi AP or the mesh.

CommandDoes
dolos statusLTE link, GNSS fix, PiSugar battery, tailnet, AP clients
dolos fox start | stopSwitches BFoxCon power (its auto-start flag means power = run)
dolos fox set --id CALL --loop MINPower-cycles the BFoxCon and writes config over J2 serial
dolos beaconPushes a GNSS / status report back over the mesh

BFoxCon link

A Pi GPIO drives a MOSFET on the BFoxCon + line to power-cycle it; the Pi UART (GPIO14/15, reached through the stacking header — the Base HAT leaves UART disconnected) talks to J2 (pin 2 Serial-In, pin 4 Serial-Out, pin 1 GND). Config is accepted only in the first three seconds after power-up, so set power-cycles, then writes.

Confirm on the build

The BFoxCon J2 baud and command framing are not printed in the manual. Read them off the byonics.com/mfconfig WebSerial tool and confirm against the board; the skeleton's serial writes are placeholders until then. Also set enable_uart=1 and free the serial console so the Pi's PL011 UART is on GPIO14/15.

Skeleton

#!/usr/bin/env python3
# dolos — Dolos control tool. Run over SSH (Wi-Fi or the mesh).
import argparse, subprocess, time, serial
import RPi.GPIO as GPIO

FOX_PWR = 17                          # GPIO -> MOSFET on the BFoxCon + line
PORT, BAUD = "/dev/serial0", 115200   # baud/framing: confirm against the BFoxCon

def power(on):
    GPIO.setmode(GPIO.BCM); GPIO.setup(FOX_PWR, GPIO.OUT); GPIO.output(FOX_PWR, on)

def fox_set(callsign, loop_min):
    power(False); time.sleep(1); power(True)      # power-cycle for the 3 s config window
    with serial.Serial(PORT, BAUD, timeout=1) as s:
        s.write(b"***\r")                         # enter config (MicroFox family)
        s.write(f"C1 {callsign} #\r".encode())    # Morse ID  (encoding: confirm vs MFConfig)
        s.write(f"A3{loop_min:02d}00\r".encode()) # loop time mm:ss

def status():
    print(subprocess.getoutput("mmcli -m 0 | grep -i state"))   # LTE link
    print(subprocess.getoutput("tailscale status | head -1"))   # mesh
    # add: GNSS fix, PiSugar battery over I2C

p = argparse.ArgumentParser(prog="dolos")
sub = p.add_subparsers(dest="cmd")
sub.add_parser("status")
f = sub.add_parser("fox"); f.add_argument("action", choices=["start","stop","set"])
f.add_argument("--id"); f.add_argument("--loop", type=int, default=10)
a = p.parse_args()
if a.cmd == "status": status()
elif a.cmd == "fox":
    if a.action == "start": power(True)
    elif a.action == "stop": power(False)
    elif a.action == "set": fox_set(a.id, a.loop)
1.14

Remote Command & Control

The three trigger paths converge on the Pi and the BFoxCon. The 2018 IFTTT and Dropbox callback is gone; the mesh VPN reaches the Pi directly.

Over the air (radio)

Send DTMF to the radio: 1 start, 2 toggle, 3 stop, D lock. The A/B/C codes reconfigure tones, timing, and the Morse ID. No Pi needed.

Over Wi-Fi or cellular (shell)

Join the Pi to your mesh, then SSH to it from anywhere — no public IP or port forwarding, which is what makes it work behind carrier NAT.

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --login-server https://YOUR_HEADSCALE
# then from any node on the mesh:
ssh user@dolos

From the shell, run any command, swap audio and configs, or drive the BFoxCon over its J2 serial within the three-second post-power-up window.

Field
1.15

Bring-up & Verification

Bring it up in layers and test each before adding the next, so a failure points at one layer.

  1. Pi base — flash Bookworm Lite, boot headless, SSH in, update.
  2. Networking — stand up the Wi-Fi AP and the LTE-M link, then join the mesh. Confirm you can SSH the Pi over Wi-Fi and over cellular.
  3. Radio, standalone — power the BFoxCon off the BL-5L, set the UV-5R to a ham frequency, set your callsign as the Morse ID; confirm it transmits the loop and IDs, listening on another radio.
  4. Serial protocol — with a USB-TTL adapter and the byonics.com/mfconfig tool, read and write the BFoxCon to capture its baud and command bytes.
  5. Pi UART — set enable_uart=1, free the serial console, loopback-test /dev/serial0.
  6. Wire J2 to the Pi (TX/RX/GND + the switched power line); confirm the Pi power-cycles the BFoxCon and reads its version back over serial.
  7. End-to-end — from a node on the mesh, SSH to the Pi over cellular and run dolos to set the ID, then start and stop the emitter; confirm RF on another radio.
1.16

Emplacement, Power & Case

Power budget

Emplaced runtime is battery capacity divided by average draw. The Pi Zero 2 W idles near 0.4 W and the LTE-M link is low-power; the radio's transmit duty cycle is what drains the pack, so the BFoxCon's off-air delays and a low duty cycle buy runtime. Pick a target runtime, size one main battery, and for indefinite emplacement add a small solar panel and charge controller.

Permanent wiring

Solder the J2 link; a friction-fit plug works loose in an emplaced box. The BFoxCon's own config cable is the easy way: cut off the USB end (the converter), ohm out the four TTL leads, and solder them to the Pi — Serial-In to TX (pin 8), Serial-Out to RX (pin 10), GND to pin 6, +V to the Pi's switched 3.3 V line. Power the BFoxCon from the Pi only, not also the BL-5L.

Case

A custom 3D-printed enclosure holds the stack on M2.5 standoffs, mounts the antennas outside (LTE/GNSS and the radio's), and seals to weather with one access/charge port.

UTILITY3D Print CalculatorOPEN →

Fleet

Build several, give each a unique hostname, and join them all to the mesh. Spread them across the area for a realistic hunt, and command any node from one console.

Reference
1.18

Sources