Skip to content

API reference

Python: hypernova.Subscriber

Subscriber(name, *, registry=None, network=None,
           address=None, publisher_id=None, writer_group_id=None,
           dataset_writer_id=None, field_names=None)

Resolve name at the registry (registry URL, default $HYPERNOVA_REGISTRY or http://localhost:4850; several comma-separated URLs give DIP-style primary/secondary failover — lookups try them in order, publishers register with every one) and receive its stream. network asks the registry for that network's endpoint (relayed copies). Passing address + ids skips the registry entirely. Successful lookups are cached under ~/.cache/hypernova/ (override with $HYPERNOVA_CACHE), so a subscriber restart works with the registry down; only a first-ever lookup needs it. Raises RegistryError with a precise message otherwise.

Use as a context manager, or call start() / stop():

Member Meaning
updates(timeout=None) Iterator of Updates; with a timeout, stops after that many silent seconds
get(timeout=5.0) Next Update or TimeoutError
dropped_updates Updates discarded because the consumer was too slow (queue of 1000)
undecodable_datagrams Datagrams on the port that were not valid UADP

Update: name, sequence_number, received_at, and values — a dict of field name → FieldValue.

FieldValue: type (BuiltinType), value (scalar or list for arrays), status (OPC UA StatusCode, is_good property), source_timestamp (source_datetime property).

Python: hypernova.Publisher

Publisher(name, *, fields, address, publisher_id, writer_group_id,
          dataset_writer_id, publisher_id_type="UINT16", registry=None,
          description="", endpoints=None, ttl=1, register=True)

fields is an ordered dict of field name → type name ("DOUBLE", "INT32[]", ... — the order defines the wire order). Construction registers the publication (replace=true) unless register=False; an unreachable registry only clears publisher.registered — publishing proceeds.

send(**values) publishes one DataSetMessage; every declared field is required (mismatches raise ValueError naming the offender). Per-field status: send(x=5, _status={"x": STATUS_BAD}); timestamp override: send(x=5, _timestamp=datetime(...)). Fields are DataValue-encoded (value + status + source time). renew() refreshes the registry lease.

Wire codec: hypernova.wire

encode_network_message(message, *, datavalue_fields=True) / decode_network_message(data) — the UADP profile spoken by supernova and open62541 (see ARCHITECTURE.md). Raises WireError with a diagnostic on anything unsupported. Scalars and one-dimensional arrays of: Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float, Double, String, DateTime.

Registry REST

Method + path Meaning
GET /api/publications All publications with live state (rate, staleness, loss)
GET /api/publications/{name} One publication + last values (quality, source time)
PUT /api/publications/{name} Register; body per below; 409 on name/stream collision, 400 with a precise message on malformed input
POST /api/publications/{name}/renew Refresh the lease
DELETE /api/publications/{name} Remove
GET /api/lookup/{name}?network=N Subscriber-facing coordinates (per-network endpoint if registered)
GET /api/health Service, version, counts
GET /api/types Accepted field type names

Registration body:

{
  "address": "opc.udp://239.10.0.1:14840",
  "publisherId": 42, "publisherIdType": "UINT16",
  "writerGroupId": 100, "dataSetWriterId": 1,
  "fields": [{"name": "temperature", "type": "DOUBLE"}],
  "endpoints": {"officenet": "opc.udp://10.147.0.5:24840"},
  "description": "optional", "leaseSeconds": 600, "replace": false
}

CLI

hypernova registry [--bind H] [--port 4850] [--store FILE]
hypernova relay CONFIG.json
hypernova browse [--registry URL]
hypernova sub NAME [--network N] [--count N] [--timeout S] [--registry URL]
hypernova pub NAME --address A --publisher-id P --writer-group-id W
              --dataset-writer-id D --field n=TYPE... --value n=V...
              [--interval S] [--count N] [--ramp] [--registry URL]
hypernova register NAME --address A --publisher-id P --writer-group-id W
              --dataset-writer-id D --field n=TYPE...
              [--endpoint NET=ADDR]... [--replace] [--registry URL]

sub waits (within --timeout) for a name that isn't registered yet — subscribers may start before their publishers. Relay config format is documented in hypernova/relay.py and deployment.md.