initial Commit

This commit is contained in:
2026-05-10 12:46:33 +02:00
commit 108f08645c
36 changed files with 8688 additions and 0 deletions

100
README.md Normal file
View File

@@ -0,0 +1,100 @@
# Custom Streamdeck Button Prototype
This project is now a local Stream Deck-style control app for the 10-button Pico prototype.
The Pico firmware still prints the same USB serial JSON events. The new backend consumes those events, stores configuration in SQLite, executes actions, loads backend plugins, and serves the built React UI.
## Button Wiring
Button order is the order you gave:
1. GP28
2. GP27
3. GP26
4. GP22
5. GP21
6. GP20
7. GP18
8. GP19
9. GP17
10. GP16
The other leg of every button goes to GND. The Pico script uses internal pull-ups, so a pressed button reads as LOW.
## Files
- `pico/main.py`: MicroPython code that runs on the Pico and prints button events over USB serial.
- `pc/listen_buttons.py`: PC listener that reads serial events and appends them to `button_log.txt`.
- `backend/`: FastAPI backend, WebSocket events, SQLite state, action engine, app discovery, plugin loading.
- `frontend/`: React + Vite + Tailwind UI.
- `plugins/`: Backend Python plugins. Each plugin exposes a top-level `PLUGIN` object.
## Run The App
Install Python dependencies:
```powershell
python -m pip install -r requirements.txt
```
Install and build the UI:
```powershell
cd frontend
npm install
npm run build
cd ..
```
Start the backend and open `http://127.0.0.1:8000/`:
```powershell
python -m uvicorn backend.main:app --host 127.0.0.1 --port 8000
```
For frontend dev mode, run the backend above and then:
```powershell
cd frontend
npm run dev
```
## Legacy Listener
```powershell
python .\pc\listen_buttons.py
```
If auto-detect fails:
```powershell
python .\pc\listen_buttons.py --port COM5
```
## Plugin Shape
Backend plugins live in `plugins/` and expose `PLUGIN`.
```python
class MyPlugin:
name = "My Plugin"
desc = "Does a thing"
actions = [
{
"id": "do_thing",
"name": "Do Thing",
"fields": [{"id": "value", "label": "Value", "type": "text"}],
}
]
def on_load(self, ctx):
pass
def on_event(self, ctx, event):
pass
def execute_action(self, ctx, action_id, config, event):
pass
PLUGIN = MyPlugin()
```