Files
DP44/docs/ai/DataPRO/SLICECommands/MulticastCommands.md

340 lines
13 KiB
Markdown
Raw Permalink 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-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<List<string>> 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<List<string>> 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<IDiscoveredDevice> 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<string, IDiscoveredDevice> MACAddressToDevice` - Get/set
- `DiscoveredConnectedSlice[] ConnectedDevices` - Get-only
**Methods:**
- `static string MACAddressToString(IEnumerable<byte> 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<IUDPQATSEntry> 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.