🚧 WIP
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to the OPC DA Diagnozer are documented here. The format
|
||||
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions
|
||||
bump per [SemVer](https://semver.org/). Dates are YYYY-MM-DD.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added — server discovery & browsing
|
||||
- `list-servers` verb: 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: `all` prints the full structure tree
|
||||
(branches with `/`, tags with `[ItemID: ...]`), `branches` the structure-only
|
||||
flat list, `tags` the flat ItemID list for config `tags:`. `--branch`
|
||||
(dotted path or repeated segments), `--depth N` (1 default, 0 = whole
|
||||
subtree), `--json`. Replaces the earlier split `list-devices`/`list-tags`.
|
||||
- `browse.max_depth` config key (default 32) as the address-space walk guard,
|
||||
validated by `check-config`; cycle-safe tree walk in `opc/browse.py`.
|
||||
- `SpaceNode` tree data model (branch/leaf) replacing the earlier
|
||||
device-centric `DeviceInfo`.
|
||||
|
||||
### Added — reading & CLI
|
||||
- `read` verb: 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.
|
||||
- `probe` verb: connect once and read every configured tag once.
|
||||
- `--server` / `--host` overrides on every connecting verb; with `--server` no
|
||||
config file is needed at all.
|
||||
- Frozen-exe default config path: `config.yaml` next to the exe (a Windows
|
||||
service starts with `CWD = System32`), not the working directory.
|
||||
|
||||
### Added — monitoring design (D16) & config
|
||||
- `devices:` config section with `DeviceEntry(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-config` prints the indicators.
|
||||
- Detection rules D16 (`DEVICE_LINK_DOWN`/`DEVICE_LINK_UP`) and the plain-text
|
||||
anomaly log reporter (`report/textlog.py` task) 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.
|
||||
- `--version` and 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 in `as_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 set` because pywin32 lazily
|
||||
imports `win32timezone` during 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 to `None`.
|
||||
- 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) and
|
||||
`OPC_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-driven
|
||||
`max_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–D15 `EventKind`s), 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.
|
||||
Reference in New Issue
Block a user