Remove obsolete audio and buzzer control documentation files, including detailed guides and HTML interfaces, to streamline the repository and eliminate redundancy. This cleanup enhances maintainability and focuses on essential resources for the reTerminal DM4 audio and buzzer functionalities.
This commit is contained in:
660
archive/chromium-setup-legacy/FLASK-BUZZER-CONTROL.md
Normal file
660
archive/chromium-setup-legacy/FLASK-BUZZER-CONTROL.md
Normal file
@@ -0,0 +1,660 @@
|
||||
# Flask Buzzer Control Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
This guide explains how to control the reTerminal DM4 buzzer from a Python Flask web application. The buzzer is accessed via the Linux sysfs interface at `/sys/class/leds/usr-buzzer/brightness`.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.x installed
|
||||
- Flask installed (`pip install flask`)
|
||||
- sudo permissions (or user in appropriate groups)
|
||||
- reTerminal DM4 with buzzer accessible
|
||||
|
||||
## Basic Buzzer Control Functions
|
||||
|
||||
### Simple Python Buzzer Control
|
||||
|
||||
```python
|
||||
import os
|
||||
|
||||
BUZZER_PATH = '/sys/class/leds/usr-buzzer/brightness'
|
||||
|
||||
def buzzer_on():
|
||||
"""Turn buzzer ON"""
|
||||
with open(BUZZER_PATH, 'w') as f:
|
||||
f.write('1')
|
||||
|
||||
def buzzer_off():
|
||||
"""Turn buzzer OFF"""
|
||||
with open(BUZZER_PATH, 'w') as f:
|
||||
f.write('0')
|
||||
|
||||
def buzzer_beep(duration=0.2):
|
||||
"""Play a beep for specified duration (in seconds)"""
|
||||
import time
|
||||
buzzer_on()
|
||||
time.sleep(duration)
|
||||
buzzer_off()
|
||||
```
|
||||
|
||||
**Note**: These functions require root privileges. See "Permission Setup" section below.
|
||||
|
||||
## Flask Application Examples
|
||||
|
||||
### Example 1: Basic Flask App with Buzzer Control
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
from flask import Flask, jsonify, request
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
app = Flask(__name__)
|
||||
BUZZER_PATH = '/sys/class/leds/usr-buzzer/brightness'
|
||||
|
||||
def buzzer_on():
|
||||
"""Turn buzzer ON"""
|
||||
try:
|
||||
subprocess.run(['sudo', 'tee', BUZZER_PATH],
|
||||
input='1', text=True,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
check=True)
|
||||
return True
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
||||
def buzzer_off():
|
||||
"""Turn buzzer OFF"""
|
||||
try:
|
||||
subprocess.run(['sudo', 'tee', BUZZER_PATH],
|
||||
input='0', text=True,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
check=True)
|
||||
return True
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
||||
def buzzer_beep(duration=0.2):
|
||||
"""Play a beep for specified duration"""
|
||||
buzzer_on()
|
||||
time.sleep(duration)
|
||||
buzzer_off()
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return jsonify({
|
||||
'status': 'Buzzer Control API',
|
||||
'endpoints': {
|
||||
'/buzzer/on': 'Turn buzzer ON',
|
||||
'/buzzer/off': 'Turn buzzer OFF',
|
||||
'/buzzer/beep': 'Play a beep (duration parameter)',
|
||||
'/buzzer/status': 'Get buzzer status'
|
||||
}
|
||||
})
|
||||
|
||||
@app.route('/buzzer/on', methods=['POST', 'GET'])
|
||||
def turn_on():
|
||||
if buzzer_on():
|
||||
return jsonify({'status': 'success', 'message': 'Buzzer turned ON'})
|
||||
return jsonify({'status': 'error', 'message': 'Failed to turn buzzer ON'}), 500
|
||||
|
||||
@app.route('/buzzer/off', methods=['POST', 'GET'])
|
||||
def turn_off():
|
||||
if buzzer_off():
|
||||
return jsonify({'status': 'success', 'message': 'Buzzer turned OFF'})
|
||||
return jsonify({'status': 'error', 'message': 'Failed to turn buzzer OFF'}), 500
|
||||
|
||||
@app.route('/buzzer/beep', methods=['POST', 'GET'])
|
||||
def beep():
|
||||
duration = float(request.args.get('duration', 0.2))
|
||||
if duration < 0 or duration > 5:
|
||||
return jsonify({'status': 'error', 'message': 'Duration must be between 0 and 5 seconds'}), 400
|
||||
|
||||
buzzer_beep(duration)
|
||||
return jsonify({'status': 'success', 'message': f'Beeped for {duration} seconds'})
|
||||
|
||||
@app.route('/buzzer/status', methods=['GET'])
|
||||
def status():
|
||||
try:
|
||||
with open(BUZZER_PATH, 'r') as f:
|
||||
state = f.read().strip()
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'buzzer': 'ON' if state == '1' else 'OFF',
|
||||
'state': state
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=5000, debug=True)
|
||||
```
|
||||
|
||||
### Example 2: Advanced Flask App with Pattern Support
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
from flask import Flask, jsonify, request
|
||||
import subprocess
|
||||
import time
|
||||
import threading
|
||||
|
||||
app = Flask(__name__)
|
||||
BUZZER_PATH = '/sys/class/leds/usr-buzzer/brightness'
|
||||
|
||||
class BuzzerController:
|
||||
def __init__(self):
|
||||
self.is_playing = False
|
||||
self.play_thread = None
|
||||
|
||||
def _write_buzzer(self, value):
|
||||
"""Internal method to write to buzzer"""
|
||||
try:
|
||||
subprocess.run(['sudo', 'tee', BUZZER_PATH],
|
||||
input=str(value), text=True,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
check=True)
|
||||
return True
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
||||
def on(self):
|
||||
"""Turn buzzer ON"""
|
||||
return self._write_buzzer(1)
|
||||
|
||||
def off(self):
|
||||
"""Turn buzzer OFF"""
|
||||
return self._write_buzzer(0)
|
||||
|
||||
def beep(self, duration=0.2):
|
||||
"""Play a single beep"""
|
||||
self.on()
|
||||
time.sleep(duration)
|
||||
self.off()
|
||||
|
||||
def play_pattern(self, pattern):
|
||||
"""
|
||||
Play a pattern
|
||||
pattern: list of tuples [(duration_on, duration_off), ...]
|
||||
Example: [(0.1, 0.1), (0.1, 0.1), (0.1, 0.3)] = two short beeps, pause, one beep
|
||||
"""
|
||||
if self.is_playing:
|
||||
return False
|
||||
|
||||
def _play():
|
||||
self.is_playing = True
|
||||
for on_time, off_time in pattern:
|
||||
self.on()
|
||||
time.sleep(on_time)
|
||||
self.off()
|
||||
time.sleep(off_time)
|
||||
self.is_playing = False
|
||||
|
||||
self.play_thread = threading.Thread(target=_play, daemon=True)
|
||||
self.play_thread.start()
|
||||
return True
|
||||
|
||||
def starwars_theme(self, duration=5):
|
||||
"""Play Star Wars theme pattern"""
|
||||
if self.is_playing:
|
||||
return False
|
||||
|
||||
def _play():
|
||||
self.is_playing = True
|
||||
start_time = time.time()
|
||||
|
||||
# Opening sequence
|
||||
self.beep(0.05)
|
||||
time.sleep(0.05)
|
||||
self.beep(0.05)
|
||||
time.sleep(0.05)
|
||||
self.beep(0.05)
|
||||
time.sleep(0.1)
|
||||
self.beep(0.1)
|
||||
time.sleep(0.1)
|
||||
self.beep(0.15)
|
||||
time.sleep(0.15)
|
||||
|
||||
# Continue pattern until duration reached
|
||||
while time.time() - start_time < duration:
|
||||
self.beep(0.08)
|
||||
time.sleep(0.05)
|
||||
self.beep(0.08)
|
||||
time.sleep(0.05)
|
||||
self.beep(0.08)
|
||||
time.sleep(0.1)
|
||||
self.beep(0.12)
|
||||
time.sleep(0.1)
|
||||
|
||||
self.off()
|
||||
self.is_playing = False
|
||||
|
||||
self.play_thread = threading.Thread(target=_play, daemon=True)
|
||||
self.play_thread.start()
|
||||
return True
|
||||
|
||||
# Create global buzzer controller
|
||||
buzzer = BuzzerController()
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return jsonify({
|
||||
'status': 'Advanced Buzzer Control API',
|
||||
'endpoints': {
|
||||
'/buzzer/on': 'Turn buzzer ON (POST/GET)',
|
||||
'/buzzer/off': 'Turn buzzer OFF (POST/GET)',
|
||||
'/buzzer/beep': 'Play a beep (GET: ?duration=0.2)',
|
||||
'/buzzer/pattern': 'Play custom pattern (POST: JSON)',
|
||||
'/buzzer/starwars': 'Play Star Wars theme (GET: ?duration=5)',
|
||||
'/buzzer/status': 'Get buzzer status (GET)'
|
||||
}
|
||||
})
|
||||
|
||||
@app.route('/buzzer/on', methods=['POST', 'GET'])
|
||||
def turn_on():
|
||||
if buzzer.on():
|
||||
return jsonify({'status': 'success', 'message': 'Buzzer turned ON'})
|
||||
return jsonify({'status': 'error', 'message': 'Failed to turn buzzer ON'}), 500
|
||||
|
||||
@app.route('/buzzer/off', methods=['POST', 'GET'])
|
||||
def turn_off():
|
||||
if buzzer.off():
|
||||
return jsonify({'status': 'success', 'message': 'Buzzer turned OFF'})
|
||||
return jsonify({'status': 'error', 'message': 'Failed to turn buzzer OFF'}), 500
|
||||
|
||||
@app.route('/buzzer/beep', methods=['POST', 'GET'])
|
||||
def beep():
|
||||
duration = float(request.args.get('duration', 0.2))
|
||||
if duration < 0 or duration > 5:
|
||||
return jsonify({'status': 'error', 'message': 'Duration must be between 0 and 5 seconds'}), 400
|
||||
|
||||
buzzer.beep(duration)
|
||||
return jsonify({'status': 'success', 'message': f'Beeped for {duration} seconds'})
|
||||
|
||||
@app.route('/buzzer/pattern', methods=['POST'])
|
||||
def play_pattern():
|
||||
data = request.get_json()
|
||||
if not data or 'pattern' not in data:
|
||||
return jsonify({'status': 'error', 'message': 'Pattern required in JSON body'}), 400
|
||||
|
||||
pattern = data['pattern']
|
||||
if not isinstance(pattern, list):
|
||||
return jsonify({'status': 'error', 'message': 'Pattern must be a list'}), 400
|
||||
|
||||
# Validate pattern format
|
||||
try:
|
||||
validated_pattern = []
|
||||
for item in pattern:
|
||||
if isinstance(item, list) and len(item) == 2:
|
||||
validated_pattern.append((float(item[0]), float(item[1])))
|
||||
else:
|
||||
return jsonify({'status': 'error', 'message': 'Each pattern item must be [on_time, off_time]'}), 400
|
||||
except (ValueError, TypeError):
|
||||
return jsonify({'status': 'error', 'message': 'Invalid pattern format'}), 400
|
||||
|
||||
if buzzer.play_pattern(validated_pattern):
|
||||
return jsonify({'status': 'success', 'message': 'Pattern playing'})
|
||||
return jsonify({'status': 'error', 'message': 'Buzzer is already playing'}), 409
|
||||
|
||||
@app.route('/buzzer/starwars', methods=['GET'])
|
||||
def starwars():
|
||||
duration = float(request.args.get('duration', 5))
|
||||
if duration < 0 or duration > 10:
|
||||
return jsonify({'status': 'error', 'message': 'Duration must be between 0 and 10 seconds'}), 400
|
||||
|
||||
if buzzer.starwars_theme(duration):
|
||||
return jsonify({'status': 'success', 'message': f'Playing Star Wars theme for {duration} seconds'})
|
||||
return jsonify({'status': 'error', 'message': 'Buzzer is already playing'}), 409
|
||||
|
||||
@app.route('/buzzer/status', methods=['GET'])
|
||||
def status():
|
||||
try:
|
||||
result = subprocess.run(['cat', BUZZER_PATH],
|
||||
capture_output=True, text=True, check=True)
|
||||
state = result.stdout.strip()
|
||||
return jsonify({
|
||||
'status': 'success',
|
||||
'buzzer': 'ON' if state == '1' else 'OFF',
|
||||
'state': state,
|
||||
'is_playing': buzzer.is_playing
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=5000, debug=True)
|
||||
```
|
||||
|
||||
## Permission Setup
|
||||
|
||||
### Option 1: Run Flask with sudo (Not Recommended for Production)
|
||||
|
||||
```bash
|
||||
sudo python3 app.py
|
||||
```
|
||||
|
||||
### Option 2: Configure sudoers for passwordless access (Recommended)
|
||||
|
||||
Create a file `/etc/sudoers.d/buzzer-control`:
|
||||
|
||||
```
|
||||
# Allow buzzer control without password
|
||||
pi ALL=(ALL) NOPASSWD: /usr/bin/tee /sys/class/leds/usr-buzzer/brightness
|
||||
```
|
||||
|
||||
Then your Flask app can use sudo without password prompts.
|
||||
|
||||
### Option 3: Use udev rules (Most Secure)
|
||||
|
||||
Create `/etc/udev/rules.d/99-buzzer.rules`:
|
||||
|
||||
```
|
||||
SUBSYSTEM=="leds", KERNEL=="usr-buzzer", MODE="0666", GROUP="audio"
|
||||
```
|
||||
|
||||
Add your user to the audio group:
|
||||
```bash
|
||||
sudo usermod -a -G audio pi
|
||||
```
|
||||
|
||||
Then reload udev:
|
||||
```bash
|
||||
sudo udevadm control --reload-rules
|
||||
sudo udevadm trigger
|
||||
```
|
||||
|
||||
After this, you can write directly without sudo:
|
||||
```python
|
||||
def buzzer_on():
|
||||
with open(BUZZER_PATH, 'w') as f:
|
||||
f.write('1')
|
||||
```
|
||||
|
||||
## API Usage Examples
|
||||
|
||||
### Using curl
|
||||
|
||||
```bash
|
||||
# Turn buzzer ON
|
||||
curl http://localhost:5000/buzzer/on
|
||||
|
||||
# Turn buzzer OFF
|
||||
curl http://localhost:5000/buzzer/off
|
||||
|
||||
# Play a beep (0.5 seconds)
|
||||
curl "http://localhost:5000/buzzer/beep?duration=0.5"
|
||||
|
||||
# Play Star Wars theme (5 seconds)
|
||||
curl "http://localhost:5000/buzzer/starwars?duration=5"
|
||||
|
||||
# Play custom pattern
|
||||
curl -X POST http://localhost:5000/buzzer/pattern \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"pattern": [[0.1, 0.1], [0.1, 0.1], [0.1, 0.3], [0.2, 0.2]]}'
|
||||
|
||||
# Check status
|
||||
curl http://localhost:5000/buzzer/status
|
||||
```
|
||||
|
||||
### Using Python requests
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
base_url = "http://localhost:5000"
|
||||
|
||||
# Turn on
|
||||
response = requests.post(f"{base_url}/buzzer/on")
|
||||
print(response.json())
|
||||
|
||||
# Play beep
|
||||
response = requests.get(f"{base_url}/buzzer/beep", params={"duration": 0.3})
|
||||
print(response.json())
|
||||
|
||||
# Play pattern
|
||||
pattern = [[0.1, 0.1], [0.1, 0.1], [0.1, 0.3]]
|
||||
response = requests.post(f"{base_url}/buzzer/pattern", json={"pattern": pattern})
|
||||
print(response.json())
|
||||
|
||||
# Check status
|
||||
response = requests.get(f"{base_url}/buzzer/status")
|
||||
print(response.json())
|
||||
```
|
||||
|
||||
### Using JavaScript/Fetch
|
||||
|
||||
```javascript
|
||||
// Turn buzzer ON
|
||||
fetch('http://localhost:5000/buzzer/on', {method: 'POST'})
|
||||
.then(res => res.json())
|
||||
.then(data => console.log(data));
|
||||
|
||||
// Play beep
|
||||
fetch('http://localhost:5000/buzzer/beep?duration=0.5')
|
||||
.then(res => res.json())
|
||||
.then(data => console.log(data));
|
||||
|
||||
// Play Star Wars theme
|
||||
fetch('http://localhost:5000/buzzer/starwars?duration=5')
|
||||
.then(res => res.json())
|
||||
.then(data => console.log(data));
|
||||
|
||||
// Play custom pattern
|
||||
fetch('http://localhost:5000/buzzer/pattern', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
pattern: [[0.1, 0.1], [0.1, 0.1], [0.1, 0.3], [0.2, 0.2]]
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => console.log(data));
|
||||
```
|
||||
|
||||
## Web Interface Example
|
||||
|
||||
### HTML/JavaScript Frontend
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Buzzer Control</title>
|
||||
<style>
|
||||
body { font-family: Arial; padding: 20px; }
|
||||
button { padding: 10px 20px; margin: 5px; font-size: 16px; }
|
||||
.status { margin-top: 20px; padding: 10px; background: #f0f0f0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>reTerminal DM4 Buzzer Control</h1>
|
||||
|
||||
<div>
|
||||
<button onclick="buzzerOn()">Buzzer ON</button>
|
||||
<button onclick="buzzerOff()">Buzzer OFF</button>
|
||||
<button onclick="beep(0.2)">Short Beep</button>
|
||||
<button onclick="beep(0.5)">Long Beep</button>
|
||||
<button onclick="starwars()">Star Wars Theme</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Custom Pattern</h3>
|
||||
<input type="text" id="pattern" placeholder="0.1,0.1,0.1,0.1,0.1,0.3" style="width: 300px;">
|
||||
<button onclick="playPattern()">Play Pattern</button>
|
||||
</div>
|
||||
|
||||
<div class="status" id="status">Ready</div>
|
||||
|
||||
<script>
|
||||
const API_URL = 'http://localhost:5000';
|
||||
|
||||
function updateStatus(message) {
|
||||
document.getElementById('status').textContent = message;
|
||||
}
|
||||
|
||||
async function buzzerOn() {
|
||||
const response = await fetch(`${API_URL}/buzzer/on`, {method: 'POST'});
|
||||
const data = await response.json();
|
||||
updateStatus(data.message);
|
||||
}
|
||||
|
||||
async function buzzerOff() {
|
||||
const response = await fetch(`${API_URL}/buzzer/off`, {method: 'POST'});
|
||||
const data = await response.json();
|
||||
updateStatus(data.message);
|
||||
}
|
||||
|
||||
async function beep(duration) {
|
||||
const response = await fetch(`${API_URL}/buzzer/beep?duration=${duration}`);
|
||||
const data = await response.json();
|
||||
updateStatus(data.message);
|
||||
}
|
||||
|
||||
async function starwars() {
|
||||
const response = await fetch(`${API_URL}/buzzer/starwars?duration=5`);
|
||||
const data = await response.json();
|
||||
updateStatus(data.message);
|
||||
}
|
||||
|
||||
async function playPattern() {
|
||||
const patternStr = document.getElementById('pattern').value;
|
||||
const parts = patternStr.split(',');
|
||||
const pattern = [];
|
||||
for (let i = 0; i < parts.length; i += 2) {
|
||||
if (i + 1 < parts.length) {
|
||||
pattern.push([parseFloat(parts[i]), parseFloat(parts[i+1])]);
|
||||
}
|
||||
}
|
||||
|
||||
const response = await fetch(`${API_URL}/buzzer/pattern`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({pattern: pattern})
|
||||
});
|
||||
const data = await response.json();
|
||||
updateStatus(data.message);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Authentication**: Add authentication for production use:
|
||||
```python
|
||||
from flask_httpauth import HTTPBasicAuth
|
||||
auth = HTTPBasicAuth()
|
||||
|
||||
@auth.verify_password
|
||||
def verify_password(username, password):
|
||||
return username == 'admin' and password == 'secret'
|
||||
|
||||
@app.route('/buzzer/on')
|
||||
@auth.login_required
|
||||
def turn_on():
|
||||
# ...
|
||||
```
|
||||
|
||||
2. **Rate Limiting**: Prevent abuse:
|
||||
```python
|
||||
from flask_limiter import Limiter
|
||||
limiter = Limiter(app, key_func=get_remote_address)
|
||||
|
||||
@app.route('/buzzer/beep')
|
||||
@limiter.limit("10 per minute")
|
||||
def beep():
|
||||
# ...
|
||||
```
|
||||
|
||||
3. **CORS**: If accessing from web pages:
|
||||
```python
|
||||
from flask_cors import CORS
|
||||
CORS(app)
|
||||
```
|
||||
|
||||
## Installation and Setup
|
||||
|
||||
1. **Install Flask:**
|
||||
```bash
|
||||
pip3 install flask
|
||||
# For advanced features:
|
||||
pip3 install flask-httpauth flask-limiter flask-cors
|
||||
```
|
||||
|
||||
2. **Set up permissions** (choose one method from above)
|
||||
|
||||
3. **Run the application:**
|
||||
```bash
|
||||
python3 app.py
|
||||
```
|
||||
|
||||
4. **Run as a service** (systemd):
|
||||
Create `/etc/systemd/system/buzzer-api.service`:
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Buzzer Control API
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=pi
|
||||
WorkingDirectory=/home/pi/buzzer-api
|
||||
ExecStart=/usr/bin/python3 /home/pi/buzzer-api/app.py
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Enable and start:
|
||||
```bash
|
||||
sudo systemctl enable buzzer-api
|
||||
sudo systemctl start buzzer-api
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Permission Denied
|
||||
- Check if user has sudo access
|
||||
- Verify udev rules are applied
|
||||
- Check file permissions: `ls -la /sys/class/leds/usr-buzzer/brightness`
|
||||
|
||||
### Buzzer Not Responding
|
||||
- Verify buzzer device exists: `ls /sys/class/leds/usr-buzzer/`
|
||||
- Test manually: `echo 1 | sudo tee /sys/class/leds/usr-buzzer/brightness`
|
||||
- Check kernel messages: `dmesg | grep buzzer`
|
||||
|
||||
### Flask App Not Starting
|
||||
- Check if port 5000 is in use: `sudo netstat -tulpn | grep 5000`
|
||||
- Verify Python and Flask are installed: `python3 --version && pip3 list | grep Flask`
|
||||
|
||||
## Complete Example Project Structure
|
||||
|
||||
```
|
||||
buzzer-api/
|
||||
├── app.py # Main Flask application
|
||||
├── buzzer.py # Buzzer control module
|
||||
├── requirements.txt # Python dependencies
|
||||
├── static/ # Static files (CSS, JS)
|
||||
│ └── index.html # Web interface
|
||||
└── README.md # Project documentation
|
||||
```
|
||||
|
||||
**requirements.txt:**
|
||||
```
|
||||
Flask==2.3.0
|
||||
flask-httpauth==4.8.0
|
||||
flask-limiter==3.0.0
|
||||
flask-cors==4.0.0
|
||||
```
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- See `BUZZER-TEST-GUIDE.md` for basic buzzer testing
|
||||
- See `AUDIO-CONFIGURATION-REPORT.md` for complete audio system info
|
||||
Reference in New Issue
Block a user