DWIS.RigOS.DownholeMechanical.Bridge 1.0.7

dotnet add package DWIS.RigOS.DownholeMechanical.Bridge --version 1.0.7
                    
NuGet\Install-Package DWIS.RigOS.DownholeMechanical.Bridge -Version 1.0.7
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DWIS.RigOS.DownholeMechanical.Bridge" Version="1.0.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DWIS.RigOS.DownholeMechanical.Bridge" Version="1.0.7" />
                    
Directory.Packages.props
<PackageReference Include="DWIS.RigOS.DownholeMechanical.Bridge" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DWIS.RigOS.DownholeMechanical.Bridge --version 1.0.7
                    
#r "nuget: DWIS.RigOS.DownholeMechanical.Bridge, 1.0.7"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DWIS.RigOS.DownholeMechanical.Bridge@1.0.7
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DWIS.RigOS.DownholeMechanical.Bridge&version=1.0.7
                    
Install as a Cake Addin
#tool nuget:?package=DWIS.RigOS.DownholeMechanical.Bridge&version=1.0.7
                    
Install as a Cake Tool

Shared downhole mechanical bridge runtime

This NuGet package implements the Server, OPCUASource and BlackboardSink hosts for BlackStream ASM/EMS and BaseStar. DWIS.RigOS.Contracts.DownholeMechanical owns the independent versioned wire contract. No provider WebApp is needed. Provider hosts consume a versioned NuGet package; the contract dependency and OPC-UA client configuration asset are included transitively, without requiring a Common checkout.

Configuration and commissioning

Read /home/config.json, or use DWIS_CONFIG_PATH for local execution. Nothing rewrites an existing configuration or creates physical UUIDs automatically. Start from the provider's config/downhole.config.example.json, replace sample equipment and sensor UUIDs with actual ones from the current DrillString description, and configure namespace URI, node ID, unit, quantity, axis, statistic, processing, role and telemetry for each individual source tag. The simulator exposes an EngineeringUnits EUInformation property for each scalar, with stable unit IDs in urn:dwis:source-units:v1; the contract metadata lists that source-unit catalog. The prepared 1.0.5 runtime depends on mechanical contract 1.1.0. Polar bending channels use BendingMomentMagnitude (N.m, kN.m, or lbf.ft) and BendingMomentAngle (rad or deg), both with Axis=None. Their Blackboard quantities are bendingMomentDrilling and planeAngleDrilling, with SI payload units N.m and rad. These are configured source measurements; the bridge does not synthesize Cartesian/polar counterpart channels. See the contract conventions. Each instrument can specify SimulatorProductionInterval and SimulatorPhaseOffset. By default, all its scalar channels on a telemetry path share one production timestamp. The interval is independent of Blackboard publication throttling; if omitted, the existing mud-pulse/wired-pipe publication intervals remain the simulator defaults. Phase defaults to zero and must be smaller than the production interval. SimulatorInterval caps the configuration-check sleep; production wakes at its own due time and is not rounded to that interval.

Production uses monotonic elapsed time with UTC timestamps anchored at source startup. Late wakes skip missed productions without catch-up bursts or accumulated phase drift. Channels wait with BadWaitingForInitialData until their first production; they do not advertise a synthetic shared startup dataset. Config reload/restart resets the phase origin. These are simulated clocks; the bridge keeps each real instrument's received source timestamps without imposing synchronization. RequiredSensorTypeMask is the explicit bit mask from the authoritative OSDC DrillString sensor enum, not an inferred value based on channel names. Optional per-channel MaximumInputAge overrides the global age for slower telemetry. Each source address is unique. --validate-config validates a host configuration without opening any connections and fails immediately on invalid input. During normal startup, the simulator and bridge wait for a valid configuration, logging one warning without a stack trace per waiting period. Each reloads the file every five seconds and starts automatically when valid physical instrument mappings are supplied. Missing/unreadable files and malformed JSON also enter this waiting state. Shutdown cancels the wait. Unexpected runtime and connection failures retain error logging and retries.

