Lab 01 — Getting Started: Repositories, Environments, and First Tools
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
.zipwith your code and (2) a PDF export oflabs/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.
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.
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:
- Bring the Raspberry Pi online and enable SSH (monitor allowed only for initial bootstrap).
- Operate the Pi remotely from your laptop (SSH-first workflow).
- Create a reproducible Python environment (virtual environment + requirements file).
- Implement a small but robust CLI program that produces structured events (JSON Lines).
- Learn a bit about proper documentation.
- Start working on the Smart Wastebin project.
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.
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.
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.pior 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
- On the Raspberry Pi desktop, open: Menu → Preferences → Raspberry Pi Configuration
- Go to the Interfaces tab.
- Set SSH to Enabled.
- Click OK and close the window.
Method 2: Command-line configuration
Open a terminal on the Raspberry Pi and run:
sudo raspi-config
Then:
- Select Interface Options
- Select SSH
- Choose Enable
- 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
- RQ7: What SSH command did you use, and which username?
- RQ8: Did you see a host key prompt the first time? What is that prompt for (in your own words)?
- RQ9: What does
uptimetell 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
- RQ10: Did you enable SSH keys? describe the steps briefly.
- RQ11: Why are SSH keys generally preferred over passwords for remote access?
[!NOTE] It is okay if you did not set up SSH key authentication for connecting to the Raspberry Pi. On some operating systems, the setup is a bit more involved than running a single command. For this lab, it is enough that you: understand the difference between password-based and key-based authentication, and can successfully connect via SSH.
Part C — Baseline smoke test
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
- RQ12: Is system time correct? If not, what could break downstream (give two examples)?
- RQ13: How much free disk space is available? Why does disk usage matter for logging systems?
- RQ14: 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
- RQ15: Who created the repository and how did you grant access to teammates (briefly)?
- RQ16: 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
- RQ17: What is the difference between
git addandgit commit(in your own words)? - RQ18: What does
git pushdo, 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
- RQ19: Can you think what problem can happen if two teammates edit the same file without pulling first?
D.4 Branching (recommended) and conflict awareness
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
- RQ20: Did your team use branches? If yes, describe your workflow briefly. If no, explain why.
- RQ21: 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
- RQ22: Which authentication method did you use to push to GitHub (HTTPS+token, SSH key, other)? Why?
D.6 .gitignore policy
A .gitignore file tells Git which files and folders it should not track or commit. This is used for generated files, local-only artifacts, and machine-specific content that should not be stored in the repository.
Add a .gitignore that at minimum ignores:
venv/__pycache__/*.pyc- local logs (
*.log)
Example .gitignore:
# Python virtual environment
venv/
# Python bytecode / cache
__pycache__/
*.pyc
# Local log files
*.log
Report Questions
- RQ23: Why should virtual environments not be committed to git?
- RQ24: 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
clone your team repo onto the Pi (if not already there) and cd to labs/lab01.
Report Questions
- RQ25: 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)
pipinstall state- executable path
It does not change the system Python for the whole Raspberry Pi.
In this course, using a venv is recommended 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 pythonandsys.executableshould point inside your.../labs/lab01/venv/...directory.
Report Questions
- RQ26: What did
sys.executableshow, and how does that prove you are using the venv? - RQ27: 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
argparseonly
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
- RQ28: What dependencies did you include and why? If you use argaprse do you need to include the requirements.txt, if not why?
- RQ29: What would happen if different teams used different dependency versions?
- RQ30: How can you verify you installed packages into the venv (not the system Python)? Give one command and explain what you look for.
F.0 Introduction
In a real smart wastebin system, the device would not usually start by producing clean, application-ready events. Real systems typically begin with lower-level signals (for example, noisy sensor readings), and software is then used to infer higher-level meaning.
For this lab, we are intentionally not starting from raw sensors.
Instead, you will build a mock event generator that produces the kind of high-level events an application would ideally like to receive, such as:
- “a deposit happened”
- “the device is online”
- “the total number of deposits is now 42”
This lets you focus on core software engineering concerns first:
- CLI design
- validation and error handling
- file output format
- append-only logging
- record sequencing
- timestamping
- clean shutdown behavior
In later labs, we will move “down the stack” and work from lower-level inputs toward these same high-level events.
No real sensors are involved in this lab.
F.1 What you will build
You will implement a command-line tool named event_generator.py that simulates a wastebin device by writing JSON Lines (JSONL) event records to an output file.
File: labs/lab01/event_generator.py
The program should emit a configurable number of events at a configurable interval and append them to a log file.
This is a mock producer: its purpose is to generate realistic event data so that other parts of a system can be tested before hardware is connected.
F.2 Event types in this lab (conceptual meaning)
In this lab, --event-type selects the kind of high-level wastebin event to simulate.
These are not raw sensor signals. They represent the kind of interpreted outputs a future smart wastebin service might produce after processing lower-level inputs.
You must support at least the following event types:
1) deposit (required)
Represents a waste deposit: something was thrown into the bin.
Each deposit event corresponds to one usage of the wastebin.
Conceptually, this answers:
“Did the wastebin just get used?”
2) heartbeat (required)
Represents a liveness signal from the device.
A heartbeat is not user activity. It simply indicates that the device/software is running and able to emit events.
Conceptually, this answers:
“Is the wastebin online and functioning?”
Optional (not required, but allowed if you wish):
lid_openlid_closemaintenance(for example, bin emptied)
Expected behavior:
- The user selects one event type using
--event-type. - The generator emits only that event type for the duration of that run.
F.3 CLI requirements
Your program must expose a real CLI parser using either:
argparse, orclick
Do not parse sys.argv manually.
Your tool must run like this:
python event_generator.py \
--device-id wastebin-01 \
--event-type deposit \
--count 10 \
--interval 2 \
--out events.log
Required parameters
--device-id(string): identifies the mock wastebin device producing events--event-type(string):depositorheartbeat--count(int,> 0): number of records to emit--interval(float/int,>= 0): seconds between emissions--out(path): output file path (append mode)
Optional parameters
--starting-total(int, default0): initial total count used for deposits--verbose(flag): enable periodic operational output
If you add optional parameters, document them clearly in your lab README.
F.4 Output format (JSON Lines)
The output file is an append-only event log.
Each emitted event must be written as:
- one JSON object
- on its own line
- in JSON Lines (JSONL) format
The file must be opened in append mode (do not overwrite existing contents).
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)
Additional fields for event_type == "deposit"
deposit_delta(integer, must be1)deposit_total(integer, monotonically increasing)
Additional fields for event_type == "heartbeat"
status(string, must be"online")
F.5 Correctness criteria
Your output is considered correct if all of the following are true:
- Each line is valid JSON and can be parsed independently.
- All required fields are present.
seqincreases by exactly 1 for each emitted record.- For
depositevents,deposit_totalincreases by exactly 1 per record. - Timestamps are valid UTC timestamps.
- Multiple runs append cleanly to the same file.
F.6 Operational logging vs event logs
Keep these two outputs separate:
- Event log (
events.log): machine-readable data (JSONL only) - Operational output (
stdout/stderr): human-readable status and error messages
The event log must contain only JSON event records.
If --verbose is enabled, print a short operational message every 5 records, for example:
generated seq=5 type=deposit out=events.log
Do not write operational messages into the JSONL file.
F.7 Strict error handling and exit codes
Your program must enforce clear validation and use consistent exit codes.
Required behavior
- Exit with code 2 for CLI/usage errors
- Exit with code 1 for runtime errors (for example, file I/O failures)
- Print errors to
stderr - Reject invalid arguments:
count <= 0interval < 0- unknown
event_type
F.8 Safe shutdown (Ctrl-C)
If the program is interrupted (Ctrl-C), it must shut down gracefully.
Required behavior:
- stop emitting new records
- close resources cleanly
- print a final message indicating how many records were successfully written
This makes the tool safer to run interactively and easier to debug.
F.9 Implementation hints
These are small patterns you may reuse in your implementation.
1) Append one JSON record to a JSONL file
import json
record = {
"event_type": "deposit",
"seq": 1,
"deposit_delta": 1,
"deposit_total": 1
}
# "a" = append mode (do not overwrite existing file)
with open("events.log", "a", encoding="utf-8") as f:
f.write(json.dumps(record) + "\n") # one JSON object per line
Important:
- Use
"a"(append mode), not"w"(overwrite mode). - JSON Lines requires exactly one JSON object per line, so include
"\n".
2) Create UTC timestamps in ISO-8601 format (...Z)
from datetime import datetime, timezone
def utc_now_iso() -> str:
# Example: 2026-02-10T12:34:56.789Z
return (
datetime.now(timezone.utc)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z")
)
You can call this for both:
event_timeingest_time
(They may be very close in value, but both should be present.)
3) Generate a unique run_id for each execution
import uuid
run_id = str(uuid.uuid4())
This lets you distinguish records from different runs, even when they are appended to the same file.
4) Print errors to stderr and use exit codes
import sys
print("Error: invalid --count (must be > 0)", file=sys.stderr)
raise SystemExit(2) # CLI/usage error
Use:
- exit code
2for invalid CLI arguments / usage problems - exit code
1for runtime failures (e.g., file write errors)
5) Periodic verbose logging (every 5 records)
if verbose and seq % 5 == 0:
print(f"generated seq={seq} type={event_type} out={out_path}")
This is operational output for humans. Do not write it into the JSONL event file.
6) Graceful Ctrl-C handling (safe shutdown)
written = 0
try:
for seq in range(1, count + 1):
# build record
# append record to file
written += 1
# sleep between records (if interval > 0)
except KeyboardInterrupt:
print(f"\nInterrupted. Wrote {written} record(s).")
This ensures the program exits cleanly and reports progress if the user stops it early.
7) Deposit totals with --starting-total
deposit_total = starting_total
for seq in range(1, count + 1):
if event_type == "deposit":
deposit_total += 1
record = {
"seq": seq,
"event_type": "deposit",
"deposit_delta": 1,
"deposit_total": deposit_total,
}
8) CLI validation example (argparse style)
if args.count <= 0:
print("Error: --count must be > 0", file=sys.stderr)
raise SystemExit(2)
if args.interval < 0:
print("Error: --interval must be >= 0", file=sys.stderr)
raise SystemExit(2)
if args.event_type not in {"deposit", "heartbeat"}:
print("Error: --event-type must be 'deposit' or 'heartbeat'", file=sys.stderr)
raise SystemExit(2)
Report Questions (Part F)
F.1 / F.2 Concept and event modeling
- RQ31: Why might it be useful to start with a mock event generator instead of connecting real hardware immediately?
- RQ32: What aspects of the system can you test with this mock that are independent of sensors?
- RQ33: Why is it useful to distinguish between “activity” events (like
deposit) and “liveness” events (likeheartbeat)? - RQ34: Give one example of how a system might misbehave if heartbeats were missing.
F.3 CLI design and validation
- RQ35: Which optional parameters (if any) did you add, and why?
- RQ36: Why is it important that invalid CLI arguments fail early and clearly?
F.4 / F.5 Data format and correctness
- RQ37: Why is JSON Lines a good fit for append-only event logs?
- RQ38: Why is it useful to include both
seqand timestamps in each record? - RQ39: Why should
deposit_totalbe monotonically increasing within a run? - RQ40: Which of the above correctness rules would be hardest to verify manually, and why?
F.6 Operations and observability
- RQ41: What problems arise if operational messages are mixed into event logs?
- RQ42: Why might operational logs still be essential during debugging?
F.7 / F.8 Reliability and execution behavior
- RQ43: Why is it important to distinguish usage errors from runtime errors?
- RQ44: How could consistent exit codes be useful in automated systems?
- RQ45: What could go wrong if a program is terminated without handling interrupts properly?
Part G — Mini-tests
G.0 Introduction
Testing is part of the deliverable. These mini-tests demonstrate that your mock generator behaves correctly, handles errors predictably, and produces valid append-only event logs.
Use a fresh output file (or separate output files per test) when you need to inspect results clearly.
G.1 Required tests
Test 1 — Deposit stream
Run:
python event_generator.py --device-id wastebin-01 --event-type deposit --count 5 --interval 0.2 --out events.log
What to verify:
- 5 new JSONL records were appended
- all records have
event_type == "deposit" seqincrements by 1deposit_delta == 1in each recorddeposit_totalincreases by 1 each time
Report Questions
- RQ46: Show the first and last JSON record produced by this test and explain how the counters changed.
Test 2 — Heartbeat stream
Run:
python event_generator.py --device-id wastebin-01 --event-type heartbeat --count 3 --interval 0.5 --out events.log
What to verify:
- 3 new JSONL records were appended
- all records have
event_type == "heartbeat" - each heartbeat record includes
status == "online" - no
deposit_*fields appear in heartbeat records
Report Questions
- RQ47: How can a consumer distinguish heartbeat records from deposit records in the log?
Test 3 — Invalid arguments
Run at least two invalid commands (for example: invalid --event-type, --count 0, or negative --interval).
What to verify:
- program prints an error to
stderr - program exits with code
2 - no invalid records are appended to the event log
Report Questions
- RQ48: For each invalid command, show the error message and exit code.
- RQ49: Which invalid input do you think is most likely in real usage, and why?
Test 4 — Ctrl-C behavior
Run a longer command (for example, --count 100 with a nonzero interval), then interrupt it with Ctrl-C.
What to verify:
- program stops cleanly
- program prints a final summary message
- only fully written JSONL records exist in the file (no broken partial line)
Report Questions
- RQ50: 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:
- Read the bad README carefully.
- Identify concrete problems that would prevent a new team from reproducing the setup and running the program.
- Propose specific improvements (what to add, remove, or rewrite).
- 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
- RQ51: 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).
- RQ52: List improvements (if any) you made to your own
labs/lab01/README.mdas 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.txtexists and installs in a fresh venv -
event_generator.pymeets 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
Deliverables and Submission
What must exist in the repository (by end of lab)
Your repository must contain at least:
/
├── README.md
├── labs/
│ └── lab01/
│ ├── README.md
│ ├── requirements.txt
│ └── event_generator.py
Required files:
labs/lab01/event_generator.py— CLI programlabs/lab01/requirements.txtlabs/lab01/README.md— runbook + report + test results- Root
README.md— team information (members, etc.)
What labs/lab01/README.md must contain
Your labs/lab01/README.md must contain two clearly separated parts:
Section A — Runbook (How to run your code)
Include:
- environment setup / activation (
venv) - dependency installation
- exact commands (copy/paste)
- expected outputs
Section B — Report (Answers to RQs)
Include:
- answers to all Report Questions (RQ#)
- short, clear responses
- evidence where requested (command output, snippets, screenshots)
Important:
- Do not mix report answers into the runbook steps.
- The runbook should read like instructions.
- The report should read like a submission.
Submission deadlines
1) End of lab session — GitHub checkpoint (required)
Before leaving the lab:
- commit your progress
- push to your team GitHub repository
- ensure TAs have access
TA GitHub accounts (must be added as collaborators):
Minimum expectation for the GitHub checkpoint:
- all required deliverables are tracked by Git
- latest commit is pushed
- commit message is clear (example:
Lab01: setup + event generator + README)
RQ0 (end of lab): What is the commit hash of your final end-of-lab commit for Lab 01?
2) Before next lab (eClass submission + git submission)
Submit both of the following on eClass:
- Code archive (
.zip) - PDF export of
labs/lab01/README.md
Required PDF filename format:
lab01_REPORT_<team>.pdf
Don’t forget to also submit on your Github Repo.
- Push/submit a final version on GitHub
What to include in the .zip
Include at least:
labs/lab01/(entire folder)- Root
README.md
Do not include:
venv/__pycache__/*.pyc- large logs or temporary files (unless explicitly requested)
What follows is a greek version of the same lab
Εργαστήριο 01 — Αρχικοποίηση Edge συσκευής, απομακρυσμένο workflow και ο πρώτος σας παραγωγός συμβάντων
Προθεσμίες:
- Τέλος εργαστηρίου (GitHub checkpoint): commit & push την πρόοδό σας στο αποθετήριο της ομάδας (οι βοηθοί πρέπει να έχουν πρόσβαση).
- Πριν την επόμενη διάλεξη (eClass): υποβάλετε (1) ένα
.zipμε τον κώδικα και (2) PDF export τουlabs/lab01/README.md.
Περιεχόμενα υποβολής: (1) .zip με τον κώδικα και (2) PDF export του labs/lab01/README.md.
Σημείωση
Θα εργαστείτε σε ομάδες όλο το εξάμηνο. Φτιάξτε την ομάδα σας στην αρχή του εργαστηρίου και κρατήστε την ίδια εκτός αν σας δοθεί ρητή οδηγία.
Μέρος A — Εφάπαξ αρχικό bootstrap Raspberry Pi
A.0 Εισαγωγή
Οι πραγματικές edge συσκευές συχνά εγκαθίστανται χωρίς οθόνη/πληκτρολόγιο. Παρ’ όλα αυτά, η αρχική παραμετροποίηση απαιτεί ένα πρώτο βήμα: σύνδεση στο δίκτυο και ενεργοποίηση απομακρυσμένης πρόσβασης. Σε αυτό το μάθημα μπορείτε να χρησιμοποιήσετε οθόνη/πληκτρολόγιο/ποντίκι μόνο για αυτό το αρχικό bootstrap (και σπάνια για άμεσο debugging). Μετά από αυτό, το Pi θεωρείται headless και το χειριζόμαστε απομακρυσμένα.
Το lab είναι σκόπιμα «βαρύ» σε workflow και «ελαφρύ» σε hardware. Πριν συνδέσουμε αισθητήρες, χρειαζόμαστε αξιόπιστο τρόπο για να (α) προσπελάζουμε την edge συσκευή, (β) τρέχουμε κώδικα αναπαραγώγιμα και (γ) παράγουμε σταθερά, δομημένα δεδομένα που θα χρησιμοποιήσουν επόμενα μέρη του συστήματος.
Μέχρι το τέλος του Lab 01 θα πρέπει να μπορείτε να:
- Βάλετε το Raspberry Pi online και να ενεργοποιήσετε SSH.
- Το χειρίζεστε απομακρυσμένα από το laptop (SSH-first workflow).
- Δημιουργείτε αναπαραγώγιμο Python περιβάλλον (venv + requirements).
- Υλοποιείτε μικρό αλλά αξιόπιστο CLI που παράγει δομημένα συμβάντα (JSON Lines).
- Εξασκηθείτε σε σωστή τεκμηρίωση.
- Ξεκινήσετε το project Smart Wastebin.
Κάθε ομάδα λαμβάνει hardware kit για όλο το εξάμηνο. Αντιμετωπίστε το ως κοινό εργαστηριακό εξοπλισμό: πλήρες, με ετικέτα, λειτουργικό. Θα το επιστρέψετε σε λειτουργική κατάσταση.
Τι παραλαμβάνετε σήμερα
| Αντικείμενο | Ποσότητα | Σημειώσεις |
|---|---|---|
| Διαφανές κουτί αποθήκευσης | 1 | Για αποθήκευση/μεταφορά |
| Raspberry Pi 5 | 1 | Edge συσκευή |
| microSD card | 1 | Το OS είναι ήδη εγκατεστημένο |
| Jumper wires θηλυκό-σε-θηλυκό | — | Διάφορα |
| PIR motion sensor | 1 | HC-SR501 |
| microHDMI-to-HDMI καλώδιο | 1 | Για αρχικό bootstrap αν χρειαστεί |
Τι θα παραλάβετε αργότερα
| Αντικείμενο | Ποσότητα | Σημειώσεις |
|---|---|---|
| Μικρός πλαστικός κάδος | 1 | Φυσική βάση του Smart Wastebin |
[!WARNING] Αν κάτι λείπει ή είναι χαλασμένο, αναφέρετέ το άμεσα. Μην «βολεύεστε» με ελλιπές hardware.
A.1 Εκκίνηση, δίκτυο και ταυτότητα
Εκκινήστε το Raspberry Pi με την SD κάρτα. Βεβαιωθείτε ότι φτάνει σε λειτουργική κατάσταση και έχει δικτυακή πρόσβαση (Ethernet ή Wi‑Fi). Βρείτε το hostname και την IP που θα χρησιμοποιήσετε για SSH.
Προτεινόμενες εντολές (στο Pi):
hostname
ip a
ping -c 3 8.8.8.8
ping -c 3 google.com
Ερωτήσεις Αναφοράς
- RQ1: Ποιο hostname και ποια IP χρησιμοποιήσατε;
- RQ2: Δούλεψε το DNS (
ping google.com); Αν όχι, τι υποδηλώνει; - RQ3: Η σύνδεση ήταν ενσύρματη ή ασύρματη;
A.2 Ενεργοποίηση SSH και έλεγχος μετά από reboot
Τι είναι SSH (και γιατί το χρησιμοποιούμε)
Το SSH (Secure Shell) είναι το βασικό πρωτόκολλο για ασφαλή σύνδεση σε απομακρυσμένο μηχάνημα μέσω δικτύου. Στο μάθημα αυτό είναι ο βασικός τρόπος αλληλεπίδρασης με το Raspberry Pi αφού θεωρηθεί «ανεπτυγμένο». Μετά από αυτό το βήμα, υποθέστε ότι το Pi δεν έχει οθόνη/πληκτρολόγιο/ποντίκι.
Το SSH προσφέρει:
- Απομακρυσμένο τερματικό: οι εντολές από το laptop εκτελούνται στο Pi.
- Κρυπτογράφηση: usernames/passwords και κίνηση δικτύου προστατεύονται.
- Επαναλήψιμο workflow: οι ίδιες εντολές μπορούν να γίνουν scripts/automation.
Νοητικό μοντέλο:
- Laptop = σταθμός ανάπτυξης
- Raspberry Pi = edge συσκευή
- SSH = ασφαλές κανάλι σύνδεσης
Τυπική εντολή:
ssh <user>@<pi-ip>
Την πρώτη φορά μπορεί να εμφανιστεί prompt για host key fingerprint (μηχανισμός προστασίας από man-in-the-middle).
Ενεργοποίηση SSH στο Raspberry Pi OS
Χρησιμοποιείτε τυπικό Raspberry Pi OS. Ενεργοποιήστε SSH με έναν από τους παρακάτω τρόπους.
Μέθοδος 1: GUI
- Menu → Preferences → Raspberry Pi Configuration
- Καρτέλα Interfaces
- Θέστε SSH σε Enabled
- OK
Μέθοδος 2: Γραμμή εντολών
sudo raspi-config
Έπειτα:
- Interface Options
- SSH
- Enable
- Έξοδος από το εργαλείο
Κάντε reboot αν ζητηθεί (ή χειροκίνητα).
Επαλήθευση ότι το SSH είναι ενεργό
systemctl status ssh
Πρέπει να δείτε active (running). Κάντε reboot και επαναλάβετε τον έλεγχο.
Ερωτήσεις Αναφοράς
- RQ4: Ποια μέθοδο χρησιμοποιήσατε (GUI ή
raspi-config); Γράψτε ακριβή βήματα. - RQ5: Ποια εντολή χρησιμοποιήσατε για επαλήθευση και ποιο σχετικό output είδατε;
- RQ6: Γιατί είναι απαραίτητο το SSH για edge συσκευές μετά την ανάπτυξη;
Μέρος B — Remote-first workflow (SSH από laptop)
B.0 Εισαγωγή
Για το υπόλοιπο του εξαμήνου, θεωρήστε ότι το Pi είναι «στο πεδίο». Το laptop είναι το development machine και το Pi ο απομακρυσμένος στόχος.
B.1 SSH από το laptop
ssh <user>@<pi-ip>
whoami
uptime
Ερωτήσεις Αναφοράς
- RQ7: Ποια εντολή SSH και ποιο username χρησιμοποιήσατε;
- RQ8: Εμφανίστηκε host key prompt; Τι εξυπηρετεί;
- RQ9: Τι χρήσιμο δείχνει το
uptimeγια edge συστήματα;
B.2 SSH key authentication
Ρυθμίστε key-based authentication ώστε να μη χρειάζεται password κάθε φορά (μπορείτε να κρατήσετε και password login αν θέλετε).
Ερωτήσεις Αναφοράς
- RQ10: Ενεργοποιήσατε SSH keys; Περιγράψτε συνοπτικά τα βήματα.
- RQ11: Γιατί προτιμώνται τα SSH keys αντί για passwords;
[!NOTE] Είναι αποδεκτό αν δεν ολοκληρώσατε key authentication, αρκεί να κατανοείτε τη διαφορά και να μπορείτε να συνδεθείτε με SSH.
Μέρος C — Βασικό smoke test
Εκτελέστε και καταγράψτε:
uname -a
cat /etc/os-release
df -h
free -h
date
python3 --version
pip3 --version
Ερωτήσεις Αναφοράς
- RQ12: Είναι σωστή η ώρα συστήματος; Αν όχι, τι μπορεί να χαλάσει downstream (2 παραδείγματα);
- RQ13: Πόσος ελεύθερος χώρος δίσκου υπάρχει; Γιατί μετράει στα logging systems;
- RQ14: Ποια έκδοση Python είναι εγκατεστημένη; Γιατί επηρεάζει την αναπαραγωγιμότητα;
Μέρος D — Git και GitHub (κάθε εβδομάδα)
D.0 Εισαγωγή
Το μάθημα θεωρεί ότι χρησιμοποιείτε git ως «μηχανική μνήμη». Χωρίς version control θα χάσετε πρόοδο. Για το Lab 01 χρειάζεστε δύο πράγματα:
- git (τοπικό εργαλείο version control)
- GitHub (remote hosting για συνεργασία)
Από εδώ και πέρα:
- Όλη η δουλειά ζει στο team repository.
- Το README πρέπει να αρκεί για να τρέξει κάποιος άλλος τη δουλειά σας.
- Το commit history να δείχνει ουσιαστικά βήματα προόδου.
D.1 Δημιουργία team repository
Ένα μέλος δημιουργεί private repository στο GitHub και δίνει πρόσβαση στους υπόλοιπους.
Ερωτήσεις Αναφοράς
- RQ15: Ποιος δημιούργησε το repository και πώς δόθηκε πρόσβαση;
- RQ16: Τι πρόβλημα θα προέκυπτε αν κάθε μέλος κρατούσε μόνο το δικό του local αντίγραφο;
D.2 Clone, add, commit, push
Στο laptop:
git clone <repo-url>
cd <repo-folder>
Απαιτούμενη δομή:
/
├── 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
Ερωτήσεις Αναφοράς
- RQ17: Διαφορά
git addvsgit commit; - RQ18: Τι κάνει το
git pushκαι γιατί είναι κρίσιμο για ομάδα;
D.3 Pull πριν ξεκινήσετε, push όταν τελειώσετε
git pull
# ...εργασία...
git status
git add <files>
git commit -m "<meaningful message>"
git push
RQ19: Τι πρόβλημα προκύπτει αν δύο μέλη αλλάξουν το ίδιο αρχείο χωρίς pull πρώτα;
D.4 Branching και conflicts
Προαιρετικά για το Lab 01, αλλά γενικά προτείνεται.
git checkout -b lab01/<shortname>
git push -u origin lab01/<shortname>
Workflow επιλογές:
- A: Branch → Pull Request → merge στο main
- B: Branch → local merge → push main
Ερωτήσεις Αναφοράς
- RQ20: Χρησιμοποιήσατε branches; Περιγράψτε το workflow ή εξηγήστε γιατί όχι.
- RQ21: Τι είναι merge conflict και πότε συμβαίνει;
D.5 Authentication (PAT vs SSH)
Σε κάποια setups απαιτείται GitHub PAT για HTTPS push. Άλλη συνηθισμένη λύση είναι SSH keys.
RQ22: Ποια μέθοδο χρησιμοποιήσατε για push στο GitHub (HTTPS+token / SSH key / άλλη) και γιατί;
D.6 .gitignore πολιτική
Το .gitignore ορίζει τι δεν πρέπει να παρακολουθείται από το git. Αγνοήστε τουλάχιστον:
venv/__pycache__/*.pyc*.log
Παράδειγμα:
venv/
__pycache__/
*.pyc
*.log
Ερωτήσεις Αναφοράς
- RQ23: Γιατί δεν κάνουμε commit virtual environments;
- RQ24: Γιατί συνήθως δεν κάνουμε commit logs;
Μέρος E — Αναπαραγώγιμο Python περιβάλλον στο Pi
E.1 Clone του repo στο Pi
Κάντε clone το team repo στο Pi και μεταβείτε στο labs/lab01.
RQ25: Σε ποιο path στο Pi κάνατε clone και γιατί εκεί;
E.2 Virtual environment (venv)
Ένα venv είναι απομονωμένο Python περιβάλλον για συγκεκριμένο project, με δικά του packages/pip state/executable path. Δεν αλλάζει τη system Python.
Δημιουργία venv
python3 -m venv venv
Ενεργοποίηση
source venv/bin/activate
Έλεγχος ότι χρησιμοποιείται το venv
which python
python --version
python -c "import sys; print(sys.executable)"
Αναμένουμε paths μέσα στο .../labs/lab01/venv/....
Ερωτήσεις Αναφοράς
- RQ26: Τι έδειξε το
sys.executableκαι πώς αποδεικνύει χρήση venv; - RQ27: Τι πρόβλημα λύνει το venv;
E.3 Dependencies (requirements.txt)
Το requirements.txt δηλώνει εξαρτήσεις ώστε το περιβάλλον να μπορεί να ξαναφτιαχτεί αναπαραγώγιμα.
Μπορείτε να χρησιμοποιήσετε:
click(προτείνεται), ή- μόνο
argparse(standard library)
Παράδειγμα:
click==8.1.7
Εγκατάσταση (με ενεργό venv):
which python
pip install -r requirements.txt
pip show click # αν χρησιμοποιήσατε click
pip list
Ερωτήσεις Αναφοράς
- RQ28: Ποιες εξαρτήσεις βάλατε και γιατί; Αν χρησιμοποιήσατε
argparse, χρειάζεταιrequirements.txt; γιατί/γιατί όχι; - RQ29: Τι γίνεται αν διαφορετικές ομάδες χρησιμοποιούν διαφορετικές εκδόσεις εξαρτήσεων;
- RQ30: Πώς ελέγχετε ότι τα πακέτα εγκαταστάθηκαν στο venv και όχι στο system Python;
Μέρος F — Mock Event Generator (CLI + JSONL)
F.0 Εισαγωγή
Στον πραγματικό κόσμο, τα smart wastebin συστήματα ξεκινούν από χαμηλού επιπέδου σήματα (αισθητήρες) και λογισμικό που εξάγει υψηλού επιπέδου γεγονότα. Σε αυτό το lab δεν ξεκινάμε από αισθητήρες. Αντίθετα, υλοποιείτε έναν mock event generator που παράγει ιδανικά υψηλού επιπέδου events, όπως:
- «έγινε απόρριψη»
- «η συσκευή είναι online»
- «το σύνολο απορρίψεων είναι 42»
Έτσι εστιάζετε σε:
- σχεδιασμό CLI
- validation και error handling
- μορφή αρχείου εξόδου
- append-only logging
- αρίθμηση εγγραφών
- timestamps
- καθαρό shutdown
F.1 Τι θα χτίσετε
Θα φτιάξετε το labs/lab01/event_generator.py, ένα CLI πρόγραμμα που γράφει JSON Lines (JSONL) records σε αρχείο log, με ρυθμιζόμενο πλήθος events και interval.
F.2 Τύποι συμβάντων
Το --event-type επιλέγει τον τύπο υψηλού επιπέδου event.
Υποχρεωτικά:
deposit— δηλώνει χρήση κάδου / απόρριψηheartbeat— δηλώνει ότι η συσκευή είναι online και λειτουργική
Προαιρετικά (αν θέλετε): lid_open, lid_close, maintenance
Συμπεριφορά: σε κάθε run εκπέμπεται μόνο ο τύπος που επέλεξε ο χρήστης.
F.3 Απαιτήσεις CLI
Χρησιμοποιήστε argparse ή click (όχι manual parse του sys.argv).
Παράδειγμα εκτέλεσης:
python event_generator.py \
--device-id wastebin-01 \
--event-type deposit \
--count 10 \
--interval 2 \
--out events.log
Υποχρεωτικά args
--device-id(string)--event-type(depositήheartbeat)--count(int,> 0)--interval(float/int,>= 0)--out(path, append mode)
Προαιρετικά args
--starting-total(int, default0)--verbose(flag)
F.4 Μορφή εξόδου (JSONL)
Append-only αρχείο log. Κάθε event = ένα JSON object σε μία γραμμή.
Υποχρεωτικά πεδία σε κάθε record:
event_time(ISO-8601 UTC)ingest_time(ISO-8601 UTC)device_idevent_typeseq(ξεκινά από 1, αυξάνει κατά 1)run_id(μοναδικό ανά εκτέλεση)
Επιπλέον για deposit:
deposit_delta(= 1)deposit_total(μονοτονικά αυξανόμενο)
Επιπλέον για heartbeat:
status(="online")
F.5 Κριτήρια ορθότητας
- Κάθε γραμμή είναι έγκυρο JSON.
- Υπάρχουν όλα τα required fields.
- Το
seqαυξάνει κατά 1. - Για
deposit, τοdeposit_totalαυξάνει κατά 1. - Timestamps είναι έγκυρα UTC.
- Πολλαπλά runs κάνουν καθαρό append στο ίδιο αρχείο.
F.6 Operational output vs event logs
Κρατήστε ξεχωριστά:
- Event log (
events.log): μόνο JSONL για μηχανές - Operational output (
stdout/stderr): ανθρώπινα μηνύματα
Με --verbose, τυπώστε μήνυμα κάθε 5 records (π.χ. generated seq=5 type=deposit out=events.log). Μην το γράφετε στο JSONL.
F.7 Error handling και exit codes
- Exit code 2 για CLI/usage errors
- Exit code 1 για runtime errors (π.χ. file I/O)
- Σφάλματα σε
stderr - Απόρριψη μη έγκυρων args:
count <= 0,interval < 0, άγνωστοevent_type
F.8 Safe shutdown (Ctrl-C)
Σε Ctrl-C:
- σταματήστε να εκπέμπετε νέα records
- κλείστε πόρους καθαρά
- τυπώστε τελικό μήνυμα με πόσα records γράφτηκαν
F.9 Υποδείξεις υλοποίησης
Παρακάτω μοτίβα (κρατούνται ως έχουν στο lab):
1) Append JSON record σε JSONL
import json
record = {"event_type": "deposit", "seq": 1, "deposit_delta": 1, "deposit_total": 1}
with open("events.log", "a", encoding="utf-8") as f:
f.write(json.dumps(record) + "\n")
2) UTC timestamps σε ISO-8601 (...Z)
from datetime import datetime, timezone
def utc_now_iso() -> str:
return (
datetime.now(timezone.utc)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z")
)
3) Μοναδικό run_id
import uuid
run_id = str(uuid.uuid4())
4) Σφάλματα σε stderr + exit codes
import sys
print("Error: invalid --count (must be > 0)", file=sys.stderr)
raise SystemExit(2)
5) Verbose κάθε 5 records
if verbose and seq % 5 == 0:
print(f"generated seq={seq} type={event_type} out={out_path}")
6) Ctrl-C handling
written = 0
try:
for seq in range(1, count + 1):
written += 1
except KeyboardInterrupt:
print(f"\nInterrupted. Wrote {written} record(s).")
7) deposit_total με --starting-total
deposit_total = starting_total
for seq in range(1, count + 1):
if event_type == "deposit":
deposit_total += 1
8) Παράδειγμα validation (argparse)
if args.count <= 0:
print("Error: --count must be > 0", file=sys.stderr)
raise SystemExit(2)
if args.interval < 0:
print("Error: --interval must be >= 0", file=sys.stderr)
raise SystemExit(2)
if args.event_type not in {"deposit", "heartbeat"}:
print("Error: --event-type must be 'deposit' or 'heartbeat'", file=sys.stderr)
raise SystemExit(2)
Ερωτήσεις Αναφοράς (Μέρος F)
- RQ31: Γιατί να ξεκινήσουμε με mock generator αντί για πραγματικό hardware;
- RQ32: Τι μπορείτε να δοκιμάσετε ανεξάρτητα από τους αισθητήρες;
- RQ33: Γιατί ξεχωρίζουμε
depositαπόheartbeat; - RQ34: Δώστε παράδειγμα προβλήματος αν λείπουν heartbeats.
- RQ35: Ποιες προαιρετικές παράμετροι προσθέσατε και γιατί;
- RQ36: Γιατί πρέπει τα invalid CLI args να αποτυγχάνουν νωρίς και καθαρά;
- RQ37: Γιατί το JSON Lines ταιριάζει σε append-only logs;
- RQ38: Γιατί χρειαζόμαστε και
seqκαι timestamps; - RQ39: Γιατί το
deposit_totalπρέπει να είναι μονοτονικά αυξανόμενο; - RQ40: Ποιος κανόνας ορθότητας είναι δυσκολότερος να επαληθευτεί χειροκίνητα και γιατί;
- RQ41: Τι γίνεται αν μπερδευτούν operational messages μέσα στα event logs;
- RQ42: Γιατί τα operational logs είναι χρήσιμα στο debugging;
- RQ43: Γιατί ξεχωρίζουμε usage από runtime errors;
- RQ44: Πώς βοηθούν τα συνεπή exit codes σε automation;
- RQ45: Τι μπορεί να πάει στραβά χωρίς σωστό interrupt handling;
Μέρος G — Mini-tests
G.1 Υποχρεωτικά tests
Test 1 — Deposit stream
python event_generator.py --device-id wastebin-01 --event-type deposit --count 5 --interval 0.2 --out events.log
Έλεγχοι:
- 5 νέα JSONL records
- όλα
event_type == "deposit" seq+1deposit_delta == 1deposit_total+1 κάθε φορά
RQ46: Δείξτε πρώτο/τελευταίο JSON record και εξηγήστε τους μετρητές.
Test 2 — Heartbeat stream
python event_generator.py --device-id wastebin-01 --event-type heartbeat --count 3 --interval 0.5 --out events.log
Έλεγχοι:
- 3 νέα JSONL records
- όλα
event_type == "heartbeat" status == "online"- κανένα
deposit_*field
RQ47: Πώς ξεχωρίζει ένας consumer heartbeat από deposit records;
Test 3 — Invalid arguments
Τρέξτε τουλάχιστον δύο μη έγκυρες εντολές (π.χ. invalid --event-type, --count 0, αρνητικό --interval).
Έλεγχοι:
- error σε
stderr - exit code
2 - κανένα invalid record στο log
RQ48: Για κάθε invalid command, δείξτε error message και exit code. RQ49: Ποια invalid είσοδος είναι πιο πιθανή στην πράξη και γιατί;
Test 4 — Ctrl-C behavior
Τρέξτε μεγαλύτερο command (π.χ. --count 100) και διακόψτε με Ctrl-C.
Έλεγχοι:
- καθαρό σταμάτημα
- τελικό summary message
- μόνο πλήρεις JSONL γραμμές στο αρχείο
RQ50: Πόσα records γράφτηκαν πριν τη διακοπή;
Μέρος H — Άσκηση αναπαραγωγιμότητας (με σκόπιμα κακό README)
H.0 Εισαγωγή
Ένα σύστημα δεν είναι «έτοιμο» επειδή δούλεψε μία φορά. Είναι έτοιμο όταν κάποιος άλλος μπορεί να το τρέξει αξιόπιστα μόνο από την τεκμηρίωση. Συνήθεις αστοχίες: χαμένες παραδοχές, ασαφή βήματα, ελλιπείς προϋποθέσεις.
H.1 Εργασία
Χρησιμοποιήστε το εσκεμμένα ελλιπές README από:
Κάντε τα εξής:
- Διαβάστε το προσεκτικά.
- Εντοπίστε συγκεκριμένα προβλήματα που εμποδίζουν την αναπαραγωγή setup/εκτέλεσης.
- Προτείνετε συγκεκριμένες βελτιώσεις.
- Εφαρμόστε το ίδιο σκεπτικό στο δικό σας
labs/lab01/README.md.
Δεν απαιτείται να εκτελέσετε τις οδηγίες του κακού README.
H.2 Checklist αξιολόγησης README
Ελέγξτε αν απαντά καθαρά στα εξής:
- Προϋποθέσεις (SSH, δίκτυο, Python κ.λπ.)
- Ακριβείς commands (copy-paste ready)
- Paths/τοποθεσίες (laptop vs Pi, φάκελος)
- Ενεργοποίηση venv
- Αναμενόμενα outputs
- Error cases και αντιμετώπιση
- Παραδοχές (π.χ. «ξέρεις την IP»)
- Σωστή σειρά βημάτων
- Αναπαραγωγιμότητα από άλλη ομάδα/άλλο Pi
H.3 Ερωτήσεις Αναφοράς
- RQ51: Καταγράψτε τουλάχιστον 5 συγκεκριμένα προβλήματα στο bad README (με παραπομπή σε γραμμή/ενότητα).
- RQ52: Τι βελτιώσεις κάνατε στο δικό σας
labs/lab01/README.mdκαι γιατί βοηθούν την αναπαραγωγιμότητα;
Υπόδειξη project (Smart Wastebin)
Το project εξελίσσεται παράλληλα με τα labs. Στόχος είναι να μη «ξεκινήσει στο τέλος». Στο Lab 01 δεν γράφετε ακόμη project λειτουργικότητα, αλλά θεμελιώνετε:
- κοινό GitHub repository
- repository README με περιγραφή project
- λειτουργικό dev περιβάλλον στο Raspberry Pi
- κοινό workflow για συνεργασία/εκτέλεση/τεκμηρίωση
Άρα, παρότι δεν υπάρχει ακόμη project code, το Smart Wastebin ήδη υπάρχει ουσιαστικά ως οργανωμένο σύστημα εργασίας.
Τελική λίστα ελέγχου
- Το SSH λειτουργεί αξιόπιστα από τουλάχιστον ένα laptop ομάδας
- Η δομή repo ταιριάζει με τις απαιτήσεις
- Κατανοείται το Git workflow (clone/add/commit/push + pull πριν τη δουλειά)
- Υπάρχει
requirements.txtκαι εγκαθίσταται σε νέο venv - Το
event_generator.pyκαλύπτει CLI + JSONL requirements - Τα tests (happy path + invalid args + Ctrl-C) είναι τεκμηριωμένα με exit codes
- Ολοκληρώθηκε η άσκηση αναπαραγωγιμότητας
- Έτοιμο πακέτο eClass:
.zip+lab01_README_<team>.pdf
Παραδοτέα και Υποβολή
Τι πρέπει να υπάρχει στο repository (μέχρι το τέλος του lab)
/
├── README.md
├── labs/
│ └── lab01/
│ ├── README.md
│ ├── requirements.txt
│ └── event_generator.py
Απαιτούμενα αρχεία:
labs/lab01/event_generator.pylabs/lab01/requirements.txtlabs/lab01/README.md— runbook + report + test results- Root
README.md— στοιχεία ομάδας
Τι πρέπει να περιέχει το labs/lab01/README.md
Δύο σαφώς χωρισμένα μέρη:
- Runbook (setup/venv/dependencies/commands/expected outputs)
- Report (απαντήσεις σε όλα τα RQ με αποδεικτικά όπου ζητούνται)
Προθεσμίες υποβολής
1) Τέλος εργαστηρίου — GitHub checkpoint
Πριν φύγετε:
- commit
- push στο team repository
- πρόσβαση στους βοηθούς
TA accounts:
RQ0: Ποιο είναι το commit hash του τελικού end-of-lab commit;
2) Πριν το επόμενο εργαστήριο — eClass + git
Υποβάλετε στο eClass:
.zipκώδικα- PDF export του
labs/lab01/README.md
PDF filename:
lab01_REPORT_<team>.pdf
Και κάντε τελικό push/submit στο GitHub.
Τι να περιλαμβάνει το .zip
Να περιλαμβάνει τουλάχιστον:
labs/lab01/(ολόκληρο)- Root
README.md
Να μην περιλαμβάνει:
venv/__pycache__/*.pyc- μεγάλα logs ή προσωρινά αρχεία (εκτός αν ζητηθούν ρητά)