Getting Started

Lab 01 — Edge Bootstrapping, Remote Workflow, and Your First Event Producer

Deadlines:

  • End of lab session (GitHub checkpoint): commit & push your progress to your team repository (TAs must have access).
  • Before next lecture (eClass submission): upload (1) a .zip with your code and (2) a PDF export of labs/lab01/README.md.

Submission contents: (1) a .zip with your code, and (2) a PDF export of labs/lab01/README.md.


Note

You will work in teams for the entire semester. Form your team at the start of the lab and keep the same team unless explicitly instructed otherwise.

1. Kit contents and responsibilities

Each team receives a hardware kit that you will use throughout the semester. Treat it as shared lab equipment: keep it complete, keep it labeled, and keep it working. You will be responsible for returning the kit in working condition.

What you receive today

Item Quantity Notes
Transparent storage box 1 For storage and transport
Raspberry Pi 5 1 Edge device for labs
microSD card 1 OS already installed
Female-to-female jumper wires Assorted
PIR motion sensor 1 HC-SR501
microHDMI-to-HDMI cable 1 For initial bootstrap if needed

What you will receive later

Item Quantity Notes
Small plastic wastebin 1 Physical base of your Smart Wastebin

[!WARNING] If anything is missing or damaged, report it immediately. Do not “make do” with incomplete hardware; it will cost you time later.


2. Purpose of Lab 01

This lab is deliberately “workflow heavy” and “hardware light”. Before we read real sensors, we need a reliable way to (a) access the edge device, (b) run code reproducibly, and (c) generate stable, structured data that later components can consume.

By the end of Lab 01 you should be able to:

  1. Bring the Raspberry Pi online and enable SSH (monitor allowed only for initial bootstrap).
  2. Operate the Pi remotely from your laptop (SSH-first workflow).
  3. Create a reproducible Python environment (virtual environment + requirements file).
  4. Implement a small but robust CLI program that produces structured events (JSON Lines).
  5. Learn a bit about proper documentation.
  6. Start working on the Smart Wastebin project.

3. Deliverables (what must be committed)

Your repository will contain the following structure by the end of the lab:

/
├── README.md
├── labs/
│   └── lab01/
│       ├── README.md
│       ├── requirements.txt
│       └── event_generator.py

Minimum deliverables:

  • labs/lab01/event_generator.py (CLI program)
  • labs/lab01/requirements.txt
  • labs/lab01/README.md (your lab report + reproducible instructions + test results)
  • Root README.md with team information

4. Lab report requirements (what you must answer in labs/lab01/README.md)

Your labs/lab01/README.md is both:

  1. a reproducible runbook (how to run your work), and
  2. a short report with answers to questions listed throughout this document.

