Files
DP44/enriched-qwen3-coder-next/DataPRO/SLICECommands/MulticastCommands.md

398 lines
18 KiB
Markdown
Raw Normal View History

2026-04-17 14:55:32 -04:00
---
source_files:
- DataPRO/SLICECommands/MulticastCommands/MulticastIdentify.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastResetMcu.cs
- DataPRO/SLICECommands/MulticastCommands/MACTableEntry.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastSetIPAddress.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastSetSubnetAddress.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastSetGatewayAddress.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastSetDhcp.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastSetDnsAddress.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastGetIpAddress.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastGetDnsAddress.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastGetSubnetAddress.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastGetDhcp.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastGetGatewayAddress.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastAutoDiscover.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastDiscoverSlice6.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastUDPQueryQATS.cs
- DataPRO/SLICECommands/MulticastCommands/MulticastCommandBase.cs
generated_at: "2026-04-16T03:55:01.601441+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "0d6bca66954e7e76"
---
# Documentation: Multicast Command Module (`DTS.DASLib.Command.SLICE.MulticastCommands`)
---
## 1. Purpose
This module provides a set of multicast-based communication commands for interacting with SLICE-series hardware devices (e.g., Slice6, S6DB) over UDP. It enables discovery, configuration (IP, subnet, gateway, DNS, DHCP), diagnostics (MAC table retrieval), and status querying (e.g., QATS sensor data) via multicast messaging. All commands inherit from `MulticastCommandBase`, which abstracts low-level UDP multicast send/receive logic, packet parsing, and MAC address handling. The module serves as the primary interface for networked device management in the DAS (Data Acquisition System) framework.
---
## 2. Public Interface
### Classes
#### `MulticastCommandBase`
*Abstract base class for all multicast commands.*
- **Constructors**
- `MulticastCommandBase(ICommunication sock)`
Initializes base with a communication socket.
- `MulticastCommandBase(ICommunication sock, int timeoutMillisec)`
Initializes with socket and custom receive timeout.
- **Properties**
- `protected abstract Commands Command { get; }`
Returns the command enum value (e.g., `Commands.Identify`).
- `public string HostMac { get; set; }`
MAC address of the sending host (used in command/response validation).
- `public string ClientMac { set; }`
MAC address of the target client device.
- `public int ReceiveTimeoutMs { get; set; } = 3000`
Timeout for receiving responses.
- `public IPAddress BindToAdapterIPAddress { get; set; } = IPAddress.Any`
Network adapter to bind to for sending/receiving.
- **Methods**
- `public void BuildPacket()`
Computes CRCs on the command packet.
- `public void SendCommand()`
Sends the multicast command packet without waiting for responses.
- `public void StartListening()`
Starts a background thread to listen for multicast responses.
- `public void StopListening()`
Signals the listening thread to terminate.
- `public void MulticastExecute(CancellationToken ct, bool waitForResponse = true)`
Sends command and optionally waits for responses (uses `StartListening` internally if `waitForResponse=true`).
- `protected virtual bool StopAfterFirstMessage => true`
Controls whether to stop after first response (overridden in `MulticastAutoDiscover`, `MulticastDiscoverSlice6`, `MulticastUdpQueryQATS`).
- `protected virtual CommandReceiveAction WholePackage()`
Parses incoming response packet (overridden in derived classes).
- `public static string GetMacAddress()`
Returns first multicast-capable, active network interfaces MAC address.
#### `MulticastIdentify`
*Command to trigger device identification (e.g., LED blink).*
- **Constructors**
- `MulticastIdentify(ICommunication sock)`
- `MulticastIdentify(ICommunication sock, int timeoutMillisec)`
- **Overrides**
- `protected override Commands Command => Commands.Identify`
- `public override void CommandToString(ref List<List<string>> lines)`
Appends `"MAC: {CommandClientMac}"` to output.
#### `MulticastResetMcu`
*Command to reset the device MCU.*
- **Constructors**
- `MulticastResetMcu(ICommunication sock)`
- `MulticastResetMcu(ICommunication sock, int timeoutMillisec)`
- **Overrides**
- `protected override Commands Command => Commands.ResetMcu`
- `public override void CommandToString(ref List<List<string>> lines)`
Appends `"MAC: {CommandClientMac}"`.
#### `MulticastSetIpAddress`
*Command to set static IP address.*
- **Constructors**
- `MulticastSetIpAddress(ICommunication sock)`
- `MulticastSetIpAddress(ICommunication sock, int timeoutMillisec)`
- **Properties**
- `public string Ip { set; }`
Sets IP address string (e.g., `"192.168.1.100"`); writes to parameter buffer.
- **Overrides**
- `protected override Commands Command => Commands.SetIpAddress`
- `public override void CommandToString(ref List<List<string>> lines)`
Appends `"MAC: {CommandClientMac} IP: {_ip}"`.
#### `MulticastSetSubnetAddress`
*Command to set subnet mask.*
- **Constructors**
- `MulticastSetSubnetAddress(ICommunication sock)`
- `MulticastSetSubnetAddress(ICommunication sock, int timeoutMillisec)`
- **Properties**
- `public string Subnet { set; }`
- **Overrides**
- `protected override Commands Command => Commands.SetSubnetAddress`
- `public override void CommandToString(ref List<List<string>> lines)`
Appends `"MAC: {CommandClientMac} Subnet: {_subnet}"`.
#### `MulticastSetGatewayAddress`
*Command to set gateway IP.*
- **Constructors**
- `MulticastSetGatewayAddress(ICommunication sock)`
- `MulticastSetGatewayAddress(ICommunication sock, int timeoutMillisec)`
- **Properties**
- `public string Gateway { set; }`
- **Overrides**
- `protected override Commands Command => Commands.SetGatewayAddress`
- `public override void CommandToString(ref List<List<string>> lines)`
Appends `"MAC: {CommandClientMac} Gateway: {_gateway}"`.
#### `MulticastSetDnsAddress`
*Command to set DNS server IP.*
- **Constructors**
- `MulticastSetDnsAddress(ICommunication sock)`
- `MulticastSetDnsAddress(ICommunication sock, int timeoutMillisec)`
- **Properties**
- `public string Dns { set; }`
- **Overrides**
- `protected override Commands Command => Commands.SetDnsAddress`
- `public override void CommandToString(ref List<List<string>> lines)`
Appends `"MAC: {CommandClientMac} DNS: {_dns}"`.
#### `MulticastSetDhcp`
*Command to enable/disable DHCP.*
- **Constructors**
- `MulticastSetDhcp(ICommunication sock)`
- `MulticastSetDhcp(ICommunication sock, int timeoutMillisec)`
- **Properties**
- `public bool Dhcp { set; }`
Converts `bool` to `byte` (0/1) and writes to parameter buffer.
- **Overrides**
- `protected override Commands Command => Commands.SetDhcp`
- `public override void CommandToString(ref List<List<string>> lines)`
Appends `"MAC: {CommandClientMac} DHCP: {_dhcp} "`.
#### `MulticastGetIpAddress`
*Command to retrieve device IP address.*
- **Constructors**
- `MulticastGetIpAddress(ICommunication sock)`
- `MulticastGetIpAddress(ICommunication sock, int timeoutMillisec)`
- **Properties**
- `public string Ip => _ip`
Populated after `WholePackage()` processes response.
- **Overrides**
- `protected override Commands Command => Commands.GetIpAddress`
- `protected override CommandReceiveAction WholePackage()`
On success, extracts IP from response at offset `DOUBLE_MAC_ADDR_SIZE`.
- `public override void CommandToString(...)` / `ResponseToString(...)`
Appends MAC and (response) IP.
#### `MulticastGetSubnetAddress`
*Command to retrieve subnet mask.*
- **Constructors**
- `MulticastGetSubnetAddress(ICommunication sock)`
- `MulticastGetSubnetAddress(ICommunication sock, int timeoutMillisec)`
- **Properties**
- `public string Subnet => _subnet`
- **Overrides**
- `protected override Commands Command => Commands.GetSubnetAddress`
- `protected override CommandReceiveAction WholePackage()`
Extracts subnet at offset `FIRST_PARAMETER_OFFSET`.
#### `MulticastGetGatewayAddress`
*Command to retrieve gateway IP.*
- **Constructors**
- `MulticastGetGatewayAddress(ICommunication sock)`
- `MulticastGetGatewayAddress(ICommunication sock, int timeoutMillisec)`
- **Properties**
- `public string Gateway => _gateway`
- **Overrides**
- `protected override Commands Command => Commands.GetGatewayAddress`
- `protected override CommandReceiveAction WholePackage()`
Extracts gateway at offset `FIRST_PARAMETER_OFFSET`.
#### `MulticastGetDnsAddress`
*Command to retrieve DNS IP.*
- **Constructors**
- `MulticastGetDnsAddress(ICommunication sock)`
- `MulticastGetDnsAddress(ICommunication sock, int timeoutMillisec)`
- **Properties**
- `public string Dns => _dns`
- **Overrides**
- `protected override Commands Command => Commands.GetDnsAddress`
- `protected override CommandReceiveAction WholePackage()`
Extracts DNS at offset `FIRST_PARAMETER_OFFSET`.
#### `MulticastGetDhcp`
*Command to retrieve DHCP status.*
- **Constructors**
- `MulticastGetDhcp(ICommunication sock)`
- `MulticastGetDhcp(ICommunication sock, int timeoutMillisec)`
- **Properties**
- `public bool Dhcp => Convert.ToBoolean(_dhcp)`
`_dhcp` is a `byte` (0/1).
- **Overrides**
- `protected override Commands Command => Commands.GetDhcp`
- `protected override CommandReceiveAction WholePackage()`
Extracts DHCP byte at `FIRST_PARAMETER_OFFSET`; returns early on error.
- `public override void CommandToString(...)` uses `ResponseClientMac` (unlike others using `CommandClientMac`).
#### `MulticastAutoDiscover`
*Command to discover devices on network via multicast.*
- **Constructors**
- `MulticastAutoDiscover()`
- `MulticastAutoDiscover(string macAddress)`
- `MulticastAutoDiscover(int timeoutMillisec)`
- `MulticastAutoDiscover(string macAddress, int timeoutMillisec)`
- **Properties**
- `public List<IDiscoveredDevice> DiscoveredDevices { get; }`
Populated with discovered devices after execution.
- `public TextLogger Logger { get; set; }`
- `public DFConstantsAndEnums.MultiCastDeviceClasses DeviceClass { set; }`
- `public ResponseOptions ResponseOption { set; }`
- `public IPAddress Address { set; }`
Sets multicast receive address/config.
- **Overrides**
- `protected override Commands Command => Commands.AutoDiscover`
- `protected override bool StopAfterFirstMessage => false`
- `protected override CommandReceiveAction WholePackage()`
Parses response payload (278 bytes) into device fields (IP, MAC, serial, etc.); appends to `DiscoveredDevices`.
- `public override void CommandToString(...)`
Appends `"AutoDiscover: [{HostMac}] {_address} : {_port}"`.
#### `MulticastDiscoverSlice6`
*Command to retrieve MAC table entries from Slice6/S6DB devices.*
- **Constructors**
- `MulticastDiscoverSlice6(DeviceClasses deviceClass, string hostMac)`
- `MulticastDiscoverSlice6(string hostMac, int timeoutMillisec)`
- **Properties**
- `public DeviceClasses DeviceClass { set; }`
- `public ResponseOptions ResponseOption { set; }`
- `public uint DesiredPort { set; }`
Bitmask for ports (e.g., `0x0F` for ports 14).
- `public byte[] MACFilter { set; }`
MAC address filter (e.g., `00:19:9B:*:*:*`).
- `public TextLogger Logger { get; set; }`
- `public Dictionary<string, IDiscoveredDevice> MACAddressToDevice { get; set; }`
- `public DiscoveredConnectedSlice[] ConnectedDevices => _connectedDevices.ToArray()`
Populated with MAC table entries per device.
- **Overrides**
- `protected override Commands Command => Commands.GetMACTable`
- `protected override bool StopAfterFirstMessage => false`
- `protected override CommandReceiveAction WholePackage()`
Parses MAC table entries (12-byte records) into `MACTableEntry` objects; adds to `_connectedDevices`.
- `public static string MACAddressToString(IEnumerable<byte> mac)`
Converts MAC byte array to `"XX:XX:XX:XX:XX:XX"` string.
#### `MulticastUdpQueryQATS`
*Command to query QATS (Quasi-Adaptive Time Series) sensor data from devices.*
- **Constructors**
- `MulticastUdpQueryQATS(ICommunication sock)`
- `MulticastUdpQueryQATS(string macAddress)`
- `MulticastUdpQueryQATS(int timeoutMillisec)`
- `MulticastUdpQueryQATS(string macAddress, int timeoutMillisec)`
- **Properties**
- `public List<IUDPQATSEntry> QATSEntry { get; set; } = new List<IUDPQATSEntry>()`
Accumulates QATS entries until `GetUDPQATs()` clears them.
- `public DFConstantsAndEnums.MultiCastDeviceClasses DeviceClass { set; }`
- `public ResponseOptions ResponseOption { set; }`
- `public IPAddress Address { set; }`
- `public int Port { set; }`
- **Overrides**
- `protected override Commands Command => Commands.UdpQueryQTAS`
- `protected override bool StopAfterFirstMessage => false`
- `protected override CommandReceiveAction WholePackage()`
Parses 215-byte response payload at offset 74 (`QATS_OFFSET`) into QATS fields (arm state, sample rate, tilt sensors, etc.); adds to `QATSEntry` (thread-safe via `lock`).
- `public IUDPQATSEntry[] GetUDPQATs()`
Returns and clears `QATSEntry` list.
---
## 3. Invariants
- **MAC Address Format**: All MAC addresses are stored and transmitted as colon-separated hex strings (e.g., `"AA:BB:CC:DD:EE:FF"`). Internal parsing uses hyphen-separated strings (e.g., `"AA-BB-CC-DD-EE-FF"`) from the protocol, converted via `Replace('-', ':')`.
- **Command/Response Validation**: `MulticastCommandBase.WholePackage()` validates that:
- `ResponseClientMac == CommandClientMac`
- `ResponseHostMac == HostMac`
- Response status is `StatusNoError`.
- **Payload Sizes**:
- Command payload size is fixed per command (e.g., `DOUBLE_MAC_ADDR_SIZE + IP_ADDR_SIZE` for IP/subnet/gateway/DNS/DHCP commands).
- Response payload size is fixed per command (e.g., 278 bytes for `AutoDiscover`, 215 for `UdpQueryQTAS`).
- **Multicast Addresses**:
- Command multicast group: `"239.1.2.3"` (configurable via `MulticastAddress`).
- Response multicast group: `"239.4.5.6"` (configurable via `MulticastReceiveAddress`).
- **Port Numbers**:
- Command port: `8501` (`Ports.Command`).
- Response port: `8503` (`Ports.Response`).
- **Timeout Handling**: Default receive timeout is 3000 ms (`DEFAULT_RECEIVE_TIMEOUT_MS`). `MulticastUdpQueryQATS` overrides to 5000 ms.
---
## 4. Dependencies
### Dependencies *of* this module:
- `DTS.Common.Interface.DASFactory.ICommunication`
Used for socket abstraction (though most commands instantiate `UdpClient` directly).
- `DTS.Common.Enums.DASFactory`
Defines enums: `Commands`, `MultiCastDeviceClasses`, `ResponseOptions`, `CommandStatus`.
- `DTS.Common.Utilities.Logging`
`TextLogger`, `APILogger`.
- `DTS.DASLib.Command.Classes`
Defines `IDiscoveredDevice`, `ConnectedEthernetDevice`, `UDPQATSEntry`, `IUDPQATSEntry`.
- `System.Net`, `System.Net.NetworkInformation`
For `UdpClient`, `IPAddress`, `NetworkInterface`, `MulticastOption`.
### Dependencies *on* this module:
- High-level discovery/configuration workflows (e.g., device setup tools).
- `MulticastAutoDiscover` and `MulticastDiscoverSlice6` are used for device enumeration.
- `MulticastUdpQueryQATS` is used for real-time sensor data acquisition.
---
## 5. Gotchas
- **MAC Address Parsing Inconsistency**:
`MulticastGetDhcp.CommandToString` uses `ResponseClientMac`, while other `CommandToString` overrides use `CommandClientMac`. This may cause mismatched MACs if `ClientMac` is set but `ResponseClientMac` is not yet populated.
- **`MulticastCommandBase.WholePackage()` Default Behavior**:
The base implementation strictly validates `CommandClientMac == ResponseClientMac`. Derived classes (`MulticastAutoDiscover`, `MulticastDiscoverSlice6`, `MulticastUdpQueryQATS`) override this to accept responses from *any* client MAC (or validate only `HostMac`), but this is not obvious from the base class.
- **`MulticastDiscoverSlice6` Port Filtering**:
`ParseSSIData` (not used in current `MulticastDiscoverSlice6`) filters ports based on device class (Slice6: port 2 only; S6DB: ports ≤4). This logic is unused in `WholePackage()`—MAC table parsing uses raw port values from the response.
- **Thread Safety in `MulticastUdpQueryQATS`**:
`QATSEntry` is accessed via `lock(MyLock)` in `WholePackage()` and `GetUDPQATs()`, but `MyLock` is `private static`, meaning *all instances share the same lock*. This may cause contention if multiple `MulticastUdpQueryQATS` instances run concurrently.
- **`MulticastAutoDiscover` Payload Parsing**:
Hardcoded offsets (e.g., `36`, `41`, `57`) assume fixed-layout binary protocol. Changes to firmware response structure will break parsing silently.
- **`MulticastSetDhcp` Parameter Size**:
`COMMAND_PAYLOAD_SIZE = DOUBLE_MAC_ADDR_SIZE + 1` implies a 1-byte DHCP flag, but `command.SetParameter(FIRST_PARAMETER_OFFSET, _dhcp)` writes a `byte`. Ensure `SetParameter` handles `byte` correctly (likely via implicit conversion to `int` or padding).
- **`MulticastCommandBase.BindToAdapterIPAddress`**:
Setting `BindToAdapterIPAddress` to `IPAddress.Any` may cause issues on multi-homed systems if the wrong interface is used for multicast traffic. No validation ensures the adapter is active/multicast-capable.
- **`GetMacAddress()` Limitation**:
Returns the *first* multicast-capable, active interface—may not be the desired interface for communication.