FOCAS Tier-C PR A — Driver.FOCAS.Shared MessagePack IPC contracts. First PR of the 5-PR #220 split (isolation plan at docs/v2/implementation/focas-isolation-plan.md). Adds a new netstandard2.0 project consumable by both the .NET 10 Proxy and the future .NET 4.8 x86 Host, carrying every wire DTO the Proxy <-> Host pair will exchange: Hello/HelloAck + Heartbeat/HeartbeatAck + ErrorResponse for session negotiation (shared-secret + protocol major/minor mirroring Galaxy.Shared); OpenSessionRequest/Response + CloseSessionRequest carrying the declared FocasCncSeries so the Host picks up the pre-flight matrix; FocasAddressDto + FocasDataTypeCode for wire-compatible serialization of parsed addresses (0=Pmc/1=Param/2=Macro matches FocasAreaKind enum order so both sides cast (int)); ReadRequest/Response + WriteRequest/Response with MessagePack-serialized boxed values tagged by FocasDataTypeCode; PmcBitWriteRequest/Response as a first-class RMW operation so the critical section stays Host-side; Subscribe/Unsubscribe/OnDataChangeNotification for poll-loop-pushes-deltas model (FOCAS has no CNC-initiated callbacks); Probe + RuntimeStatusChange + Recycle surface for Tier-C supervision. Framing is [4-byte BE length][1-byte kind][body] with 16 MiB body cap matching Galaxy; FocasMessageKind byte values align with Galaxy ranges so an operator reading a hex dump doesn't have to context-switch. FrameReader/FrameWriter ported from Galaxy.Shared with thread-safe concurrent-write serialization. 24 new unit tests: 18 per-DTO round-trip tests covering every field + 6 framing tests (single-frame round-trip, clean-EOF returns null, oversized-length rejection, mid-frame EOF throws, 20-way concurrent-write ordering preserved, MessageKind byte values locked as wire-stable). No driver changes; existing 165 FOCAS unit tests still pass unchanged. PR B (Host skeleton) goes next.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Shared.Contracts;
|
||||
|
||||
/// <summary>
|
||||
/// Length-prefixed framing. Each IPC frame is:
|
||||
/// <c>[4-byte big-endian length][1-byte message kind][MessagePack body]</c>.
|
||||
/// Length is the body size only; the kind byte is not part of the prefixed length.
|
||||
/// Mirrors the Galaxy Tier-C framing so operators see one wire format across hosts.
|
||||
/// </summary>
|
||||
public static class Framing
|
||||
{
|
||||
public const int LengthPrefixSize = 4;
|
||||
public const int KindByteSize = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum permitted body length (16 MiB). Protects the receiver from a hostile or
|
||||
/// misbehaving peer sending an oversized length prefix.
|
||||
/// </summary>
|
||||
public const int MaxFrameBodyBytes = 16 * 1024 * 1024;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wire identifier for each contract. Values are stable — new contracts append, never
|
||||
/// reuse. Ranges kept aligned with Galaxy so an operator reading a hex dump doesn't have
|
||||
/// to context-switch between drivers.
|
||||
/// </summary>
|
||||
public enum FocasMessageKind : byte
|
||||
{
|
||||
Hello = 0x01,
|
||||
HelloAck = 0x02,
|
||||
Heartbeat = 0x03,
|
||||
HeartbeatAck = 0x04,
|
||||
|
||||
OpenSessionRequest = 0x10,
|
||||
OpenSessionResponse = 0x11,
|
||||
CloseSessionRequest = 0x12,
|
||||
|
||||
ReadRequest = 0x30,
|
||||
ReadResponse = 0x31,
|
||||
WriteRequest = 0x32,
|
||||
WriteResponse = 0x33,
|
||||
PmcBitWriteRequest = 0x34,
|
||||
PmcBitWriteResponse = 0x35,
|
||||
|
||||
SubscribeRequest = 0x40,
|
||||
SubscribeResponse = 0x41,
|
||||
UnsubscribeRequest = 0x42,
|
||||
OnDataChangeNotification = 0x43,
|
||||
|
||||
ProbeRequest = 0x70,
|
||||
ProbeResponse = 0x71,
|
||||
RuntimeStatusChange = 0x72,
|
||||
|
||||
RecycleHostRequest = 0xF0,
|
||||
RecycleStatusResponse = 0xF1,
|
||||
|
||||
ErrorResponse = 0xFE,
|
||||
}
|
||||
Reference in New Issue
Block a user