ProviderID must be unique for independently deployed providers. DrillStringID can select one specific current description when several exist; otherwise discovery must return exactly one. The semantic query is the Current + DrillStringDescription + HasDynamicValue pattern used by ContextualDataBridgeBHADrillString. New candidates are subscribed through registered-query callbacks; description values are subscribed separately. Discovery is not polled. The publisher's generated DrillString DTOs must preserve EquipmentIdentity, SensorID and ComponentID.

Identity, positions and meaning

Match physical EquipmentInstanceID, then SensorID, then the sensor's ComponentID within the current snapshot. The configured instrument model independently advertises manufacturer and model (NOV / BlackStream ASM, NOV / BlackStream EMS, Halliburton / BaseStar), with canonical model identifiers NOV/BlackStreamASM, NOV/BlackStreamEMS and Halliburton/BaseStar. A matching snapshot enriches serial/asset fields; an absent or mismatched snapshot cannot supply these fields. Duplicate equipment/sensors, repeated sections, wrong ownership, missing positions and model mismatches produce unavailable values with explicit reasons. There is no list-index, name or distance fallback. Component record IDs may change between snapshots; physical equipment UUIDs stay stable. Distance is nonnegative SI metres along the string from the bit. Axes are explicitly instrument-local; this bridge does not infer a coordinate transformation from sensor angles.

Groups are formed by quantity, axis, processing, role and telemetry. Statistics remain explicit per entry, so Min/Max/Average/StandardDeviation share a compound signal rather than causing four independent writes. Each group is one compound Blackboard JSON signal with repeated instrument measurements, individual source timestamps and an equipment descriptor catalog. Bias/calibration channels use Statistic=None; Peak remains distinct from Maximum. Configured corrected values are read, never synthesized from raw values. BlackStream ASM rejects EMS-only capabilities. Both BlackStream models require wired pipe and Min/Max/Average/StandardDeviation statistics. BaseStar requires mud pulse, with optional additional wired-pipe channels. No wired-only BaseStar or artificial wired copies are created. Publication intervals and freshness are independent across those telemetry paths.

Each JSON data point advertises SchemaURL and MetaDataURL under /DownholeMechanical/v1. InstrumentInstance/InstrumentModel attributes and HasManufacturer are published at startup even without a DrillString or source connection. Configured sensors link through IsSensorOf and IsMeasuredBy (IsRecordedFrom for bias/calibration). Stable graph node names are unchanged. To join JSON UUIDs without guessing node names, each instance/sensor has an IsDependentOn DataEndPoint descriptor whose EndPointDescription is respectively https://digiwells.no/daq/downhole-mechanical/1/equipmentInstanceId/<UUID> or https://digiwells.no/daq/downhole-mechanical/1/sensorId/<UUID> (canonical D-format UUID). This is a versioned application profile using existing vocabulary, not a new DWIS attribute. Only instruments/sensors belonging to the compound stream are linked. This independent identity does not create ComponentIDs, positions, or equipment descriptors in JSON: missing context still means NoContext, null values and null distances. Runtime 1.0.5 prepares this identity fix; contract 1.1.0 and its schema/metadata are unchanged. Mechanical quantity and telemetry are also described semantically. Availability and current positions remain explicit in the versioned payload, including when source signals are dead.

Callback and reconnection behavior

The input SDK subscription uses StatusValueTimestamp notifications, preserving quality and numeric/string/GUID node identifiers without repeated tag reads. The DWIS client handles semantic query subscriptions, context values and Blackboard writes. Callbacks queue samples; worker code performs conversion, logging and publication. All delivered samples are journaled; wired-pipe publication forwards every changed frame, while mud pulse retains its configured publication throttle. Invalid/nonfinite/bad-quality/future/stale values become null. A cached-age watchdog performs no scalar reads. Confirmed session/subscription loss triggers immediate reconnection. Transient publish/keepalive errors allow 30 seconds for SDK recovery without deleting queued notifications; persistent silence still reconnects even when Session.Connected is stale. Subscription keepalive/lifetime requests are specified as durations (10 seconds/five minutes), independent of sampling interval. Disposal closes sessions/subscriptions. Blackboard health uses one standard server-state probe every 30 seconds, not per-tag polling. Unavailable nodes stay null while other nodes continue; only unresolved mappings and namespace metadata are retried every 30 seconds. Source reconnection retains the Blackboard session and registered query/manifests, avoiding semantic reinjection storms. Configuration modification causes a validated session rebuild. Startup failures retry without ending the process. An unavailable input endpoint publishes an unavailable snapshot when the Blackboard is reachable. Samples not delivered during an outage cannot be reconstructed.

