Skip to main content

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
PropertyMeaning
ENROLLMENT_TOKENA Sphere connector enrollment token (Connectors in Sphere).
SERVER_URLSphere's address, including /sphere.
  • Installs to %ProgramFiles%\Entrosity Sphere Connector\ (64-bit, per machine) and registers the service SphereConnector (display name Entrosity Sphere Connector, LocalSystem, automatic start, run) and an Application event log source of the same name.
  • With both properties, sphere-connector enroll runs 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.json and 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) publish sphere-connector.msi, its sphere-connector.msi.sha256 and the EXE on the repository's GitHub release; every push to main replaces them on the rolling dev pre-release (version 0.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
  • enroll on an enrolled computer prints already enrolled (use --force to enroll again) unless --force is given. Errors name the cause: the token is invalid (not a Sphere connector token), has no uses left, or has expired or was revoked.
  • run without credentials and without --server/--token waits, checking every 10 seconds, until enroll has stored them.
  • status prints enrolled: connector <id>, server <url>, NVRs: <n> and alarms waiting for the server: <n> (or not enrolled).
  • Without a command it prints the usage, flags and environment variables.
  • When the server revokes the connector (removed in Sphere, tenant suspended), run stops.

Environment​

VariableDefaultMeaning
SPHERE_CONNECTOR_DATA_DIR%ProgramData%\Entrosity Sphere Connector (Windows), ~/.sphere-connector elsewhereData directory.
SPHERE_LOG_LEVELinfodebug, info, warn or error.
SPHERE_SIM_ADDR127.0.0.1:9554RTSP address of the simulator with --dev.
SPHERE_CONNECTOR_MAX_STREAMS64Streams 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:

ToPortFor
hub.entrosity.comTCP 443Sphere API and WebSocket (HTTPS), credentials
media.entrosity.comTCP 8322Media server (RTSP over TLS): published video
NVRs on the LAN80 or the HTTPS port, and 554The 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​

DriverWhat
dahuaDahua NVRs and OEM NVRs on the same firmware: HTTP CGI API with digest authentication, and RTSP.
simulatorSoftware 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​

EndpointUsed for
/cgi-bin/magicBox.cgi?action=getDeviceTypeSign-in check and the model (also the 30-second check)
/cgi-bin/magicBox.cgi?action=getSerialNo, getSoftwareVersion, getProductDefinition&name=MaxRemoteInputChannelsSerial number, firmware, number of channels
/cgi-bin/devVideoInput.cgi?action=getCollectNumber of channels (fallback)
/cgi-bin/configManager.cgi?action=getConfig&name=ChannelTitle, Encode, NTPCamera 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=getCameraStateWhich channels have a camera signal
/cgi-bin/ptz.cgi?action=getCurrentProtocolCapsWhether a camera is PTZ
/cgi-bin/ptz.cgi?action=start|stop&channel=N&code=…&arg1=…&arg2=…&arg3=0PTZ commands (speed 1–8, default 4; preset number)
/cgi-bin/eventManager.cgi?action=attach&codes=[All]&heartbeat=5The 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=NSnapshots
RTSP /cam/realmonitor?channel=N&subtype=0|1Live 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​

LaneJobsParallelism
configsphere.nvr.apply, sphere.nvr.remove1
probesphere.nvr.test, sphere.recordings.find, sphere.nvr.tune_live2
streamsphere.stream.start, sphere.stream.stop, sphere.playback.start, sphere.playback.stop8
ptzsphere.ptz4 (never behind a stream start)
snapshotsphere.snapshot2
updateupdate_agent1

Payloads and results: Sphere connector protocol.

Timing​

WhatInterval
Heartbeat1 minute
Check of each connected NVR30 seconds
NVR description read again5 minutes
NVR reconnect back-off1 to 30 seconds
Status report30 seconds, and 200 ms after each change
Upload of the alarm queueAt once when alarms arrive, else every 5 seconds; back-off up to 1 minute on errors
Resend of an unacknowledged alarm chunk over HTTP15 seconds
Stream start8 seconds for the NVR to play and the media server to accept
Stream stall10 seconds without video from the NVR reconnects the stream; back-off 1 to 30 seconds
Snapshot upload30 seconds
Reconnect to SphereExponential 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.

  1. 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_KEY at build time, -X github.com/entrosity/entrosity-shared-go/agentkit/update.PublicKey=) before downloading anything: a build without the key answers update_unsigned, a bad signature signature_invalid.
  2. 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 task SphereConnectorUpdate that starts a minute later (its own name, so an Axis or Edge connector on the same computer keeps its own task). The job succeeds with UpdateResult {scheduled, from_version, to_version, rollback}.
  3. The task runs msiexec /i <new MSI> /qn /norestart. Its watchdog then waits (up to five minutes) for the SphereConnector service 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.
  4. The outcome (installed, rolled_back or failed, both versions and the detail) is written to update\result.json and logged at the next start (connector update finished); the new version is reported in hello and 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.