Add documentation and utility modules

- Add API specification documentation
- Add system specification document
- Add UI mockups and documentation
- Add utility modules (wifi)
This commit is contained in:
2026-01-11 21:34:18 +13:00
parent 5f6e45af09
commit 9e2409430c
26 changed files with 7374 additions and 0 deletions

359
docs/mockups/dashboard.html Normal file
View File

@@ -0,0 +1,359 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LED Driver - Dashboard</title>
<link rel="stylesheet" href="color-picker.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.header {
background: white;
border-radius: 12px;
padding: 24px;
margin-bottom: 24px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.header h1 {
color: #667eea;
margin-bottom: 8px;
}
.header p {
color: #666;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 24px;
margin-bottom: 24px;
}
.card {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: transform 0.2s, box-shadow 0.2s;
}
.card:hover {
transform: translateY(-2px);
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
}
.card h2 {
color: #667eea;
margin-bottom: 16px;
font-size: 1.25rem;
}
.pattern-selector {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
gap: 12px;
}
.pattern-btn {
padding: 16px;
border: 2px solid #e0e0e0;
border-radius: 8px;
background: white;
cursor: pointer;
transition: all 0.2s;
text-align: center;
font-weight: 500;
}
.pattern-btn:hover {
border-color: #667eea;
background: #f0f0ff;
}
.pattern-btn.active {
border-color: #667eea;
background: #667eea;
color: white;
}
.slider-group {
margin-bottom: 20px;
}
.slider-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #333;
}
.slider {
width: 100%;
height: 8px;
border-radius: 4px;
background: #e0e0e0;
outline: none;
-webkit-appearance: none;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
border-radius: 50%;
background: #667eea;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 20px;
height: 20px;
border-radius: 50%;
background: #667eea;
cursor: pointer;
border: none;
}
.value-display {
display: inline-block;
margin-left: 12px;
font-weight: 600;
color: #667eea;
}
.color-picker-group {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.color-picker-wrapper {
display: inline-block;
}
.btn {
padding: 12px 24px;
border: none;
border-radius: 8px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.btn-primary {
background: #667eea;
color: white;
}
.btn-primary:hover {
background: #5568d3;
}
.btn-secondary {
background: #e0e0e0;
color: #333;
}
.btn-secondary:hover {
background: #d0d0d0;
}
.device-list {
list-style: none;
}
.device-item {
padding: 12px;
border: 1px solid #e0e0e0;
border-radius: 8px;
margin-bottom: 8px;
display: flex;
justify-content: space-between;
align-items: center;
}
.device-status {
width: 12px;
height: 12px;
border-radius: 50%;
background: #4caf50;
}
.device-status.offline {
background: #f44336;
}
.actions {
display: flex;
gap: 12px;
margin-top: 20px;
}
.btn-full {
width: 100%;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>LED Driver Control Panel</h1>
<p>Manage your LED devices and patterns</p>
</div>
<div class="grid">
<!-- Pattern Selection -->
<div class="card">
<h2>Pattern Selection</h2>
<div class="pattern-selector">
<div class="pattern-btn active">On</div>
<div class="pattern-btn">Off</div>
<div class="pattern-btn">Blink</div>
<div class="pattern-btn">Chase</div>
<div class="pattern-btn">Circle</div>
<div class="pattern-btn">Pulse</div>
<div class="pattern-btn">Rainbow</div>
<div class="pattern-btn">Transition</div>
</div>
</div>
<!-- Brightness & Speed -->
<div class="card">
<h2>Brightness & Speed</h2>
<div class="slider-group">
<label>
Brightness
<span class="value-display" id="brightness-value">100</span>%
</label>
<input type="range" class="slider" id="brightness" min="0" max="100" value="100">
</div>
<div class="slider-group">
<label>
Delay
<span class="value-display" id="delay-value">100</span>ms
</label>
<input type="range" class="slider" id="delay" min="10" max="1000" value="100" step="10">
</div>
</div>
<!-- Color Selection -->
<div class="card">
<h2>Colors</h2>
<div class="color-picker-group">
<input type="color" class="color-input" value="#000000">
<input type="color" class="color-input" value="#FF0000">
<input type="color" class="color-input" value="#00FF00">
<input type="color" class="color-input" value="#0000FF">
</div>
<div class="actions">
<button class="btn btn-secondary btn-full">Add Color</button>
</div>
</div>
<!-- Device Status -->
<div class="card">
<h2>Connected Devices</h2>
<ul class="device-list">
<li class="device-item">
<div>
<strong>led-device1</strong>
<div style="font-size: 0.875rem; color: #666;">Group: group1</div>
</div>
<div class="device-status"></div>
</li>
<li class="device-item">
<div>
<strong>led-device2</strong>
<div style="font-size: 0.875rem; color: #666;">Group: group2</div>
</div>
<div class="device-status"></div>
</li>
<li class="device-item">
<div>
<strong>led-device3</strong>
<div style="font-size: 0.875rem; color: #666;">No group</div>
</div>
<div class="device-status offline"></div>
</li>
</ul>
</div>
</div>
<!-- Action Buttons -->
<div class="card">
<div class="actions">
<button class="btn btn-primary btn-full">Apply Settings</button>
<button class="btn btn-secondary btn-full">Save to Device</button>
</div>
</div>
</div>
<script>
// Brightness slider
document.getElementById('brightness').addEventListener('input', function(e) {
document.getElementById('brightness-value').textContent = e.target.value;
});
// Delay slider
document.getElementById('delay').addEventListener('input', function(e) {
document.getElementById('delay-value').textContent = e.target.value;
});
// Pattern selection
document.querySelectorAll('.pattern-btn').forEach(btn => {
btn.addEventListener('click', function() {
document.querySelectorAll('.pattern-btn').forEach(b => b.classList.remove('active'));
this.classList.add('active');
});
});
// Initialize color pickers
const colorPickers = [];
const initialColors = ['#000000', '#FF0000'];
function addColorPicker(color = '#000000') {
const container = document.createElement('div');
container.className = 'color-picker-wrapper';
document.getElementById('color-pickers').appendChild(container);
const picker = new ColorPicker(container, {
initialColor: color,
onColorChange: (newColor) => {
console.log('Color changed:', newColor);
// Update device colors
}
});
colorPickers.push(picker);
return picker;
}
// Add initial color pickers
initialColors.forEach(color => addColorPicker(color));
</script>
<script src="color-picker.js"></script>
</body>
</html>