Compact persistent logs

Raw accepted and published states have separate compact JSONL files in DataLogDirectory. A header records ordered channels, units, physical identity and position/context once; rows hold observation time and arrays of value, source timestamp and availability. Context changes start new headers. Default segment duration is six hours, budget one GiB. Size-driven parts may close earlier under retention pressure. Every exact input batch is force-flushed before processing, including the queued tail during graceful shutdown; raw/published views flush to the operating system and share that durable sample boundary. Restart repairs an incomplete final row. Closed parts are compressed to verified gzip files with an atomic rename. Retention deletes oldest files to honor the budget, including older active streams when archives are insufficient. Allocate enough budget for at least one complete header and record. Retention is intentional data expiry, not indefinite preservation. File errors are logged and do not stop Blackboard publication. Use one distinct /home volume per host; do not share log writers.

Build, test and release

Build the explicit Common/provider solutions. Run DownholeMechanical.Tests with --filter 'TestCategory!=Integration' for focused tests. For live tests, set DWIS_DOWNHOLE_TEST_BLACKBOARD to an isolated Blackboard and run with --filter TestCategory=Integration. Tests inject their own current context and create scalar simulators on ports 48151/48152; never use production/shared data. They test repeated instruments, constant-valued inputs, current-position changes, nulling and source reconnection. Publish contract 1.0.0 first with publish-downhole-contract.yml, then runtime 1.0.3 with publish-downhole-bridge.yml. Both workflows use NuGet Trusted Publishing, GitHub OIDC and the existing NUGET_USER repository secret. Configure nuget.org policies for owner D-WIS, repository Common and the exact workflow filenames; no GitHub environment is specified. The runtime package carries a contract 1.0.0 dependency and buildTransitive configuration copy rules. Local source changes are not a published package or a deployed upgrade.

Verification

Provider hosts consume a published runtime NuGet; the contract version remains 1.0.0. For unpublished development builds, pack into a local feed rather than introducing a cross-repository ProjectReference. Run the isolated native OPC-UA source test with --filter TestCategory=SourceIntegration (port 48154). No Blackboard is needed for this timing check. Existing Blackboard integration tests remain separately gated.

BaseStar sequential mud pulse (runtime 1.0.2)

Runtime 1.0.2 adds sequential mud-pulse transmission. A BaseStar instrument can set SimulatorMudPulseCycleDuration to 00:01:00. This selects one-at-a-time transmission of its mud-pulse channels in their configuration order. For N channels, slots are spaced through the complete cycle: channel zero at 0, channel one at 60/N seconds, and channel zero again at 60 seconds. Integer tick arithmetic preserves the complete cycle exactly when division is uneven. Only the transmitted node gets a new value/timestamp. Other nodes retain their last transmission; before their first slot they remain BadWaitingForInitialData. Stalls skip missed slots without a catch-up burst. A nonzero SimulatorPhaseOffset shifts the cycle origin.

SimulatorProductionInterval still controls full wired-pipe datasets independently (2.54 seconds in the BaseStar example). The explicit mud-pulse cycle takes precedence for mud pulse only. Omitting SimulatorMudPulseCycleDuration preserves existing batch behavior, including BlackStream. The option is rejected for BlackStream and for nonpositive or unrepresentably short cycles. Blackboard publication intervals are independent of source transmission; the BaseStar sample uses a one-second mud-pulse throttle so individual arrivals are forwarded without a 30-second batching delay. Per-channel timestamps/freshness remain independent.