Where you see Report Question (RQ#), you must include an answer in your lab README.

To keep your README readable, separate the runbook from the report.

Use the following structure inside labs/lab01/README.md:

  • Section A — Runbook (How to run)

    • prerequisite checks (SSH, paths, venv activation)
    • exact commands (copy/paste)
    • expected outputs / how to verify success
  • Section B — Report (Answers to RQs)

    • list RQ1, RQ2, … with short, clear answers
    • include evidence where requested (command outputs, screenshots/snippets)

Do not mix RQ answers into the runbook steps. The runbook should read like instructions for a new team; the report should read like a concise lab submission.


5. Submission on eClass

You must submit on eClass before the next lab:

  1. Code (.zip)
    Include at least:
  • labs/lab01/
  • Root README.md

Do not include:

  • venv/
  • caches (__pycache__, *.pyc)
  • large logs or similar files (unless explicitly asked)
  1. PDF of your Lab 01 README
    Export labs/lab01/README.md to PDF and name it:
  • lab01_REPORT_<team>.pdf

6. Repository commit requirement (end of lab)

Before leaving the lab session, your team must commit and push the current state of your work to your team repository.

Additionally, for every lab you must include the lab TAs in your GitHub repository (as collaborators with access):

Why:

  • It records your in-lab progress (what was completed during the session).
  • It allows us to evaluate progress and collaboration consistently across teams.
  • It reduces last-minute “everything changed at home” submissions.

Minimum expectation:

  • All required deliverables for the lab are tracked by Git.
  • Your latest commit is pushed to GitHub and includes a clear message (e.g., Lab01: setup + event generator + README).

Report Question (RQ0): What is the commit hash of your final “end-of-lab” commit for Lab 01?

Part A — One-time Raspberry Pi bootstrap

A.0 Introduction

Real edge devices are often deployed without a keyboard or monitor. However, initial provisioning still needs a “first contact” step: connecting to the network and enabling remote access. In this course, you may use a monitor/keyboard/mouse only for this initial bootstrap (and if in rare cases direct debugging is needed). After that, we should treat the Pi as headless and operate it remotely.


A.1 Boot, network, and identity

Boot the Raspberry Pi with the provided SD card. Ensure it reaches a usable state and has network access (Ethernet or Wi‑Fi). Identify the hostname and IP address you will use for SSH later.

Suggested commands (on the Pi):

hostname
ip a
ping -c 3 8.8.8.8
ping -c 3 google.com

Report Questions

  • RQ1: What hostname and IP address did you use?
  • RQ2: Did DNS resolution work (ping google.com)? If it failed, what does that imply?
  • RQ3: Was the connection wired or wireless?

A.2 Enable SSH and verify it survives reboot

What SSH is (and why we use it)

SSH (Secure Shell) is the standard protocol for securely logging into and operating a remote machine over a network. In this course, SSH is the primary way you will interact with the Raspberry Pi once it is considered “deployed”. After this step, you should assume that the Pi has no keyboard, mouse, or monitor attached.

What SSH gives you:

  • Remote terminal access: commands you type on your laptop are executed on the Raspberry Pi.
  • Encryption: usernames, passwords, and all traffic are protected from interception on the network.
  • A repeatable operational workflow: the same commands can later be scripted, automated, or executed remotely without physical access.

Mental model to keep in mind:

  • Your laptop is the development workstation.
  • The Raspberry Pi is a remote edge device.
  • SSH is the secure channel that connects them.

Typical SSH command:

ssh <user>@<pi-ip>

Where:

  • <user> is the Linux username on the Raspberry Pi (e.g. pi or a lab-provided user)
  • <pi-ip> is the IP address you identified in Part A.1

The first time you connect, SSH may ask you to confirm a host key fingerprint. This is a security mechanism that prevents man‑in‑the‑middle attacks. If you are confident the IP address is correct and you are on the lab network, you may accept it.


How to enable SSH on Raspberry Pi OS

You are using standard Raspberry Pi OS. Enable SSH using one of the following supported methods (choose one).

Method 1: Graphical interface

  1. On the Raspberry Pi desktop, open: Menu → Preferences → Raspberry Pi Configuration
  2. Go to the Interfaces tab.
  3. Set SSH to Enabled.
  4. Click OK and close the window.

Method 2: Command-line configuration

Open a terminal on the Raspberry Pi and run:

sudo raspi-config

Then:

  1. Select Interface Options
  2. Select SSH
  3. Choose Enable
  4. Exit the tool

You may be asked to reboot. If not, reboot manually once.


Verifying that SSH is active

After enabling SSH, confirm that the SSH service is running:

systemctl status ssh

You should see output indicating that the service is active (running).

Reboot the Raspberry Pi once and repeat the check to confirm that SSH remains enabled after restart.


Report Questions

  • RQ4: Which method did you use to enable SSH (GUI or raspi-config)? List the exact steps.
  • RQ5: What command did you run to verify that SSH is active? Include the relevant output snippet.
  • RQ6: In your own words, why is SSH a necessary tool for managing edge devices after deployment?

Why we do this: physical access does not scale. Once an edge device is installed in a real environment, SSH is often the only practical way to configure, monitor, debug, and update it remotely.


Part B — Remote-first workflow (SSH from laptop)

B.0 Introduction

In the rest of the semester you should assume the Pi is “in the field”. Your development machine is your laptop; the Pi is a remote target.


B.1 SSH from your laptop

From your laptop terminal:

ssh <user>@<pi-ip>

Run:

whoami
uptime

Report Questions

  • RQ6: What SSH command did you use, and which username?
  • RQ7: Did you see a host key prompt the first time? What is that prompt for (in your own words)?
  • RQ8: What does uptime tell you that is relevant for edge systems?

B.2 SSH key authentication

Configure key-based authentication so that SSH does not require a password every time. (You may still keep password login enabled if you prefer, but keys should work.)

Report Questions

  • RQ9: Did you enable SSH keys? describe the steps briefly.
  • RQ10: Why are SSH keys generally preferred over passwords for remote access?

Part C — Baseline smoke test

C.0 Introduction

Edge systems are operational systems. “Observability” begins with basic checks: OS version, disk space, time correctness, and software versions. These are frequent root causes of failures and inconsistent results.

Run and record:

uname -a
cat /etc/os-release
df -h
free -h
date
python3 --version
pip3 --version

Report Questions

  • RQ11: Is system time correct? If not, what could break downstream (give two examples)?
  • RQ12: How much free disk space is available? Why does disk usage matter for logging systems?
  • RQ13: What Python version is installed? Why might the Python version affect reproducibility?

Part D — Git and GitHub basics (you will use this every week)

D.0 Introduction

This course assumes you use git as your engineering “memory”. Every lab and the project will build on previous work; without version control you will lose progress and waste time. If you have never used GitHub, this section tells you exactly what you need for Lab 01.

You will use two separate concepts:

  • git: the tool on your computer (version control)
  • GitHub: a remote hosting service (a shared place to push/pull and collaborate)

From Lab 01 onward:

  • All work must live in your team repository.
  • Your README must be sufficient for someone else to run your work.
  • Your commit history should show meaningful progress (not one giant commit at the end).

D.1 Create the team repository (GitHub)

One member creates a repository on GitHub and grants access to all teammates.

Repository settings (recommended):

  • Private repository
  • Do not add large files (logs, binaries)

Report Questions

  • RQ14: Who created the repository and how did you grant access to teammates (briefly)?
  • RQ15: What would likely go wrong if each team member kept their own local version of the lab/project work?

D.2 Clone, add, commit, push (minimum workflow)

On your laptop (recommended place to edit code), clone the repository:

git clone <repo-url>
cd <repo-folder>

Create the required folders and files (Section 3), then stage and commit:

Remember, your repository must contain the following structure by the end of the lab!

/
├── README.md
├── labs/
│   └── lab01/
│       ├── README.md
│       ├── requirements.txt
│       └── event_generator.py
git status
git add README.md labs/
git commit -m "Lab01: initialize repository structure"
git push

Commit message rule: Write messages that explain what changed and why (not “update” / “stuff”).

Report Questions

  • RQ16: What is the difference between git add and git commit (in your own words)?
  • RQ17: What does git push do, and why is it important in a team setting?

D.3 Pull before you start, push when you finish

Before starting work each day, run:

git pull

When finishing a piece of work:

git status
git add <files>
git commit -m "<meaningful message>"
git push

Report Question

  • RQ18: What problem can happen if two teammates edit the same file without pulling first?

For Lab 01, you may work directly on main, but in general branching is recommended.

Create a branch:

git checkout -b lab01/<shortname>

Push the branch:

git push -u origin lab01/<shortname>

Merge workflow options (choose one and state it):

  • Option A (simple): work on a branch, open a Pull Request on GitHub, merge to main
  • Option B (minimal): branch + merge locally, then push main

If you hit a merge conflict, do not panic: it usually means “two people edited the same lines”. Resolve by choosing the correct final content, then commit the resolution.

Report Questions

  • RQ19: Did your team use branches? If yes, describe your workflow briefly. If no, explain why.
  • RQ20: What is a merge conflict, and when does it happen?

D.5 Authentication notes (tokens vs SSH keys)

Some setups require a GitHub Personal Access Token (PAT) instead of a password when pushing over HTTPS. Another common approach is using SSH for GitHub.

You do not need to describe secrets in your report; just describe which method you used.

Report Question

  • RQ21: Which authentication method did you use to push to GitHub (HTTPS+token, SSH key, other)? Why?

D.6 .gitignore policy

Add a .gitignore that at minimum ignores:

  • venv/
  • __pycache__/
  • *.pyc
  • local logs (*.log)

Report Questions

  • RQ22: Why should virtual environments not be committed to git?
  • RQ23: Why is it usually not acceptable to commit logs?

Part E — Reproducible Python environment on the Pi

E.0 Introduction

A reproducible environment is a prerequisite for reliable systems. In edge deployments you often cannot “just install random things until it works”. You define the environment once and rebuild it reliably.


E.1 Clone the repository on the Pi

From SSH, clone your team repo onto the Pi and cd to labs/lab01.

Report Questions

  • RQ24: Where on the Pi did you clone the repo (path)? Why did you choose that location?

E.2 Create and validate a virtual environment

What a virtual environment is (and why we require it)

A Python virtual environment (often called a venv) is an isolated Python installation for a specific project or lab. It has its own:

  • Python packages (dependencies)
  • pip install state
  • executable path

It does not change the system Python for the whole Raspberry Pi.

In this course, using a venv is mandatory because:

  • installing packages “globally” on the Pi quickly becomes messy and hard to reproduce
  • you must be able to rebuild your environment from scratch using only the repository

A good mental model:

  • system Python = “the operating system’s Python” (shared by everything)
  • venv Python = “this lab’s Python” (controlled, reproducible)

Create the venv (inside labs/lab01)

From the labs/lab01 directory on the Raspberry Pi, run:

python3 -m venv venv

This creates a folder named venv/ that contains the isolated environment.


Enable (activate) the venv

To use the venv, you must activate it in your current terminal session:

source venv/bin/activate

After activation, your terminal prompt typically changes (often showing (venv)), and commands like python and pip will refer to the venv versions, not the system ones.

Important: activation is per-terminal-session. If you open a new SSH session or a new terminal, you must activate again. Important: never push your venv


Validate you are using the venv

Run the following checks:

which python
python --version
python -c "import sys; print(sys.executable)"

Expected result:

  • which python and sys.executable should point inside your .../labs/lab01/venv/... directory.

Report Questions

  • RQ25: What did sys.executable show, and how does that prove you are using the venv?
  • RQ26: In one paragraph: what problem does a venv solve?

E.3 Dependencies (requirements.txt)

What requirements.txt is (and why we use it)

A requirements.txt file is a declaration of dependencies required to run your code. It allows someone else (or you, on a clean machine) to recreate the same environment by running a single command.

Why it matters:

  • managing dependencies explicitly prevents “works on my Pi” problems

Create requirements.txt

Create labs/lab01/requirements.txt. For this lab you may choose:

  • click (recommended) if you want a structured CLI library, or
  • standard library argparse only

Example requirements.txt:

click==8.1.7

(Exact version pinning is recommended once you know what works reliably for your lab.)


Install dependencies into the venv (make sure it is activated)

Before installing, confirm your venv is active:

which python

Install:

pip install -r requirements.txt

Verify:

pip show click   # if you used click
pip list

Report Questions

  • RQ27: What dependencies did you include and why? If you use argaprse do you need to include the requirements.txt, if not why?
  • RQ28: What would happen if different teams used different dependency versions?
  • RQ29: How can you verify you installed packages into the venv (not the system Python)? Give one command and explain what you look for.

Part F — Programming exercise: High-level “smart wastebin” mock event generator (CLI)

F.0 Introduction

A finished “smart wastebin” would ideally provide high-level events that are immediately useful to an application (for example: “a deposit happened” or “the bin was used five times today”). Such events are easy to understand, easy to log, and easy to consume by dashboards or automation systems.

In practice, real systems rarely start with perfect high-level signals. They start from low-level, noisy inputs and progressively build higher-level meaning in software. We will move in that direction in later labs.

For Lab 01, however, we deliberately start from the idealized output. You will implement a mock wastebin event source that generates the kind of events one might wish to get directly from a smart wastebin.

No real sensors are involved yet, and no assumptions about hardware behavior are required.


F.1 Implement event_generator.py

File: labs/lab01/event_generator.py

Your tool must run like:

python event_generator.py \
  --device-id wastebin-01 \
  --event-type deposit \
  --count 10 \
  --interval 2 \
  --out events.log

You may use click or argparse, but you must implement a real CLI parser (do not parse sys.argv manually).

Report Questions

  • RQ29: Why it might be useful to start with a mock event generator instead of connecting real hardware immediately?
  • RQ30: What aspects of the system can you test with this mock that are independent of sensors?

F.2 Event types in this lab (conceptual meaning)

In this lab, --event-type selects the kind of high-level wastebin event you want to simulate. These event types represent expected outputs of a future smart wastebin, not raw sensor signals.

You must support at least the following:

1) deposit (required)

