--- 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-17T15:46:31.054314+00:00" model: "zai-org/GLM-5-FP8" schema_version: 1 sha256: "4ef2eef25bbbfbe1" --- # MulticastCommands Module Documentation ## 1. Purpose This module provides multicast command infrastructure for discovering and configuring SLICE devices (Slice6, S6DB, TSR-Air, etc.) on a network. It implements a UDP multicast command/response pattern supporting device auto-discovery, network configuration (IP, subnet, gateway, DNS, DHCP settings), device identification, MCU reset, MAC table retrieval, and QATS (Query Arm-Trigger Status) polling. The module serves as the network-level device management layer for the DASLib command system. --- ## 2. Public Interface ### MulticastCommandBase (Abstract Base Class) **Constructors:** - `MulticastCommandBase(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastCommandBase(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Properties:** - `string HostMac` - Gets/sets the host MAC address; setter writes to parameter offset 0 - `string ClientMac` - Sets the target client MAC address at offset 18 - `int ReceiveTimeoutMs` - Get/set receive timeout (default 3000ms) - `IPAddress BindToAdapterIPAddress` - Get/set adapter binding (default `IPAddress.Any`) **Methods:** - `void BuildPacket()` - Computes CRCs on the base command - `void SendCommand()` - Sends multicast request without waiting for response - `void MulticastExecute(CancellationToken ct, bool waitForResponse = true)` - Sends command and waits for responses - `void StartListening()` - Starts async listening thread - `void StopListening()` - Signals listening thread to terminate - `static string GetMacAddress()` - Returns first multicast-compatible, operational network interface's MAC **Static Configuration:** - `string MulticastAddress` - Default "239.1.2.3" - `string MulticastReceiveAddress` - Default "239.4.5.6" - `int CommandPort` - Default 8501 - `int ResponsePort` - Default 8503 **Nested Enums:** - `Commands` - Command IDs (AutoDiscover=0x01, SetIpAddress=0x02, GetIpAddress=0x03, etc.) - `Ports` - Command=8501, Response=8503 - `DeviceClasses` - Slice6, SDB, ECM, S6DB, Slice6Air, PowerPro, TsrAir, S6DB3, Any - `ResponseOptions` - AlwaysRespond, RespondIfNotBusy, RespondIfNotConnected --- ### MulticastIdentify **Constructors:** - `MulticastIdentify(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastIdentify(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Methods:** - `override void CommandToString(ref List> lines)` - Appends MAC to output --- ### MulticastResetMcu **Constructors:** - `MulticastResetMcu(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastResetMcu(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Methods:** - `override void CommandToString(ref List> lines)` - Appends MAC to output --- ### MulticastSetIpAddress **Constructors:** - `MulticastSetIpAddress(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastSetIpAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Properties:** - `string Ip` - Set-only; writes IP to parameter at `FIRST_PARAMETER_OFFSET` --- ### MulticastSetSubnetAddress **Constructors:** - `MulticastSetSubnetAddress(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastSetSubnetAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Properties:** - `string Subnet` - Set-only; writes subnet to parameter at `FIRST_PARAMETER_OFFSET` --- ### MulticastSetGatewayAddress **Constructors:** - `MulticastSetGatewayAddress(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastSetGatewayAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Properties:** - `string Gateway` - Set-only; writes gateway to parameter at `FIRST_PARAMETER_OFFSET` --- ### MulticastSetDhcp **Constructors:** - `MulticastSetDhcp(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastSetDhcp(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Properties:** - `bool Dhcp` - Set-only; converts to byte and writes at `FIRST_PARAMETER_OFFSET` --- ### MulticastSetDnsAddress **Constructors:** - `MulticastSetDnsAddress(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastSetDnsAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Properties:** - `string Dns` - Set-only; writes DNS to parameter at `FIRST_PARAMETER_OFFSET` --- ### MulticastGetIpAddress **Constructors:** - `MulticastGetIpAddress(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastGetIpAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Properties:** - `string Ip` - Get-only; populated after successful response --- ### MulticastGetSubnetAddress **Constructors:** - `MulticastGetSubnetAddress(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastGetSubnetAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Properties:** - `string Subnet` - Get-only; populated after successful response --- ### MulticastGetGatewayAddress **Constructors:** - `MulticastGetGatewayAddress(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastGetGatewayAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Properties:** - `string Gateway` - Get-only; populated after successful response --- ### MulticastGetDnsAddress **Constructors:** - `MulticastGetDnsAddress(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastGetDnsAddress(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Properties:** - `string Dns` - Get-only; populated after successful response --- ### MulticastGetDhcp **Constructors:** - `MulticastGetDhcp(DTS.Common.Interface.DASFactory.ICommunication sock)` - `MulticastGetDhcp(DTS.Common.Interface.DASFactory.ICommunication sock, int timeoutMillisec)` **Properties:** - `bool Dhcp` - Get-only; converted from byte after successful response --- ### MulticastAutoDiscover **Constructors:** - `MulticastAutoDiscover()` - `MulticastAutoDiscover(string macAddress)` - `MulticastAutoDiscover(int timeoutMillisec)` - `MulticastAutoDiscover(string macAddress, int timeoutMillisec)` **Properties:** - `List DiscoveredDevices` - Get-only; populated during response processing - `TextLogger Logger` - Get/set for debug logging - `MultiCastDeviceClasses DeviceClass` - Set-only; default is `Any` - `ResponseOptions ResponseOption` - Set-only; default is `AlwaysRespond` - `IPAddress Address` - Set-only; updates multicast config **Methods:** - `void Init(string macAddress = "")` - Initializes command parameters --- ### MulticastDiscoverSlice6 **Constructors:** - `MulticastDiscoverSlice6(DeviceClasses deviceClass, string hostMac)` - `MulticastDiscoverSlice6(string hostMac, int timeoutMillisec)` **Properties:** - `DeviceClasses DeviceClass` - Set-only - `ResponseOptions ResponseOption` - Set-only; default `AlwaysRespond` - `uint DesiredPort` - Set-only; port bitmask - `byte[] MACFilter` - Set-only; default filters to 00:19:9b prefix - `TextLogger Logger` - Get/set - `Dictionary MACAddressToDevice` - Get/set - `DiscoveredConnectedSlice[] ConnectedDevices` - Get-only **Methods:** - `static string MACAddressToString(IEnumerable mac)` - Converts byte array to hex string format --- ### MulticastUdpQueryQATS **Constructors:** - `MulticastUdpQueryQATS(ICommunication sock)` - `MulticastUdpQueryQATS(string macAddress)` - `MulticastUdpQueryQATS(int timeoutMillisec)` - `MulticastUdpQueryQATS(string macAddress, int timeoutMillisec)` - `MulticastUdpQueryQATS(ICommunication sock, int TimeoutMillisec)` **Properties:** - `MultiCastDeviceClasses DeviceClass` - Set-only; default `Any` - `ResponseOptions ResponseOption` - Set-only; default `AlwaysRespond` - `IPAddress Address` - Set-only - `int Port` - Set-only - `List QATSEntry` - Get/set; populated from responses **Methods:** - `void Init(string macAddress = "")` - Initializes with 5000ms receive timeout - `IUDPQATSEntry[] GetUDPQATs()` - Returns all entries and clears the list (thread-safe) --- ### MACTableEntry **Constructor:** - `MACTableEntry(ushort age, ushort port, ushort filter, byte[] mac)` **Properties:** - `ushort Age` - Get-only - `ushort Port` - Get-only - `ushort Filter` - Get-only - `byte[] MAC` - Get-only --- ### DiscoveredConnectedSlice **Constructor:** - `DiscoveredConnectedSlice(string deviceMAC, MACTableEntry[] devices)` **Properties:** - `string DeviceMAC` - Get-only - `MACTableEntry[] ConnectedDevices` - Get-only --- ## 3. Invariants - **MAC Address Size:** Always 18 bytes in command payloads - **IP Address Size:** Always 16 bytes in command payloads - **Double MAC Size:** 36 bytes (2 × 18) - **Parameter Offsets:** Host MAC at offset 0, Client MAC at offset 18, first parameter at offset 36 - **Response Validation:** `WholePackage()` in base class validates that `CommandClientMac` equals `ResponseClientMac` AND `HostMac` equals `ResponseHostMac` - **Command Type:** All multicast commands set `command.Type = CommandPacket.CommandType.Multicast` - **StopAfterFirstMessage:** Defaults to `true`; discovery commands override to `false` to collect multiple responses - **Payload Sizes:** - Set commands (IP/Subnet/Gateway/DNS): `DOUBLE_MAC_ADDR_SIZE + IP_ADDR_SIZE` = 52 bytes - SetDhcp: `DOUBLE_MAC_ADDR_SIZE + 1` = 37 bytes - AutoDiscover command: 63 bytes, response: 278 bytes - DiscoverSlice6 command: 80 bytes - UDPQueryQATS command: 63 bytes, response: 215 bytes --- ## 4. Dependencies **External Dependencies (inferred from imports):** - `DTS.Common.ICommunication` - Command packet infrastructure - `DTS.Common.Interface.DASFactory` - `ICommunication` interface - `DTS.Common.Enums.DASFactory` - `DFConstantsAndEnums`, `CommandStatus` - `DTS.Common.Utilities.Logging` - `TextLogger`, `APILogger` - `DTS.Common.Utils` - `NetworkUtils` - `DTS.DASLib.Command.Classes` - `IDiscoveredDevice`, `DiscoveredDevice`, `ConnectedEthernetDevice`, `IUDPQATSEntry`, `UDPQATSEntry` **System Dependencies:** - `System.Net`, `System.Net.Sockets`, `System.Net.NetworkInformation` - UDP multicast networking - `System.Threading`, `System.Threading.Tasks` - Async operations - `System.Collections.Generic` - Collections **Dependents:** - Unknown from source alone (this module appears to be a leaf library consumed by higher-level application code) --- ## 5. Gotchas 1. **GetMacAddress() returns first available interface:** The method returns the first network interface that is `Up` and supports multicast, which may not be the interface intended for device communication. The comment in source acknowledges this is "a little hokey." 2. **Inconsistent MAC reference in MulticastGetDhcp:** `CommandToString()` uses `ResponseClientMac` while other get commands use `CommandClientMac`. This appears to be an inconsistency. 3. **Null socket in discovery constructors:** `MulticastAutoDiscover` and `MulticastUdpQueryQATS` have constructors that pass `null` to the base class for the `ICommunication` parameter. 4. **MAC address format conversion:** Response MACs are converted from dash-separated to colon-separated format (`Replace('-', ':')`) in discovery commands, but the wire format handling is not explicitly documented. 5. **Thread safety on QATSEntry:** `MulticastUdpQueryQATS.QATSEntry` uses a lock (`MyLock`) for thread safety, but other list properties like `DiscoveredDevices` in `MulticastAutoDiscover` do not appear to have equivalent synchronization. 6. **Silent exception handling in MulticastAutoDiscover:** The try/catch block around device class checking (lines ~100-107) has an empty body for Slice6/S6DB device classes, suggesting incomplete implementation or dead code. 7. **Hardcoded magic numbers:** Response parsing uses hardcoded offsets (e.g., 36, 40, 41, 57, 73, 89, 105, 107, 108, 118, 198, 230, 262 in `MulticastAutoDiscover`) without named constants for all fields.