4.4 KiB
4.4 KiB
NotifyPulse V4 (Server + Clients)
This V4 scaffold splits NotifyPulse into:
- Linux-hosted server (
v4/server) for API, Web UI, PWA, settings, command routing. - Windows agent (
v4/windows_client) built as.exe, connected to server by WebSocket. - Shared command protocol with ack/event flow.
V3 stays untouched in the repo root (notifier.py).
Architecture
- Server is the source of truth for settings, usecases, and command dispatch.
- Windows client registers itself and executes device-local actions:
- toast notifications
- wallpaper changes
- (overlay hook included, implementation placeholder)
- PWA/web clients connect to the server and use the same API.
- Updates are centralized with server-hosted update manifests:
GET /api/v4/update/manifest/windows- Client checks and reports update availability.
Quick start (Linux server)
cd v4/server
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
uvicorn app.main:app --host 0.0.0.0 --port 8080
Server defaults:
- Web UI:
http://<server>:8080/ - PWA:
http://<server>:8080/pwa/ - Device WebSocket:
ws://<server>:8080/ws/device
Deploy on Linux (systemd)
Example target folder: /opt/notifypulse.
- Copy repo to server and install deps:
sudo mkdir -p /opt/notifypulse
sudo chown -R $USER:$USER /opt/notifypulse
cd /opt/notifypulse
python3 -m venv v4/server/.venv
source v4/server/.venv/bin/activate
pip install -r v4/server/requirements.txt
- Create env file:
cat > /opt/notifypulse/v4/server/.env <<'EOF'
NP4_HOST=0.0.0.0
NP4_PORT=8080
NP4_API_TOKEN=replace-with-long-random-token
NP4_DATA_DIR=/opt/notifypulse/v4_data
EOF
- Create systemd service
/etc/systemd/system/notifypulse-v4.service:
[Unit]
Description=NotifyPulse V4 Server
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/notifypulse/v4/server
EnvironmentFile=/opt/notifypulse/v4/server/.env
ExecStart=/opt/notifypulse/v4/server/.venv/bin/uvicorn app.main:app --host ${NP4_HOST} --port ${NP4_PORT}
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
- Enable service:
sudo systemctl daemon-reload
sudo systemctl enable --now notifypulse-v4
sudo systemctl status notifypulse-v4
Optional: Nginx reverse proxy + HTTPS
Minimal Nginx vhost:
server {
listen 80;
server_name your.domain.tld;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /ws/device {
proxy_pass http://127.0.0.1:8080/ws/device;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
Then add TLS (recommended) with Certbot.
Quick start (Windows client)
cd v4\windows_client
py -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
$env:NP4_SERVER_URL="http://<server>:8080"
$env:NP4_API_TOKEN="<optional token>"
python client.py
Build Windows .exe
cd v4\windows_client
build.bat
Output: dist\NotifyPulseAgent-V4.exe
Easy update model
- Publish new Windows agent builds on your server/CDN.
- Update the manifest in server data:
v4_data/update_manifest.json(auto-created on first boot)
- Client periodically checks
GET /api/v4/update/manifest/windows. - If newer version is detected, client emits
update_availableevent.
You can later switch this to silent self-update (download + staged swap + restart), but this scaffold keeps it safe and transparent first.
iOS note
PWA is the practical path. iOS sideloading native apps is possible but adds signing/provisioning/distribution complexity and is not "easy update" compared to PWA.
Troubleshooting
Desktop test -> Wallpaperdoes nothing:- Ensure an active usecase exists.
- Add files under
v4_data/usecases/<usecase_id>/wallpapers/.
Desktop test -> Overlaydoes nothing:- Add files under
v4_data/usecases/<usecase_id>/overlay/. - Rebuild/update the Windows agent so it includes overlay support.
- Add files under
- PWA wallpaper is identical for lock/home:
- Add at least 2 images under
v4_data/usecases/<usecase_id>/mobile/. - With only one image, both slots intentionally use that single image.
- Add at least 2 images under