Represents a waste deposit: something was thrown into the bin. Each deposit event corresponds to a single usage of the wastebin.

Conceptually, a deposit answers the question:

“Did the wastebin just get used?”

2) heartbeat (required)

Represents a liveness signal from the device. A heartbeat does not represent user activity; it only indicates that the system is running and capable of producing events.

Conceptually, a heartbeat answers the question:

“Is the wastebin online and functioning?”

Optional (not required, but allowed if you wish):

  • lid_open
  • lid_close
  • maintenance (e.g. bin emptied)

Expected behavior: once an event type is selected, the generator emits only that type for the duration of the run.

Report Questions

  • RQ31: Why is it useful to distinguish between “activity” events (like deposit) and “liveness” events (like heartbeat)?
  • RQ32: Give one example of how a system might misbehave if heartbeats were missing.

F.3 CLI parameters (requirements)

Required parameters

  • --device-id (string): identifies the (mock) wastebin device producing events
  • --event-type (string): deposit or heartbeat
  • --count (int, > 0): number of records to emit
  • --interval (float/int, >= 0): seconds between emissions
  • --out (path): output file path (append mode)
  • --starting-total (int, default 0): initial total count used for deposits
  • --verbose (flag): enable periodic operational output

If you add optional parameters, document them clearly in your lab README.