The SourceIntegration category now includes a real 60-second BaseStar cycle test on port 48156, as well as the BlackStream timing test on port 48154. These isolated native tests need no Blackboard. Runtime 1.0.2 is published through the Trusted Publishing workflow. Restore BaseStar from nuget.org; keep cross-repository ProjectReferences out of consuming hosts.

Batch-processing optimization (runtime 1.0.3)

Runtime 1.0.3 uses input subscription callbacks that enqueue complete OPC-UA DataChange notifications in server sequence order. Queued versions of one channel, even with identical or backwards timestamps, are retained separately. Source-time frames update all affected statistics together; one OPC-UA Write sends the affected compound signals. Wired pipe forwards every changed frame and no longer uses WiredPipePublishInterval as an output throttle. That setting remains the simulator's fallback production interval when an instrument has no explicit SimulatorProductionInterval. Mud-pulse throttling is unchanged.

Channel/stream indexes and equipment/sensor placements are cached. Replacing the current DrillString invalidates all placement caches. State comparisons exclude observation time but retain source timestamps, values, quality-derived availability and identity/position changes. The age watchdog still checks cached samples and performs no tag polling.

The simulator production clock runs on a dedicated sleeping thread. Configuration metadata checks run independently and cannot block production on a Windows bind mount. Late production still skips missed simulator slots instead of inventing data; this does not reconstruct real source data that were never delivered. Thread sleeps remain cancellable and do not busy-wait.

Durable input journal and derived views

The additional ProviderID-input-source-*.jsonl journal is the authoritative received-sample record. Its dwis-downhole-input-v1 header contains the ordered channel mappings, source units, physical equipment/sensor UUIDs, measurement qualifications, and a frozen current DrillString snapshot. A context change rotates the header. Each row contains observation time t and samples: arrays of channel index, original scalar value, source timestamp and numeric OPC-UA StatusCode. Duplicate values/timestamps, bad quality and nonfinite scalar values are retained; named nonfinite numbers use JSON strings. No SI conversion or availability filtering is applied to this journal.

Each dequeued input notification is appended and force-flushed to disk before its samples are processed or published. A journal storage failure retains the packet and suspends processing until storage recovers. Raw/published compound JSONL files remain compatible derived views; their appends flush to the operating system, sharing the input journal's durable sample boundary, and are force-flushed when closed. Open file handles and cached headers remove repeated file open/metadata/tail-read work. Restart repairs an incomplete final row once when opening a file. Existing logs are retained; no database, volume or legacy log migration is required.

All three log kinds share the existing six-hour segmentation and storage/retention budget. Graceful shutdown stops callbacks and drains their queued tail. An abrupt process failure retains completed force-flushed journal records; samples still in transport or awaiting their journal flush cannot be recovered from local disk. No bridge can reconstruct source samples it never received during an outage. Retention still deliberately expires old data at the configured limit. Use separate volumes and one writer per volume.

BatchDeliveryTests covers multi-frame notifications, duplicates, backwards timestamps, quality/nonfinite values, interrupted-tail recovery and context cache invalidation. FrameDeliveryTests uses 3 ASM plus 1 EMS (168 scalar channels) against an explicitly configured isolated Blackboard and captures actual notification values, not callback-triggered latest reads. It requires every per-channel 2.54-second timestamp, even with a 30-second publication setting. Do not run these injecting integration tests against an operational/shared Blackboard.

Query lifecycle release: the common package family 1.0.8 and mechanical bridge 1.0.6 use OPC Foundation client 2.2.55, which deduplicates query registrations and releases session subscriptions. Configuration and persisted data are unchanged.

Runtime 1.0.7: simulator and bridge wait quietly for valid instrument configuration, reload every five seconds, and start automatically when corrected. Validation-only mode still fails immediately. Existing configuration and persistent storage are unchanged.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.7 55 10/28/2026
1.0.6 104 10/24/2026
1.0.5 95 10/24/2026
1.0.4 98 10/24/2026
1.0.3 99 10/23/2026
1.0.2 90 10/23/2026
1.0.1 96 10/23/2026
1.0.0 98 10/23/2026