Parallel expert review of the four-commit scaffold surfaced 13 actionable
items split across API design, ONVIF domain accuracy, Go idiomaticity and
test rigor. This change addresses them before the Stream type lands, when
the public surface is still cheap to move.
API shape (hard-to-reverse before tagging)
------------------------------------------
* Rename EventKind -> Kind and EventState -> State to avoid the
stream.EventKind / stream.EventState stutter when imported.
* Restructure Event for non-lossy decode:
- Source string and RawValue string replaced with Source/Data maps so
multi-item ONVIF Source and Data lists (e.g. AXIS AOA emitting
active+classType+confidence; DigitalInput carrying InputToken+
LogicalState) are preserved.
- Add DeviceID so a single channel can fan in events from multiple
cameras.
- Add DeviceTime parsed from wsnt:UtcTime alongside the local
observation Timestamp. The earlier doc-comment decision to bake-in
'drop UtcTime' was a policy disguised as an API; expose both and let
callers choose.
Classifier accuracy (ONVIF domain audit)
----------------------------------------
* Introduce KindImageQuality for tns1:VideoSource/ImageTooDark|Bright|
Blurry. These are imaging-quality alarms that integrators route
separately because they fire on sunset/dawn/condensation, not tamper.
Previously mis-classified as KindTampering.
* Add tns1:VideoSource/GlobalSceneChange -> KindTampering, which is the
real lens-cover signal on firmwares without TamperDetector.
* Anchor the TamperDetector rule to 'TamperDetector/Tamper' so a
hypothetical 'TamperDetectorLog' path cannot match.
* Narrow MyRuleDetector from container-match to an explicit whitelist
(HumanDetect, VehicleDetect, PeopleDetect, ObjectsInside, FaceDetect).
Bosch publishes Counter and Occupancy under MyRuleDetector too; those
must not classify as ObjectDetected.
* Add the AXIS Guard suite (MotionGuard, FenceGuard, LoiteringGuard) ->
KindMotion. Common on AXIS deployments configured with these apps
instead of basic VMD.
* Drop the bogus Device1ScenarioANY test fixture; AOA uses numeric
scenarios (Device1Scenario1, Device1Scenario2). The 'ANY' suffix was a
borrow from the older Guard suite's Camera1ProfileANY pattern.
* Document the edge-trigger semantics of LineDetector/Crossed in the rule
comment so decoder consumers do not expect a State boolean.
Tests
-----
* String tests now use t.Run subtests so failures name the case.
* TestKindStringsAreUnique guards against accidental String() aliasing
when adding new kinds.
* TestEventFieldAssignmentRoundTrip exercises the new field set
including DeviceID, Source/Data maps and DeviceTime.
* Canonicalisation table now covers: double slash, colon-only segment,
trailing colon, multi-colon-in-segment, leading/trailing slash,
no-colon passthrough. Locks the actual behaviour so future refactors
see regressions.
* False-positive negatives: Counter and Occupancy under MyRuleDetector,
AudioEncoderConfiguration, RelayFailure, DigitalInputConfiguration,
TamperDetectorLog, MotionRecording/Started — all assert KindUnknown.
* TestClassifyRuleOrder_ObjectAnalyticsBeforeGenericObjects pins the
ordering invariant called out by the architect reviewer.
Documentation
-------------
* doc.go trimmed so it does not advertise NewStream / Events / Errors /
Close before those identifiers exist — the godoc reader will no longer
see dead names. Re-expanded when the Stream type lands.
Deferred to the Stream commit
-----------------------------
* PropertyUnknown vs PropertyUnset disambiguation — kept as
PropertyUnknown for now with a clarified doc comment; revisit when the
decoder needs to distinguish 'absent on wire' from 'unparseable'.
* Classifier pluggability (WithClassifier option) — meaningful only once
there is a Stream; revisit at that commit.
Onvif library
Simple management of onvif IP-devices cameras. onvif is an implementation of ONVIF protocol for managing onvif IP devices. The purpose of this library is convenient and easy management of IP cameras and other devices that support ONVIF standard.
Overview
This repository is forked from: use-go/onvif
Supported services
The following services are implemented:
- Device
- Media
- PTZ
- Event
- Discovery
Using
General concept
- Connecting to the device
- Authentication (if necessary)
- Defining Data Types
- Carrying out the required method
Connecting to the device
If there is a device on the network at the address 192.168.13.42, and its ONVIF services use the 1234 port, then you can connect to the device in the following way:
dev, err := onvif.NewDevice(onvif.DeviceParams{Xaddr: "192.168.13.42:1234"})
The ONVIF port may differ depending on the device , to find out which port to use, you can go to the web interface of the device. Usually this is 80 port.
Authentication
If any function of the ONVIF services requires authentication, you must use the Authenticate method.
device := onvif.NewDevice(onvif.DeviceParams{Xaddr: "192.168.13.42:1234", Username: "username", Password: password})
Defining Data Types
Each ONVIF service in this library has its own package, in which all data types of this service are defined, and the package name is identical to the service name and begins with a capital letter. onvif defines the structures for each function of each ONVIF service supported by this library. Define the data type of the GetCapabilities function of the Device service. This is done as follows:
capabilities := device.GetCapabilities{Category:"All"}
Why does the GetCapabilities structure have the Category field and why is the value of this field All?
The figure below shows the documentation for the GetCapabilities. It can be seen that the function takes one Category parameter and its value should be one of the following: 'All', 'Analytics',' Device ',' Events', 'Imaging', 'Media' or 'PTZ'`.
An example of defining the data type of GetServiceCapabilities function in PTZ:
ptzCapabilities := ptz.GetServiceCapabilities{}
The figure below shows that GetServiceCapabilities does not accept any arguments.
Common data types are in the xsd/onvif package. The types of data (structures) that can be shared by all services are defined in the onvif package.
An example of how to define the data type of the CreateUsers function in Devicemgmt:
createUsers := device.CreateUsers{User: onvif.User{Username:"admin", Password:"qwerty", UserLevel:"User"}}
The figure below shows that ,in this example, the CreateUsers structure field must be a User whose data type is the User structure containing the Username, Password, UserLevel, and optional Extension fields. The User structure is in the onvif package.
Carrying out the required method
To perform any function of one of the ONVIF services whose structure has been defined, you must use the CallMethod of the device object.
createUsers := device.CreateUsers{User: onvif.User{Username:"admin", Password:"qwerty", UserLevel:"User"}}
device := onvif.NewDevice(onvif.DeviceParams{Xaddr: "192.168.13.42:1234", Username: "username", Password: password})
device.Authenticate("username", "password")
resp, err := dev.CallMethod(createUsers)
Development
See here