Report Questions

  • RQ33: Which optional parameters (if any) did you add, and why?
  • RQ34: Why is it important that invalid CLI arguments fail early and clearly?

F.4 Output format (JSON Lines)

Each record must be written as one JSON object per line (JSONL). The file must be appended to (not overwritten).

Fields required in every record

  • event_time (ISO-8601 UTC, e.g. 2026-02-10T12:34:56.789Z)
  • ingest_time (ISO-8601 UTC)
  • device_id (string)
  • event_type (string)
  • seq (integer; starts at 1 and increments by 1)
  • run_id (string; unique per execution)

Fields required for event_type == "deposit"

  • deposit_delta (integer, must be 1)
  • deposit_total (integer, monotonically increasing)

Fields required for event_type == "heartbeat"

  • status (string, must be "online")

Report Questions

  • RQ35: Why is JSON Lines a good fit for append-only event logs?
  • RQ36: Why is it useful to include both seq and timestamps in each record?
  • RQ37: Why should deposit_total be monotonically increasing within a run?

F.5 What “correct output” means

Your output is considered correct if:

  1. Each line is valid JSON and stands alone.
  2. All required fields are present.
  3. seq increases by exactly 1 per record.
  4. For deposits, deposit_total increases by exactly 1 per event.
  5. Timestamps are valid UTC timestamps.
  6. Multiple runs append cleanly to the same file.

