5.0 KiB
5.0 KiB
Changelog
All notable changes to the OPC DA Diagnozer are documented here. The format follows Keep a Changelog; versions bump per SemVer. Dates are YYYY-MM-DD.
[Unreleased]
Added — server discovery & browsing
list-serversverb: enumerates OPC DA servers locally or on a DCOM host via the Automation Wrapper (GetOPCServers), with a no-COM registry-scan fallback (--source registry|automation|auto), JSON output, and DA-version metadata.- Browsing of the connected server's address space, unified in the
list-items [all|branches|tags]verb:allprints the full structure tree (branches with/, tags with[ItemID: ...]),branchesthe structure-only flat list,tagsthe flat ItemID list for configtags:.--branch(dotted path or repeated segments),--depth N(1 default, 0 = whole subtree),--json. Replaces the earlier splitlist-devices/list-tags. browse.max_depthconfig key (default 32) as the address-space walk guard, validated bycheck-config; cycle-safe tree walk inopc/browse.py.SpaceNodetree data model (branch/leaf) replacing the earlier device-centricDeviceInfo.
Added — reading & CLI
readverb: one-shot read of explicit tags (or the config's tags) with a table or--json,--source device|cache, and a non-zero exit when any tag doesn't read GOOD — scriptable as a health check.probeverb: connect once and read every configured tag once.--server/--hostoverrides on every connecting verb; with--serverno config file is needed at all.- Frozen-exe default config path:
config.yamlnext to the exe (a Windows service starts withCWD = System32), not the working directory.
Added — monitoring design (D16) & config
devices:config section withDeviceEntry(name, tag, ok_values): D16 device-link indicators. The normal (connected) reading is configurable per indicator (ok_values, default[true]) — inverted fault flags[false, 0]and string states["RUN"]are first-class. Strict validation: duplicate indicators and indicator/tag-list overlap are rejected;check-configprints the indicators.- Detection rules D16 (
DEVICE_LINK_DOWN/DEVICE_LINK_UP) and the plain-text anomaly log reporter (report/textlog.pytask) specified in the docs (SPECIFICATION §6.1, §9.1; IMPLEMENTATION_PLAN Phases 1–2) — implementation pending, see TODO.md. - Clear-text status rule (spec §7): every reporter writes
NAME (0xNN)— e.g.BAD / communication failure (0x18).
Added — packaging
scripts/build_exe.ps1: PyInstaller build of the 32-bit console exe with hidden imports for the deferred COM modules (incl.win32timezone— see Fixed), embedded version metadata, a PE-bitness check, and smoke tests including a frozen-read canary against a live server.--versionand this CHANGELOG.md / TODO.md.
Fixed
- COM lifecycle: all COM references (browsers, groups, items) are released
inside the apartment before
CoUninitialize; retained exception tracebacks are cleared inas_com_error— both caused "Win32 exception occurred releasing IUnknown" noise and hard crashes at exit. - Frozen exe: every tag read failed with
SystemError: ... InvokeTypes ... exception setbecause pywin32 lazily importswin32timezoneduring VARIANT-DATE conversion and PyInstaller never bundles it — now a hidden import, with the build canary guarding it. - Reads: per-tag failures now carry the underlying exception's own type and
text (
_per_tag_error) instead of a bare "failed"; a degenerate device timestamp (never-updated alias, DST math) can no longer fail a read — the timestamp is metadata and is dropped toNone. - Matrikon browse quirk: servers may return an empty ItemID for special leaves (alias roots); the adapter falls back to the bare browse name.
- HRESULT labels:
OPC_E_UNKNOWNITEMID(0xC0040007) andOPC_E_INVALIDITEMID(0xC0040008) were swapped; now corrected everywhere.
Verified
- All CLI verbs live-tested against Matrikon OPC Simulation Server
(
Matrikon.OPC.Simulation.1): discovery, browse (all kinds/depths), reads (incl. alias tags after server-side alias repair), config-drivenmax_depth, and the frozen exe (onedir + onefile) including the read canary. - Test suite: 108 tests, all passing (pure logic + fake-client driven, runs on any OS; COM paths are live-smoke-tested on dev boxes only).
[0.1.0] - 2026-10-07
Added
- Initial project skeleton: typed YAML config with strict actionable
validation (
check-config), OPC DA quality decode tables (spec §7), event model skeletons (DiagEvent, D1–D15EventKinds), client/protocol abstractions, and the fake in-process client powering cross-OS tests. - Phase 0 decisions recorded: 32-bit interpreter mandatory (Automation Wrapper is a 32-bit in-proc DLL), ruamel.yaml over PyYAML (no 32-bit cp314 wheels), COM imports import-guarded for cross-OS test runs.