Skip to content

Commit 696a64e

Browse files
committed
Add OSC server implementation and CI workflow for ARM64 binaries
- Introduced a new OSC server for BLE LED badge control with installation as a systemd service. - Added build workflow for ARM64 binaries on Linux and macOS. - Updated README with installation instructions and CLI commands. - Enhanced .gitignore to exclude build artifacts. - Added PyInstaller spec for building the OSC server binary.
1 parent c4b0f10 commit 696a64e

File tree

8 files changed

+606
-50
lines changed

8 files changed

+606
-50
lines changed

.github/workflows/build-arm64.yml

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
name: Build ARM64 Binaries
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
workflow_dispatch:
8+
9+
jobs:
10+
build-linux:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout repository
14+
uses: actions/checkout@v4
15+
16+
- name: Set up QEMU for ARM64
17+
uses: docker/setup-qemu-action@v3
18+
with:
19+
platforms: arm64
20+
21+
- name: Build ARM64 binary in container
22+
run: |
23+
docker run --rm --platform linux/arm64 \
24+
-v "${{ github.workspace }}:/workspace" \
25+
-w /workspace \
26+
python:3.11-slim-bookworm \
27+
bash -c '
28+
set -ex
29+
30+
# Install system dependencies for bleak/dbus + UPX for compression
31+
apt-get update && apt-get install -y --no-install-recommends \
32+
gcc \
33+
libdbus-1-dev \
34+
pkg-config \
35+
bluetooth \
36+
libbluetooth-dev \
37+
upx-ucl
38+
39+
# Install Python dependencies
40+
pip install --no-cache-dir \
41+
bleak \
42+
pycryptodome \
43+
python-osc \
44+
pyinstaller \
45+
dbus-fast
46+
47+
# Build the binary
48+
pyinstaller badge-osc-server.spec
49+
50+
# Show size
51+
ls -lh dist/badge-osc-server
52+
53+
# Quick smoke test
54+
dist/badge-osc-server --help
55+
'
56+
57+
- name: Upload artifact
58+
uses: actions/upload-artifact@v4
59+
with:
60+
name: badge-osc-server-linux-arm64
61+
path: dist/badge-osc-server
62+
63+
build-macos:
64+
runs-on: macos-14 # Apple Silicon (M1) runner
65+
steps:
66+
- name: Checkout repository
67+
uses: actions/checkout@v4
68+
69+
- name: Set up Python
70+
uses: actions/setup-python@v5
71+
with:
72+
python-version: '3.11'
73+
74+
- name: Install UPX
75+
run: brew install upx
76+
77+
- name: Install dependencies
78+
run: |
79+
pip install --no-cache-dir \
80+
bleak \
81+
pycryptodome \
82+
python-osc \
83+
pyinstaller
84+
85+
- name: Build binary
86+
run: pyinstaller badge-osc-server.spec
87+
88+
- name: Show size and smoke test
89+
run: |
90+
ls -lh dist/badge-osc-server
91+
dist/badge-osc-server --help
92+
93+
- name: Upload artifact
94+
uses: actions/upload-artifact@v4
95+
with:
96+
name: badge-osc-server-macos-arm64
97+
path: dist/badge-osc-server
98+
99+
release:
100+
needs: [build-linux, build-macos]
101+
if: startsWith(github.ref, 'refs/tags/v')
102+
runs-on: ubuntu-latest
103+
permissions:
104+
contents: write
105+
steps:
106+
- name: Download Linux artifact
107+
uses: actions/download-artifact@v4
108+
with:
109+
name: badge-osc-server-linux-arm64
110+
path: linux-arm64
111+
112+
- name: Download macOS artifact
113+
uses: actions/download-artifact@v4
114+
with:
115+
name: badge-osc-server-macos-arm64
116+
path: macos-arm64
117+
118+
- name: Rename binaries for release
119+
run: |
120+
mv linux-arm64/badge-osc-server badge-osc-server-linux-arm64
121+
mv macos-arm64/badge-osc-server badge-osc-server-macos-arm64
122+
123+
- name: Create GitHub Release
124+
uses: softprops/action-gh-release@v2
125+
with:
126+
files: |
127+
badge-osc-server-linux-arm64
128+
badge-osc-server-macos-arm64
129+
generate_release_notes: true

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ venv/
1111
.env
1212
.venv/
1313
.idea/
14+
build/*
15+
dist/*

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,15 @@ ble-led-badge/
275275
│ ├── encryption.py # AES-ECB encryption
276276
│ ├── protocol.py # BLE UUIDs and constants
277277
│ └── text_renderer.py # Text-to-bitmap conversion
278+
├── osc_server/ # OSC server for creative tools
279+
│ ├── server.py # OSC server with scan/install/run
280+
│ └── README.md # OSC server documentation
278281
├── font-editor/ # Web-based font editor
279282
│ ├── index.html # Font editor application
280283
│ └── font.json # Font data file
284+
├── .github/workflows/ # CI/CD
285+
│ └── build-arm64.yml # Build ARM64 binaries (Linux + macOS)
286+
├── badge-osc-server.spec # PyInstaller spec for building binaries
281287
├── examples/ # Example scripts
282288
├── experiments/ # Experimental code
283289
├── initial_analysis/ # Reverse engineering notes

badge-osc-server.spec

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# -*- mode: python ; coding: utf-8 -*-
2+
# PyInstaller spec for badge-osc-server
3+
# Build with: pyinstaller badge-osc-server.spec
4+
5+
import sys
6+
import platform
7+
from PyInstaller.utils.hooks import collect_submodules
8+
9+
# Collect all bleak submodules (platform-specific backends)
10+
bleak_hiddenimports = collect_submodules('bleak')
11+
12+
# Collect all badge_controller submodules
13+
badge_hiddenimports = collect_submodules('badge_controller')
14+
15+
# dbus-fast is Linux-only (used by bleak's bluezdbus backend)
16+
dbus_imports = []
17+
if platform.system() == 'Linux':
18+
dbus_imports = [
19+
'dbus_fast',
20+
'dbus_fast.aio',
21+
'dbus_fast.service',
22+
'dbus_fast.message',
23+
'dbus_fast.constants',
24+
'dbus_fast.signature',
25+
'dbus_fast.introspection',
26+
'dbus_fast.message_bus',
27+
'dbus_fast.auth',
28+
]
29+
30+
# Exclude unused stdlib and cross-platform modules to reduce size
31+
excludes = [
32+
'tkinter', '_tkinter',
33+
'unittest',
34+
'xmlrpc',
35+
'pydoc',
36+
'doctest',
37+
'test',
38+
'multiprocessing.popen_spawn_win32',
39+
]
40+
41+
a = Analysis(
42+
['osc_server/server.py'],
43+
pathex=['.'],
44+
binaries=[],
45+
datas=[],
46+
hiddenimports=(
47+
bleak_hiddenimports
48+
+ badge_hiddenimports
49+
+ dbus_imports
50+
+ [
51+
'pythonosc',
52+
'pythonosc.osc_server',
53+
'pythonosc.dispatcher',
54+
'pythonosc.udp_client',
55+
'Crypto',
56+
'Crypto.Cipher',
57+
'Crypto.Cipher.AES',
58+
]
59+
),
60+
hookspath=[],
61+
hooksconfig={},
62+
runtime_hooks=[],
63+
excludes=excludes,
64+
noarchive=False,
65+
)
66+
67+
pyz = PYZ(a.pure)
68+
69+
exe = EXE(
70+
pyz,
71+
a.scripts,
72+
a.binaries,
73+
a.datas,
74+
[],
75+
name='badge-osc-server',
76+
debug=False,
77+
bootloader_ignore_signals=False,
78+
strip=True,
79+
upx=True,
80+
upx_exclude=[],
81+
runtime_tmpdir=None,
82+
console=True,
83+
disable_windowed_traceback=False,
84+
argv_emulation=False,
85+
target_arch=None,
86+
codesign_identity=None,
87+
entitlements_file=None,
88+
)

font-editor/similey.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
0,
2121
0,
2222
0,
23+
0,
24+
0,
25+
0,
2326
15,
2427
31,
2528
140,
@@ -71,9 +74,6 @@
7174
0,
7275
0,
7376
0,
74-
0,
75-
0,
76-
0,
7777
0
7878
]
7979
}

osc_server/README.md

Lines changed: 100 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,88 @@ An OSC (Open Sound Control) server that provides a network interface for control
44

55
## Installation
66

7+
### From source (development)
8+
79
The OSC server is part of the main project. Install dependencies using Poetry:
810

911
```bash
1012
cd /path/to/ble-led-badge
1113
poetry install
1214
```
1315

14-
## Usage
16+
### Pre-built binary (Raspberry Pi / macOS)
17+
18+
Download the latest binary for your platform from the [GitHub Releases](../../releases) page:
1519

16-
### Starting the Server
20+
- `badge-osc-server-linux-arm64` — Raspberry Pi / Linux ARM64
21+
- `badge-osc-server-macos-arm64` — macOS Apple Silicon
1722

1823
```bash
19-
# Using poetry run
20-
poetry run badge-osc-server
24+
chmod +x badge-osc-server-linux-arm64
25+
./badge-osc-server-linux-arm64 --help
26+
```
27+
28+
No Python, pip, or Poetry required when using the pre-built binary.
29+
30+
## CLI Commands
31+
32+
The tool uses subcommands. Running without a subcommand defaults to `run`.
33+
34+
```bash
35+
badge-osc-server <command> [options]
36+
```
37+
38+
| Command | Description |
39+
|---------|-------------|
40+
| `run` | Start the OSC server (default) |
41+
| `scan` | Scan for nearby BLE LED badges |
42+
| `install` | Install as a systemd service (Linux, requires root) |
43+
| `uninstall` | Remove the systemd service (Linux, requires root) |
44+
| `status` | Show systemd service status (Linux) |
45+
46+
### Scanning for badges
2147

22-
# Or with custom ports
23-
poetry run badge-osc-server --port 9000 --reply-port 9001
48+
Find the BLE address of nearby badges before connecting:
49+
50+
```bash
51+
# Scan for LED badges (filtered by service UUID and name patterns)
52+
badge-osc-server scan
53+
54+
# Scan for all BLE devices
55+
badge-osc-server scan --all
56+
57+
# Custom timeout (default 10 seconds)
58+
badge-osc-server scan --timeout 20
59+
```
60+
61+
Example output:
62+
63+
```
64+
Scanning for LED badges (10.0s)...
65+
66+
Found 1 badge(s):
67+
68+
1. LSLED
69+
Address: AA:BB:CC:DD:EE:FF
70+
```
71+
72+
### Starting the server
73+
74+
```bash
75+
# Start with defaults
76+
badge-osc-server run
77+
78+
# Or simply (run is the default subcommand)
79+
badge-osc-server
80+
81+
# With custom ports
82+
badge-osc-server run --port 9000 --reply-port 9001
2483

2584
# All options
26-
poetry run badge-osc-server --host 0.0.0.0 --port 9000 --reply-host 127.0.0.1 --reply-port 9001 --verbose
85+
badge-osc-server run --host 0.0.0.0 --port 9000 --reply-host 127.0.0.1 --reply-port 9001 --verbose
2786
```
2887

29-
### Command Line Options
88+
**`run` options:**
3089

3190
| Option | Default | Description |
3291
|--------|---------|-------------|
@@ -36,6 +95,39 @@ poetry run badge-osc-server --host 0.0.0.0 --port 9000 --reply-host 127.0.0.1 --
3695
| `--reply-port`, `-R` | `9001` | Port to send reply messages to |
3796
| `--verbose`, `-v` | - | Enable verbose logging |
3897

98+
### Installing as a systemd service (Raspberry Pi)
99+
100+
Run the pre-built binary on a Pi to install it as a service that starts on boot:
101+
102+
```bash
103+
# Install and start the service
104+
sudo ./badge-osc-server install
105+
106+
# With custom options
107+
sudo ./badge-osc-server install --port 8000 --badge-address AA:BB:CC:DD:EE:FF
108+
109+
# Check service status
110+
sudo badge-osc-server status
111+
112+
# View logs
113+
journalctl -u badge-osc-server -f
114+
115+
# Remove the service
116+
sudo badge-osc-server uninstall
117+
```
118+
119+
**`install` options:**
120+
121+
| Option | Default | Description |
122+
|--------|---------|-------------|
123+
| `--host`, `-H` | `0.0.0.0` | Host the service listens on |
124+
| `--port`, `-p` | `9000` | Port the service listens on |
125+
| `--reply-host`, `-r` | `127.0.0.1` | Host for reply messages |
126+
| `--reply-port`, `-R` | `9001` | Port for reply messages |
127+
| `--badge-address`, `-b` | - | Badge BLE address (set as `BADGE_ADDRESS` env var in service) |
128+
129+
The installer copies the binary to `/usr/local/bin/badge-osc-server` and creates a systemd unit at `/etc/systemd/system/badge-osc-server.service`.
130+
39131
## OSC Commands
40132

41133
### Connection Management

0 commit comments

Comments
 (0)