Report Question

  • RQ38: Which of the above correctness rules would be hardest to verify manually, and why?

F.6 Operational logging vs event logs

Event logs (events.log) are data. They must contain only JSON records.

Operational logs are for humans. If --verbose is enabled, print a short line every 5 records, such as:

generated seq=5 type=deposit out=events.log

Report Questions

  • RQ39: What problems arise if operational messages are mixed into event logs?
  • RQ40: Why might operational logs still be essential during debugging?

F.7 Strict error handling and exit codes

Your program must:

  • Exit with code 2 for CLI/usage errors
  • Exit with code 1 for runtime errors (e.g. file I/O)
  • Print errors to stderr
  • Reject invalid arguments (count <= 0, interval < 0, unknown event_type)

Report Questions

  • RQ41: Why is it important to distinguish usage errors from runtime errors?
  • RQ42: How could consistent exit codes be useful in automated systems?

F.8 Safe shutdown (Ctrl-C)

If interrupted:

  • stop gracefully
  • print a final message indicating how many records were written

Report Questions

  • RQ43: What could go wrong if a program is terminated without handling interrupts properly?

Part G — Mini-tests (must be included in your README)

G.0 Introduction

Testing is part of the deliverable. These tests demonstrate that your mock generator is reliable and predictable.


G.1 Required tests

Test 1 — Deposit stream

python event_generator.py --device-id wastebin-01 --event-type deposit --count 5 --interval 0.2 --out events.log

