Sphere connector
sphere-connector.exe runs as the Windows service SphereConnector
on a computer on a site's network. Source: entrosity-sphere-connector
(cmd/sphere-connector, packages app, nvrs, media, driver
(dahua, sim), spool, state), sharing
entrosity-shared-go/agentkit (transport, job executor, DPAPI secret
store, logging, service wrapper) with the other Entrosity connectors. How
to install it: Connectors.
Installation
msiexec /i sphere-connector.msi /qn ENROLLMENT_TOKEN=<token> SERVER_URL=https://hub.entrosity.com/sphere
| Property | Meaning |
|---|---|
ENROLLMENT_TOKEN | A Sphere connector enrollment token (Connectors in Sphere). |
SERVER_URL | Sphere's address, including /sphere. |
- Installs to
%ProgramFiles%\Entrosity Sphere Connector\(64-bit, per machine) and registers the serviceSphereConnector(display name Entrosity Sphere Connector, LocalSystem, automatic start,run) and an Application event log source of the same name. - With both properties,
sphere-connector enrollruns as SYSTEM before the service starts; a failed enrollment rolls the install back. On a computer that is already enrolled it does nothing and succeeds. Without the properties the service starts and waits for an enrollment. - After start, the service is set to restart 30 seconds after each of its
first three failures, the count reset after a day (
sc.exe failure, best effort). - Upgrades keep the data directory, so the connector stays enrolled. The
MSI installs over any installed version, newer ones included
(
AllowDowngrades: the self-update watchdog reinstalls the previous version). Connectors built with the release key update themselves (Self-update); any connector can be upgraded by running the new MSI. - Uninstalling removes the service,
connector.dat,state.json,nvrs.jsonand the alarm queue (spool\: alarms not yet uploaded are lost); the logs are kept. - A verbose install log (
/l*v) contains the token: delete it afterwards. - Releases (tags
vX.Y.Z) publishsphere-connector.msi, itssphere-connector.msi.sha256and the EXE on the repository's GitHub release; every push tomainreplaces them on the rollingdevpre-release (version0.0.<build>-dev.<commit>). Both are also uploaded to Sphere for self-updates (Connector releases), and tenant admins download the newest from Download connector (sphere-connector-<version>.msi).
Command line
sphere-connector <command> [flags]
run run the connector (foreground, or as a service under the SCM)
--server URL --token T enroll first if not enrolled yet
--dev also drive simulated NVRs (driver "simulator")
enroll enroll this machine: --server URL --token T [--force]
(URL is the Sphere address, e.g. https://hub.example.com/sphere)
status show enrollment state, NVRs and alarms waiting for the server
install install the Windows service
uninstall remove the Windows service
version print the version
enrollon an enrolled computer printsalready enrolled (use --force to enroll again)unless--forceis given. Errors name the cause: the token is invalid (not a Sphere connector token), has no uses left, or has expired or was revoked.runwithout credentials and without--server/--tokenwaits, checking every 10 seconds, untilenrollhas stored them.statusprintsenrolled: connector <id>, server <url>,NVRs: <n>andalarms waiting for the server: <n>(ornot enrolled).- Without a command it prints the usage, flags and environment variables.
- When the server revokes the connector (removed in Sphere, tenant
suspended),
runstops.
Environment
| Variable | Default | Meaning |
|---|---|---|
SPHERE_CONNECTOR_DATA_DIR | %ProgramData%\Entrosity Sphere Connector (Windows), ~/.sphere-connector elsewhere | Data directory. |
SPHERE_LOG_LEVEL | info | debug, info, warn or error. |
SPHERE_SIM_ADDR | 127.0.0.1:9554 | RTSP address of the simulator with --dev. |
SPHERE_CONNECTOR_MAX_STREAMS | 64 | Streams published at once (64 fills an 8×8 grid); more are refused with stream_limit. |
For the service, set variables as a service environment
(HKLM\SYSTEM\CurrentControlSet\Services\SphereConnector, value
Environment, REG_MULTI_SZ) and restart it.
Files
%ProgramData%\Entrosity Sphere Connector\
connector.dat credentials {connector_id, connector_key, server_url, ws_url},
encrypted with machine-scope DPAPI
nvrs.json the NVRs it drives: each one's NVRRef, desired state and
latest credentials, sealed with machine-scope DPAPI
state.json jobs in progress (reported as failed after a restart)
spool\ the alarm queue: segments <first seq>.jsonl (4 MiB each)
and "acked" (the highest acknowledged sequence number)
logs\connector.log rotating JSON log (10 MB, 5 files, 30 days; the service also
writes warnings and errors to the Application event log)
update\ self-update: the new MSI (rmm-sphere-connector-<version>.msi),
previous.msi (rollback), update.ps1, install.log and
result.json (the outcome, read and removed at the next start)
The data directory is created with owner-only permissions. Outside
Windows the credentials are stored unencrypted (development only). A
restart resumes where the connector stopped: it signs in again to every
connected NVR in nvrs.json, and the server resends states it lost.
Network
Outbound only:
| To | Port | For |
|---|---|---|
hub.entrosity.com | TCP 443 | Sphere API and WebSocket (HTTPS), credentials |
media.entrosity.com | TCP 8322 | Media server (RTSP over TLS): published video |
| NVRs on the LAN | 80 or the HTTPS port, and 554 | The NVR's HTTP CGI API and RTSP, as set per NVR in Sphere |
The media server's certificate is verified against the system roots. The NVRs' self-signed certificates are not verified (digest authentication never sends the password itself). RTSP to the NVR and to the media server runs over TCP.
Drivers
| Driver | What |
|---|---|
dahua | Dahua NVRs and OEM NVRs on the same firmware: HTTP CGI API with digest authentication, and RTSP. |
simulator | Software NVRs, with run --dev only: 4 channels, channel 1 PTZ, a motion alarm about once a minute, a continuous recording per hour for the last 24 hours, an in-process RTSP server laid out like a Dahua NVR's. See Trying Sphere with the simulator. |
Drivers implement one interface (internal/driver): sign in, describe
the NVR, check it, follow its events, PTZ, find recordings, take a
snapshot, shorten the sub streams' keyframe interval, and build the RTSP addresses of live and recorded streams.
Channels are 1-based everywhere outside the driver.
Dahua endpoints
| Endpoint | Used for |
|---|---|
/cgi-bin/magicBox.cgi?action=getDeviceType | Sign-in check and the model (also the 30-second check) |
/cgi-bin/magicBox.cgi?action=getSerialNo, getSoftwareVersion, getProductDefinition&name=MaxRemoteInputChannels | Serial number, firmware, number of channels |
/cgi-bin/devVideoInput.cgi?action=getCollect | Number of channels (fallback) |
/cgi-bin/configManager.cgi?action=getConfig&name=ChannelTitle, Encode, NTP | Camera titles, main and sub stream codecs, the NVR's time zone; Encode also the sub streams' frame rate and keyframe interval for sphere.nvr.tune_live |
/cgi-bin/configManager.cgi?action=setConfig&Encode[i].ExtraFormat[0].Video.GOP=… | sphere.nvr.tune_live: a camera's sub-stream keyframe interval, in frames (main streams are never changed) |
/cgi-bin/LogicDeviceManager.cgi?action=getCameraState | Which channels have a camera signal |
/cgi-bin/ptz.cgi?action=getCurrentProtocolCaps | Whether a camera is PTZ |
/cgi-bin/ptz.cgi?action=start|stop&channel=N&code=…&arg1=…&arg2=…&arg3=0 | PTZ commands (speed 1–8, default 4; preset number) |
/cgi-bin/eventManager.cgi?action=attach&codes=[All]&heartbeat=5 | The event stream (alarms) |
/cgi-bin/mediaFileFind.cgi (factory.create, findFile, findNextFile, close, destroy) | Recording search (.dav files, in the NVR's local time) |
/cgi-bin/snapshot.cgi?channel=N | Snapshots |
RTSP /cam/realmonitor?channel=N&subtype=0|1 | Live main (0) and sub (1) streams |
RTSP /cam/playback?channel=N&starttime=YYYY_MM_DD_HH_MM_SS&endtime=… | Recordings |
CGI requests time out after 10 seconds (the event stream has no timeout). The NVR user needs the rights for what Sphere does with it: live view, playback, PTZ and events.
Jobs and lanes
| Lane | Jobs | Parallelism |
|---|---|---|
config | sphere.nvr.apply, sphere.nvr.remove | 1 |
probe | sphere.nvr.test, sphere.recordings.find, sphere.nvr.tune_live | 2 |
stream | sphere.stream.start, sphere.stream.stop, sphere.playback.start, sphere.playback.stop | 8 |
ptz | sphere.ptz | 4 (never behind a stream start) |
snapshot | sphere.snapshot | 2 |
update | update_agent | 1 |
Payloads and results: Sphere connector protocol.
Timing
| What | Interval |
|---|---|
| Heartbeat | 1 minute |
| Check of each connected NVR | 30 seconds |
| NVR description read again | 5 minutes |
| NVR reconnect back-off | 1 to 30 seconds |
| Status report | 30 seconds, and 200 ms after each change |
| Upload of the alarm queue | At once when alarms arrive, else every 5 seconds; back-off up to 1 minute on errors |
| Resend of an unacknowledged alarm chunk over HTTP | 15 seconds |
| Stream start | 8 seconds for the NVR to play and the media server to accept |
| Stream stall | 10 seconds without video from the NVR reconnects the stream; back-off 1 to 30 seconds |
| Snapshot upload | 30 seconds |
| Reconnect to Sphere | Exponential back-off with jitter, as for Axis agents (Protocol) |
The connector announces the capability video in hello, and update
when it is built with the release public key.
Self-update
Sphere offers a newer connector version as an update_agent job
(component: sphere-connector, Sphere connector protocol);
how releases get there: Running Entrosity Sphere.
- The job carries the release (
target) and, when Sphere has it, the MSI of the running version (rollback), each with an Ed25519 signature over its component, version, SHA-256 and size. The connector checks the signatures against the public key built into it (RELEASE_PUBLIC_KEYat build time,-X github.com/entrosity/entrosity-shared-go/agentkit/update.PublicKey=) before downloading anything: a build without the key answersupdate_unsigned, a bad signaturesignature_invalid. - It downloads both MSIs from the job's links (valid 2 hours) into
<data dir>\update\, checks their SHA-256 and size (download_failed,hash_mismatch), and registers a one-shot SYSTEM scheduled taskSphereConnectorUpdatethat starts a minute later (its own name, so an Axis or Edge connector on the same computer keeps its own task). The job succeeds withUpdateResult{scheduled, from_version, to_version, rollback}. - The task runs
msiexec /i <new MSI> /qn /norestart. Its watchdog then waits (up to five minutes) for theSphereConnectorservice to be running and still running a minute later; if it is not, it installs the previous MSI again (the MSI allows downgrades) and starts the service. The task then removes itself. - The outcome (
installed,rolled_backorfailed, both versions and the detail) is written toupdate\result.jsonand logged at the next start (connector update finished); the new version is reported inhelloand shows in Connectors.
Job errors: update_unsigned, signature_invalid, download_failed,
hash_mismatch, exec_failed (the update folder or the scheduled task
could not be created), invalid_payload. A job for the version already
running succeeds at once.
Connectors built without RELEASE_PUBLIC_KEY do not announce update
and are never offered updates: install the new version by hand once
(Connectors → Updates).
Development
The repository needs entrosity-shared-go checked out next to it, with a
go.work (git-ignored) that uses both, until the shared module is tagged
with proto/sphere.
make build-local
dist/sphere-connector enroll --server http://localhost:5175/sphere --token <token>
make dev # sphere-connector run --dev, data in ~/.sphere-connector
make lint vet test
make vet also vets GOOS=windows; make build cross-compiles
dist/sphere-connector.exe (make build RELEASE_PUBLIC_KEY=<base64>
builds in the release key; without it the build does not update itself); make msi (Windows, PowerShell 7 and the
.NET SDK) builds the MSI with WiX v4. The tests run the whole connector
against a fake backend, the simulator and a fake media server, and the
relay against plain RTSP and RTSP through a TLS-terminating proxy, as in
production.