feat: add --via-discovery for canonical "find then connect" flow#28
feat: add --via-discovery for canonical "find then connect" flow#28tylerkron wants to merge 1 commit into
Conversation
Adds a new --via-discovery flag that routes the streaming session through WiFiDeviceFinder.DiscoverAsync + DaqifiDeviceFactory.ConnectFromDeviceInfoAsync instead of the direct ConnectTcpAsync call. This exercises the public API surface that real applications should prefer for WiFi devices, and is the only path that honors IDeviceInfo.LocalInterfaceAddress — required on multi-homed hosts so the outbound socket binds to the NIC that received the discovery reply (see daqifi-core PR #187). UX: - --via-discovery alone connects to the first discovered device. - --via-discovery + --ip <addr> filters discovery to that address. - --via-discovery + --serial is rejected (WiFi-only). Existing --ip and --serial paths are unchanged, so this is purely additive. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Review Summary by QodoAdd --via-discovery flag for canonical WiFi find-then-connect flow
WalkthroughsDescription• Add --via-discovery flag for canonical WiFi device discovery and connection flow • Route streaming through WiFiDeviceFinder.DiscoverAsync + DaqifiDeviceFactory.ConnectFromDeviceInfoAsync • Support filtering discovered devices by IP address with --via-discovery --ip <addr> • Validate that --via-discovery cannot be combined with --serial (WiFi-only) • Update help documentation and README with discovery usage examples Diagramflowchart LR
A["CLI Arguments"] --> B{"--via-discovery?"}
B -->|Yes| C["WiFiDeviceFinder.DiscoverAsync"]
B -->|No| D["Direct ConnectTcpAsync or ConnectSerialAsync"]
C --> E{"--ip specified?"}
E -->|Yes| F["Filter to matching IP"]
E -->|No| G["Use first device"]
F --> H["ConnectFromDeviceInfoAsync"]
G --> H
H --> I["Bind to LocalInterfaceAddress"]
D --> J["Stream Session"]
I --> J
File Changes1. Program.cs
|
Code Review by Qodo
1. Discovery allowed for non-stream commands
|
| // Check if we have a connection target (IP, serial, or via-discovery) | ||
| var hasIpTarget = !string.IsNullOrWhiteSpace(options.IpAddress); | ||
| var hasSerialTarget = !string.IsNullOrWhiteSpace(options.SerialPort); | ||
|
|
||
| if (!hasIpTarget && !hasSerialTarget) | ||
| if (!hasIpTarget && !hasSerialTarget && !options.ViaDiscovery) | ||
| { | ||
| if (options.Discover || options.DiscoverSerial) | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| Console.Error.WriteLine("Missing required option: --ip or --serial"); | ||
| Console.Error.WriteLine("Missing required option: --ip, --serial, or --via-discovery"); | ||
| Console.Error.WriteLine("Use --help to see available options."); | ||
| return 1; | ||
| } |
There was a problem hiding this comment.
1. Discovery allowed for non-stream commands 🐞 Bug ≡ Correctness
Main() now accepts --via-discovery as a valid connection target globally, but SD ops / capture-and-parse / LAN chip info / firmware update paths still connect via ConnectTcpAsync(options.IpAddress!) when --serial is absent. Invocations like `--via-discovery --sd-list` can dereference a null IpAddress and throw before any try/catch, crashing the CLI.
Agent Prompt
### Issue description
`--via-discovery` is treated as a valid "connection target" for the entire CLI, but only `RunStreamingSessionAsync` implements the discovery connection branch. Other command paths still call `ConnectTcpAsync(options.IpAddress!)` (or similar) and will crash when `IpAddress` is null (e.g., `--via-discovery --sd-list`).
### Issue Context
The connection target validation happens before routing to firmware update, capture-and-parse, SD operations, and LAN chip info. Those commands currently require `--ip` or `--serial` (and some are serial-only by design), but `--via-discovery` now bypasses that requirement.
### Fix Focus Areas
- Program.cs[72-139]
- Program.cs[713-744]
- Program.cs[1122-1152]
- Program.cs[1234-1264]
- Program.cs[400-439]
### What to change
Choose one of these approaches:
1) **Restrict `--via-discovery` to streaming only (recommended for minimal change):**
- Keep the global requirement as `--ip` or `--serial` for non-streaming commands.
- Add an explicit validation in `Main()` such as:
- If `options.ViaDiscovery` is set AND any non-streaming command flag is selected (SD ops, capture-and-parse, firmware update, LAN chip info), then print a clear error and exit 1.
- Only allow `--via-discovery` to satisfy the missing-target gate when the program will route to `RunStreamingSessionAsync`.
2) **Implement via-discovery connection for each command:**
- Add `else if (options.ViaDiscovery)` branches to `RunSdCardOperationAsync`, `RunCaptureAndParseAsync`, `RunLanChipInfoAsync`, `RunFirmwareUpdateAsync` (and any other command using TCP) similar to the streaming implementation, or explicitly reject in serial-only scenarios.
Either way, ensure no command can reach `ConnectTcpAsync(options.IpAddress!)` when `IpAddress` is null.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Summary
Adds a new
--via-discoveryflag that routes the WiFi streaming session throughWiFiDeviceFinder.DiscoverAsync+DaqifiDeviceFactory.ConnectFromDeviceInfoAsyncinstead of the directConnectTcpAsynccall.This serves two purposes:
ConnectFromDeviceInfoAsyncis the canonical WiFi entry point inDaqifi.Core(find the device, then connect to it). The current--ipexample only demonstrates the "I already know the IP" path. Real consumers should generally discover first; this example now shows them how.IDeviceInfo.LocalInterfaceAddress, which controls which NIC the outbound socket binds to. Required on multi-homed hosts (see daqifi-core#187). Without an example-app path that exercises this, regressions to that behavior would not be caught by hardware tests.UX
--via-discovery(alone)--via-discovery --ip <addr><addr>.--via-discovery --serial <port>--ip <addr>(no--via-discovery)ConnectTcpAsync.--serial <port>The change is purely additive: existing
--ipand--serialpaths and their callers are untouched.Example output
Test plan
dotnet build— clean (againstdaqifi-corePR #187 sources)--via-discovery(no--ip) — discovers and connects to single device on network, printsLocalInterfaceAddress--via-discovery --ip 192.168.1.39— discovers, filters to that IP, connects--via-discovery --serial /dev/cu.usbmodem101— rejected with a clear error--ippath — unchanged, still works--serialpath — unchanged, still works (29 samples in 3s)Note: under hardware testing, the device's WiFi side stopped emitting stream messages partway through (USB serial kept working). This affected the legacy
--ippath identically, so it's a device-state issue and not a regression from this change. The successful run above (hundreds of samples) was captured prior to the WiFi hang.🤖 Generated with Claude Code