Files
DP44/docs/ai/DataPRO/SLICECommands/MulticastCommands.md
2026-04-17 14:55:32 -04:00

340 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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.