import Foundation import IOKit /// Device-Info für den aktuellen Mac. /// Wird für /api/magic/register benötigt. struct MacDeviceInfo { let deviceId: String // IOPlatformUUID let hostname: String // Host.current().localizedName let model: String // hw.model via sysctl let osVersion: String // ProductVersion } enum MacDeviceDetectorError: Error, LocalizedError { case platformUUIDNotFound case sysctlFailed(String) var errorDescription: String? { switch self { case .platformUUIDNotFound: return "IOPlatformUUID nicht gefunden" case .sysctlFailed(let msg): return "sysctl fehlgeschlagen: \(msg)" } } } /// Erkennt Mac-Hardware-Infos via IOKit + sysctl. enum MacDeviceDetector { /// Liest IOPlatformUUID — eindeutige Hardware-ID des Mac. static func platformUUID() throws -> String { let service = IOServiceGetMatchingService( kIOMainPortDefault, IOServiceMatching("IOPlatformExpertDevice") ) guard service != 0 else { throw MacDeviceDetectorError.platformUUIDNotFound } defer { IOObjectRelease(service) } guard let uuidCF = IORegistryEntryCreateCFProperty( service, "IOPlatformUUID" as CFString, kCFAllocatorDefault, 0 )?.takeRetainedValue() as? String else { throw MacDeviceDetectorError.platformUUIDNotFound } return uuidCF } /// Liest hw.model via sysctl (z.B. "MacBookPro18,3"). static func hwModel() throws -> String { var size: size_t = 0 sysctlbyname("hw.model", nil, &size, nil, 0) var model = [CChar](repeating: 0, count: size) guard sysctlbyname("hw.model", &model, &size, nil, 0) == 0 else { throw MacDeviceDetectorError.sysctlFailed("hw.model read failed") } return String(cString: model) } /// Sammelt alle Infos für /api/magic/register. static func detect() throws -> MacDeviceInfo { let deviceId = try platformUUID() let hostname = Host.current().localizedName ?? "Unknown Mac" let model = try hwModel() let osVersion = ProcessInfo.processInfo.operatingSystemVersionString return MacDeviceInfo( deviceId: deviceId, hostname: hostname, model: model, osVersion: osVersion ) } }