clean up whep delivery

This commit is contained in:
legop3
2025-11-14 01:45:06 -05:00
parent 31e31bfe2d
commit c0dce561bd
9 changed files with 40 additions and 28 deletions
+1 -1
View File
@@ -56,7 +56,7 @@ cd ~/MultiRoombaRover
sudo ./pi/install_roverd.sh --mediamtx
```
Then point each rover's `/etc/roverd.yaml` at `ws://<server>:8080/rover`, set (or leave blank to auto-derive) `media.whepUrl` for the Pis mediaMTX instance (defaults to `http://<pi-ip>:8889/whep/rovercam`), enable the sensor stream from the UI, and drive with WASD.
Then point each rover's `/etc/roverd.yaml` at `ws://<server>:8080/rover`, enable the sensor stream from the UI, and drive with WASD. `roverd` automatically advertises its local mediaMTX WHEP endpoint (derived from the Pis DHCP address), so no video URL configuration is required unless you want to override the defaults.
Use the “Restart Camera” button if you enable media management so roverd can bounce the mediamtx service remotely.
Heads-up: the BRC pulser now uses libgpiod; make sure the `roverd` service account is in the `gpio` group (or otherwise allowed to access `/dev/gpiochip*`) and set `brc.gpioChip` if your hardware exposes a different chip name.
-1
View File
@@ -14,7 +14,6 @@ battery:
urgent: 1650
maxWheelSpeed: 350
media:
whepUrl: http://dummy1.local:8889/whep/rovercam
manage: false
service: mediamtx.service
healthUrl: http://127.0.0.1:9997/v3/paths/list
-1
View File
@@ -14,7 +14,6 @@ battery:
urgent: 1650
maxWheelSpeed: 350
media:
whepUrl: http://dummy2.local:8889/whep/rovercam
manage: false
service: mediamtx.service
healthUrl: http://127.0.0.1:9997/v3/paths/list
Vendored
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -5,7 +5,7 @@ Each rover runs mediaMTX locally to capture the Pi camera, and the control serve
## Pi (publisher)
- mediaMTX samples the Pi camera (`paths.rovercam.source: rpiCamera`) and exposes the HTTP API on `http://127.0.0.1:9997`.
- `/etc/roverd.yaml` contains `media.whepUrl`, pointing at the Pis own WHEP endpoint (e.g. `http://roomba-alpha.local:8889/whep/rovercam`). This is what the central server will pull.
- `roverd` automatically detects the Pis own WHEP endpoint (e.g. `http://roomba-alpha.local:8889/whep/rovercam`) and reports a `bridgeWhepUrl` (converted to `whep://.../whep`) to the server. No manual per-rover video URL configuration is required.
- The `media.manage` flag keeps the local service alive via `systemctl` and hits the API for health checks (`media.healthUrl`, defaults to `http://127.0.0.1:9997/v3/paths/list`).
## Control server (viewer)
+33
View File
@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"net"
"net/url"
"os"
"strings"
"time"
@@ -59,6 +60,7 @@ type MediaConfig struct {
WhepPort int `yaml:"whepPort" json:"-"`
WhepPath string `yaml:"whepPath" json:"-"`
LegacyPublish string `yaml:"publishUrl,omitempty" json:"-"`
BridgeWhepURL string `yaml:"-" json:"bridgeWhepUrl,omitempty"`
Manage bool `yaml:"manage"`
Service string `yaml:"service"`
HealthURL string `yaml:"healthUrl"`
@@ -141,9 +143,40 @@ func LoadConfig(path string) (*Config, error) {
scheme := "http"
cfg.Media.WhepURL = fmt.Sprintf("%s://%s:%d%s", scheme, ip, effectivePort(cfg.Media.WhepPort), path)
}
if bridge, err := buildBridgeURL(cfg.Media.WhepURL); err == nil {
cfg.Media.BridgeWhepURL = bridge
}
return &cfg, nil
}
func buildBridgeURL(src string) (string, error) {
if src == "" {
return "", errors.New("empty whep url")
}
parsed, err := url.Parse(src)
if err != nil {
return "", err
}
if parsed.Host == "" {
return "", errors.New("missing host")
}
proto := "whep"
if parsed.Scheme == "https" {
proto = "wheps"
}
path := parsed.Path
if path == "" || path == "/" {
path = "/"
}
if !strings.HasSuffix(path, "/whep") {
if !strings.HasSuffix(path, "/") {
path += "/"
}
path += "whep"
}
return fmt.Sprintf("%s://%s%s", proto, parsed.Host, path), nil
}
func ensureLeadingSlash(path string) string {
if !strings.HasPrefix(path, "/") {
return "/" + path
-1
View File
@@ -15,7 +15,6 @@ battery:
urgent: 1650
maxWheelSpeed: 350
media:
whepUrl: http://roomba-alpha.local:8889/whep/rovercam
manage: false
service: mediamtx.service
healthUrl: http://127.0.0.1:9997/v3/paths/list
-1
View File
@@ -15,7 +15,6 @@ battery:
urgent: 1650
maxWheelSpeed: 350
media:
whepUrl: http://roomba-alpha.local:8889/whep/rovercam
manage: false
service: mediamtx.service
healthUrl: http://127.0.0.1:9997/v3/paths/list
+5 -22
View File
@@ -36,8 +36,12 @@ async function syncRover(record) {
await removePath(record?.id);
return;
}
const source = normalizeSource(record.meta.media.whepUrl);
const source = record.meta.media.bridgeWhepUrl;
if (!source) {
logger.warn(
'rover %s missing bridgeWhepUrl; video bridge disabled for this rover',
record.id
);
await removePath(record.id);
return;
}
@@ -81,27 +85,6 @@ async function removePath(roverId) {
}
}
function normalizeSource(raw) {
if (!raw) return null;
const trimmed = raw.trim();
if (!trimmed) return null;
try {
const parsed = new URL(/^[a-z]+:\/\//i.test(trimmed) ? trimmed : `http://${trimmed}`);
const protocol = parsed.protocol === 'https:' ? 'wheps' : 'whep';
let path = parsed.pathname || '/';
if (!path.endsWith('/whep')) {
if (!path.endsWith('/')) {
path += '/';
}
path += 'whep';
}
return `${protocol}://${parsed.host}${path}`;
} catch (err) {
logger.warn('invalid WHEP URL: %s (%s)', raw, err.message);
return null;
}
}
async function callApi(method, path, body) {
const url = `${apiBase}${path}`;
const res = await fetch(url, {