diff --git a/Sources/KitchenSyncApp/Discovery/DeviceMatch.swift b/Sources/KitchenSyncApp/Discovery/DeviceMatch.swift index d96e551..c90785e 100644 --- a/Sources/KitchenSyncApp/Discovery/DeviceMatch.swift +++ b/Sources/KitchenSyncApp/Discovery/DeviceMatch.swift @@ -31,17 +31,17 @@ enum DeviceMatch { /// /// The firmware advertises generic `_http._tcp` with no TXT record, so the hostname is all a /// client has. The hostname is `-`: `kitchensync-a4f2` on the - /// P4, `kstouch-dfd0` on the Touch, `x32link-7a1c` on the headless (ESP-035). Missing - /// `kstouch` is what made a real device invisible once already. + /// P4, `kstouch-dfd0` on the Touch. Missing `kstouch` made a real device invisible once. private static func matchesKnownHostname(_ name: String) -> Bool { let lower = name.lowercased() // a Bonjour instance name's case is not meaningful — // the P4 advertises "KitchenSync", the Touch "kstouch-…" return knownHostPrefixes.contains { lower.hasPrefix($0) } } - /// `x32link` joined this list in ESP-035 — but adding it here was the SMALL half. That - /// unit had no mDNS whatsoever: it never advertised, so no matcher could have found it. - /// The user saw it exactly that way — "I see kstouch, not the headless" — while the box - /// sat there powered, on the network, and following the session. - private static let knownHostPrefixes = ["kitchensync", "kstouch", "x32link"] + /// KitchenSync ONLY — the P4 and its Touch / Super Mini versions. X32Link is a SEPARATE + /// product (it happens to speak Link too) with its own app, so it is deliberately NOT + /// here, and the firmware publishes `dev=x32link` so the TXT path excludes it as well. + /// `x32link` was briefly in this list (ESP-035); removed once it became clear this app is + /// KitchenSync's, not the fleet's. + private static let knownHostPrefixes = ["kitchensync", "kstouch"] } diff --git a/Tests/KitchenSyncAppTests/DeviceMatchTests.swift b/Tests/KitchenSyncAppTests/DeviceMatchTests.swift index f8c9122..eee753f 100644 --- a/Tests/KitchenSyncAppTests/DeviceMatchTests.swift +++ b/Tests/KitchenSyncAppTests/DeviceMatchTests.swift @@ -58,14 +58,14 @@ final class DeviceMatchTests: XCTestCase { "a TXT record that says it ISN'T ours must beat a hostname that says it is") } - /// ESP-035: the headless X32Link. It was the last unit in the fleet with NO mDNS at - /// all -- it never advertised, so it could not be found no matter what this matcher - /// did. Now it announces `x32link-`, and the prefix list has to know the name. - /// - /// The user hit this exactly: "I see kstouch. not the headless." The device was - /// powered, on the network, and following the Link session. - func test_the_headless_x32link_is_one_of_ours() { - XCTAssertTrue(DeviceMatch.isKitchenSync(serviceName: "x32link-7a1c", txt: nil)) + /// X32Link is a SEPARATE product with its own app — this KitchenSync app must NOT show + /// it, by hostname OR by its (now `dev=x32link`) TXT. It was briefly included (ESP-035) + /// before the product line was clarified. + func test_the_x32link_is_not_shown_in_the_kitchensync_app() { + XCTAssertFalse(DeviceMatch.isKitchenSync(serviceName: "x32link-7a1c", txt: nil)) + XCTAssertFalse(DeviceMatch.isKitchenSync(serviceName: "X32Link", txt: nil)) + XCTAssertFalse(DeviceMatch.isKitchenSync(serviceName: "x32link-6160", + txt: ["dev": "x32link", "model": "x32link"])) } /// The prefix is still a HEURISTIC, and it must not swallow the whole network. A