Commit Graph

885 Commits

Author SHA1 Message Date
Joseph Doherty d48674ba31 fix(opcuaclient): review — UTC-kind the missing-time sentinel + test hardening
Code-review I2: CoerceDateTime's missing-field sentinel was DateTime.MinValue
(Kind=Unspecified) — a downstream .ToUniversalTime() could shift it; now UTC-kinded.
M4: assert BrowsePath namespace==0 + the sentinel's UTC Kind.
2026-06-18 06:05:58 -04:00
Joseph Doherty e859963853 feat(opcuaclient): add BuildBaseEventFilter + MapHistoryEvents pure cores 2026-06-18 06:02:11 -04:00
Joseph Doherty b47fc10ec0 feat(adminui): CertificateStoreManager — by-thumbprint trust/untrust/delete 2026-06-18 05:04:36 -04:00
Joseph Doherty 15922d8483 test(galaxy): live-gw smoke — writer borrows subscription handle, skips AddItem
Subscribe a real tag, register its gateway item handle, write via the
registry-wired writer: asserts the borrowed-handle write commits Good with
AddItemCallCount==0 (control with no source: ==1). Proves the subscription
handle is usable for a committing no-login supervisory write. Skip-gated on
MXGW_ENDPOINT + GALAXY_MXGW_API_KEY; verified live vs 10.100.0.48:5120 (3/3).
2026-06-18 04:34:11 -04:00
Joseph Doherty e9da9c29d2 fix(galaxy): authoritative handle resolution + review cleanups
Make SubscriptionRegistry.TryResolveItemHandle confirm a live subscription
genuinely binds fullRef->handle (via the reverse index) rather than trusting
the forward-map hint + a bare liveness check. Fixes the cross-ref-same-handle
hazard (wrong-tag borrow) while preserving the legitimate
multiple-subscriptions-per-tag borrow. Adds cross-ref + same-ref-multi-sub
tests; drops a duplicate SubscriptionEntry <summary>; documents the writer's
supervisory-advise reconnect lifecycle.
2026-06-18 04:29:45 -04:00
Joseph Doherty 2e3f528afc feat(galaxy): writer borrows live subscription item handles (skip redundant AddItem)
GatewayGalaxyDataWriter now accepts an optional subscribedHandleSource
delegate; TryResolveCachedOrBorrowed checks _itemHandles first then the
source, so the first write to an already-subscribed tag skips the
AddItem round-trip. Borrowed handles are not cached (subscription
registry owns lifecycle). AddItemCallCount seam confirms gateway calls.
2026-06-18 04:18:35 -04:00
Joseph Doherty 1411950077 feat(galaxy): SubscriptionRegistry.TryResolveItemHandle forward lookup
Add _itemHandleByFullRef (OrdinalIgnoreCase ConcurrentDictionary) maintained
in lock-step with _subscribersByItemHandle across Register/Remove/Rebind.
TryResolveItemHandle cross-checks the authoritative reverse map so a stale
forward entry can never hand out a dead handle. Also wires the scaffolded
_addItemCallCount increment in EnsureItemHandleAsync (field was declared but
never assigned, causing a TreatWarningsAsErrors build failure on the branch).
8 new xUnit + Shouldly facts covering register/case-insensitive/remove/rebind/
failed-handle/liveness-guard paths.
2026-06-18 04:18:01 -04:00
Joseph Doherty ac3450d5f4 fix(adminui): ctx-receiver guard + truthful SetVirtualTag hover in script-editor completions 2026-06-18 02:39:12 -04:00
Joseph Doherty 4a7b0fde7b fix(abcip): thread CIP template-instance-id so discovered-UDT expansion works in production (review) 2026-06-17 20:30:12 -04:00
Joseph Doherty fdd6b332fe fix(twincat): update BrowseSymbolsAsync doc + cache adapter fields + Flat-mode note (review)
- ITwinCATClient.BrowseSymbolsAsync XML doc updated: states the implementation now
  expands struct/UDT/FB symbols into atomic member leaves via TwinCATSymbolExpander;
  callers receive only atomic/array leaves with full InstancePaths, never struct containers.
- AdsSymbolNode: cache IsStruct, Mapped, Children, ReadOnly as readonly fields computed
  once in the ctor so repeated property access during recursive expansion doesn't
  re-materialize or re-invoke MapSymbolType/IsSymbolWritable.
- BrowseSymbolsAsync: add operator-gated live risk note next to SymbolsLoadMode.Flat
  warning that a real TC3 target may not populate SubSymbols in Flat mode, with
  guidance to switch to VirtualTree if members don't surface — do not change mode now.
