Files
wecker/README.md
T

130 lines
4.1 KiB
Markdown

# Arcade Button Alarm Clock
A unique Raspberry Pi-based alarm clock that makes sure you are fully awake before it turns off!
Instead of simply pressing a button to stop the alarm, this clock requires you to solve a short memory and attention puzzle. When the alarm rings, you press the button, and the built-in LED will blink a random number of times (between 1 and 7). You then have to press the button exactly that many times to confirm. Get it right, and the music stops. Get it wrong, and you'll have to try again!
## Hardware Requirements
* **Raspberry Pi 4 Model B** (2018)
* **33mm Illuminated Arcade Button** (e.g., from bastelgarage.ch)
* **External Speakers** (connected via 3.5mm jack or a USB Soundcard for better audio quality)
## Software Requirements
This project uses Python 3 and `uv` for dependency management. To set up the environment:
1. Install `uv` if you haven't already:
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```
2. The project contains a `pyproject.toml` file with all dependencies.
```bash
uv sync
```
Note: The system also requires `python3-pygame` and `python3-rpi.gpio` which should be installed via system packages:
```bash
sudo apt-get install python3-pygame python3-rpi.gpio
```
## Wiring
Please refer to the [arcade-button-wiring.md](arcade-button-wiring.md) file for detailed instructions on how to connect the arcade button and its LED to the Raspberry Pi's GPIO pins.
## Usage
1. Make sure your audio file (`Laid Back - Sunshine Reggae.mp3` or any other MP3 you prefer) is in the project directory.
2. Run the alarm clock script manually:
```bash
python3 wecker.py
```
## Automating and Managing Alarms (GraphQL API)
Instead of manually editing your crontab, this project provides a simple GraphQL API to List, Get, Set, and Delete your alarms.
### API Setup & Authentication
1. Create a `.env` file in the project root to set up your Static API Key:
```bash
cp .env.example .env
# Edit .env and set your own secure API_KEY
```
2. Start the API server:
```bash
uv run uvicorn api.main:app --host 0.0.0.0 --port 8000
```
3. The API will be available at `http://<YOUR_PI_IP>:8000/graphql`.
**Authentication:** All requests to the `/graphql` endpoint require a custom header:
`X-API-Key: <YOUR_API_KEY>`
### Example API Usage
**Get all alarms:**
```graphql
query {
getAlarms {
id
cronExpression
command
isEnabled
}
}
```
**Set an alarm:**
```graphql
mutation {
setAlarm(
cronExpression: "45 6 * * 1-5",
command: "cd /home/pi/workspace/wecker && /usr/bin/python3 wecker.py > wecker.log 2>&1",
isEnabled: true
) {
id
cronExpression
}
}
```
**Delete an alarm:**
```graphql
mutation {
deleteAlarm(id: "YOUR-ALARM-ID")
}
```
## How the Puzzle Works
1. **Ringing:** The music plays in an endless loop.
2. **Start:** Press the arcade button once to start the puzzle. Wait 3 seconds.
3. **Observe:** The arcade button's LED will blink between 1 and 7 times.
4. **Input:** Press the button the exact number of times the LED blinked. Every press is confirmed by the LED lighting up.
5. **Wait:** Stop pressing for 3 seconds to lock in your answer.
6. **Evaluation:**
* *Correct:* The music stops and the script exits.
* *Incorrect:* The alarm waits a few seconds and generates a completely new sequence for you to solve.
## Troubleshooting
**Audio issues when running via Cron (ALSA: Couldn't open audio device: Unknown error 524):**
If the script runs perfectly from the terminal but crashes when triggered by cron, it might be trying to use an invalid audio output (like a disconnected HDMI port) because background jobs don't have the same environment variables as interactive sessions.
To force the system to use the 3.5mm headphone jack (Audio Jack), you can create a `~/.asoundrc` file for the `pi` user with the following content:
```
pcm.!default {
type asym
playback.pcm {
type plug
slave.pcm "hw:2,0"
}
}
ctl.!default {
type hw
card 2
}
```
*(Note: Change `hw:2,0` and `card 2` to match your actual headphone jack card index, which you can find by running `aplay -l`).*
## Author
Markus Graf (info@marksugraf.ch)