Report Questions

  • RQ44: Show the first and last JSON record produced by this test and explain how the counters changed.

Test 2 — Heartbeat stream

python event_generator.py --device-id wastebin-01 --event-type heartbeat --count 3 --interval 0.5 --out events.log

Report Questions

  • RQ45: How can a consumer distinguish heartbeat records from deposit records in the log?

Test 3 — Invalid arguments

Run at least two invalid commands.

Report Questions

  • RQ46: For each invalid command, show the error message and exit code.
  • RQ47: Which invalid input do you think is most likely in real usage, and why?

Test 4 — Ctrl-C behavior

Interrupt a long-running command.

Report Questions

  • RQ48: How many records were written before interruption?

Part H — Reproducibility drill (using an intentionally bad README)

H.0 Introduction

A system is not finished when it works once. It is finished when someone else can run it reliably using only the documentation. In practice, most failures are not “hard bugs” but they are missing assumptions, ambiguous steps, unstated prerequisites, and documentation that only works for the author.

For Lab 01, you will not read or run another team’s README. Instead, we will give you an intentionally bad README. Your job is to analyze it critically and extract lessons about reproducibility and documentation quality.


H.1 Task

For the reproducibility exercise, use the intentionally incomplete/ambiguous README from here:

Your tasks:

  1. Read the bad README carefully.
  2. Identify concrete problems that would prevent a new team from reproducing the setup and running the program.
  3. Propose specific improvements (what to add, remove, or rewrite).
  4. Apply the same thinking to your own Lab 01 README and improve it.

You are not required to execute the bad README instructions. This is a documentation review exercise.


H.2 What to look for (checklist)

When reviewing the bad README, consider whether it answers the following, clearly and unambiguously:

  • Prerequisites: What must already be installed or configured (SSH enabled, network access, Python version, etc.)?
  • Exact commands: Are the commands complete and copy‑pasteable?
  • Paths and locations: Does it say where to run commands (laptop vs Pi, which folder)?
  • Environment activation: Does it mention activating the venv before running/installing?
  • Expected outputs: Does it show what “success” looks like (example output, file created, number of lines)?
  • Error cases: Does it mention common failures and what to do?
  • Assumptions: Does it assume knowledge like “you know the IP” or “you already have permissions”?
  • Order of steps: Is the sequence correct, or are steps missing?
  • Reproducibility: Could a different team on a different Pi reproduce it without guessing?

H.3 Report Questions

  • RQ48: List at least five concrete problems in the bad README that would block or confuse a new team. Be specific (quote or reference the problematic line/section).
  • RQ49: For three of those problems, rewrite the relevant README lines/sections as you think they should be written (improved version).
  • RQ50: List improvements (if any) you made to your own labs/lab01/README.md as a result of this exercise, and explain why each improvement matters for reproducibility.

Project hint (Smart Wastebin)

Your project runs in parallel with the labs. The goal is to avoid “starting the project at the end”.

In Lab 01, you are not building project functionality yet. Instead, you are setting up everything that makes project development possible later. By completing this lab, you have already established the core foundations of a team-based project:

  • a shared GitHub repository
  • a repository README that describes what the project is
  • a working development environment on the Raspberry Pi
  • a common workflow for collaborating, running code, and documenting work

Even though there is no project code yet, the Smart Wastebin project already exists in a meaningful way: it has a place in the repository, a description, and a team that can reliably develop and run software on the target device.

As the semester progresses, the labs will gradually contribute pieces that can become part of the project. The setup you completed today ensures that those pieces can be integrated incrementally, rather than rushed together at the end.

For now, keep this perspective in mind: what you built in each Lab is the groundwork for developing the Smart Wastebin as a real system, one step at a time.

Final checklist

To make sure you have finished, confirm:

  • SSH works reliably from at least one team laptop
  • Repo structure matches the required layout
  • Git workflow understood: clone, add, commit, push; pull before working
  • requirements.txt exists and installs in a fresh venv
  • event_generator.py meets the CLI + JSONL requirements
  • Tests (happy path + invalid args + Ctrl‑C) are documented with exit codes
  • Reproducibility drill completed and documented
  • eClass package prepared: .zip + lab01_README_<team>.pdf