- TwinCATSymbolExpanderTests: simplify confusing `new string('.', 0)` no-op to `""`.
2026-06-17 20:22:45 -04:00
Joseph Doherty 4e1414026e feat(abcip): expand controller-discovered UDTs into addressable member variables 2026-06-17 20:11:41 -04:00
Joseph Doherty 2e6c6d3ab6 feat(historian): page within oversized tie clusters (#400) instead of loud-failing 2026-06-17 20:11:09 -04:00
Joseph Doherty 3699fc16a8 feat(twincat): expand discovered struct/UDT symbols into addressable member leaves 2026-06-17 20:05:01 -04:00
Joseph Doherty 098adf43d0 fix(ablegacy): dispose per-parent RMW locks on teardown (review symmetry)
DisposeRuntimes() now disposes and clears _rmwLocks, _creationLocks, and
_runtimeLocks so ReinitializeAsync/ShutdownAsync cycles don't orphan their
SemaphoreSlim instances. Mirrors the TwinCAT _bitRmwLocks fix already shipped.
2026-06-17 12:10:42 -04:00
Joseph Doherty c48f299994 test(ablegacy): bit write surfaces device rejection status (review)
Adds `Bit_write_surfaces_device_rejection_status` to AbLegacyBitRmwTests,
verifying that a non-zero libplctag status returned by the parent-word write
in WriteBitInWordAsync propagates as a non-Good OPC UA StatusCode rather than
being silently swallowed. Added a minimal `WriteStatusOverride` hook to
FakeAbLegacyTag (test-project-only) so the read half of the RMW still
returns 0/Good while the write half returns the seeded error code.
2026-06-17 12:02:10 -04:00
Joseph Doherty 340c145e87 fix(twincat): dispose bit-RMW locks on shutdown + guard null parent read (review) 2026-06-17 12:01:55 -04:00
Joseph Doherty a73e20fb28 feat(twincat): BOOL-within-word writes via driver-level parent-word RMW 2026-06-17 11:55:44 -04:00
Joseph Doherty 5c6b7cd6f9 feat(ablegacy): B/I/O-file bit-within-word writes via existing RMW path 2026-06-17 11:54:03 -04:00
Joseph Doherty 988a7a938f fix(s7): UInt64 box cast + Timer/Counter transient-write returns BadNotWritable (final review)
M1: add missing (object) cast to UInt64 arm of DecodeScalarBlock switch expression,
matching the Int64 arm style and the comment that each arm is boxed explicitly.
M2: short-circuit Timer/Counter writes in WriteAsync to BadNotWritable before
WriteOneAsync, so transient equipment-tag refs (Writable=true from parser) return
the same status code as authored tags rejected at init — documented in the docs.
Adds 6 pure unit tests pinning the area-detection precondition the guard relies on.
EncodeScalarBlock Timer/Counter throws remain as the defensive backstop.
2026-06-17 06:31:41 -04:00
Joseph Doherty 11e8e4302d fix(s7): Counter raw-word note + reject Writable Timer/Counter + Timer time-base tests (bundle review) 2026-06-17 06:18:48 -04:00
Joseph Doherty 8cfb8e920e feat(s7): Timer/Counter read (read-only) + route Timer/Counter through buffer path 2026-06-17 06:03:47 -04:00
Joseph Doherty 5db08e9e85 feat(s7): DateTime (S7 DATE_AND_TIME) scalar read+write via S7.Net.Types.DateTime 2026-06-17 05:54:08 -04:00
Joseph Doherty 1e5fec2f85 feat(s7): String (S7 STRING) scalar read+write via S7.Net.Types.S7String 2026-06-17 05:50:49 -04:00
Joseph Doherty 286be5df88 feat(s7): byte-buffer codec dispatch + Int64/UInt64/LReal scalar read+write 2026-06-17 05:38:18 -04:00
Joseph Doherty 06b858eb02 feat(s7): unblock wide-type/Timer-Counter init guards + fix Int64/UInt64 node mapping 2026-06-17 05:24:48 -04:00
Joseph Doherty 0f92e9e238 fix(adminui): reject AbLegacy array length >256 at author-time (review I-3)
v2-ci / build (push) Failing after 1m3s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
2026-06-16 22:31:42 -04:00
Joseph Doherty 3bb2031d1d fix(opcua): array equipment-tag nodes are read-only (array writes out of scope, review M-1) 2026-06-16 22:31:15 -04:00
Joseph Doherty 5f7a2acd27 fix(abcip): isArray:true without a positive arrayLength is scalar (review I-2 consistency) 2026-06-16 22:30:11 -04:00
Joseph Doherty 94e8c55b5c fix(abcip): explicit IsArray flag so 1-element arrays read as arrays (review I-1) 2026-06-16 22:14:41 -04:00
Joseph Doherty ce5d46be08 fix(ablegacy): gate array read on isArray:true; 1-element arrays + assumption comments (review C-2/I-3) 2026-06-16 22:14:36 -04:00
Joseph Doherty 3bbe39c166 fix(s7): treat ArrayCount>=1 as array so 1-element arrays read as arrays (review I-2) 2026-06-16 22:12:30 -04:00
Joseph Doherty 49ac1392a8 fix(modbus): gate array read on isArray:true; 1-element arrays (review C-1) 2026-06-16 22:12:18 -04:00
Joseph Doherty 3e74239532 feat(twincat): 1-D array symbol read via ADS + IsArray discovery 2026-06-16 21:59:17 -04:00
Joseph Doherty 950069392c feat(ablegacy): PCCC multi-element file array read + IsArray discovery 2026-06-16 21:55:41 -04:00
Joseph Doherty f4d5a5ee9c feat(abcip): 1-D array read via libplctag + IsArray discovery 2026-06-16 21:55:20 -04:00
Joseph Doherty a82c22c645 feat(s7): 1-D array block read + decode loop + IsArray discovery 2026-06-16 21:54:50 -04:00
Joseph Doherty 8d3dc32148 feat(modbus): String + BitInRegister array decode + equipment-tag arrayLength
- DecodeRegisterArray: add String and BitInRegister cases replacing the
  default:throw; each element decoded by reusing DecodeRegister on its
  contiguous register slice → string[] / bool[]
- ModbusEquipmentTagParser.TryParse: read optional arrayLength key from
  TagConfig JSON and thread it into ModbusTagDefinition.ArrayCount
  (null when absent or zero, preserving scalar behaviour)
- ModbusArrayTests: 8 new tests covering the two decode cases and the
  equipment-tag parser/resolver path; 285/285 green
2026-06-16 21:51:55 -04:00
Joseph Doherty c2006dfb57 feat(adminui): driver-agnostic isArray/arrayLength Tag-modal control 2026-06-16 21:50:27 -04:00
Joseph Doherty eb8a8dc19d test(runtime): cover disabled-array + zero-length in artifact parity round-trip (review) 2026-06-16 21:45:19 -04:00
Joseph Doherty 0a747c343d feat(runtime): decode IsArray/ArrayLength byte-parity in DeploymentArtifact 2026-06-16 21:40:22 -04:00
Joseph Doherty 584e9f2aee test(opcua): applier forwards array params + overflow rows + doc fix (review)
Extends RecordingSink to capture isArray/arrayLength per EnsureVariable call,
adds two applier-level tests asserting the wire-through for array and scalar
plans, adds float/overflow InlineData rows to ExtractTagArray theory, and
corrects the ExtractTagArray XML-doc wording (null => unbounded ArrayDimensions=[0]).
2026-06-16 21:36:38 -04:00
Joseph Doherty 71cc417182 feat(opcua): EquipmentTagPlan IsArray/ArrayLength + composer ExtractTagArray + applier wire-in 2026-06-16 21:27:43 -04:00
Joseph Doherty 3172b7bdee test(opcua): cover null-arrayLength dimension + tighten scalar assertion (review) 2026-06-16 21:22:43 -04:00
Joseph Doherty a792820283 feat(opcua): EnsureVariable array params (ValueRank=OneDimension + ArrayDimensions) 2026-06-16 21:16:07 -04:00
Joseph Doherty 6855be288f feat(focas): per-axis auto-scale from cnc_getfigure figures (manual config = fallback) 2026-06-16 19:52:45 -04:00
Joseph Doherty a40c77de87 fix(adminui): flip remaining ModbusTcp test seeds + doc comments to Modbus (review) 2026-06-16 19:51:56 -04:00
Joseph Doherty bec37848d5 fix(galaxy): degrade all parent-cycle members to root (review) 2026-06-16 19:51:20 -04:00
Joseph Doherty 21c7645da8 feat(galaxy): nest gobject browse tree by parent_gobject_id (degrade-to-flat) 2026-06-16 19:41:26 -04:00
Joseph Doherty 8b4675b1a5 fix(adminui): canonicalize Modbus driver-type string on "Modbus" (was ModbusTcp) 2026-06-16 19:39:41 -04:00
Joseph Doherty 3fcbc70cba feat(focas): add cnc_getfigure per-axis position-figure client binding 2026-06-16 19:38:49 -04:00