Half of every connected system runs on an ordinary computer: the program that receives the devices' messages, the code that stores and checks them, the page that shows them. In this course that computer is yours. This section installs the software once, so later chapters can say "start Mosquitto" or "run the tests" and mean something you can do in a minute. All of it is free and runs locally. Nothing here signs you up for an online service.
Five tools and what each is for
A toolchain is the set of programs that turn the code you write into something that runs. For the board, you already have one: the Arduino tools. This section sets up a second toolchain, on your own computer. Five programs, each with one job.
Mosquitto is a small message server. Your boards will send their readings to it, and other programs will pick them up from it. Chapter 9 explains it properly.
Python is the main language for everything that isn't on the board: little test programs, the service that saves readings, checks on the data. You'll add one extra piece to it, called paho-mqtt, which lets Python talk to Mosquitto.
Node.js runs JavaScript and TypeScript outside a browser. .NET runs C#. Rust is a language some later chapters use for the board itself. These three are only for comparisons and later chapters, so they can wait.
All five are free and run on your own machine. Docker, a tool that packages programs in sealed boxes, is never required.
After installing anything, ask it for its version number. That one line tells you it worked. It's also the first thing a helper will ask for.
The software on your computer that the labs need is this course's toolchain: the programs that run outside the board. A toolchain in general is the set of compilers, interpreters and command-line tools that turn source code into something that runs. Five pieces make up this course's, each with one job:
| Tool | Version used here | Its job in this course |
|---|---|---|
| Mosquitto | 2.x (the build checks against 2.1.2) | A message server that devices send readings to and receive commands from; introduced fully in Chapter 9 |
| Python | 3.14, with paho-mqtt 2.1.0 | The reference language for everything off the board: test clients, the main service that stores readings, data checks |
| Node.js | a current LTS release (the build was checked with 22 in October 2026; check https://nodejs.org/ for the current LTS) | TypeScript versions of the main service and the browser dashboard |
| .NET SDK | 10 | C# gateways and services, Chapter 16 |
| Rust (rustup) | stable, plus the riscv32imac-unknown-none-elf target |
Rust firmware for the ESP32-C6, Chapters 17–18 |
Only Mosquitto and Python are needed before Chapter 14. Install the others when a chapter first uses them, or now if you prefer.
LTS (long-term support) marks a release that gets fixes for years, not months. Docker is optional everywhere. Some projects include a Compose file as a convenience, but every lab runs without it, and the course's own build never needs it.
Each tool prints its version with one command. That command is the first thing to run after an install, and the first thing to paste when asking for help.
Installing them
Pick your operating system once; every block like this on every page follows your choice.
Mosquitto: download the 64-bit installer from
https://mosquitto.org/download/. It installs to
C:\Program Files\mosquitto.
Python 3.14: the installer from https://www.python.org/downloads/,
or winget install Python.Python.3.14. Windows starts Python with the
py launcher.
Node.js: the LTS installer from https://nodejs.org/.
.NET 10 SDK: winget install Microsoft.DotNet.SDK.10, or the
installer from https://dotnet.microsoft.com/download.
Rust: run rustup-init.exe from https://rustup.rs/, then add the
ESP32-C6 target.
Check each one in a new terminal:
& "C:\Program Files\mosquitto\mosquitto.exe" -h
py -3.14 --version
node --version
dotnet --version
rustup target add riscv32imac-unknown-none-elf
rustc --version
With Homebrew (https://brew.sh/):
brew install mosquitto python@3.14
Node.js: the LTS installer from https://nodejs.org/, or a version
manager such as nvm.
.NET 10 SDK: the installer from https://dotnet.microsoft.com/download.
Rust: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh,
then add the ESP32-C6 target.
Check each one:
$(brew --prefix)/sbin/mosquitto -h
python3.14 --version
node --version
dotnet --version
rustup target add riscv32imac-unknown-none-elf
rustc --version
On Debian or Ubuntu:
sudo apt install mosquitto mosquitto-clients
Python 3.14: if python3 --version shows an older release, install
3.14 with a tool such as uv (uv python install 3.14) or from
https://www.python.org/downloads/.
Node.js: an LTS release from https://nodejs.org/, or a version
manager such as nvm.
.NET 10 SDK: follow https://learn.microsoft.com/dotnet/core/install/linux for your distribution.
Rust: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh,
then add the ESP32-C6 target.
Check each one:
mosquitto -h
python3.14 --version
node --version
dotnet --version
rustup target add riscv32imac-unknown-none-elf
rustc --version
mosquitto -h prints its version on the first line, such as
mosquitto version 2.1.2, then its options. dotnet --version should
start with 10..
Which tool does the job?
Sort each job under the tool this course uses for it. Decide before you drag, then check.
Loading interactive…
Right on try — credit. Right — the answer had already been shown, so no credit this time. Next try is worth Answer shown after three tries — this one no longer earns credit. You chose to see the answer — this one earns no credit.
What this task checks
Structure checked automatically. Whether your ideas are convincing isn't graded, so reread with the checklist.
The compiler says
A model answer
Correct answer
Also accepted:
Why
Why
A virtual environment for each project
Python programs borrow ready-made pieces, called packages. paho-mqtt is one. If every project put its packages in one shared place, two projects needing different versions would fight.
A virtual environment solves that. It's a folder inside your project with its own private shelf of packages. While it is switched on, which is called activated, anything you install lands on that shelf only. Delete the folder and those packages are gone. Nothing else is touched.
The four commands above make that folder, switch it on, install paho-mqtt, and print its version.
Notice the ==2.1.0. That asks for exactly version 2.1.0. Version 2 of
paho-mqtt changed how programs must use it, so code written for version
1 breaks on version 2. Asking for an exact version means your machine
has the same release these pages were tested with. Then, if something
fails, you know it's your code and not a version mismatch.
A virtual environment (venv) is a folder holding its own copy of the Python interpreter's package directory. Packages installed while it is active go into that folder only, so two projects can pin different versions of the same library without conflict, and deleting the folder removes them all.
python3.14 -m venv .venv # Windows: py -3.14 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
python -m pip install "paho-mqtt==2.1.0"
python -c "import paho.mqtt; print(paho.mqtt.__version__)"
Each lab project in this course carries its own pyproject.toml that
pins every dependency exactly, and its README repeats these steps.
Why pin ==2.1.0. paho-mqtt 2.0 changed how a client is created and
how its callbacks are called; code written for 1.x fails on 2.x and the
reverse. A pin means the code on the page and the library on your
machine are the same release, so an error is yours to fix, not a
version mismatch. Use python -m pip, not a bare pip: it installs
into whichever Python python is, which inside an active venv is the
venv's.
Worked example
pip installed it, but Python can't find it
-
1
A learner activates a venv, types
pip install paho-mqtt==2.1.0, then runspython client.pyand getsModuleNotFoundError: No module named 'paho'. What happened? -
2
Two Pythons. On this machine, the
pipcommand on the path belongs to a different Python than thepythoninside the venv, a common result of several installs. -
3
Check which is which.
python -m pip --versionprints the folder pip will install into. If it isn't inside.venv, the venv isn't the one in use. -
4
Fix. Always install with
python -m pip install .... That runs pip as part of the exact interpreter that will run the program.
Worked example
Port 1883 is already taken
-
1
On Ubuntu,
sudo apt install mosquittosucceeds, butmosquitto -vin a terminal stops with an error that the address is already in use. Why? -
2
The package started a service. The Debian package runs Mosquitto in the background as soon as it is installed, and that copy is listening on port 1883, Mosquitto's standard port.
-
3
Only one program can listen on a port. The second copy can't start.
-
4
Fix.
sudo systemctl stop mosquitto, then run it in the terminal where you can watch its log. Chapter 9 §2 does exactly this.
Do I need Docker for this?
A project's folder contains a docker-compose.yml next to its README. The learner has Python 3.14 and Mosquitto installed but no Docker. Answer each question to land on what to do.
Loading interactive…
Right on try — credit. Right — the answer had already been shown, so no credit this time. Next try is worth Answer shown after three tries — this one no longer earns credit. You chose to see the answer — this one earns no credit.
What this task checks
Structure checked automatically. Whether your ideas are convincing isn't graded, so reread with the checklist.
The compiler says
A model answer
Correct answer
Also accepted:
Why
Check your understanding (counts toward your progress)
Which rustup command prepares Rust to build firmware for the ESP32-C6?
Right on try — credit. Right — the answer had already been shown, so no credit this time. Next try is worth Answer shown after three tries — this one no longer earns credit. You chose to see the answer — this one earns no credit.
That's the S3's Xtensa target, which stock rustup doesn't provide.
Boards aren't installed by name; Rust adds compilation targets.
The C6 uses stable Rust, not nightly.
Why
The C6 is a RISC-V chip with no operating system, so its target is riscv32imac-unknown-none-elf, available in stock stable Rust.
The C6's cores are RISC-V.
On Ubuntu, mosquitto -v fails right after sudo apt install mosquitto with "address already in use". What is the most likely cause?
Right on try — credit. Right — the answer had already been shown, so no credit this time. Next try is worth Answer shown after three tries — this one no longer earns credit. You chose to see the answer — this one earns no credit.
The install worked: that's why a copy is already running.
Your provider can't see a port on your own computer's loopback address.
Docker is never required.
Why
The Debian package starts a service immediately. Stop it with sudo systemctl stop mosquitto, then run your own copy where you can see its log.
Only one program can listen on a port at a time.
What is a Python virtual environment for?
Right on try — credit. Right — the answer had already been shown, so no credit this time. Next try is worth Answer shown after three tries — this one no longer earns credit. You chose to see the answer — this one earns no credit.
It changes where packages go, not how fast code runs.
It lives on your computer. Nothing here runs Python on a board.
It has nothing to do with network access.
Why
A venv is a folder with its own package directory, so each project's pinned versions don't collide with another's.
Think of two projects that need different versions of one package.
A learner runs pip install paho-mqtt==2.1.0, then python client.py, and gets ModuleNotFoundError: No module named 'paho'. Which command tells them the most about why?
Right on try — credit. Right — the answer had already been shown, so no credit this time. Next try is worth Answer shown after three tries — this one no longer earns credit. You chose to see the answer — this one earns no credit.
Installing again into the same wrong place changes nothing.
Mosquitto isn't involved in a Python import error.
Node is a different tool entirely.
Why
python -m pip --version prints the folder pip installs into. If it isn't the venv the program runs in, that's the mismatch.
The package went somewhere. Where?
Practice: Installing and checking the tools (5 problems · doesn’t affect your progress)
What is the first thing to run after installing any of the course's tools?
Right on try — credit. Right — the answer had already been shown, so no credit this time. Next try is worth Answer shown after three tries — this one no longer earns credit. You chose to see the answer — this one earns no credit.
A lab mixes several tools; check each one alone first.
A reboot is rarely needed and tells you nothing.
Docker is optional, and unrelated to checking an install.
Why
One version line proves the tool is installed and on the path, and it's what a helper will ask for.
Its version command, such as dotnet --version
Sort each job under the tool this course uses for it.
Right on try — credit. Right — the answer had already been shown, so no credit this time. Next try is worth Answer shown after three tries — this one no longer earns credit. You chose to see the answer — this one earns no credit.
What this task checks
Structure checked automatically. Whether your ideas are convincing isn't graded, so reread with the checklist.
The compiler says
A model answer
Why
C# runs on .NET, quick test clients are Python, TypeScript is checked with Node's tools, and C6 firmware outside Arduino is the Rust track.
Correct answer
Also accepted:
Why
Two projects need paho-mqtt 1.6 and 2.1.0. How can both work on one computer?
Right on try — credit. Right — the answer had already been shown, so no credit this time. Next try is worth Answer shown after three tries — this one no longer earns credit. You chose to see the answer — this one earns no credit.
A global install holds one version at a time.
It would work, but a venv is the simpler, standard answer, and Docker is never required.
Separate venvs solve exactly this.
Why
Each venv has its own package directory, so each project keeps its own pinned version.
Give each project its own virtual environment
mosquitto -h prints mosquitto version 2.1.2 and then a list of options. What has that shown?
Right on try — credit. Right — the answer had already been shown, so no credit this time. Next try is worth Answer shown after three tries — this one no longer earns credit. You chose to see the answer — this one earns no credit.
-h prints help and exits. It starts nothing.
Nothing about the network was tested.
It never opened a port, so it can't tell.
Why
The help text proves the program is installed and names its version. Running it is Chapter 9 §2's job.
Mosquitto is installed and which version it is
A learner on Windows activates .venv and runs python -m pip install "paho-mqtt==2.1.0". Later, in a new terminal, python client.py can't import paho. What did they forget?
Right on try — credit. Right — the answer had already been shown, so no credit this time. Next try is worth Answer shown after three tries — this one no longer earns credit. You chose to see the answer — this one earns no credit.
Mosquitto isn't involved in a Python import.
The pin was fine; the package is in the venv.
Activation is per terminal; a restart doesn't activate anything.
Why
Activation lasts for one terminal session. Each new terminal needs .venv\Scripts\activate again.
To activate the venv in the new terminal
Where this goes next
Mosquitto starts in Chapter 9 §2 and stays running through most of the course. Python with paho-mqtt drives the presence lab in Chapter 9 §6 and becomes the reference service in Chapter 14. Node.js and .NET appear side by side with Python in Chapter 14 §3, and .NET again for gateways in Chapter 16. The Rust target added above is what Chapters 17 and 18 compile for.