IoT and Smart Systems Engineer · Projects
Project 2: Readings that survive drops and power cuts
Marking guide version 1 · Lessons: IO7 lessons 1–5, IO8 lessons 1–5, IO10 lesson 3
The problem and who it's for
The school's Wi-Fi is switched off at night and sometimes for days, and power cuts are common. In the starter, waiting readings are kept in a list in memory that a reset loses and that grows without limit. The device waits up to 30 seconds for Wi-Fi every time, sends everything at once with QoS 0 to a made-up topic, and forgets readings whether or not they arrived. It keeps every reading even when nothing has changed, and has no status or last will, so the dashboard can't tell a sleeping device from a dead one. The committee needs every reading that matters, once each, and a clear view of which devices are alive.
Scope
- Keep waiting readings in flash, so they survive a reset and a power cut part-way through a write.
- Hold a fixed number of readings, dropping and counting the oldest when full.
- Send oldest first with QoS 1 in batches, and forget a reading only after the broker confirms it.
- Use the topics and payloads in
docs/FORMATS.md, so a standard MQTT client receives them. - Give up on Wi-Fi in time and back off between attempts, and clear a backlog when Wi-Fi returns.
- Publish a retained status ("online", then "asleep" before sleeping) and a retained "offline" last will.
- Keep a reading only when the level changes enough or an hour has passed, and send alarms straight away.
- Write
docs/buffer-design.mdfor the next developer.
Not included
- A real broker on the internet, TLS or per-device credentials (IO7 teaches them; plan them in the capstone design notes).
- A dashboard or database: the kit's collector stores one copy per device and sequence number.
- Real flash wear: the kit's flash is simulated.
Before you start
-
Core: Module 4 (Computer Networks), Module 5 (IP Addresses and Ports), Module 24 (Asynchronous Programming), Module 25 (APIs and JSON), Module 57 (Transactions and Indexes), Module 94 (Distributed Systems).
- The kit installed, with
pytest tests/test_buffer.pyrunning (all 10 of its tests fail at first).
Starter files
jalsetu/firmware/buffer.py: waiting readings in a list in memory, with no limit.-
jalsetu/firmware/uplink.py: a 30-second Wi-Fi wait, QoS 0 to a made-up topic, readings forgotten whether or not they arrived, and no status or last will. -
jalsetu/firmware/edge.py: keeps every reading. jalsetu/lib/mqtt.py: the MQTT client the firmware uses.jalsetu/tools/broker.py: a practice MQTT broker on port 1884, for watching messages with a standard client.jalsetu/docs/FORMATS.md: the topics, payloads and file names the tests read.jalsetu/tests/test_buffer.py: the 10 acceptance tests for this project.
Download everything at once: starter/iot-starter.zip.
Milestones
- Read
docs/FORMATS.md, runpython tools/broker.py, and watch the starter's messages with a standard MQTT client. - Keep readings in flash and survive power cuts (tests 1 and 2).
- Add the capacity limit and sending oldest first with QoS 1 in batches (tests 3 and 4).
- Forget readings only after confirmation, and match the agreed format (tests 5 and 6).
- Add backoff, status and the last will (tests 7 and 8).
- Add edge filtering and write
docs/buffer-design.md(tests 9 and 10), then run all 10 tests twice in a row.
Expected outputs
- 10 of 10 buffer tests passing, twice in a row.
- The buffer, uplink and edge logic, and
docs/buffer-design.md. - A screenshot or log from a standard MQTT client showing a reading, a status and the last will.
Acceptance tests
| # | Input | Expected result |
|---|---|---|
| 1 | pytest tests/test_buffer.py |
10 of 10 pass, twice in a row |
| 2 | A reset; a power cut part-way through a write; a full buffer | Waiting readings survive, nothing already saved is lost, and the oldest are dropped and counted when full (tests 1, 2 and 3) |
| 3 | Wi-Fi returns; a PUBACK is lost; a standard client subscribes | Readings go oldest first with QoS 1 in batches, a reading is sent again until confirmed, and the client receives the agreed format (tests 4, 5 and 6) |
| 4 | A day without Wi-Fi; sleeping; a lost connection | Few attempts, short wakes and the backlog cleared afterwards; "asleep" before sleep, and "offline" from the last will (tests 7 and 8) |
| 5 | A steady tank; an alarm; docs/buffer-design.md |
Fewer readings when nothing changes, alarms at once, and the design written down (tests 9 and 10) |
Failure and recovery exercises
- Forget readings as soon as they're sent and run test 5. Count what's missing and explain what the committee would see, then restore it.
- Rewrite the whole log in place and run test 2. Explain what a power cut does to it, then restore the append-only log.
- Remove the backoff and run
python tools/simulate.py --days 3 --wifi-down 1. Compare the Wi-Fi attempts and battery life, then restore it.
Evidence to submit
- Link to your repository or a shared folder with the kit and your changes: the deliverable link.
- The output of
pytest tests/test_buffer.pyshowing 10 passed, pasted into test evidence. - Your buffer design and the MQTT client screenshot or log.
- Your explanation: what happens to a reading taken while Wi-Fi is off, from the sensor to the server.
Marking guide and self-check
Pass rule: every Safety-critical (S) and Mandatory (M) item must be met. A single unmet safety item means the project is not complete, whatever else is done. Quality items are for your own improvement.
Your answers are saved in this browser on this device. Self-checked means you checked your own work against this guide; it is not a reviewer's approval. Never paste passwords, keys, tokens or real customer data here.
