From 32bb24ad4142c125981cfa87285a7431232b88f4 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Tue, 29 Sep 2026 12:47:25 +0200 Subject: [PATCH 01/13] fix(logging): stop os_log crashing on more than five arguments OSLog.log handed the [CVarArg] array to os_log for 6+ arguments, which reads garbage pointers for each %@ and segfaults in _os_log_fmt_flatten_object_impl. The seven-argument "Backfill acknowledged" line hit this on every backfill, crash-looping the app. The fallback now asserts in debug and logs the pre-rendered line as a single argument in release. The backfill ack line is collapsed to one argument. --- .../Session/TransmitterSession.swift | 8 ++++---- Sources/G6SensorCore/Transport/OSLog.swift | 20 ++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Sources/G6SensorCore/Session/TransmitterSession.swift b/Sources/G6SensorCore/Session/TransmitterSession.swift index 3176be4..17d77a9 100644 --- a/Sources/G6SensorCore/Session/TransmitterSession.swift +++ b/Sources/G6SensorCore/Session/TransmitterSession.swift @@ -466,10 +466,10 @@ public final class TransmitterSession: TransmitterConnectionDelegate { let ack = try peripheral.requestBackfill(startTime: startTime, endTime: endTime) - log.default("Backfill acknowledged: status %{public}@, backfillStatus %{public}@, id %{public}@, range %{public}@-%{public}@, length %{public}@, crc %{public}@", - String(ack.status), String(ack.backfillStatus), String(ack.identifier), - String(ack.startTime), String(ack.endTime), - String(ack.bufferLength), String(format: "%04x", ack.bufferCRC)) + log.default("Backfill acknowledged: %{public}@", + "status \(ack.status), backfillStatus \(ack.backfillStatus), id \(ack.identifier), " + + "range \(ack.startTime)-\(ack.endTime), length \(ack.bufferLength), " + + "crc \(String(format: "%04x", ack.bufferCRC))") // Nothing stored for the window: an empty result, not a failure. guard ack.bufferLength > 0 else { diff --git a/Sources/G6SensorCore/Transport/OSLog.swift b/Sources/G6SensorCore/Transport/OSLog.swift index 847d5be..999052d 100644 --- a/Sources/G6SensorCore/Transport/OSLog.swift +++ b/Sources/G6SensorCore/Transport/OSLog.swift @@ -34,7 +34,8 @@ extension OSLog { } private func log(_ message: StaticString, type: OSLogType, _ args: [CVarArg]) { - mirrorToFile(message, type: type, args) + let rendered = render(message, args) + mirrorToFile(rendered, type: type) switch args.count { case 0: @@ -50,7 +51,10 @@ extension OSLog { case 5: os_log(message, log: self, type: type, args[0], args[1], args[2], args[3], args[4]) default: - os_log(message, log: self, type: type, args) + // os_log can't take the array as varargs: handing it over reads + // garbage pointers for each %@ and crashes. Log the rendered line. + assertionFailure("OSLog supports at most 5 arguments, got \(args.count): \(message)") + os_log("%{public}@", log: self, type: type, rendered) } } @@ -65,15 +69,17 @@ extension OSLog { return Self.categories[ObjectIdentifier(self)] ?? "G6SensorKit" } - /// Mirrors every OSLog line into the exportable file log. Format - /// specifiers are OSLog-flavoured (%{public}@), so the privacy qualifier - /// is stripped before String(format:) sees them. - private func mirrorToFile(_ message: StaticString, type: OSLogType, _ args: [CVarArg]) { + /// Format specifiers are OSLog-flavoured (%{public}@), so the privacy + /// qualifier is stripped before String(format:) sees them. + private func render(_ message: StaticString, _ args: [CVarArg]) -> String { let template = "\(message)" .replacingOccurrences(of: "%{public}", with: "%") .replacingOccurrences(of: "%{private}", with: "%") - let rendered = args.isEmpty ? template : String(format: template, arguments: args) + return args.isEmpty ? template : String(format: template, arguments: args) + } + /// Mirrors every OSLog line into the exportable file log. + private func mirrorToFile(_ rendered: String, type: OSLogType) { let level: String switch type { case .debug: level = "DEBUG" From 182377a1d6360427b560687a81851dcc2b955804 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Thu, 24 Sep 2026 11:02:26 +0200 Subject: [PATCH 02/13] feat(onboarding): add transmitter/sensor code scanning from GS1 data matrix + bump minimum target to iOS 17.6 --- G6SensorKit.xcodeproj/project.pbxproj | 772 +++++----- .../xcschemes/G6SensorKit.xcscheme | 2 +- .../xcschemes/G6SensorKitPlugin.xcscheme | 2 +- .../xcschemes/G6SensorKitUI.xcscheme | 2 +- G6SensorKitUI/Localizable.xcstrings | 1300 +++++++++-------- G6SensorKitUI/Views/G6OnboardingViews.swift | 414 +++++- .../Views/G6PackageScannerView.swift | 85 ++ Package.swift | 2 +- Scripts/generate_project.rb | 2 +- .../Pairing/GS1DataMatrixParser.swift | 207 +++ .../GS1DataMatrixParserTests.swift | 239 +++ 11 files changed, 1986 insertions(+), 1041 deletions(-) create mode 100644 G6SensorKitUI/Views/G6PackageScannerView.swift create mode 100644 Sources/G6SensorCore/Pairing/GS1DataMatrixParser.swift create mode 100644 Tests/G6SensorCoreTests/GS1DataMatrixParserTests.swift diff --git a/G6SensorKit.xcodeproj/project.pbxproj b/G6SensorKit.xcodeproj/project.pbxproj index 1fcbec7..c978d84 100644 --- a/G6SensorKit.xcodeproj/project.pbxproj +++ b/G6SensorKit.xcodeproj/project.pbxproj @@ -7,81 +7,82 @@ objects = { /* Begin PBXBuildFile section */ - 0012909C39D62B9E08C9B064 /* G6SensorKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E1FE9C6D076DA1E91289E83 /* G6SensorKitUI.framework */; }; - 04A2B67E2547E628203F1358 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 429E660585726604E67AECFD /* Localizable.xcstrings */; }; - 04B8053FDEAE43229A81457E /* G6CGMManager+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3CDBC2872D089CCFC608914 /* G6CGMManager+UI.swift */; }; - 1E4F189DD2133923C1AFE92E /* G6OnboardingViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9A74B38BAA7E148D962602A /* G6OnboardingViews.swift */; }; - 1F73E2F944A55A9AC25A90D2 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8F0591ED59D9FDBBE9B979F /* LoopKit.framework */; }; - 20ADEEB69E1914A498A8288C /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48E317B6199E7FDA3530EB43 /* LocalizedString.swift */; }; - 2B177BC4AA7B5AC20A0C1CF0 /* G6SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3226DB4412DBC72DFFA90E /* G6SettingsView.swift */; }; - 348D78E88E7AB61A3EA8B5A6 /* G6DetailViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F3FBE9FF2D0785F9F703D83 /* G6DetailViews.swift */; }; - 3B345FE82B0B128320B404C0 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = BE9888BF3A30CE450E970741 /* Localizable.xcstrings */; }; - 3D9CC651E9C531C097620F89 /* OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 253838547314B57604F7AD40 /* OSLog.swift */; }; - 43A3BB61380CE04F8ADF97F5 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73742E0944319E3A7E474AB9 /* LoopKitUI.framework */; }; - 43CCBACB96EC5B4551CE5E7A /* G6ReadingDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BC5A15D4A759F997F7FC541 /* G6ReadingDetailView.swift */; }; - 44180D8F790DF0B7AD6858A6 /* G6CGMManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ED4B45A9BCAFD7FD14DE50A /* G6CGMManager.swift */; }; - 5124B64274AC3FE6A2C96D55 /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7B63810D31CCFC9F7F186D2 /* G6SensorKit.framework */; }; - 55F5DF80BE7C11261D02F92D /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73742E0944319E3A7E474AB9 /* LoopKitUI.framework */; }; - 5C0BDAD9F8F46B1894220D75 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B534C9F9F094DA2E641E1F56 /* HKUnit.swift */; }; - 60CA6A4323498F0AA5733921 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F64DEB4B031D1C5CFE809317 /* Foundation.framework */; }; - 6B46867393D9926E754A0B1C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F64DEB4B031D1C5CFE809317 /* Foundation.framework */; }; - 6B717441841D031D0B28D767 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F64DEB4B031D1C5CFE809317 /* Foundation.framework */; }; - 75FB2E8B0FA7123C2ED8DAE4 /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F7B63810D31CCFC9F7F186D2 /* G6SensorKit.framework */; }; - 80A0E78EA46BE2777673109D /* G6SensorKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0E1FE9C6D076DA1E91289E83 /* G6SensorKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 8BB678C1F2BD1D88FA1CFBBC /* G6SimulatedSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74783BF907EE99207B30B578 /* G6SimulatedSession.swift */; }; - 8FF638A85A7E67CA3BC5D9F9 /* G6Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03906F90369E7A2BF4DED672 /* G6Alert.swift */; }; - A69AF218C10E883AEB62C3BD /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8F0591ED59D9FDBBE9B979F /* LoopKit.framework */; }; - A81FAA3A42066C630B773A7A /* G6SensorKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F7B63810D31CCFC9F7F186D2 /* G6SensorKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - A8E3935009CCE36B2536A64C /* G6ApplySensorViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76466FB9DD611978BC655632 /* G6ApplySensorViews.swift */; }; - A9E3573682AB3B40EC374CA7 /* G6CalibrationGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFE94E843AB267DF79DBE2E3 /* G6CalibrationGuideView.swift */; }; - AF6D1CDCC2147D486CC666B0 /* G6AlertEvaluator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58664EFC566ECB3D78CCFAF /* G6AlertEvaluator.swift */; }; - B379B66CE81079E346AC7C74 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FCBBEB66782BF39C6C015CB /* LocalizedString.swift */; }; - B62C7DB071276B15C354E424 /* G6ActivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C5694A019EAD8454DABAA13 /* G6ActivityViewController.swift */; }; - B920AFAF7C31F1E389D677D6 /* G6UICoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB91998500832B7983C5050 /* G6UICoordinator.swift */; }; - B974B8BBB65603583E2AA9B6 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89D79C9A64B80B4CC5B3DE78 /* HKUnit.swift */; }; - C2A26CF0F1BB14468B041B94 /* G6Graphics.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD441CA0C87A3361D4ABC996 /* G6Graphics.swift */; }; - C402E99C66F01260013FBB1A /* G6ShareCredentialStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C22FE5054AF7D52948DDD28 /* G6ShareCredentialStore.swift */; }; - CDBF362147EF86005600539C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FF491D549C3EF35172BD575E /* Assets.xcassets */; }; - E733B5AF9AC6DDC38B92A330 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8F0591ED59D9FDBBE9B979F /* LoopKit.framework */; }; - EB7246F1D6D512CC2D28B53C /* G6CGMManagerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADFDEDB952EC717B78C87578 /* G6CGMManagerState.swift */; }; - F605B5DD6F6B98C7BA18BE26 /* G6SensorKitPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7985708466B1C12CA524C462 /* G6SensorKitPlugin.swift */; }; - F63FF74AB43CFAC6FA5BB9F1 /* Locked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2737F7376B1AEBD38191DE68 /* Locked.swift */; }; - FCEF70D7853D669835A2C2A2 /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEFF2008F7747472D563331E /* TimeInterval.swift */; }; + 0693C7476402404DE20D9B4F /* G6SensorKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7D03FEB69599D0AF52C22E7 /* G6SensorKitUI.framework */; }; + 08A233C9F8B1EEE650BF50FD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A05FE6FDE339FE9321E759CE /* Foundation.framework */; }; + 0DCAF3F659A2703E9CE24557 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A05FE6FDE339FE9321E759CE /* Foundation.framework */; }; + 113A6AADAEB5985A9833663C /* G6UICoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5028E90A753D82115E51BAB /* G6UICoordinator.swift */; }; + 1A031090C7910D3B4BF01246 /* G6ApplySensorViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4C8C72C6C5749880D0BD5C /* G6ApplySensorViews.swift */; }; + 1D75C9FD5B5D1798EA308C39 /* G6CGMManagerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70699BE714273A4BD5D45AC /* G6CGMManagerState.swift */; }; + 22BB2B2C62819EF28F71536C /* G6ShareCredentialStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DFA312ADF260746CCC9301B /* G6ShareCredentialStore.swift */; }; + 29A6CAB9D3F1429C79C19511 /* G6OnboardingViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E000DC9B3FDC9F2050CED65 /* G6OnboardingViews.swift */; }; + 2E65773EEED2B72034485C42 /* G6SensorKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DDAD343CEBAA70172F375006 /* G6SensorKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 3098352571C4019F26687C99 /* G6CGMManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0275C0BBB9440BE16CBDF2 /* G6CGMManager.swift */; }; + 37DEA0FE2BA2BF0AE14ADF13 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9B5551B35D84DFE748E0B321 /* Localizable.xcstrings */; }; + 3AE0A4224E186716AD9B38BA /* G6CGMManager+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C499A8F2A45C5A5F2F6804C /* G6CGMManager+UI.swift */; }; + 47095EDB584677B51133FB55 /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CA1FD8713E9A195D3BEA65 /* TimeInterval.swift */; }; + 49DEA9F14CC66EE8CF7A1938 /* G6AlertEvaluator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5890F3F14505D20A3BF454AA /* G6AlertEvaluator.swift */; }; + 4B60FA598DDD83373BF9AF9A /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54F40591DF7546BD56902D34 /* LocalizedString.swift */; }; + 51E9F176C1D5B4D4C16A59A3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8951478AD4BD18A38807B735 /* Assets.xcassets */; }; + 52069C196E0860E1FCAA8146 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 119FBC1B7DA145CCFD8E17F3 /* LoopKitUI.framework */; }; + 56DB4016BF61B7A5DEE9F47F /* G6ActivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7732FACCE0CBE0F2F3B38C /* G6ActivityViewController.swift */; }; + 59206A3FBADAC02D985182A1 /* G6PackageScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA1B967C98FAF4A32CF34800 /* G6PackageScannerView.swift */; }; + 66AF27897E99EE1859962C21 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = CDEF209176738C95929680EC /* Localizable.xcstrings */; }; + 69F9DC12AEE8DB64C7D39D7E /* OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD71DF7E83AF717270ABEB4F /* OSLog.swift */; }; + 766AD55DDB016FA0D4CE7531 /* G6SensorKitPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCA7C7B1082F4DB56383E62 /* G6SensorKitPlugin.swift */; }; + 779E0E2EFCD8988DB0D48E1E /* G6ReadingDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1C1DFABF454CD486038D23B /* G6ReadingDetailView.swift */; }; + 7C492DE3E17736DC551DA2EB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A05FE6FDE339FE9321E759CE /* Foundation.framework */; }; + 7F02F2A865E554B97A785906 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E87AE5D60C3B9C9E8C81472 /* LoopKit.framework */; }; + 81AF0901E0F6A16A4634AAF5 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE39687E90C268D1324F4928 /* LocalizedString.swift */; }; + 88F90B528970A11DC5A0D6A0 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E87AE5D60C3B9C9E8C81472 /* LoopKit.framework */; }; + 8955744E48E5793B6019A69D /* G6Graphics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BECD386214266280C635EF4 /* G6Graphics.swift */; }; + 90E1E35D64D8B5B905A2C2A4 /* G6SimulatedSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7D978600747DD5D213658C /* G6SimulatedSession.swift */; }; + 957A9D07764B7C40DFBBEF6A /* G6DetailViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B9AFCC06065A5816CF9B0D0 /* G6DetailViews.swift */; }; + 990AF949E54DE82A45F260E6 /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDAD343CEBAA70172F375006 /* G6SensorKit.framework */; }; + A8D7FD3BA2F4591BC1E043C5 /* G6Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32113D2719FEFFC866A296E /* G6Alert.swift */; }; + B07CE4D488047BAB8E73A5D5 /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDAD343CEBAA70172F375006 /* G6SensorKit.framework */; }; + B4312F20327B994F68EA3B2F /* Locked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4757E22C8DF1FFACB0F5FE55 /* Locked.swift */; }; + B74C908295343E4D9541421A /* G6SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 701FB5943D703C73F0914901 /* G6SettingsView.swift */; }; + BAB668D8A5161A2CFA99EE4F /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E87AE5D60C3B9C9E8C81472 /* LoopKit.framework */; }; + C156DFB9A7376B332B0A9090 /* G6CalibrationGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1400B7D723677F1F4E972C6 /* G6CalibrationGuideView.swift */; }; + C5A03437EB059CD181CD4931 /* G6SensorKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D7D03FEB69599D0AF52C22E7 /* G6SensorKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + CA78A9937F8B70F55524820B /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 868A9B29D7E79FF89C96DB5D /* HKUnit.swift */; }; + CBDC88F219D43D305FB343B0 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EFA396B891E4BDFE3D274C7 /* HKUnit.swift */; }; + F5B979D63490B082BA6EDAF6 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 119FBC1B7DA145CCFD8E17F3 /* LoopKitUI.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 393AD5FC1C4D642198DBF3BA /* PBXContainerItemProxy */ = { + 6DEB037B2C11C81B47415311 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 9254155A3D36B6309735ED9B /* Project object */; + containerPortal = 7DEBAED43E1D4606FF3FD912 /* Project object */; proxyType = 1; - remoteGlobalIDString = 3ADDB0CD055A33C01C7B54FE; - remoteInfo = G6SensorKitUI; + remoteGlobalIDString = 09335603AF5648226FC57BDD; + remoteInfo = G6SensorKit; }; - 5DCC41D3B8AE0AF30CAAD2E3 /* PBXContainerItemProxy */ = { + AAE0E5C2368DE5F178EBA0A0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 9254155A3D36B6309735ED9B /* Project object */; + containerPortal = 7DEBAED43E1D4606FF3FD912 /* Project object */; proxyType = 1; - remoteGlobalIDString = 1B26058BD31E40741B0058A5; - remoteInfo = G6SensorKit; + remoteGlobalIDString = 81F390A243C74FC62F2D96A1; + remoteInfo = G6SensorKitUI; }; - CC0AE83086E9B970A7244CCE /* PBXContainerItemProxy */ = { + EEC597C8A44555CBC2C31860 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 9254155A3D36B6309735ED9B /* Project object */; + containerPortal = 7DEBAED43E1D4606FF3FD912 /* Project object */; proxyType = 1; - remoteGlobalIDString = 1B26058BD31E40741B0058A5; + remoteGlobalIDString = 09335603AF5648226FC57BDD; remoteInfo = G6SensorKit; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 4FFBC74F2EB40DC4B5ED7514 /* Embed Frameworks */ = { + 8DADB55D2D89E3F4C5997BF2 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - A81FAA3A42066C630B773A7A /* G6SensorKit.framework in Embed Frameworks */, - 80A0E78EA46BE2777673109D /* G6SensorKitUI.framework in Embed Frameworks */, + 2E65773EEED2B72034485C42 /* G6SensorKit.framework in Embed Frameworks */, + C5A03437EB059CD181CD4931 /* G6SensorKitUI.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -89,194 +90,196 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 03906F90369E7A2BF4DED672 /* G6Alert.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6Alert.swift; sourceTree = ""; }; - 0BC5A15D4A759F997F7FC541 /* G6ReadingDetailView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ReadingDetailView.swift; path = Views/G6ReadingDetailView.swift; sourceTree = ""; }; - 0E1FE9C6D076DA1E91289E83 /* G6SensorKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 1DB91998500832B7983C5050 /* G6UICoordinator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6UICoordinator.swift; sourceTree = ""; }; - 253838547314B57604F7AD40 /* OSLog.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OSLog.swift; sourceTree = ""; }; - 2737F7376B1AEBD38191DE68 /* Locked.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Locked.swift; sourceTree = ""; }; - 2C5694A019EAD8454DABAA13 /* G6ActivityViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ActivityViewController.swift; path = Views/G6ActivityViewController.swift; sourceTree = ""; }; - 429E660585726604E67AECFD /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; - 48E317B6199E7FDA3530EB43 /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; - 4F3226DB4412DBC72DFFA90E /* G6SettingsView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6SettingsView.swift; path = Views/G6SettingsView.swift; sourceTree = ""; }; - 5F3FBE9FF2D0785F9F703D83 /* G6DetailViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6DetailViews.swift; path = Views/G6DetailViews.swift; sourceTree = ""; }; - 5FCBBEB66782BF39C6C015CB /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; - 6ED4B45A9BCAFD7FD14DE50A /* G6CGMManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManager.swift; sourceTree = ""; }; - 73742E0944319E3A7E474AB9 /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 74783BF907EE99207B30B578 /* G6SimulatedSession.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SimulatedSession.swift; sourceTree = ""; }; - 76466FB9DD611978BC655632 /* G6ApplySensorViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ApplySensorViews.swift; path = Views/G6ApplySensorViews.swift; sourceTree = ""; }; - 7985708466B1C12CA524C462 /* G6SensorKitPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SensorKitPlugin.swift; sourceTree = ""; }; - 89D79C9A64B80B4CC5B3DE78 /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; - 8C22FE5054AF7D52948DDD28 /* G6ShareCredentialStore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6ShareCredentialStore.swift; sourceTree = ""; }; - A9A74B38BAA7E148D962602A /* G6OnboardingViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6OnboardingViews.swift; path = Views/G6OnboardingViews.swift; sourceTree = ""; }; - ADFDEDB952EC717B78C87578 /* G6CGMManagerState.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManagerState.swift; sourceTree = ""; }; - B534C9F9F094DA2E641E1F56 /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; - B58664EFC566ECB3D78CCFAF /* G6AlertEvaluator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6AlertEvaluator.swift; sourceTree = ""; }; - BE9888BF3A30CE450E970741 /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; - BEFF2008F7747472D563331E /* TimeInterval.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TimeInterval.swift; sourceTree = ""; }; - C3CDBC2872D089CCFC608914 /* G6CGMManager+UI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "G6CGMManager+UI.swift"; sourceTree = ""; }; - CFE94E843AB267DF79DBE2E3 /* G6CalibrationGuideView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6CalibrationGuideView.swift; path = Views/G6CalibrationGuideView.swift; sourceTree = ""; }; - F566E5E3758DE9D2DBE17607 /* G6SensorKitPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - F64DEB4B031D1C5CFE809317 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - F7B63810D31CCFC9F7F186D2 /* G6SensorKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - F8F0591ED59D9FDBBE9B979F /* LoopKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - FD441CA0C87A3361D4ABC996 /* G6Graphics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6Graphics.swift; path = Views/G6Graphics.swift; sourceTree = ""; }; - FF491D549C3EF35172BD575E /* Assets.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 0E000DC9B3FDC9F2050CED65 /* G6OnboardingViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6OnboardingViews.swift; path = Views/G6OnboardingViews.swift; sourceTree = ""; }; + 119FBC1B7DA145CCFD8E17F3 /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1FCA7C7B1082F4DB56383E62 /* G6SensorKitPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SensorKitPlugin.swift; sourceTree = ""; }; + 3B9AFCC06065A5816CF9B0D0 /* G6DetailViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6DetailViews.swift; path = Views/G6DetailViews.swift; sourceTree = ""; }; + 3C499A8F2A45C5A5F2F6804C /* G6CGMManager+UI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "G6CGMManager+UI.swift"; sourceTree = ""; }; + 4757E22C8DF1FFACB0F5FE55 /* Locked.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Locked.swift; sourceTree = ""; }; + 54F40591DF7546BD56902D34 /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; + 5890F3F14505D20A3BF454AA /* G6AlertEvaluator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6AlertEvaluator.swift; sourceTree = ""; }; + 701FB5943D703C73F0914901 /* G6SettingsView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6SettingsView.swift; path = Views/G6SettingsView.swift; sourceTree = ""; }; + 7BECD386214266280C635EF4 /* G6Graphics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6Graphics.swift; path = Views/G6Graphics.swift; sourceTree = ""; }; + 7E87AE5D60C3B9C9E8C81472 /* LoopKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 84CA1FD8713E9A195D3BEA65 /* TimeInterval.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TimeInterval.swift; sourceTree = ""; }; + 868A9B29D7E79FF89C96DB5D /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; + 8951478AD4BD18A38807B735 /* Assets.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 8DFA312ADF260746CCC9301B /* G6ShareCredentialStore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6ShareCredentialStore.swift; sourceTree = ""; }; + 8EFA396B891E4BDFE3D274C7 /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; + 98A7EC476C76B121A139FB05 /* G6SensorKitPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9B5551B35D84DFE748E0B321 /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; + A05FE6FDE339FE9321E759CE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS26.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + AD71DF7E83AF717270ABEB4F /* OSLog.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OSLog.swift; sourceTree = ""; }; + B5028E90A753D82115E51BAB /* G6UICoordinator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6UICoordinator.swift; sourceTree = ""; }; + CDEF209176738C95929680EC /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; + CE0275C0BBB9440BE16CBDF2 /* G6CGMManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManager.swift; sourceTree = ""; }; + CE7D978600747DD5D213658C /* G6SimulatedSession.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SimulatedSession.swift; sourceTree = ""; }; + D70699BE714273A4BD5D45AC /* G6CGMManagerState.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManagerState.swift; sourceTree = ""; }; + D7D03FEB69599D0AF52C22E7 /* G6SensorKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DDAD343CEBAA70172F375006 /* G6SensorKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + EA1B967C98FAF4A32CF34800 /* G6PackageScannerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6PackageScannerView.swift; path = Views/G6PackageScannerView.swift; sourceTree = ""; }; + EA4C8C72C6C5749880D0BD5C /* G6ApplySensorViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ApplySensorViews.swift; path = Views/G6ApplySensorViews.swift; sourceTree = ""; }; + EA7732FACCE0CBE0F2F3B38C /* G6ActivityViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ActivityViewController.swift; path = Views/G6ActivityViewController.swift; sourceTree = ""; }; + EE39687E90C268D1324F4928 /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; + F1400B7D723677F1F4E972C6 /* G6CalibrationGuideView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6CalibrationGuideView.swift; path = Views/G6CalibrationGuideView.swift; sourceTree = ""; }; + F1C1DFABF454CD486038D23B /* G6ReadingDetailView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ReadingDetailView.swift; path = Views/G6ReadingDetailView.swift; sourceTree = ""; }; + F32113D2719FEFFC866A296E /* G6Alert.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6Alert.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 08CFF0A2C0AF7A01359571D3 /* Frameworks */ = { + 0DADADB95F8B6B4EE8BBD291 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 6B46867393D9926E754A0B1C /* Foundation.framework in Frameworks */, - A69AF218C10E883AEB62C3BD /* LoopKit.framework in Frameworks */, - 55F5DF80BE7C11261D02F92D /* LoopKitUI.framework in Frameworks */, - 5124B64274AC3FE6A2C96D55 /* G6SensorKit.framework in Frameworks */, - 0012909C39D62B9E08C9B064 /* G6SensorKitUI.framework in Frameworks */, + 7C492DE3E17736DC551DA2EB /* Foundation.framework in Frameworks */, + BAB668D8A5161A2CFA99EE4F /* LoopKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4BBD731E15A4EBB02214C814 /* Frameworks */ = { + 7E51350C1DFCD8D28A2734F5 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 60CA6A4323498F0AA5733921 /* Foundation.framework in Frameworks */, - E733B5AF9AC6DDC38B92A330 /* LoopKit.framework in Frameworks */, + 0DCAF3F659A2703E9CE24557 /* Foundation.framework in Frameworks */, + 7F02F2A865E554B97A785906 /* LoopKit.framework in Frameworks */, + F5B979D63490B082BA6EDAF6 /* LoopKitUI.framework in Frameworks */, + 990AF949E54DE82A45F260E6 /* G6SensorKit.framework in Frameworks */, + 0693C7476402404DE20D9B4F /* G6SensorKitUI.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 7034F2C68438154861EB8766 /* Frameworks */ = { + B0308539A01D8375A0B43EF4 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 6B717441841D031D0B28D767 /* Foundation.framework in Frameworks */, - 1F73E2F944A55A9AC25A90D2 /* LoopKit.framework in Frameworks */, - 43A3BB61380CE04F8ADF97F5 /* LoopKitUI.framework in Frameworks */, - 75FB2E8B0FA7123C2ED8DAE4 /* G6SensorKit.framework in Frameworks */, + 08A233C9F8B1EEE650BF50FD /* Foundation.framework in Frameworks */, + 88F90B528970A11DC5A0D6A0 /* LoopKit.framework in Frameworks */, + 52069C196E0860E1FCAA8146 /* LoopKitUI.framework in Frameworks */, + B07CE4D488047BAB8E73A5D5 /* G6SensorKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 0B2EBDB688CC9F72D51B8750 /* Products */ = { + 1B6E3A15801163A7EDDC18B0 = { isa = PBXGroup; children = ( - F7B63810D31CCFC9F7F186D2 /* G6SensorKit.framework */, - 0E1FE9C6D076DA1E91289E83 /* G6SensorKitUI.framework */, - F566E5E3758DE9D2DBE17607 /* G6SensorKitPlugin.framework */, + 73C056E01BDF2C32C4010248 /* G6SensorKit */, + FE65C9531147916346925C03 /* Common */, + 86FEC5F564DA61606B5AAC38 /* G6SensorKitUI */, + 8735A9ACBBACA7E2C94847D0 /* G6SensorKitPlugin */, + 9306DFA63B200FA524EDB85D /* Products */, + D8EFE4C33EF051BAA9C3642E /* Frameworks */, ); - name = Products; sourceTree = ""; }; - 1DCBFFA30E3C8A0058AA3F9E /* Common */ = { + 6A6E300163BCF6800DE164CC /* iOS */ = { isa = PBXGroup; children = ( - 89D79C9A64B80B4CC5B3DE78 /* HKUnit.swift */, - 48E317B6199E7FDA3530EB43 /* LocalizedString.swift */, - 2737F7376B1AEBD38191DE68 /* Locked.swift */, - 253838547314B57604F7AD40 /* OSLog.swift */, - BEFF2008F7747472D563331E /* TimeInterval.swift */, - B534C9F9F094DA2E641E1F56 /* HKUnit.swift */, + A05FE6FDE339FE9321E759CE /* Foundation.framework */, ); - name = Common; - path = Common; + name = iOS; sourceTree = ""; }; - 473EA52459AC5B5F384D87B9 /* iOS */ = { + 73C056E01BDF2C32C4010248 /* G6SensorKit */ = { isa = PBXGroup; children = ( - F64DEB4B031D1C5CFE809317 /* Foundation.framework */, + F32113D2719FEFFC866A296E /* G6Alert.swift */, + 5890F3F14505D20A3BF454AA /* G6AlertEvaluator.swift */, + CE0275C0BBB9440BE16CBDF2 /* G6CGMManager.swift */, + D70699BE714273A4BD5D45AC /* G6CGMManagerState.swift */, + 8DFA312ADF260746CCC9301B /* G6ShareCredentialStore.swift */, + CE7D978600747DD5D213658C /* G6SimulatedSession.swift */, + 9B5551B35D84DFE748E0B321 /* Localizable.xcstrings */, ); - name = iOS; + name = G6SensorKit; + path = G6SensorKit; sourceTree = ""; }; - 96B57708CA5A86D6435C7B27 /* Frameworks */ = { + 86FEC5F564DA61606B5AAC38 /* G6SensorKitUI */ = { isa = PBXGroup; children = ( - F8F0591ED59D9FDBBE9B979F /* LoopKit.framework */, - 73742E0944319E3A7E474AB9 /* LoopKitUI.framework */, - 473EA52459AC5B5F384D87B9 /* iOS */, + 3C499A8F2A45C5A5F2F6804C /* G6CGMManager+UI.swift */, + B5028E90A753D82115E51BAB /* G6UICoordinator.swift */, + 54F40591DF7546BD56902D34 /* LocalizedString.swift */, + EA7732FACCE0CBE0F2F3B38C /* G6ActivityViewController.swift */, + EA4C8C72C6C5749880D0BD5C /* G6ApplySensorViews.swift */, + F1400B7D723677F1F4E972C6 /* G6CalibrationGuideView.swift */, + 3B9AFCC06065A5816CF9B0D0 /* G6DetailViews.swift */, + 7BECD386214266280C635EF4 /* G6Graphics.swift */, + 0E000DC9B3FDC9F2050CED65 /* G6OnboardingViews.swift */, + EA1B967C98FAF4A32CF34800 /* G6PackageScannerView.swift */, + F1C1DFABF454CD486038D23B /* G6ReadingDetailView.swift */, + 701FB5943D703C73F0914901 /* G6SettingsView.swift */, + CDEF209176738C95929680EC /* Localizable.xcstrings */, + 8951478AD4BD18A38807B735 /* Assets.xcassets */, ); - name = Frameworks; + name = G6SensorKitUI; + path = G6SensorKitUI; sourceTree = ""; }; - BC0A237992092A7C2BE9B0C1 /* G6SensorKit */ = { + 8735A9ACBBACA7E2C94847D0 /* G6SensorKitPlugin */ = { isa = PBXGroup; children = ( - 03906F90369E7A2BF4DED672 /* G6Alert.swift */, - B58664EFC566ECB3D78CCFAF /* G6AlertEvaluator.swift */, - 6ED4B45A9BCAFD7FD14DE50A /* G6CGMManager.swift */, - ADFDEDB952EC717B78C87578 /* G6CGMManagerState.swift */, - 8C22FE5054AF7D52948DDD28 /* G6ShareCredentialStore.swift */, - 74783BF907EE99207B30B578 /* G6SimulatedSession.swift */, - BE9888BF3A30CE450E970741 /* Localizable.xcstrings */, + 1FCA7C7B1082F4DB56383E62 /* G6SensorKitPlugin.swift */, ); - name = G6SensorKit; - path = G6SensorKit; + name = G6SensorKitPlugin; + path = G6SensorKitPlugin; sourceTree = ""; }; - C15E860FAD47DBE3D41E4EC3 /* G6SensorKitPlugin */ = { + 9306DFA63B200FA524EDB85D /* Products */ = { isa = PBXGroup; children = ( - 7985708466B1C12CA524C462 /* G6SensorKitPlugin.swift */, + DDAD343CEBAA70172F375006 /* G6SensorKit.framework */, + D7D03FEB69599D0AF52C22E7 /* G6SensorKitUI.framework */, + 98A7EC476C76B121A139FB05 /* G6SensorKitPlugin.framework */, ); - name = G6SensorKitPlugin; - path = G6SensorKitPlugin; + name = Products; sourceTree = ""; }; - CC50F2BDBEBFB7D6BD059422 /* G6SensorKitUI */ = { + D8EFE4C33EF051BAA9C3642E /* Frameworks */ = { isa = PBXGroup; children = ( - C3CDBC2872D089CCFC608914 /* G6CGMManager+UI.swift */, - 1DB91998500832B7983C5050 /* G6UICoordinator.swift */, - 5FCBBEB66782BF39C6C015CB /* LocalizedString.swift */, - 2C5694A019EAD8454DABAA13 /* G6ActivityViewController.swift */, - 76466FB9DD611978BC655632 /* G6ApplySensorViews.swift */, - CFE94E843AB267DF79DBE2E3 /* G6CalibrationGuideView.swift */, - 5F3FBE9FF2D0785F9F703D83 /* G6DetailViews.swift */, - FD441CA0C87A3361D4ABC996 /* G6Graphics.swift */, - A9A74B38BAA7E148D962602A /* G6OnboardingViews.swift */, - 0BC5A15D4A759F997F7FC541 /* G6ReadingDetailView.swift */, - 4F3226DB4412DBC72DFFA90E /* G6SettingsView.swift */, - 429E660585726604E67AECFD /* Localizable.xcstrings */, - FF491D549C3EF35172BD575E /* Assets.xcassets */, + 7E87AE5D60C3B9C9E8C81472 /* LoopKit.framework */, + 119FBC1B7DA145CCFD8E17F3 /* LoopKitUI.framework */, + 6A6E300163BCF6800DE164CC /* iOS */, ); - name = G6SensorKitUI; - path = G6SensorKitUI; + name = Frameworks; sourceTree = ""; }; - FA22E5F750CC96151439CB10 = { + FE65C9531147916346925C03 /* Common */ = { isa = PBXGroup; children = ( - BC0A237992092A7C2BE9B0C1 /* G6SensorKit */, - 1DCBFFA30E3C8A0058AA3F9E /* Common */, - CC50F2BDBEBFB7D6BD059422 /* G6SensorKitUI */, - C15E860FAD47DBE3D41E4EC3 /* G6SensorKitPlugin */, - 0B2EBDB688CC9F72D51B8750 /* Products */, - 96B57708CA5A86D6435C7B27 /* Frameworks */, + 868A9B29D7E79FF89C96DB5D /* HKUnit.swift */, + EE39687E90C268D1324F4928 /* LocalizedString.swift */, + 4757E22C8DF1FFACB0F5FE55 /* Locked.swift */, + AD71DF7E83AF717270ABEB4F /* OSLog.swift */, + 84CA1FD8713E9A195D3BEA65 /* TimeInterval.swift */, + 8EFA396B891E4BDFE3D274C7 /* HKUnit.swift */, ); + name = Common; + path = Common; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 46CF0A3AEA3068EC92793F50 /* Headers */ = { + 73AF5A35F193528B276B30B4 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 8871D9EC41336D32DC93F0A1 /* Headers */ = { + B371086234D0EE811F02EC7D /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - D0DCBEE1011D380E0DAB9521 /* Headers */ = { + BB4D67F09424EEBE210E689C /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( @@ -286,14 +289,14 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 1B26058BD31E40741B0058A5 /* G6SensorKit */ = { + 09335603AF5648226FC57BDD /* G6SensorKit */ = { isa = PBXNativeTarget; - buildConfigurationList = 3C02D248834BA3228A2A0985 /* Build configuration list for PBXNativeTarget "G6SensorKit" */; + buildConfigurationList = CCF0FF127493D98642A8659A /* Build configuration list for PBXNativeTarget "G6SensorKit" */; buildPhases = ( - D0DCBEE1011D380E0DAB9521 /* Headers */, - 8BC23E60728EBBC538BC019C /* Sources */, - 4BBD731E15A4EBB02214C814 /* Frameworks */, - 840346A90686729F6FA69249 /* Resources */, + 73AF5A35F193528B276B30B4 /* Headers */, + A7014F2B4A8E71778514B0ED /* Sources */, + 0DADADB95F8B6B4EE8BBD291 /* Frameworks */, + A14A0BEC872E5B61AAEF9C97 /* Resources */, ); buildRules = ( ); @@ -301,62 +304,62 @@ ); name = G6SensorKit; packageProductDependencies = ( - 7B648B7A7143DAA0CE2F4FF9 /* G6SensorCore */, + D394DBFFF1C24A5BE57AD26C /* G6SensorCore */, ); productName = G6SensorKit; - productReference = F7B63810D31CCFC9F7F186D2 /* G6SensorKit.framework */; + productReference = DDAD343CEBAA70172F375006 /* G6SensorKit.framework */; productType = "com.apple.product-type.framework"; }; - 3ADDB0CD055A33C01C7B54FE /* G6SensorKitUI */ = { + 350C634F69815B1C4E0D8ACC /* G6SensorKitPlugin */ = { isa = PBXNativeTarget; - buildConfigurationList = 0871B09F7297CFA1E6F3ADCB /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */; + buildConfigurationList = BF1A336FAFA87AA5EAEAF56A /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */; buildPhases = ( - 8871D9EC41336D32DC93F0A1 /* Headers */, - 488FB4793D06FDDE73E64813 /* Sources */, - 7034F2C68438154861EB8766 /* Frameworks */, - FF4CE3D3A177620D8B97B7A2 /* Resources */, + B371086234D0EE811F02EC7D /* Headers */, + B52E76D39F272FBFCA5CFC20 /* Sources */, + 7E51350C1DFCD8D28A2734F5 /* Frameworks */, + F94EE9C2A48DF3DA8B2F856E /* Resources */, + 8DADB55D2D89E3F4C5997BF2 /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( - 17B55B286FE0A660013A668D /* PBXTargetDependency */, + 765B7BD50495DB444A1963DB /* PBXTargetDependency */, + 02D3824D7998AA7BB603E4B0 /* PBXTargetDependency */, ); - name = G6SensorKitUI; - productName = G6SensorKitUI; - productReference = 0E1FE9C6D076DA1E91289E83 /* G6SensorKitUI.framework */; + name = G6SensorKitPlugin; + productName = G6SensorKitPlugin; + productReference = 98A7EC476C76B121A139FB05 /* G6SensorKitPlugin.framework */; productType = "com.apple.product-type.framework"; }; - EDCCBEADE99E54A732DD551F /* G6SensorKitPlugin */ = { + 81F390A243C74FC62F2D96A1 /* G6SensorKitUI */ = { isa = PBXNativeTarget; - buildConfigurationList = 5C9202DE59969D7F24D99477 /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */; + buildConfigurationList = 46716CE46FCB498D573CFB95 /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */; buildPhases = ( - 46CF0A3AEA3068EC92793F50 /* Headers */, - A4FF0114F6295250522E88B0 /* Sources */, - 08CFF0A2C0AF7A01359571D3 /* Frameworks */, - BD1DA6A29C055EAE3F534D12 /* Resources */, - 4FFBC74F2EB40DC4B5ED7514 /* Embed Frameworks */, + BB4D67F09424EEBE210E689C /* Headers */, + 645A1FC8D344F4493716F92A /* Sources */, + B0308539A01D8375A0B43EF4 /* Frameworks */, + BC0BD21D3B7639D7D9899099 /* Resources */, ); buildRules = ( ); dependencies = ( - 07F9FA8A5643278CD0C1E3DC /* PBXTargetDependency */, - 53F05EC0188A4EBC5A8F5A4F /* PBXTargetDependency */, + 7B658B66EC05118906BACD6A /* PBXTargetDependency */, ); - name = G6SensorKitPlugin; - productName = G6SensorKitPlugin; - productReference = F566E5E3758DE9D2DBE17607 /* G6SensorKitPlugin.framework */; + name = G6SensorKitUI; + productName = G6SensorKitUI; + productReference = D7D03FEB69599D0AF52C22E7 /* G6SensorKitUI.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 9254155A3D36B6309735ED9B /* Project object */ = { + 7DEBAED43E1D4606FF3FD912 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1600; LastUpgradeCheck = 1600; }; - buildConfigurationList = 1F831DF837A28B0445B1871F /* Build configuration list for PBXProject "G6SensorKit" */; + buildConfigurationList = 5B553683CF19BBB44D32F54D /* Build configuration list for PBXProject "G6SensorKit" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = en; hasScannedForEncodings = 0; @@ -364,121 +367,122 @@ en, Base, ); - mainGroup = FA22E5F750CC96151439CB10; + mainGroup = 1B6E3A15801163A7EDDC18B0; minimizedProjectReferenceProxies = 0; packageReferences = ( - 17A8E591A82F95E6476AA1C9 /* XCLocalSwiftPackageReference "." */, + EDC1BC10B795C488BF680E84 /* XCLocalSwiftPackageReference "." */, ); - preferredProjectObjectVersion = 77; - productRefGroup = 0B2EBDB688CC9F72D51B8750 /* Products */; + preferredProjectObjectVersion = 100; + productRefGroup = 9306DFA63B200FA524EDB85D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 1B26058BD31E40741B0058A5 /* G6SensorKit */, - 3ADDB0CD055A33C01C7B54FE /* G6SensorKitUI */, - EDCCBEADE99E54A732DD551F /* G6SensorKitPlugin */, + 09335603AF5648226FC57BDD /* G6SensorKit */, + 81F390A243C74FC62F2D96A1 /* G6SensorKitUI */, + 350C634F69815B1C4E0D8ACC /* G6SensorKitPlugin */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 840346A90686729F6FA69249 /* Resources */ = { + A14A0BEC872E5B61AAEF9C97 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3B345FE82B0B128320B404C0 /* Localizable.xcstrings in Resources */, + 37DEA0FE2BA2BF0AE14ADF13 /* Localizable.xcstrings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - BD1DA6A29C055EAE3F534D12 /* Resources */ = { + BC0BD21D3B7639D7D9899099 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 66AF27897E99EE1859962C21 /* Localizable.xcstrings in Resources */, + 51E9F176C1D5B4D4C16A59A3 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - FF4CE3D3A177620D8B97B7A2 /* Resources */ = { + F94EE9C2A48DF3DA8B2F856E /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 04A2B67E2547E628203F1358 /* Localizable.xcstrings in Resources */, - CDBF362147EF86005600539C /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 488FB4793D06FDDE73E64813 /* Sources */ = { + 645A1FC8D344F4493716F92A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 04B8053FDEAE43229A81457E /* G6CGMManager+UI.swift in Sources */, - B920AFAF7C31F1E389D677D6 /* G6UICoordinator.swift in Sources */, - B379B66CE81079E346AC7C74 /* LocalizedString.swift in Sources */, - B62C7DB071276B15C354E424 /* G6ActivityViewController.swift in Sources */, - A8E3935009CCE36B2536A64C /* G6ApplySensorViews.swift in Sources */, - A9E3573682AB3B40EC374CA7 /* G6CalibrationGuideView.swift in Sources */, - 348D78E88E7AB61A3EA8B5A6 /* G6DetailViews.swift in Sources */, - C2A26CF0F1BB14468B041B94 /* G6Graphics.swift in Sources */, - 1E4F189DD2133923C1AFE92E /* G6OnboardingViews.swift in Sources */, - 43CCBACB96EC5B4551CE5E7A /* G6ReadingDetailView.swift in Sources */, - 2B177BC4AA7B5AC20A0C1CF0 /* G6SettingsView.swift in Sources */, - 5C0BDAD9F8F46B1894220D75 /* HKUnit.swift in Sources */, + 3AE0A4224E186716AD9B38BA /* G6CGMManager+UI.swift in Sources */, + 113A6AADAEB5985A9833663C /* G6UICoordinator.swift in Sources */, + 4B60FA598DDD83373BF9AF9A /* LocalizedString.swift in Sources */, + 56DB4016BF61B7A5DEE9F47F /* G6ActivityViewController.swift in Sources */, + 1A031090C7910D3B4BF01246 /* G6ApplySensorViews.swift in Sources */, + C156DFB9A7376B332B0A9090 /* G6CalibrationGuideView.swift in Sources */, + 957A9D07764B7C40DFBBEF6A /* G6DetailViews.swift in Sources */, + 8955744E48E5793B6019A69D /* G6Graphics.swift in Sources */, + 29A6CAB9D3F1429C79C19511 /* G6OnboardingViews.swift in Sources */, + 59206A3FBADAC02D985182A1 /* G6PackageScannerView.swift in Sources */, + 779E0E2EFCD8988DB0D48E1E /* G6ReadingDetailView.swift in Sources */, + B74C908295343E4D9541421A /* G6SettingsView.swift in Sources */, + CBDC88F219D43D305FB343B0 /* HKUnit.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8BC23E60728EBBC538BC019C /* Sources */ = { + A7014F2B4A8E71778514B0ED /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8FF638A85A7E67CA3BC5D9F9 /* G6Alert.swift in Sources */, - AF6D1CDCC2147D486CC666B0 /* G6AlertEvaluator.swift in Sources */, - 44180D8F790DF0B7AD6858A6 /* G6CGMManager.swift in Sources */, - EB7246F1D6D512CC2D28B53C /* G6CGMManagerState.swift in Sources */, - C402E99C66F01260013FBB1A /* G6ShareCredentialStore.swift in Sources */, - 8BB678C1F2BD1D88FA1CFBBC /* G6SimulatedSession.swift in Sources */, - B974B8BBB65603583E2AA9B6 /* HKUnit.swift in Sources */, - 20ADEEB69E1914A498A8288C /* LocalizedString.swift in Sources */, - F63FF74AB43CFAC6FA5BB9F1 /* Locked.swift in Sources */, - 3D9CC651E9C531C097620F89 /* OSLog.swift in Sources */, - FCEF70D7853D669835A2C2A2 /* TimeInterval.swift in Sources */, + A8D7FD3BA2F4591BC1E043C5 /* G6Alert.swift in Sources */, + 49DEA9F14CC66EE8CF7A1938 /* G6AlertEvaluator.swift in Sources */, + 3098352571C4019F26687C99 /* G6CGMManager.swift in Sources */, + 1D75C9FD5B5D1798EA308C39 /* G6CGMManagerState.swift in Sources */, + 22BB2B2C62819EF28F71536C /* G6ShareCredentialStore.swift in Sources */, + 90E1E35D64D8B5B905A2C2A4 /* G6SimulatedSession.swift in Sources */, + CA78A9937F8B70F55524820B /* HKUnit.swift in Sources */, + 81AF0901E0F6A16A4634AAF5 /* LocalizedString.swift in Sources */, + B4312F20327B994F68EA3B2F /* Locked.swift in Sources */, + 69F9DC12AEE8DB64C7D39D7E /* OSLog.swift in Sources */, + 47095EDB584677B51133FB55 /* TimeInterval.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - A4FF0114F6295250522E88B0 /* Sources */ = { + B52E76D39F272FBFCA5CFC20 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - F605B5DD6F6B98C7BA18BE26 /* G6SensorKitPlugin.swift in Sources */, + 766AD55DDB016FA0D4CE7531 /* G6SensorKitPlugin.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 07F9FA8A5643278CD0C1E3DC /* PBXTargetDependency */ = { + 02D3824D7998AA7BB603E4B0 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = G6SensorKit; - target = 1B26058BD31E40741B0058A5 /* G6SensorKit */; - targetProxy = 5DCC41D3B8AE0AF30CAAD2E3 /* PBXContainerItemProxy */; + name = G6SensorKitUI; + target = 81F390A243C74FC62F2D96A1 /* G6SensorKitUI */; + targetProxy = AAE0E5C2368DE5F178EBA0A0 /* PBXContainerItemProxy */; }; - 17B55B286FE0A660013A668D /* PBXTargetDependency */ = { + 765B7BD50495DB444A1963DB /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = G6SensorKit; - target = 1B26058BD31E40741B0058A5 /* G6SensorKit */; - targetProxy = CC0AE83086E9B970A7244CCE /* PBXContainerItemProxy */; + target = 09335603AF5648226FC57BDD /* G6SensorKit */; + targetProxy = 6DEB037B2C11C81B47415311 /* PBXContainerItemProxy */; }; - 53F05EC0188A4EBC5A8F5A4F /* PBXTargetDependency */ = { + 7B658B66EC05118906BACD6A /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = G6SensorKitUI; - target = 3ADDB0CD055A33C01C7B54FE /* G6SensorKitUI */; - targetProxy = 393AD5FC1C4D642198DBF3BA /* PBXContainerItemProxy */; + name = G6SensorKit; + target = 09335603AF5648226FC57BDD /* G6SensorKit */; + targetProxy = EEC597C8A44555CBC2C31860 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 000A188CB4AC3C534F7DEDA5 /* Debug */ = { + 00710D3BA9DAD1A2388461E2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -498,7 +502,7 @@ GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = G6SensorKitPlugin/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitPlugin; @@ -514,63 +518,76 @@ }; name = Debug; }; - 0A0532B628C24522B116C2FD /* Release */ = { + 2BDD209E0CD6A5C0AEFACFA1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; + CLANG_ENABLE_OBJC_WEAK = NO; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)", + ); + INFOPLIST_FILE = G6SensorKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKit; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.9; + TARGETED_DEVICE_FAMILY = 1; VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Release; }; - 1AE1D80C0367AD875A928588 /* Release */ = { + 77859602A5958F6C7636159C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = NO; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)", + ); + INFOPLIST_FILE = G6SensorKitUI/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitUI; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.9; + TARGETED_DEVICE_FAMILY = 1; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 9A188B7C6508D5BE865290DF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -589,7 +606,7 @@ ); INFOPLIST_FILE = G6SensorKitUI/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitUI; @@ -605,7 +622,7 @@ }; name = Release; }; - 222C333070D0F8651A5DDC09 /* Debug */ = { + A8C5BF1B01A31FCB77220DF6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -656,7 +673,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -667,7 +684,7 @@ }; name = Debug; }; - 98F6F8109B911D276CB9A52E /* Debug */ = { + B67CF6E49F25C51A744E1B8D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -675,41 +692,7 @@ CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = NO; CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_MODULE_VERIFIER = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(BUILT_PRODUCTS_DIR)", - ); - INFOPLIST_FILE = G6SensorKit/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKit; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.9; - TARGETED_DEVICE_FAMILY = 1; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - D9853CD9CF2489E939E9B1B7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUILD_LIBRARY_FOR_DISTRIBUTION = YES; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = NO; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; + DEFINES_MODULE = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -718,24 +701,27 @@ "$(inherited)", "$(BUILT_PRODUCTS_DIR)", ); - INFOPLIST_FILE = G6SensorKitUI/Info.plist; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = G6SensorKitPlugin/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitUI; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitPlugin; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.9; TARGETED_DEVICE_FAMILY = 1; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WRAPPER_EXTENSION = loopplugin; }; - name = Debug; + name = Release; }; - F5F1150AA306D577B24CACB2 /* Release */ = { + BC493465B0E8800363FF8DAC /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -754,7 +740,7 @@ ); INFOPLIST_FILE = G6SensorKit/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKit; @@ -764,84 +750,102 @@ SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.9; TARGETED_DEVICE_FAMILY = 1; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - FC3AF832A0B14A9957D5966C /* Release */ = { + FD0873526D7652433984E911 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = NO; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = NO; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_MODULE_VERIFIER = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(BUILT_PRODUCTS_DIR)", - ); - GENERATE_INFOPLIST_FILE = NO; - INFOPLIST_FILE = G6SensorKitPlugin/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.1; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitPlugin; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.9; - TARGETED_DEVICE_FAMILY = 1; VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WRAPPER_EXTENSION = loopplugin; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 0871B09F7297CFA1E6F3ADCB /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */ = { + 46716CE46FCB498D573CFB95 /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */ = { isa = XCConfigurationList; buildConfigurations = ( - 1AE1D80C0367AD875A928588 /* Release */, - D9853CD9CF2489E939E9B1B7 /* Debug */, + 9A188B7C6508D5BE865290DF /* Release */, + 77859602A5958F6C7636159C /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 1F831DF837A28B0445B1871F /* Build configuration list for PBXProject "G6SensorKit" */ = { + 5B553683CF19BBB44D32F54D /* Build configuration list for PBXProject "G6SensorKit" */ = { isa = XCConfigurationList; buildConfigurations = ( - 222C333070D0F8651A5DDC09 /* Debug */, - 0A0532B628C24522B116C2FD /* Release */, + A8C5BF1B01A31FCB77220DF6 /* Debug */, + FD0873526D7652433984E911 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 3C02D248834BA3228A2A0985 /* Build configuration list for PBXNativeTarget "G6SensorKit" */ = { + BF1A336FAFA87AA5EAEAF56A /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */ = { isa = XCConfigurationList; buildConfigurations = ( - F5F1150AA306D577B24CACB2 /* Release */, - 98F6F8109B911D276CB9A52E /* Debug */, + B67CF6E49F25C51A744E1B8D /* Release */, + 00710D3BA9DAD1A2388461E2 /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 5C9202DE59969D7F24D99477 /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */ = { + CCF0FF127493D98642A8659A /* Build configuration list for PBXNativeTarget "G6SensorKit" */ = { isa = XCConfigurationList; buildConfigurations = ( - FC3AF832A0B14A9957D5966C /* Release */, - 000A188CB4AC3C534F7DEDA5 /* Debug */, + 2BDD209E0CD6A5C0AEFACFA1 /* Release */, + BC493465B0E8800363FF8DAC /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -849,18 +853,18 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 17A8E591A82F95E6476AA1C9 /* XCLocalSwiftPackageReference "." */ = { + EDC1BC10B795C488BF680E84 /* XCLocalSwiftPackageReference "." */ = { isa = XCLocalSwiftPackageReference; relativePath = .; }; /* End XCLocalSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 7B648B7A7143DAA0CE2F4FF9 /* G6SensorCore */ = { + D394DBFFF1C24A5BE57AD26C /* G6SensorCore */ = { isa = XCSwiftPackageProductDependency; productName = G6SensorCore; }; /* End XCSwiftPackageProductDependency section */ }; - rootObject = 9254155A3D36B6309735ED9B /* Project object */; + rootObject = 7DEBAED43E1D4606FF3FD912 /* Project object */; } diff --git a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme index 6c3c107..dacccc3 100644 --- a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme +++ b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> diff --git a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme index 7fedca5..cbfeedb 100644 --- a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme +++ b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> diff --git a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme index ad990c8..60e523c 100644 --- a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme +++ b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> diff --git a/G6SensorKitUI/Localizable.xcstrings b/G6SensorKitUI/Localizable.xcstrings index f218d5c..309d047 100644 --- a/G6SensorKitUI/Localizable.xcstrings +++ b/G6SensorKitUI/Localizable.xcstrings @@ -1,838 +1,904 @@ { "sourceLanguage": "en", "strings": { - "Sensor Failed": { - "extractionState": "manual", - "comment": "Status highlight for failed sensor" + "": { }, - "Sensor Warmup": { - "extractionState": "manual", - "comment": "Status highlight during warm-up" + "—": { + "comment": "Placeholder for missing value", + "extractionState": "manual" }, - "Transmitter Expired": { - "extractionState": "manual", - "comment": "Status highlight when the transmitter is past end of life" + "“Dexcom”, “G6”, and “ONE” are trademarks of Dexcom, Inc., used here only to describe which devices are compatible. This app is not made by or endorsed by Dexcom.": { + "comment": "Trademark attribution footer", + "extractionState": "manual" }, - "No Sensor": { - "extractionState": "manual", - "comment": "Status highlight when no session is running" + "%@ remaining": { + "comment": "Session remaining (1: duration)", + "extractionState": "manual" }, - "Sensor Expired": { - "extractionState": "manual", - "comment": "Status highlight for expired sensor" + "%@ until ready": { + "comment": "Warm-up remaining (1: duration)", + "extractionState": "manual" + }, + "%@. %@": { + "comment": "A label that describes the phase and detail of a lifecycle bar.", + "isCommentAutoGenerated": true, + "localizations": { + "en": { + "stringUnit": { + "state": "new", + "value": "%1$@. %2$@" + } + } + } }, - "Calibration Needed": { - "extractionState": "manual", - "comment": "Status highlight when a calibration is requested" + "%1$@ talks to your G6 or Dexcom ONE transmitter directly. It starts and stops sensor sessions, sends your calibrations, and fills in readings it missed.": { + "comment": "Introduction: what the native driver does (1: app name)", + "extractionState": "manual" }, - "Signal Loss": { - "extractionState": "manual", - "comment": "Status highlight for signal loss" + "%1$@%2$@ per minute": { + "comment": "Trend rate (1: sign, 2: formatted rate with unit)", + "extractionState": "manual" }, - "This app": { - "extractionState": "manual", - "comment": "Fallback when the host app name cannot be read" + "%1$@%2$@/min": { + "comment": "Trend rate (1: sign, 2: formatted rate with unit)", + "extractionState": "manual" }, - "Transmitter ID": { - "extractionState": "manual", - "comment": "Navigation title for transmitter ID entry" + "%d °C": { + "comment": "Temperature in Celsius (1: degrees)", + "extractionState": "manual" }, - "Sensor Code": { - "extractionState": "manual", - "comment": "Navigation title for sensor code entry" + "%d days": { + "comment": "Number of days (1: day count)", + "extractionState": "manual" }, - "Applying Your Sensor": { - "extractionState": "manual", - "comment": "Navigation title for placement guide" + "%d min ago": { + "comment": "Minutes since last reading (1: minutes)", + "extractionState": "manual" }, - "Pairing": { - "extractionState": "manual", - "comment": "Navigation title for pairing screen" + "%d mV": { + "comment": "Voltage in millivolts (1: millivolts)", + "extractionState": "manual" }, - "Warm-Up": { - "extractionState": "manual", - "comment": "Navigation title for warm-up screen" + "%dd %dh": { + "comment": "Duration in days and hours", + "extractionState": "manual" }, - "Dexcom G6 / ONE": { - "extractionState": "manual", - "comment": "Navigation title for settings" + "%dh %dm": { + "comment": "Duration in hours and minutes", + "extractionState": "manual" }, - "Calibration": { - "extractionState": "manual", - "comment": "Navigation title for calibration" + "%dm": { + "comment": "Duration in minutes", + "extractionState": "manual" }, - "Transmitter": { - "extractionState": "manual", - "comment": "Navigation title for transmitter details" + "%lld": { + "comment": "A number in the center of a circle.", + "isCommentAutoGenerated": true }, - "Session Length": { - "extractionState": "manual", - "comment": "Navigation title for sensor life settings" + "4-digit code": { + "comment": "Sensor code text field placeholder", + "extractionState": "manual" }, - "Dexcom Share": { - "extractionState": "manual", - "comment": "Navigation title for Share upload settings" + "6-character ID": { + "comment": "Transmitter ID text field placeholder", + "extractionState": "manual" }, - "INSERT SENSOR": { - "extractionState": "manual", - "comment": "Section label for the insert-sensor steps" + "A display-only value has been shifted by a recent calibration. It is shown for continuity and is not used for dosing.": { + "comment": "Footer explaining display-only readings", + "extractionState": "manual" }, - "STEP %d of 10": { - "extractionState": "manual", - "comment": "Insert-sensor step counter (1: step number)" + "A pairing request will appear": { + "comment": "Pairing callout title", + "extractionState": "manual" }, - "Thoroughly wash and dry your hands.": { - "extractionState": "manual", - "comment": "Insert step 1 body" + "Accept the Bluetooth pairing request within about a minute. If it disappears, the app tries again on the next connection.": { + "comment": "Pairing callout body while awaiting the prompt", + "extractionState": "manual" }, - "Clean the insertion site with alcohol. Let it dry.": { - "extractionState": "manual", - "comment": "Insert step 2 body" + "Active": { + "comment": "Session phase: active", + "extractionState": "manual" }, - "The site must be completely dry or the adhesive will not stick.": { - "extractionState": "manual", - "comment": "Insert step 2 note" + "Adults wear the sensor on the belly. Children aged 2 to 17 can use the belly or upper buttocks.": { + "comment": "Apply-sensor site instruction", + "extractionState": "manual" }, - "Optional: if you use a skin adhesive, draw an empty oval on the skin and let it dry.": { - "extractionState": "manual", - "comment": "Insert step 3 body" + "After warm-up": { + "comment": "Why calibration is unavailable during warm-up", + "extractionState": "manual" }, - "Insert the sensor on clean skin in the centre of the oval, not on the adhesive itself.": { - "extractionState": "manual", - "comment": "Insert step 3 note" + "Allow camera access in Settings to scan the Data Matrix code on your Dexcom transmitter packaging.": { + "comment": "Camera denied alert message", + "extractionState": "manual" }, - "Take out the applicator whose sensor code you entered, and peel off its cover.": { - "extractionState": "manual", - "comment": "Insert step 4 body" + "Apply a new sensor": { + "comment": "Apply-sensor screen title", + "extractionState": "manual" }, - "Do not use it if the packaging is damaged or was already opened. Keep the packaging until the session is finished.": { - "extractionState": "manual", - "comment": "Insert step 4 note" + "Applying Your Sensor": { + "comment": "Navigation title for placement guide", + "extractionState": "manual" }, - "Pull off both adhesive labels.": { - "extractionState": "manual", - "comment": "Insert step 5 body" + "ATTACH TRANSMITTER": { + "comment": "Section label for the attach-transmitter steps", + "extractionState": "manual" }, - "Keep the tab showing the sensor code. Do not touch the adhesive.": { - "extractionState": "manual", - "comment": "Insert step 5 note" + "Battery": { + "comment": "Transmitter details section header for battery", + "extractionState": "manual" }, - "Place the applicator flat against your skin — horizontally, not upright — and press down firmly.": { - "extractionState": "manual", - "comment": "Insert step 6 body" + "Battery B is the cell that runs down first and determines whether the transmitter can finish a session.": { + "comment": "Footer explaining what battery B means", + "extractionState": "manual" }, - "Fold and break off the safety guard, then throw it away.": { - "extractionState": "manual", - "comment": "Insert step 7 body" + "CALIBRATE": { + "comment": "Section label for the calibration steps", + "extractionState": "manual" }, - "Push and release the button to insert the sensor.": { - "extractionState": "manual", - "comment": "Insert step 8 body" + "Calibration": { + "comment": "Navigation title for calibration", + "extractionState": "manual" }, - "Lift the applicator away.": { - "extractionState": "manual", - "comment": "Insert step 9 body" + "Calibration becomes available once warm-up finishes. Do not make insulin decisions from early readings — use a fingerstick meter and follow your care team's guidance.": { + "comment": "Footer explaining warm-up restrictions", + "extractionState": "manual" }, - "Dispose of the applicator following your local rules for items that have touched blood.": { - "extractionState": "manual", - "comment": "Insert step 9 note" + "Calibration Needed": { + "comment": "Status highlight when a calibration is requested", + "extractionState": "manual" }, - "Left on your skin: the sensor wire and the transmitter holder. The sensor is in.": { - "extractionState": "manual", - "comment": "Insert step 10 body" + "Calibration requested": { + "comment": "Algorithm state: needs calibration", + "extractionState": "manual" }, - "ATTACH TRANSMITTER": { - "extractionState": "manual", - "comment": "Section label for the attach-transmitter steps" + "Calibrations must be between %1$@ and %2$@. If your meter reads outside that range, treat it and follow your care team's guidance instead of calibrating.": { + "comment": "Validation message for out-of-range calibration (1: minimum with unit, 2: maximum with unit)", + "extractionState": "manual" }, - "STEP %d of 4": { - "extractionState": "manual", - "comment": "Attach-transmitter step counter (1: step number)" + "Camera access is off": { + "comment": "Camera denied alert title", + "extractionState": "manual" }, - "Take the transmitter out of its box and prepare it for use. Wipe the bottom with an alcohol wipe and let it dry.": { - "extractionState": "manual", - "comment": "Attach step 1 body" + "Cancel": { + "comment": "Cancel button", + "extractionState": "manual" }, - "Do not touch the metal contacts and do not scratch the bottom — that can break the waterproof seal.": { - "extractionState": "manual", - "comment": "Attach step 1 note" + "Check that the Dexcom app is not connected to this transmitter, that the transmitter ID is exactly right, and that your phone is next to it. Bluetooth must be on.": { + "comment": "Pairing troubleshooting body", + "extractionState": "manual" }, - "Slide the transmitter tab into the slot at the narrow end of the holder.": { - "extractionState": "manual", - "comment": "Attach step 3 body" + "Clean the insertion site with alcohol. Let it dry.": { + "comment": "Insert step 2 body", + "extractionState": "manual" }, - "Press the wide end of the transmitter until it clicks into the holder.": { - "extractionState": "manual", - "comment": "Attach step 4 body" + "Connected to your transmitter": { + "comment": "Pairing status: connected", + "extractionState": "manual" }, - "Rub your fingers around the patch three times to secure it.": { - "extractionState": "manual", - "comment": "Attach step 5 body" + "Connecting to your transmitter": { + "comment": "Pairing screen heading", + "extractionState": "manual" }, - "You are almost done — the sensor session starts next.": { - "extractionState": "manual", - "comment": "Attach step 5 note" + "Continue": { + "comment": "Confirm pairing a new transmitter", + "extractionState": "manual" }, - "Apply a new sensor": { - "extractionState": "manual", - "comment": "Apply-sensor screen title" + "Could not save your credentials. Try again.": { + "comment": "Status message when saving Share credentials fails", + "extractionState": "manual" }, - "Adults wear the sensor on the belly. Children aged 2 to 17 can use the belly or upper buttocks.": { - "extractionState": "manual", - "comment": "Apply-sensor site instruction" + "Credentials saved to the Keychain.": { + "comment": "Status message after saving Share credentials", + "extractionState": "manual" }, - "Keep at least 8 cm (3 inches) away from insulin pump sites and injection sites, and avoid scars, bony areas, and your waistband.": { - "extractionState": "manual", - "comment": "Apply-sensor spacing instruction" + "Device": { + "comment": "Reading detail label for device", + "extractionState": "manual" }, - "HOW TO APPLY A SENSOR": { - "extractionState": "manual", - "comment": "Apply-sensor help button" + "Dexcom Account": { + "comment": "Section header for Share account", + "extractionState": "manual" }, - "Next": { - "extractionState": "manual", - "comment": "Next button" + "Dexcom G6": { + "comment": "Introduction screen product title", + "extractionState": "manual" }, - "How to apply a sensor": { - "extractionState": "manual", - "comment": "Apply-sensor help screen title" + "Dexcom G6 / ONE": { + "comment": "Navigation title for settings", + "extractionState": "manual" }, - "Done": { - "extractionState": "manual", - "comment": "Done button" + "Dexcom Share": { + "comment": "Navigation title for Share upload settings", + "extractionState": "manual" }, - "CALIBRATE": { - "extractionState": "manual", - "comment": "Section label for the calibration steps" + "Dexcom Share Upload": { + "comment": "Row to Share upload settings", + "extractionState": "manual" }, - "STEP %d of 3": { - "extractionState": "manual", - "comment": "Calibration step counter (1: step number)" + "Display only": { + "comment": "Reading detail label for display-only flag", + "extractionState": "manual" }, - "Wash and dry your hands with soap and water — not a gel cleaner.": { - "extractionState": "manual", - "comment": "Calibration step 1 body" + "Dispose of the applicator following your local rules for items that have touched blood.": { + "comment": "Insert step 9 note", + "extractionState": "manual" }, - "Poorly washed hands are behind most inaccurate meter readings, and an inaccurate reading teaches the sensor the wrong thing.": { - "extractionState": "manual", - "comment": "Calibration step 1 note" + "Do not dose on early readings": { + "comment": "Warm-up callout title", + "extractionState": "manual" }, - "Take a blood sample from your fingertip and measure it with your meter.": { - "extractionState": "manual", - "comment": "Calibration step 2 body" + "Do not make insulin decisions from the first readings after warm-up, or from readings that look wrong for how you feel. Use a fingerstick meter instead, and follow your care team's guidance.": { + "comment": "Warm-up callout body about dosing safety", + "extractionState": "manual" }, - "Use a fingertip only — samples from other sites are less accurate. Use the same meter throughout a sensor session, and check that your strips are in date.": { - "extractionState": "manual", - "comment": "Calibration step 2 note" + "Do not round the number or reuse an older reading. If more than 5 minutes have passed, measure again.": { + "comment": "Calibration step 3 note", + "extractionState": "manual" }, - "Enter the exact value your meter showed, within 5 minutes of the fingerstick.": { - "extractionState": "manual", - "comment": "Calibration step 3 body" + "Do not touch the metal contacts and do not scratch the bottom — that can break the waterproof seal.": { + "comment": "Attach step 1 note", + "extractionState": "manual" }, - "Do not round the number or reuse an older reading. If more than 5 minutes have passed, measure again.": { - "extractionState": "manual", - "comment": "Calibration step 3 note" + "Do not use it if the packaging is damaged or was already opened. Keep the packaging until the session is finished.": { + "comment": "Insert step 4 note", + "extractionState": "manual" }, - "How to calibrate": { - "extractionState": "manual", - "comment": "Calibration help screen title" + "Done": { + "comment": "Done button", + "extractionState": "manual" + }, + "Ending Soon": { + "comment": "Session phase: expiring soon", + "extractionState": "manual" }, "Enter a fingerstick value": { - "extractionState": "manual", - "comment": "Calibration screen heading" + "comment": "Calibration screen heading", + "extractionState": "manual" }, - "Use a fresh fingerstick reading from your meter, taken just now. Wash and dry your hands first — a value from unwashed fingers can be badly wrong and will teach the sensor the wrong thing.": { - "extractionState": "manual", - "comment": "Calibration instructions" + "Enter a number.": { + "comment": "Validation message for non-numeric calibration entry", + "extractionState": "manual" }, - "HOW TO CALIBRATE": { - "extractionState": "manual", - "comment": "Calibration help button" + "Enter Calibration": { + "comment": "Button to enter a calibration", + "extractionState": "manual" }, - "It may take a few minutes": { - "extractionState": "manual", - "comment": "Calibration callout title" + "Enter the Code": { + "comment": "Return to entering the sensor code", + "extractionState": "manual" }, - "The calibration is sent the next time your transmitter connects, which can be up to 5 minutes away. The transmitter may accept it, ask for a second value, or reject it — this screen's status will tell you which.": { - "extractionState": "manual", - "comment": "Calibration callout body about delivery timing" + "Enter the exact value your meter showed, within 5 minutes of the fingerstick.": { + "comment": "Calibration step 3 body", + "extractionState": "manual" }, - "Send Calibration": { - "extractionState": "manual", - "comment": "Calibration submit button" + "Enter your sensor code": { + "comment": "Sensor code screen heading", + "extractionState": "manual" }, - "Enter a number.": { - "extractionState": "manual", - "comment": "Validation message for non-numeric calibration entry" + "Enter your transmitter ID": { + "comment": "Transmitter ID screen heading", + "extractionState": "manual" }, - "Pair New Transmitter": { - "extractionState": "manual", - "comment": "Row to pair a different transmitter" + "Expected to expire": { + "comment": "Transmitter detail label for expiry", + "extractionState": "manual" }, - "Pair a new transmitter?": { - "extractionState": "manual", - "comment": "Confirmation title for pairing a new transmitter" + "Expected to finish at %1$@, about %2$d minutes from now": { + "comment": "Warm-up completion time (1: time, 2: minutes remaining)", + "extractionState": "manual" }, - "Continue": { - "extractionState": "manual", - "comment": "Confirm pairing a new transmitter" + "Firmware": { + "comment": "Transmitter detail label for firmware", + "extractionState": "manual" }, - "Your current sensor session will end. A session lives on the transmitter, so it cannot move to a new one — you will start a fresh session after pairing, and can reuse the sensor you are wearing. Stop the sensor first if your old transmitter is still attached and you want it stopped cleanly. Your other settings are kept.": { - "extractionState": "manual", - "comment": "Confirmation message for pairing a new transmitter while a session is running" + "First used": { + "comment": "Transmitter detail label for activation date", + "extractionState": "manual" }, - "You will enter the new transmitter's ID and can then start a sensor session on it. Your other settings are kept.": { - "extractionState": "manual", - "comment": "Confirmation message for pairing a new transmitter with no session running" + "Fold and break off the safety guard, then throw it away.": { + "comment": "Insert step 7 body", + "extractionState": "manual" }, - "Model": { - "extractionState": "manual", - "comment": "Transmitter detail label for model" + "How to apply a sensor": { + "comment": "Apply-sensor help screen title", + "extractionState": "manual" }, - "Firmware": { - "extractionState": "manual", - "comment": "Transmitter detail label for firmware" + "How to Apply a Sensor": { + "comment": "Row to the placement guide", + "extractionState": "manual" }, - "Unknown": { - "extractionState": "manual", - "comment": "Placeholder for unknown value" + "HOW TO APPLY A SENSOR": { + "comment": "Apply-sensor help button", + "extractionState": "manual" }, - "First used": { - "extractionState": "manual", - "comment": "Transmitter detail label for activation date" + "How to calibrate": { + "comment": "Calibration help screen title", + "extractionState": "manual" }, - "Expected to expire": { - "extractionState": "manual", - "comment": "Transmitter detail label for expiry" + "HOW TO CALIBRATE": { + "comment": "Calibration help button", + "extractionState": "manual" }, - "Reported lifetime": { - "extractionState": "manual", - "comment": "Transmitter detail label for reported lifetime" + "Identifier": { + "comment": "Reading detail label for sync identifier", + "extractionState": "manual" }, - "%d days": { - "extractionState": "manual", - "comment": "Number of days (1: day count)" + "IDs that begin with 4 belong to Dexcom G5 transmitters, which this app does not support.": { + "comment": "Validation message for G5 transmitter ID", + "extractionState": "manual" }, - "Lifetime": { - "extractionState": "manual", - "comment": "Transmitter details section header for lifetime" + "INSERT SENSOR": { + "comment": "Section label for the insert-sensor steps", + "extractionState": "manual" }, - "This transmitter is past the end of its life. It still reports readings for a running session, but cannot start a new sensor.": { - "extractionState": "manual", - "comment": "Footer shown when the transmitter has expired" + "Insert the sensor on clean skin in the centre of the oval, not on the adhesive itself.": { + "comment": "Insert step 3 note", + "extractionState": "manual" }, - "This transmitter reports an extended 180-day lifetime, which means it has been modified. Warm-up is shorter and you can choose how long sessions run.": { - "extractionState": "manual", - "comment": "Footer explaining Anubis detection" + "It may take a few minutes": { + "comment": "Calibration callout title", + "extractionState": "manual" }, - "Session length: %d days": { - "extractionState": "manual", - "comment": "Session length value (1: day count)" + "Just now": { + "comment": "Reading received less than a minute ago", + "extractionState": "manual" }, - "Modified transmitters can keep a sensor running past the standard 10 days. This setting only changes when this app treats the session as finished; it does not change the sensor's accuracy. Sensor readings can drift the longer a sensor is worn, so check against a fingerstick meter if a reading does not match how you feel.": { - "extractionState": "manual", - "comment": "Footer explaining extended session length and its accuracy caveat" + "Keep at least 8 cm (3 inches) away from insulin pump sites and injection sites, and avoid scars, bony areas, and your waistband.": { + "comment": "Apply-sensor spacing instruction", + "extractionState": "manual" }, - "Upload to Dexcom Share": { - "extractionState": "manual", - "comment": "Toggle label for Share upload" + "Keep the tab showing the sensor code. Do not touch the adhesive.": { + "comment": "Insert step 5 note", + "extractionState": "manual" }, - "Turning this on sends your readings to Dexcom Share so people who follow you can see them in the Dexcom Follow app. It is optional, and your readings still work in this app without it.": { - "extractionState": "manual", - "comment": "Footer explaining Share upload" + "Last checked": { + "comment": "Transmitter detail label for last battery read", + "extractionState": "manual" }, - "Username": { - "extractionState": "manual", - "comment": "Share account username field" + "Last Reading": { + "comment": "Settings section: last reading", + "extractionState": "manual" }, - "Password": { - "extractionState": "manual", - "comment": "Share account password field" + "Latest Reading": { + "comment": "Reading detail screen title", + "extractionState": "manual" }, - "Save Credentials": { - "extractionState": "manual", - "comment": "Button to save Share credentials" + "Left on your skin: the sensor wire and the transmitter holder. The sensor is in.": { + "comment": "Insert step 10 body", + "extractionState": "manual" }, - "Dexcom Account": { - "extractionState": "manual", - "comment": "Section header for Share account" + "Lifetime": { + "comment": "Transmitter details section header for lifetime", + "extractionState": "manual" }, - "Your username and password are stored in the iOS Keychain on this device only. They are never written into app settings, logs, or backups of this app's data.": { - "extractionState": "manual", - "comment": "Footer explaining Keychain credential storage" + "Lift the applicator away.": { + "comment": "Insert step 9 body", + "extractionState": "manual" }, - "Upload turned off and saved credentials removed.": { - "extractionState": "manual", - "comment": "Status message after disabling Share upload" + "Looking for your transmitter…": { + "comment": "Pairing status: searching", + "extractionState": "manual" }, - "Credentials saved to the Keychain.": { - "extractionState": "manual", - "comment": "Status message after saving Share credentials" + "Model": { + "comment": "Transmitter detail label for model", + "extractionState": "manual" }, - "Could not save your credentials. Try again.": { - "extractionState": "manual", - "comment": "Status message when saving Share credentials fails" + "Modified transmitters can keep a sensor running past the standard 10 days. This setting only changes when this app treats the session as finished; it does not change the sensor's accuracy. Sensor readings can drift the longer a sensor is worn, so check against a fingerstick meter if a reading does not match how you feel.": { + "comment": "Footer explaining extended session length and its accuracy caveat", + "extractionState": "manual" }, - "Warming Up": { - "extractionState": "manual", - "comment": "Session phase: warm-up" + "Next": { + "comment": "Next button", + "extractionState": "manual" }, - "Active": { - "extractionState": "manual", - "comment": "Session phase: active" + "No": { + "comment": "Negative", + "extractionState": "manual" }, - "Ending Soon": { - "extractionState": "manual", - "comment": "Session phase: expiring soon" + "No code on your sensor?": { + "comment": "Sensor code callout title", + "extractionState": "manual" }, - "Session Ended": { - "extractionState": "manual", - "comment": "Session phase: expired" + "No readings — replace the sensor.": { + "comment": "Placeholder when the sensor has failed", + "extractionState": "manual" }, - "No Signal": { - "extractionState": "manual", - "comment": "Session phase: signal loss" + "No sensor": { + "comment": "Why calibration is unavailable without a session", + "extractionState": "manual" }, - "Dexcom G6": { - "extractionState": "manual", - "comment": "Introduction screen product title" + "No Sensor": { + "comment": "Status highlight when no session is running", + "extractionState": "manual" }, - "%1$@ talks to your G6 or Dexcom ONE transmitter directly. It starts and stops sensor sessions, sends your calibrations, and fills in readings it missed.": { - "extractionState": "manual", - "comment": "Introduction: what the native driver does (1: app name)" + "No Signal": { + "comment": "Session phase: signal loss", + "extractionState": "manual" }, - "You do not need the Dexcom app — and you must not let it use the same transmitter at the same time.": { - "extractionState": "manual", - "comment": "Introduction: single-app requirement" + "Not available": { + "comment": "Value when the transmitter reports no trend", + "extractionState": "manual" }, - "Enter your transmitter ID": { - "extractionState": "manual", - "comment": "Transmitter ID screen heading" + "Not used": { + "comment": "Value when a session runs without a sensor code", + "extractionState": "manual" + }, + "OK": { + "comment": "Algorithm state: ok", + "extractionState": "manual" }, "On the transmitter box, next to the barcode.": { - "extractionState": "manual", - "comment": "Transmitter ID: location on the box" + "comment": "Transmitter ID: location on the box", + "extractionState": "manual" + }, + "Open Settings": { + "comment": "Open Settings button", + "extractionState": "manual" + }, + "Optional: if you use a skin adhesive, draw an empty oval on the skin and let it dry.": { + "comment": "Insert step 3 body", + "extractionState": "manual" }, "Or on the back of the transmitter itself.": { - "extractionState": "manual", - "comment": "Transmitter ID: location on the transmitter" + "comment": "Transmitter ID: location on the transmitter", + "extractionState": "manual" }, - "6-character ID": { - "extractionState": "manual", - "comment": "Transmitter ID text field placeholder" + "Pair a new transmitter?": { + "comment": "Confirmation title for pairing a new transmitter", + "extractionState": "manual" }, - "This app works with Dexcom G6 and Dexcom ONE transmitters. Older G5 transmitters, whose IDs begin with 4, are not supported.": { - "extractionState": "manual", - "comment": "Transmitter ID: supported hardware note" + "Pair New Transmitter": { + "comment": "Row to pair a different transmitter", + "extractionState": "manual" }, - "IDs that begin with 4 belong to Dexcom G5 transmitters, which this app does not support.": { - "extractionState": "manual", - "comment": "Validation message for G5 transmitter ID" + "Pairing": { + "comment": "Navigation title for pairing screen", + "extractionState": "manual" }, - "Enter your sensor code": { - "extractionState": "manual", - "comment": "Sensor code screen heading" + "Password": { + "comment": "Share account password field", + "extractionState": "manual" }, - "The 4-digit code is on the applicator’s adhesive label, and is unique to that sensor. Use the code from the applicator you are about to insert — a code from a different one will make readings inaccurate.": { - "extractionState": "manual", - "comment": "Sensor code: where to find it" + "Place the applicator flat against your skin — horizontally, not upright — and press down firmly.": { + "comment": "Insert step 6 body", + "extractionState": "manual" }, - "4-digit code": { - "extractionState": "manual", - "comment": "Sensor code text field placeholder" + "Poorly washed hands are behind most inaccurate meter readings, and an inaccurate reading teaches the sensor the wrong thing.": { + "comment": "Calibration step 1 note", + "extractionState": "manual" }, - "No code on your sensor?": { - "extractionState": "manual", - "comment": "Sensor code callout title" + "Press the wide end of the transmitter until it clicks into the holder.": { + "comment": "Attach step 4 body", + "extractionState": "manual" }, - "You can start without one. The transmitter will then ask you for two fingerstick glucose values after warm-up, and for one more each day. \"Calibration\" means telling the sensor what your meter reads, so it can correct itself.": { - "extractionState": "manual", - "comment": "Sensor code callout body explaining calibration" + "Pull off both adhesive labels.": { + "comment": "Insert step 5 body", + "extractionState": "manual" }, - "Use This Code": { - "extractionState": "manual", - "comment": "Sensor code submit button" + "Push and release the button to insert the sensor.": { + "comment": "Insert step 8 body", + "extractionState": "manual" }, - "Start Without a Code": { - "extractionState": "manual", - "comment": "Button to start a session with no sensor code" + "Reading": { + "comment": "Reading detail section header", + "extractionState": "manual" }, - "Start without a sensor code?": { - "extractionState": "manual", - "comment": "Confirmation title for a code-less session" + "Readings will appear as they arrive from the transmitter, about every 5 minutes.": { + "comment": "Explanation shown once warm-up has completed", + "extractionState": "manual" }, - "Enter the Code": { - "extractionState": "manual", - "comment": "Return to entering the sensor code" + "Remove CGM": { + "comment": "Confirm CGM removal", + "extractionState": "manual" }, - "Without the code the sensor cannot use its factory calibration, and the transmitter will ask you for two fingerstick values after warm-up and one every day after that. The code is on the applicator label.": { - "extractionState": "manual", - "comment": "Confirmation message explaining a code-less session" + "Remove CGM from App": { + "comment": "Button to delete the CGM manager", + "extractionState": "manual" }, - "That code isn't one this app recognizes. Check the digits on the applicator label, or start without a code.": { - "extractionState": "manual", - "comment": "Validation message for unrecognized sensor code" + "Remove this CGM?": { + "comment": "Confirmation title for removing the CGM", + "extractionState": "manual" }, - "Connecting to your transmitter": { - "extractionState": "manual", - "comment": "Pairing screen heading" + "Replace sensor": { + "comment": "Detail when the session is over", + "extractionState": "manual" }, - "Your transmitter only talks to your phone about once every 5 minutes, so this can take a few minutes. Keep your phone nearby.": { - "extractionState": "manual", - "comment": "Pairing: explanation of the 5-minute cycle" + "Reported lifetime": { + "comment": "Transmitter detail label for reported lifetime", + "extractionState": "manual" + }, + "Resistance": { + "comment": "Transmitter detail label for battery resistance", + "extractionState": "manual" + }, + "Rub your fingers around the patch three times to secure it.": { + "comment": "Attach step 5 body", + "extractionState": "manual" + }, + "Save Credentials": { + "comment": "Button to save Share credentials", + "extractionState": "manual" + }, + "Scan package code": { + "comment": "Scan package barcode button", + "extractionState": "manual" + }, + "Scanned a Dexcom package, but couldn't find a transmitter ID in it. Type the ID manually.": { + "comment": "Scanned Dexcom barcode without a transmitter ID", + "extractionState": "manual" + }, + "Send Calibration": { + "comment": "Calibration submit button", + "extractionState": "manual" + }, + "Sensor": { + "comment": "Settings section: sensor", + "extractionState": "manual" + }, + "Sensor code": { + "comment": "Metadata label for sensor code", + "extractionState": "manual" }, - "Tap Pair on the iOS prompt": { - "extractionState": "manual", - "comment": "Pairing callout title while awaiting the prompt" + "Sensor Code": { + "comment": "Navigation title for sensor code entry", + "extractionState": "manual" }, - "Accept the Bluetooth pairing request within about a minute. If it disappears, the app tries again on the next connection.": { - "extractionState": "manual", - "comment": "Pairing callout body while awaiting the prompt" + "Sensor Expired": { + "comment": "Status highlight for expired sensor", + "extractionState": "manual" }, - "A pairing request will appear": { - "extractionState": "manual", - "comment": "Pairing callout title" + "Sensor failed": { + "comment": "Algorithm state: failed", + "extractionState": "manual" }, - "The first time they connect, iOS shows a Bluetooth pairing request. Tap Pair within about a minute — if it disappears, the app will try again on the next connection.": { - "extractionState": "manual", - "comment": "Pairing callout body about the iOS prompt" + "Sensor Failed": { + "comment": "Status highlight for failed sensor", + "extractionState": "manual" }, "Sensor session found": { - "extractionState": "manual", - "comment": "Pairing success label for an existing session" + "comment": "Pairing success label for an existing session", + "extractionState": "manual" }, - "Still looking": { - "extractionState": "manual", - "comment": "Pairing troubleshooting title" + "Sensor start queued — it is sent the next time the transmitter connects, which can take up to 5 minutes.": { + "comment": "Shown while a session start is waiting for the next connection", + "extractionState": "manual" }, - "Check that the Dexcom app is not connected to this transmitter, that the transmitter ID is exactly right, and that your phone is next to it. Bluetooth must be on.": { - "extractionState": "manual", - "comment": "Pairing troubleshooting body" + "Sensor started": { + "comment": "Metadata label for sensor start", + "extractionState": "manual" }, - "Share Logs": { - "extractionState": "manual", - "comment": "Row to export the log files" + "Sensor status": { + "comment": "Reading detail label for algorithm state", + "extractionState": "manual" }, - "Connected to your transmitter": { - "extractionState": "manual", - "comment": "Pairing status: connected" + "Sensor Warmup": { + "comment": "Status highlight during warm-up", + "extractionState": "manual" }, - "Waiting for you to accept pairing…": { - "extractionState": "manual", - "comment": "Pairing status: awaiting prompt" + "Session Ended": { + "comment": "Session phase: expired", + "extractionState": "manual" }, - "Looking for your transmitter…": { - "extractionState": "manual", - "comment": "Pairing status: searching" + "Session ends": { + "comment": "Metadata label for session end", + "extractionState": "manual" }, - "Your sensor is warming up": { - "extractionState": "manual", - "comment": "Warm-up screen heading" + "Session Length": { + "comment": "Navigation title for sensor life settings", + "extractionState": "manual" }, - "Warm-up takes about %d minutes. You will not get any glucose readings until it finishes.": { - "extractionState": "manual", - "comment": "Warm-up duration explanation (1: minutes)" + "Session length: %d days": { + "comment": "Session length value (1: day count)", + "extractionState": "manual" }, - "Do not dose on early readings": { - "extractionState": "manual", - "comment": "Warm-up callout title" + "Session stopped": { + "comment": "Algorithm state: stopped", + "extractionState": "manual" }, - "Do not make insulin decisions from the first readings after warm-up, or from readings that look wrong for how you feel. Use a fingerstick meter instead, and follow your care team's guidance.": { - "extractionState": "manual", - "comment": "Warm-up callout body about dosing safety" + "Share Logs": { + "comment": "Row to export the log files", + "extractionState": "manual" }, - "Trend": { - "extractionState": "manual", - "comment": "Reading detail label for trend" + "Signal Loss": { + "comment": "Status highlight for signal loss", + "extractionState": "manual" }, - "Sensor status": { - "extractionState": "manual", - "comment": "Reading detail label for algorithm state" + "Slide the transmitter tab into the slot at the narrow end of the holder.": { + "comment": "Attach step 3 body", + "extractionState": "manual" }, - "Display only": { - "extractionState": "manual", - "comment": "Reading detail label for display-only flag" + "Source": { + "comment": "Reading detail section header for source", + "extractionState": "manual" }, - "Yes": { - "extractionState": "manual", - "comment": "Affirmative" + "Start New Sensor": { + "comment": "Button to begin a new sensor session", + "extractionState": "manual" }, - "No": { - "extractionState": "manual", - "comment": "Negative" + "Start time unknown": { + "comment": "Detail when a session is running but its start is unknown", + "extractionState": "manual" }, - "Reading": { - "extractionState": "manual", - "comment": "Reading detail section header" + "Start Without a Code": { + "comment": "Button to start a session with no sensor code", + "extractionState": "manual" }, - "A display-only value has been shifted by a recent calibration. It is shown for continuity and is not used for dosing.": { - "extractionState": "manual", - "comment": "Footer explaining display-only readings" + "Start without a sensor code?": { + "comment": "Confirmation title for a code-less session", + "extractionState": "manual" }, - "Device": { - "extractionState": "manual", - "comment": "Reading detail label for device" + "STEP %d of 3": { + "comment": "Calibration step counter (1: step number)", + "extractionState": "manual" }, - "Identifier": { - "extractionState": "manual", - "comment": "Reading detail label for sync identifier" + "STEP %d of 4": { + "comment": "Attach-transmitter step counter (1: step number)", + "extractionState": "manual" }, - "Source": { - "extractionState": "manual", - "comment": "Reading detail section header for source" + "STEP %d of 10": { + "comment": "Insert-sensor step counter (1: step number)", + "extractionState": "manual" }, - "The identifier is derived from the transmitter's own clock, so the same reading keeps one identity whether it arrives live or is filled in later.": { - "extractionState": "manual", - "comment": "Footer explaining the sync identifier" + "Still looking": { + "comment": "Pairing troubleshooting title", + "extractionState": "manual" }, - "Latest Reading": { - "extractionState": "manual", - "comment": "Reading detail screen title" + "Stop Sensor Session": { + "comment": "Button to stop the sensor session", + "extractionState": "manual" }, - "Not available": { - "extractionState": "manual", - "comment": "Value when the transmitter reports no trend" + "Stop Session": { + "comment": "Confirm stop session", + "extractionState": "manual" }, - "Sensor failed": { - "extractionState": "manual", - "comment": "Algorithm state: failed" + "Stop this sensor session?": { + "comment": "Confirmation title for stopping a session", + "extractionState": "manual" }, - "Warming up": { - "extractionState": "manual", - "comment": "Algorithm state: warm-up" + "Take a blood sample from your fingertip and measure it with your meter.": { + "comment": "Calibration step 2 body", + "extractionState": "manual" }, - "Session stopped": { - "extractionState": "manual", - "comment": "Algorithm state: stopped" + "Take out the applicator whose sensor code you entered, and peel off its cover.": { + "comment": "Insert step 4 body", + "extractionState": "manual" }, - "Calibration requested": { - "extractionState": "manual", - "comment": "Algorithm state: needs calibration" + "Take the transmitter out of its box and prepare it for use. Wipe the bottom with an alcohol wipe and let it dry.": { + "comment": "Attach step 1 body", + "extractionState": "manual" }, - "OK": { - "extractionState": "manual", - "comment": "Algorithm state: ok" + "Tap Pair on the iOS prompt": { + "comment": "Pairing callout title while awaiting the prompt", + "extractionState": "manual" }, - "Unusable (code %d)": { - "extractionState": "manual", - "comment": "Algorithm state: unusable with raw code" + "Temperature": { + "comment": "Transmitter detail label for temperature", + "extractionState": "manual" }, - "Start time unknown": { - "extractionState": "manual", - "comment": "Detail when a session is running but its start is unknown" + "That code isn't one this app recognizes. Check the digits on the applicator label, or start without a code.": { + "comment": "Validation message for unrecognized sensor code", + "extractionState": "manual" }, - "%@ until ready": { - "extractionState": "manual", - "comment": "Warm-up remaining (1: duration)" + "That doesn't look like a Dexcom package. Try again or type the ID manually.": { + "comment": "Scanned non-Dexcom barcode", + "extractionState": "manual" }, - "Replace sensor": { - "extractionState": "manual", - "comment": "Detail when the session is over" + "The 4-digit code is on the applicator’s adhesive label, and is unique to that sensor. Use the code from the applicator you are about to insert — a code from a different one will make readings inaccurate.": { + "comment": "Sensor code: where to find it", + "extractionState": "manual" }, - "%@ remaining": { - "extractionState": "manual", - "comment": "Session remaining (1: duration)" + "The calibration is sent the next time your transmitter connects, which can be up to 5 minutes away. The transmitter may accept it, ask for a second value, or reject it — this screen's status will tell you which.": { + "comment": "Calibration callout body about delivery timing", + "extractionState": "manual" }, - "—": { - "extractionState": "manual", - "comment": "Placeholder for missing value" + "The camera couldn't start. Try again or type the ID manually.": { + "comment": "Scanner failed to start", + "extractionState": "manual" }, - "Just now": { - "extractionState": "manual", - "comment": "Reading received less than a minute ago" + "The first time they connect, iOS shows a Bluetooth pairing request. Tap Pair within about a minute — if it disappears, the app will try again on the next connection.": { + "comment": "Pairing callout body about the iOS prompt", + "extractionState": "manual" }, - "%d min ago": { - "extractionState": "manual", - "comment": "Minutes since last reading (1: minutes)" + "The identifier is derived from the transmitter's own clock, so the same reading keeps one identity whether it arrives live or is filled in later.": { + "comment": "Footer explaining the sync identifier", + "extractionState": "manual" }, - "%dd %dh": { - "extractionState": "manual", - "comment": "Duration in days and hours" + "The site must be completely dry or the adhesive will not stick.": { + "comment": "Insert step 2 note", + "extractionState": "manual" }, - "%dh %dm": { - "extractionState": "manual", - "comment": "Duration in hours and minutes" + "This app": { + "comment": "Fallback when the host app name cannot be read", + "extractionState": "manual" }, - "%dm": { - "extractionState": "manual", - "comment": "Duration in minutes" + "This app will stop reading from your transmitter. Your sensor session keeps running on the transmitter itself.": { + "comment": "Confirmation message for removing the CGM", + "extractionState": "manual" }, - "Sensor start queued — it is sent the next time the transmitter connects, which can take up to 5 minutes.": { - "extractionState": "manual", - "comment": "Shown while a session start is waiting for the next connection" + "This app works with Dexcom G6 and Dexcom ONE transmitters. Older G5 transmitters, whose IDs begin with 4, are not supported.": { + "comment": "Transmitter ID: supported hardware note", + "extractionState": "manual" }, - "Sensor": { - "extractionState": "manual", - "comment": "Settings section: sensor" + "This transmitter is past the end of its life. It still reports readings for a running session, but cannot start a new sensor.": { + "comment": "Footer shown when the transmitter has expired", + "extractionState": "manual" }, - "Last Reading": { - "extractionState": "manual", - "comment": "Settings section: last reading" + "This transmitter reports an extended 180-day lifetime, which means it has been modified. Warm-up is shorter and you can choose how long sessions run.": { + "comment": "Footer explaining Anubis detection", + "extractionState": "manual" }, - "No readings — replace the sensor.": { - "extractionState": "manual", - "comment": "Placeholder when the sensor has failed" + "Thoroughly wash and dry your hands.": { + "comment": "Insert step 1 body", + "extractionState": "manual" }, - "Warming up — readings start soon.": { - "extractionState": "manual", - "comment": "Placeholder during warm-up" + "Transmitter": { + "comment": "Navigation title for transmitter details", + "extractionState": "manual" }, - "Waiting for first reading…": { - "extractionState": "manual", - "comment": "Placeholder before the first reading" + "Transmitter Details": { + "comment": "Row to transmitter details", + "extractionState": "manual" }, - "Sensor started": { - "extractionState": "manual", - "comment": "Metadata label for sensor start" + "Transmitter Expired": { + "comment": "Status highlight when the transmitter is past end of life", + "extractionState": "manual" }, - "Session ends": { - "extractionState": "manual", - "comment": "Metadata label for session end" + "Transmitter ID": { + "comment": "Navigation title for transmitter ID entry", + "extractionState": "manual" }, - "Sensor code": { - "extractionState": "manual", - "comment": "Metadata label for sensor code" + "Trend": { + "comment": "Reading detail label for trend", + "extractionState": "manual" }, - "Not used": { - "extractionState": "manual", - "comment": "Value when a session runs without a sensor code" + "Turning this on sends your readings to Dexcom Share so people who follow you can see them in the Dexcom Follow app. It is optional, and your readings still work in this app without it.": { + "comment": "Footer explaining Share upload", + "extractionState": "manual" }, - "Start New Sensor": { - "extractionState": "manual", - "comment": "Button to begin a new sensor session" + "Unknown": { + "comment": "Placeholder for unknown value", + "extractionState": "manual" }, - "Enter Calibration": { - "extractionState": "manual", - "comment": "Button to enter a calibration" + "Unusable (code %d)": { + "comment": "Algorithm state: unusable with raw code", + "extractionState": "manual" }, - "After warm-up": { - "extractionState": "manual", - "comment": "Why calibration is unavailable during warm-up" + "Upload to Dexcom Share": { + "comment": "Toggle label for Share upload", + "extractionState": "manual" }, - "No sensor": { - "extractionState": "manual", - "comment": "Why calibration is unavailable without a session" + "Upload turned off and saved credentials removed.": { + "comment": "Status message after disabling Share upload", + "extractionState": "manual" }, - "Stop Sensor Session": { - "extractionState": "manual", - "comment": "Button to stop the sensor session" + "Use a fingertip only — samples from other sites are less accurate. Use the same meter throughout a sensor session, and check that your strips are in date.": { + "comment": "Calibration step 2 note", + "extractionState": "manual" }, - "Stop this sensor session?": { - "extractionState": "manual", - "comment": "Confirmation title for stopping a session" + "Use a fresh fingerstick reading from your meter, taken just now. Wash and dry your hands first — a value from unwashed fingers can be badly wrong and will teach the sensor the wrong thing.": { + "comment": "Calibration instructions", + "extractionState": "manual" }, - "Stop Session": { - "extractionState": "manual", - "comment": "Confirm stop session" + "Use This Code": { + "comment": "Sensor code submit button", + "extractionState": "manual" }, - "You will stop getting readings until you start a new sensor. A stopped session cannot be restarted.": { - "extractionState": "manual", - "comment": "Confirmation message for stopping a session" + "Username": { + "comment": "Share account username field", + "extractionState": "manual" }, - "Calibration becomes available once warm-up finishes. Do not make insulin decisions from early readings — use a fingerstick meter and follow your care team's guidance.": { - "extractionState": "manual", - "comment": "Footer explaining warm-up restrictions" + "Voltage A": { + "comment": "Transmitter detail label for battery A", + "extractionState": "manual" }, - "Transmitter Details": { - "extractionState": "manual", - "comment": "Row to transmitter details" + "Voltage B": { + "comment": "Transmitter detail label for battery B", + "extractionState": "manual" }, - "Dexcom Share Upload": { - "extractionState": "manual", - "comment": "Row to Share upload settings" + "Voltage B is getting low. The transmitter should finish the sensor you are wearing, but order a replacement now.": { + "comment": "Footer shown when battery B is low", + "extractionState": "manual" }, - "How to Apply a Sensor": { - "extractionState": "manual", - "comment": "Row to the placement guide" + "Voltage B is very low. This transmitter may stop sending readings at any time, even during a session. Replace it as soon as you can.": { + "comment": "Footer shown when battery B is very low", + "extractionState": "manual" }, - "Remove CGM from App": { - "extractionState": "manual", - "comment": "Button to delete the CGM manager" + "Waiting for first reading…": { + "comment": "Placeholder before the first reading", + "extractionState": "manual" }, - "Remove this CGM?": { - "extractionState": "manual", - "comment": "Confirmation title for removing the CGM" + "Waiting for you to accept pairing…": { + "comment": "Pairing status: awaiting prompt", + "extractionState": "manual" }, - "Remove CGM": { - "extractionState": "manual", - "comment": "Confirm CGM removal" + "Warm-Up": { + "comment": "Navigation title for warm-up screen", + "extractionState": "manual" }, - "This app will stop reading from your transmitter. Your sensor session keeps running on the transmitter itself.": { - "extractionState": "manual", - "comment": "Confirmation message for removing the CGM" + "Warm-up is finished": { + "comment": "Warm-up screen heading once warm-up has completed", + "extractionState": "manual" }, - "“Dexcom”, “G6”, and “ONE” are trademarks of Dexcom, Inc., used here only to describe which devices are compatible. This app is not made by or endorsed by Dexcom.": { - "extractionState": "manual", - "comment": "Trademark attribution footer" + "Warm-up takes about %d minutes. You will not get any glucose readings until it finishes.": { + "comment": "Warm-up duration explanation (1: minutes)", + "extractionState": "manual" }, - "Warm-up is finished": { - "extractionState": "manual", - "comment": "Warm-up screen heading once warm-up has completed" + "Warming up": { + "comment": "Algorithm state: warm-up", + "extractionState": "manual" }, - "Readings will appear as they arrive from the transmitter, about every 5 minutes.": { - "extractionState": "manual", - "comment": "Explanation shown once warm-up has completed" + "Warming Up": { + "comment": "Session phase: warm-up", + "extractionState": "manual" }, - "Expected to finish at %1$@, about %2$d minutes from now": { - "extractionState": "manual", - "comment": "Warm-up completion time (1: time, 2: minutes remaining)" + "Warming up — readings start soon.": { + "comment": "Placeholder during warm-up", + "extractionState": "manual" }, - "Calibrations must be between %1$@ and %2$@. If your meter reads outside that range, treat it and follow your care team's guidance instead of calibrating.": { - "extractionState": "manual", - "comment": "Validation message for out-of-range calibration (1: minimum with unit, 2: maximum with unit)" + "Wash and dry your hands with soap and water — not a gel cleaner.": { + "comment": "Calibration step 1 body", + "extractionState": "manual" }, - "Voltage A": { - "extractionState": "manual", - "comment": "Transmitter detail label for battery A" + "Without the code the sensor cannot use its factory calibration, and the transmitter will ask you for two fingerstick values after warm-up and one every day after that. The code is on the applicator label.": { + "comment": "Confirmation message explaining a code-less session", + "extractionState": "manual" }, - "%d mV": { - "extractionState": "manual", - "comment": "Voltage in millivolts (1: millivolts)" + "Yes": { + "comment": "Affirmative", + "extractionState": "manual" }, - "Voltage B": { - "extractionState": "manual", - "comment": "Transmitter detail label for battery B" + "You are almost done — the sensor session starts next.": { + "comment": "Attach step 5 note", + "extractionState": "manual" }, - "Resistance": { - "extractionState": "manual", - "comment": "Transmitter detail label for battery resistance" + "You can start without one. The transmitter will then ask you for two fingerstick glucose values after warm-up, and for one more each day. \"Calibration\" means telling the sensor what your meter reads, so it can correct itself.": { + "comment": "Sensor code callout body explaining calibration", + "extractionState": "manual" }, - "Temperature": { - "extractionState": "manual", - "comment": "Transmitter detail label for temperature" + "You do not need the Dexcom app — and you must not let it use the same transmitter at the same time.": { + "comment": "Introduction: single-app requirement", + "extractionState": "manual" }, - "%d °C": { - "extractionState": "manual", - "comment": "Temperature in Celsius (1: degrees)" + "You will enter the new transmitter's ID and can then start a sensor session on it. Your other settings are kept.": { + "comment": "Confirmation message for pairing a new transmitter with no session running", + "extractionState": "manual" }, - "Last checked": { - "extractionState": "manual", - "comment": "Transmitter detail label for last battery read" + "You will stop getting readings until you start a new sensor. A stopped session cannot be restarted.": { + "comment": "Confirmation message for stopping a session", + "extractionState": "manual" }, - "Battery": { - "extractionState": "manual", - "comment": "Transmitter details section header for battery" + "Your current sensor session will end. A session lives on the transmitter, so it cannot move to a new one — you will start a fresh session after pairing, and can reuse the sensor you are wearing. Stop the sensor first if your old transmitter is still attached and you want it stopped cleanly. Your other settings are kept.": { + "comment": "Confirmation message for pairing a new transmitter while a session is running", + "extractionState": "manual" }, - "Voltage B is very low. This transmitter may stop sending readings at any time, even during a session. Replace it as soon as you can.": { - "extractionState": "manual", - "comment": "Footer shown when battery B is very low" + "Your sensor is warming up": { + "comment": "Warm-up screen heading", + "extractionState": "manual" }, - "Voltage B is getting low. The transmitter should finish the sensor you are wearing, but order a replacement now.": { + "Your transmitter only talks to your phone about once every 5 minutes, so this can take a few minutes. Keep your phone nearby.": { + "comment": "Pairing: explanation of the 5-minute cycle", + "extractionState": "manual" + }, + "Your username and password are stored in the iOS Keychain on this device only. They are never written into app settings, logs, or backups of this app's data.": { + "comment": "Footer explaining Keychain credential storage", + "extractionState": "manual" + }, + "Scan applicator code": { "extractionState": "manual", - "comment": "Footer shown when battery B is low" + "comment": "Scan applicator barcode button" }, - "Battery B is the cell that runs down first and determines whether the transmitter can finish a session.": { + "Allow camera access in Settings to scan the Data Matrix code on your sensor applicator.": { "extractionState": "manual", - "comment": "Footer explaining what battery B means" + "comment": "Camera denied alert message (sensor code)" }, - "%1$@%2$@ per minute": { + "Couldn't find a sensor code in that barcode. The code is in the Data Matrix on the applicator, not the sensor box.": { "extractionState": "manual", - "comment": "Trend rate (1: sign, 2: formatted rate with unit)" + "comment": "Scanned barcode without a sensor code" }, - "%1$@%2$@/min": { + "The camera couldn't start. Try again or type the code manually.": { "extractionState": "manual", - "comment": "Trend rate (1: sign, 2: formatted rate with unit)" + "comment": "Scanner failed to start" } }, - "version": "1.0" + "version": "1.1" } diff --git a/G6SensorKitUI/Views/G6OnboardingViews.swift b/G6SensorKitUI/Views/G6OnboardingViews.swift index 7655934..34a81ae 100644 --- a/G6SensorKitUI/Views/G6OnboardingViews.swift +++ b/G6SensorKitUI/Views/G6OnboardingViews.swift @@ -19,6 +19,21 @@ import LoopKitUI import G6SensorKit import G6SensorCore +#if targetEnvironment(simulator) +/// Simulator stand-in for the camera scanner, which needs hardware the +/// simulator lacks: the scan buttons stay visible there and deliver a +/// fixed payload, so the whole scan flow can be exercised without a +/// device. Compiled out on hardware. Both payloads are real, public +/// Dexcom packaging data (the same ones the parser tests use). +enum G6DemoScan { + /// The full Data Matrix from a public G6 transmitter box photo. + static let transmitterBox = G6PackageScan(payload: + "241STT-OM-001\u{1D}1018038762\u{1D}2188H03B\u{1D}17250226") + /// A real, public G6 applicator label. + static let applicator = G6PackageScan(payload: "10731863521434687D2405937") +} +#endif + // MARK: - Shared building blocks /// A numbered instruction row used by the placement guide. @@ -74,6 +89,75 @@ struct G6ContinueButton: View { } } +/// Large per-character boxes over a hidden text field that does the real +/// input. Shared by the transmitter-ID screen (6 boxes, alphanumeric) +/// and the sensor-code screen (4 boxes, numeric). +struct G6CodeBoxField: View { + enum AllowedCharacters { + case alphanumericUppercased + case numeric + } + + @Binding var text: String + let length: Int + let allowedCharacters: AllowedCharacters + var focused: FocusState.Binding + + private var filteredText: Binding { + Binding( + get: { text }, + set: { newValue in + let filtered: String + switch allowedCharacters { + case .alphanumericUppercased: + filtered = newValue.filter { $0.isLetter || $0.isNumber }.uppercased() + case .numeric: + filtered = newValue.filter(\.isNumber) + } + text = String(filtered.prefix(length)) + } + ) + } + + var body: some View { + ZStack { + TextField("", text: filteredText) + .focused(focused) + .keyboardType(allowedCharacters == .alphanumericUppercased ? .asciiCapable : .numberPad) + .autocorrectionDisabled() + .textInputAutocapitalization(allowedCharacters == .alphanumericUppercased ? .characters : .never) + .foregroundColor(.clear) + .accentColor(.clear) + .opacity(0.02) + + HStack(spacing: 10) { + ForEach(0 ..< length, id: \.self) { index in + let characters = Array(text) + let character = index < characters.count ? String(characters[index]) : "" + let isActive = index == characters.count + + Text(character) + .font(.title.weight(.semibold).monospaced()) + .frame(maxWidth: .infinity) + .frame(height: 64) + .background( + RoundedRectangle(cornerRadius: 12, style: .continuous) + .fill(Color(.secondarySystemGroupedBackground)) + ) + .overlay( + RoundedRectangle(cornerRadius: 12, style: .continuous) + .stroke(isActive ? Color.accentColor : Color(.separator), lineWidth: isActive ? 2 : 1) + ) + } + } + .allowsHitTesting(false) + } + .frame(height: 64) + .contentShape(Rectangle()) + .onTapGesture { focused.wrappedValue = true } + } +} + // MARK: - 1. Introduction /// Product hero, in the shape G7SensorKit uses: name, device, a short @@ -172,6 +256,10 @@ struct G6TransmitterIDEntryView: View { @State private var transmitterID: String = "" @State private var validationMessage: String? + @State private var showScanner = false + @State private var showCameraDeniedAlert = false + @State private var scanFailedMessage: String? + @FocusState private var fieldFocused: Bool init(initialValue: String, didSubmit: @escaping (String) -> Void) { self.initialValue = initialValue @@ -202,24 +290,42 @@ struct G6TransmitterIDEntryView: View { G6TransmitterBackGlyph(size: 150) } - TextField(LocalizedString("6-character ID", comment: "Transmitter ID text field placeholder"), text: $transmitterID) - .textCase(.uppercase) - .autocorrectionDisabled() - .textInputAutocapitalization(.characters) - .font(.title3.monospaced()) - .padding() - .background(Color(.secondarySystemBackground)) - .cornerRadius(10) - .onChange(of: transmitterID) { newValue in - transmitterID = String(newValue.uppercased().prefix(6)) - validationMessage = nil - } + G6CodeBoxField( + text: $transmitterID, + length: 6, + allowedCharacters: .alphanumericUppercased, + focused: $fieldFocused + ) + .frame(maxWidth: .infinity) + .onChange(of: transmitterID) { + validationMessage = nil + autoSubmitIfComplete() + } - if let validationMessage = validationMessage { - Text(validationMessage) - .font(.subheadline) - .foregroundColor(.red) - .fixedSize(horizontal: false, vertical: true) + VStack(spacing: 6) { + if let validationMessage = validationMessage { + Text(validationMessage) + .foregroundColor(.red) + } + if let scanFailedMessage = scanFailedMessage { + Text(verbatim: scanFailedMessage) + .foregroundColor(.red) + } + } + .font(.subheadline) + .multilineTextAlignment(.center) + .fixedSize(horizontal: false, vertical: true) + .frame(maxWidth: .infinity) + + if isScanAvailable { + Button(action: scanTapped) { + HStack(spacing: 8) { + Image(systemName: "barcode.viewfinder") + Text(LocalizedString("Scan package code", comment: "Scan package barcode button")) + } + .font(.subheadline.weight(.semibold)) + } + .frame(maxWidth: .infinity) } Text(LocalizedString("This app works with Dexcom G6 and Dexcom ONE transmitters. Older G5 transmitters, whose IDs begin with 4, are not supported.", comment: "Transmitter ID: supported hardware note")) @@ -229,11 +335,120 @@ struct G6TransmitterIDEntryView: View { } .padding() } + .onTapGesture { fieldFocused = false } G6ContinueButton(isEnabled: transmitterID.count == 6) { submit() } } + .sheet(isPresented: $showScanner) { scannerSheet } + .alert( + Text(LocalizedString("Camera access is off", comment: "Camera denied alert title")), + isPresented: $showCameraDeniedAlert + ) { + Button(action: { + if let url = URL(string: UIApplication.openSettingsURLString) { + UIApplication.shared.open(url) + } + }) { Text(LocalizedString("Open Settings", comment: "Open Settings button")) } + Button(role: .cancel, action: {}) { Text(LocalizedString("Cancel", comment: "Cancel button")) } + } message: { + Text(LocalizedString("Allow camera access in Settings to scan the Data Matrix code on your Dexcom transmitter packaging.", comment: "Camera denied alert message")) + } + } + + /// A complete ID submits itself, typed or scanned: with the boxes full + /// there is nothing left to enter. A short delay lets the last box + /// visibly fill first. + private func autoSubmitIfComplete() { + guard transmitterID.count == 6, !isG5 else { + return + } + fieldFocused = false + let submitted = transmitterID + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { + guard transmitterID == submitted else { return } + didSubmit(submitted) + } + } + + // MARK: - Package scanning + + /// The camera scanner needs hardware support and a camera usage + /// description; the simulator gets the demo-payload stand-in instead + /// (see `G6DemoScan`). + private var isScanAvailable: Bool { + #if targetEnvironment(simulator) + return true + #else + return G6PackageScannerView.isSupported + #endif + } + + private func scanTapped() { + #if targetEnvironment(simulator) + handleScan(G6DemoScan.transmitterBox) + #else + switch G6PackageScannerView.cameraAuthorization { + case .authorized: + showScanner = true + case .notDetermined: + G6PackageScannerView.requestCameraAccess { granted in + if granted { + showScanner = true + } else { + showCameraDeniedAlert = true + } + } + default: + showCameraDeniedAlert = true + } + #endif + } + + private func handleScan(_ scan: G6PackageScan) { + showScanner = false + scanFailedMessage = nil + + // A usable ID outweighs the GTIN check: the transmitter box's own + // Data Matrices carry no (01) — the GTIN sits on a separate linear + // barcode — so gating on isDexcomPackage would reject the box. + guard let candidate = scan.transmitterIDCandidate else { + scanFailedMessage = scan.isDexcomPackage + ? LocalizedString("Scanned a Dexcom package, but couldn't find a transmitter ID in it. Type the ID manually.", comment: "Scanned Dexcom barcode without a transmitter ID") + : LocalizedString("That doesn't look like a Dexcom package. Try again or type the ID manually.", comment: "Scanned non-Dexcom barcode") + return + } + + // Assigning the field fires the auto-submit path, same as typing. + transmitterID = candidate + } + + private func handleScanStartFailure(_: Error) { + showScanner = false + scanFailedMessage = LocalizedString("The camera couldn't start. Try again or type the ID manually.", comment: "Scanner failed to start") + } + + private var scannerSheet: some View { + NavigationView { + G6PackageScannerView(onScan: handleScan, onStartFailure: handleScanStartFailure) + .edgesIgnoringSafeArea(.all) + .navigationTitle(Text(LocalizedString("Scan package code", comment: "Scanner screen title"))) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button(action: { showScanner = false }) { + Text(LocalizedString("Cancel", comment: "Cancel button")) + } + } + } + } + } + + // MARK: - Submit + + private var isG5: Bool { + return transmitterID.hasPrefix("4") } private func submit() { @@ -241,7 +456,7 @@ struct G6TransmitterIDEntryView: View { return } - if transmitterID.hasPrefix("4") { + if isG5 { validationMessage = LocalizedString("IDs that begin with 4 belong to Dexcom G5 transmitters, which this app does not support.", comment: "Validation message for G5 transmitter ID") return } @@ -259,6 +474,9 @@ struct G6SensorCodeEntryView: View { @State private var sensorCode: String = "" @State private var validationMessage: String? @State private var confirmingNoCode = false + @State private var showScanner = false + @State private var showCameraDeniedAlert = false + @State private var scanFailedMessage: String? @FocusState private var codeFieldFocused: Bool var body: some View { @@ -275,23 +493,43 @@ struct G6SensorCodeEntryView: View { G6SensorCodeLabelGlyph(size: 150) } - TextField(LocalizedString("4-digit code", comment: "Sensor code text field placeholder"), text: $sensorCode) - .keyboardType(.numberPad) - .focused($codeFieldFocused) - .font(.title3.monospaced()) - .padding() - .background(Color(.secondarySystemBackground)) - .cornerRadius(10) - .onChange(of: sensorCode) { newValue in - sensorCode = String(newValue.filter(\.isNumber).prefix(4)) - validationMessage = nil - } + G6CodeBoxField( + text: $sensorCode, + length: 4, + allowedCharacters: .numeric, + focused: $codeFieldFocused + ) + .frame(maxWidth: .infinity) + .padding(.horizontal, 32) + .onChange(of: sensorCode) { + validationMessage = nil + autoSubmitIfComplete() + } - if let validationMessage = validationMessage { - Text(validationMessage) - .font(.subheadline) - .foregroundColor(.red) - .fixedSize(horizontal: false, vertical: true) + VStack(spacing: 6) { + if let validationMessage = validationMessage { + Text(validationMessage) + .foregroundColor(.red) + } + if let scanFailedMessage = scanFailedMessage { + Text(verbatim: scanFailedMessage) + .foregroundColor(.red) + } + } + .font(.subheadline) + .multilineTextAlignment(.center) + .fixedSize(horizontal: false, vertical: true) + .frame(maxWidth: .infinity) + + if isScanAvailable { + Button(action: scanTapped) { + HStack(spacing: 8) { + Image(systemName: "barcode.viewfinder") + Text(LocalizedString("Scan applicator code", comment: "Scan applicator barcode button")) + } + .font(.subheadline.weight(.semibold)) + } + .frame(maxWidth: .infinity) } G6CalloutBox( @@ -304,7 +542,7 @@ struct G6SensorCodeEntryView: View { } .padding() } - .onAppear { codeFieldFocused = true } + .onTapGesture { codeFieldFocused = false } VStack(spacing: 10) { G6ContinueButton( @@ -334,8 +572,114 @@ struct G6SensorCodeEntryView: View { } } } + .sheet(isPresented: $showScanner) { scannerSheet } + .alert( + Text(LocalizedString("Camera access is off", comment: "Camera denied alert title")), + isPresented: $showCameraDeniedAlert + ) { + Button(action: { + if let url = URL(string: UIApplication.openSettingsURLString) { + UIApplication.shared.open(url) + } + }) { Text(LocalizedString("Open Settings", comment: "Open Settings button")) } + Button(role: .cancel, action: {}) { Text(LocalizedString("Cancel", comment: "Cancel button")) } + } message: { + Text(LocalizedString("Allow camera access in Settings to scan the Data Matrix code on your sensor applicator.", comment: "Camera denied alert message (sensor code)")) + } + } + + /// A complete code submits itself when it is a known factory code, + /// typed or scanned. Unknown codes show the validation message instead + /// of advancing. + private func autoSubmitIfComplete() { + guard sensorCode.count == 4 else { + return + } + guard SensorCode(sensorCode) != nil else { + validationMessage = LocalizedString("That code isn't one this app recognizes. Check the digits on the applicator label, or start without a code.", comment: "Validation message for unrecognized sensor code") + return + } + codeFieldFocused = false + let submitted = sensorCode + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { + guard sensorCode == submitted else { return } + didSubmit(submitted) + } + } + + // MARK: - Package scanning + + /// The camera scanner needs hardware support and a camera usage + /// description; the simulator gets the demo-payload stand-in instead + /// (see `G6DemoScan`). + private var isScanAvailable: Bool { + #if targetEnvironment(simulator) + return true + #else + return G6PackageScannerView.isSupported + #endif + } + + private func scanTapped() { + #if targetEnvironment(simulator) + handleScan(G6DemoScan.applicator) + #else + switch G6PackageScannerView.cameraAuthorization { + case .authorized: + showScanner = true + case .notDetermined: + G6PackageScannerView.requestCameraAccess { granted in + if granted { + showScanner = true + } else { + showCameraDeniedAlert = true + } + } + default: + showCameraDeniedAlert = true + } + #endif } + private func handleScan(_ scan: G6PackageScan) { + showScanner = false + scanFailedMessage = nil + + // Applicator labels carry no GTIN, so unlike the transmitter-ID + // screen there is no Dexcom-package gate: either a sensor code + // falls out of the payload or it does not. + guard let candidate = scan.sensorCodeCandidate else { + scanFailedMessage = LocalizedString("Couldn't find a sensor code in that barcode. The code is in the Data Matrix on the applicator, not the sensor box.", comment: "Scanned barcode without a sensor code") + return + } + + // Assigning the field fires the auto-submit path, same as typing. + sensorCode = candidate + } + + private func handleScanStartFailure(_: Error) { + showScanner = false + scanFailedMessage = LocalizedString("The camera couldn't start. Try again or type the code manually.", comment: "Scanner failed to start") + } + + private var scannerSheet: some View { + NavigationView { + G6PackageScannerView(onScan: handleScan, onStartFailure: handleScanStartFailure) + .edgesIgnoringSafeArea(.all) + .navigationTitle(Text(LocalizedString("Scan applicator code", comment: "Scanner screen title (sensor code)"))) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button(action: { showScanner = false }) { + Text(LocalizedString("Cancel", comment: "Cancel button")) + } + } + } + } + } + + // MARK: - Submit + private func submit() { guard SensorCode(sensorCode) != nil else { validationMessage = LocalizedString("That code isn't one this app recognizes. Check the digits on the applicator label, or start without a code.", comment: "Validation message for unrecognized sensor code") diff --git a/G6SensorKitUI/Views/G6PackageScannerView.swift b/G6SensorKitUI/Views/G6PackageScannerView.swift new file mode 100644 index 0000000..eb0f057 --- /dev/null +++ b/G6SensorKitUI/Views/G6PackageScannerView.swift @@ -0,0 +1,85 @@ +// +// G6PackageScannerView.swift +// G6SensorKitUI +// +// Copyright © 2026 Nightscout Foundation. MIT License. +// + +import AVFoundation +import G6SensorCore +import SwiftUI +import VisionKit + +/// Camera scanner for the GS1 Data Matrix barcodes on Dexcom packaging: +/// the applicator label and the transmitter box. The box carries two Data +/// Matrices — serial-only (21) and the full (241)(10)(21)(17) — and +/// either yields the transmitter ID. +struct G6PackageScannerView: UIViewControllerRepresentable { + let onScan: (G6PackageScan) -> Void + let onStartFailure: (Error) -> Void + + static var isSupported: Bool { + return DataScannerViewController.isSupported + && Bundle.main.object(forInfoDictionaryKey: "NSCameraUsageDescription") != nil + } + + static var cameraAuthorization: AVAuthorizationStatus { + return AVCaptureDevice.authorizationStatus(for: .video) + } + + static func requestCameraAccess(completion: @escaping (Bool) -> Void) { + AVCaptureDevice.requestAccess(for: .video) { granted in + DispatchQueue.main.async { completion(granted) } + } + } + + func makeUIViewController(context: Context) -> DataScannerViewController { + let scanner = DataScannerViewController( + recognizedDataTypes: [.barcode(symbologies: [.dataMatrix])], + qualityLevel: .balanced, + recognizesMultipleItems: false, + isHighFrameRateTrackingEnabled: false, + isHighlightingEnabled: true + ) + scanner.delegate = context.coordinator + do { + try scanner.startScanning() + } catch { + DispatchQueue.main.async { onStartFailure(error) } + } + return scanner + } + + func updateUIViewController(_: DataScannerViewController, context _: Context) {} + + func makeCoordinator() -> Coordinator { + return Coordinator(onScan: onScan) + } + + final class Coordinator: NSObject, DataScannerViewControllerDelegate { + private let onScan: (G6PackageScan) -> Void + private var didDeliver = false + + init(onScan: @escaping (G6PackageScan) -> Void) { + self.onScan = onScan + } + + func dataScanner( + _ dataScanner: DataScannerViewController, + didAdd addedItems: [RecognizedItem], + allItems _: [RecognizedItem] + ) { + guard !didDeliver else { return } + for item in addedItems { + guard case let .barcode(barcode) = item, + let payload = barcode.payloadStringValue + else { continue } + didDeliver = true + AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate)) + onScan(G6PackageScan(payload: payload)) + dataScanner.stopScanning() + return + } + } + } +} diff --git a/Package.swift b/Package.swift index 79005f4..815577b 100644 --- a/Package.swift +++ b/Package.swift @@ -12,7 +12,7 @@ import PackageDescription let package = Package( name: "G6SensorCore", platforms: [ - .iOS(.v15), + .iOS(.v17), .macOS(.v13), ], products: [ diff --git a/Scripts/generate_project.rb b/Scripts/generate_project.rb index e0b9b6f..5ce1b7b 100644 --- a/Scripts/generate_project.rb +++ b/Scripts/generate_project.rb @@ -20,7 +20,7 @@ ROOT = File.expand_path('..', __dir__) PROJECT_PATH = File.join(ROOT, 'G6SensorKit.xcodeproj') -DEPLOYMENT_TARGET = '15.1' +DEPLOYMENT_TARGET = '17.6' SWIFT_VERSION = '5.9' BUNDLE_PREFIX = 'org.nightscout' diff --git a/Sources/G6SensorCore/Pairing/GS1DataMatrixParser.swift b/Sources/G6SensorCore/Pairing/GS1DataMatrixParser.swift new file mode 100644 index 0000000..e161428 --- /dev/null +++ b/Sources/G6SensorCore/Pairing/GS1DataMatrixParser.swift @@ -0,0 +1,207 @@ +// +// GS1DataMatrixParser.swift +// G6SensorKit +// +// Ported from DexKit (Pairing/GS1DataMatrixParser.swift), trimmed to G6 +// and extended with applicator sensor-code extraction (AI 240) and +// FNC1-stripped payload fallbacks. +// Copyright © 2026 Nightscout Foundation. MIT License. +// + +import Foundation + +/// One GS1 element string: application identifier + value. +public struct GS1Element: Equatable { + public let ai: String + public let value: String +} + +/// Pure GS1 Data Matrix parser for Dexcom packaging barcodes. +/// +/// The Data Matrix on Dexcom packaging encodes (GS1 element structure, +/// verified against our own captures of G6/ONE packaging): +/// - AI (01) GTIN: 14 digits; Dexcom company prefix `0038627` +/// - AI (21) serial: G6: 6-char transmitter ID; G7: 12-char sensor serial +/// - AI (240) additional product ID: G6: the 4-digit sensor code on the +/// applicator label; G7: the 4-digit pairing code +/// - AI (10) lot, AI (11) production date, AI (17) expiry +/// Variable-length AIs are terminated by FNC1 (ASCII GS, 0x1D) when more +/// elements follow. +public enum GS1DataMatrixParser { + /// GS1 FNC1 separator as delivered in scanned payload strings. + public static let fnc1: Character = "\u{1D}" + + private struct AIInfo { + let fixedLength: Int? + let maxLength: Int + } + + /// AI registry: fixed-length AIs never need a trailing FNC1; variable + /// ones are read up to FNC1 or end of payload. + private static let registry: [String: AIInfo] = [ + "01": AIInfo(fixedLength: 14, maxLength: 14), // GTIN + "11": AIInfo(fixedLength: 6, maxLength: 6), // production date YYMMDD + "17": AIInfo(fixedLength: 6, maxLength: 6), // expiry YYMMDD + "10": AIInfo(fixedLength: nil, maxLength: 20), // lot/batch + "21": AIInfo(fixedLength: nil, maxLength: 20), // serial + "240": AIInfo(fixedLength: nil, maxLength: 30), // additional product ID (G6 sensor code / G7 pairing code) + "241": AIInfo(fixedLength: nil, maxLength: 30), // customer part number + "250": AIInfo(fixedLength: nil, maxLength: 30) // secondary serial + ] + + /// Parses a scanned payload into GS1 elements. Tolerates the AIM + /// symbology identifier ("]d1"/"]d2") and/or a leading FNC1 that some + /// scanners prepend. Stops at the first unrecognized AI and keeps + /// everything parsed up to that point. + public static func parse(_ payload: String) -> [GS1Element] { + var remaining = Substring(normalize(payload)) + var elements: [GS1Element] = [] + + while !remaining.isEmpty { + // Skip stray FNC1 separators (robustness). + if remaining.first == fnc1 { + remaining = remaining.dropFirst() + continue + } + + guard let (ai, info) = readAI(remaining) else { + break + } + remaining = remaining.dropFirst(ai.count) + + let value: Substring + if let fixed = info.fixedLength { + guard remaining.count >= fixed else { break } + value = remaining.prefix(fixed) + remaining = remaining.dropFirst(fixed) + } else { + let end = remaining.firstIndex(of: fnc1) ?? remaining.endIndex + value = remaining[.. info.maxLength { + break + } + } + elements.append(GS1Element(ai: ai, value: String(value))) + } + + return elements + } + + /// Strips the AIM symbology identifier and any leading FNC1. + static func normalize(_ payload: String) -> String { + var s = payload.trimmingCharacters(in: .whitespacesAndNewlines) + if s.hasPrefix("]d") { + // AIM identifier for Data Matrix: ]d1 = plain, ]d2 = GS1. + s = String(s.dropFirst(3)) + } + while s.first == fnc1 { + s = String(s.dropFirst()) + } + return s + } + + /// Longest-match AI read: 4 digits, then 3, then 2. + private static func readAI(_ s: Substring) -> (String, AIInfo)? { + for length in [4, 3, 2] { + guard s.count >= length else { continue } + let candidate = String(s.prefix(length)) + guard candidate.allSatisfy(\.isNumber) else { continue } + if let info = registry[candidate] { + return (candidate, info) + } + } + return nil + } +} + +/// A scanned Dexcom package, mapped to what G6 onboarding needs. +public struct G6PackageScan: Equatable { + public let elements: [GS1Element] + + /// The normalized payload, kept for the fallback candidate extraction: + /// some scanners strip the FNC1 separators, leaving one long string the + /// strict element parse cannot segment. + private let normalizedPayload: String + + public init(payload: String) { + normalizedPayload = GS1DataMatrixParser.normalize(payload) + elements = GS1DataMatrixParser.parse(payload) + } + + public func value(forAI ai: String) -> String? { + elements.first(where: { $0.ai == ai })?.value + } + + /// AI (01); identifies the product model. + public var gtin: String? { value(forAI: "01") } + /// AI (10) lot/batch. + public var lot: String? { value(forAI: "10") } + /// AI (21); G6: 6-char transmitter ID; G7: 12-char sensor serial. + public var serial: String? { value(forAI: "21") } + + /// Dexcom's GS1 company prefix (0038627…) inside the GTIN. + public var isDexcomPackage: Bool { + gtin?.hasPrefix("0038627") == true + } + + /// The AI (21) serial as a transmitter ID. Three shapes occur: the + /// serial is the ID exactly; the ID is followed by a non-alphanumeric + /// delimiter and trailing packaging data (seen on G6 transmitter boxes: + /// "-"); or the payload lost its FNC1 separators, in which + /// case the raw payload is scanned for the pattern. A 12-char + /// alphanumeric G7 serial never matches: the character after the + /// would-be ID is alphanumeric too. G5 rejection ("4…" prefix) is left + /// to the entry view, matching how a typed ID is handled. + public var transmitterIDCandidate: String? { + if let serial = serial, let id = Self.transmitterIDPrefix(of: serial) { + return id + } + guard isDexcomPackage else { return nil } + var rest = normalizedPayload[...] + while let range = rest.range(of: "21") { + if let id = Self.transmitterIDPrefix(of: String(rest[range.upperBound...])) { + return id + } + rest = rest[range.upperBound...] + } + return nil + } + + /// The AI (240) field as a sensor code. On G6 the applicator's Data + /// Matrix carries the 4-digit session code there (the field G7 uses + /// for its pairing code). It is the last element on applicator labels, + /// so an FNC1-stripped payload is recovered by reading the tail. + /// Applicator labels carry no GTIN, so unlike the transmitter ID this + /// is not gated on `isDexcomPackage`. Validity against the known-code + /// table is left to the entry view, matching a typed code. + public var sensorCodeCandidate: String? { + if let pin = value(forAI: "240"), pin.count == 4, pin.allSatisfy(\.isNumber) { + return pin + } + let tail = normalizedPayload.suffix(7) + guard tail.count == 7, + tail.hasPrefix("240"), + tail.dropFirst(3).allSatisfy(\.isNumber) + else { return nil } + return String(tail.dropFirst(3)) + } + + /// The leading 6 characters when they are alphanumeric and the string + /// either ends there or continues with a non-alphanumeric delimiter. + /// FNC1 does not count as a delimiter: a 6-char run followed by FNC1 is + /// a complete (21) field the strict parse handles, and in the fallback + /// scan it is the middle of a longer serial (a G7's 12-char serial + /// contains "21" six digits in), never a truncated transmitter ID. + private static func transmitterIDPrefix(of serial: String) -> String? { + guard serial.count >= 6 else { return nil } + let prefix = serial.prefix(6) + guard prefix.allSatisfy({ $0.isLetter || $0.isNumber }) else { return nil } + if serial.count == 6 { + return prefix.uppercased() + } + let next = serial.dropFirst(6).first! + guard !next.isLetter, !next.isNumber, next != GS1DataMatrixParser.fnc1 else { return nil } + return prefix.uppercased() + } +} diff --git a/Tests/G6SensorCoreTests/GS1DataMatrixParserTests.swift b/Tests/G6SensorCoreTests/GS1DataMatrixParserTests.swift new file mode 100644 index 0000000..c21b7d5 --- /dev/null +++ b/Tests/G6SensorCoreTests/GS1DataMatrixParserTests.swift @@ -0,0 +1,239 @@ +// +// GS1DataMatrixParserTests.swift +// G6SensorKit +// +// Ported from DexKit (DexKitTests/GS1DataMatrixParserTests.swift), trimmed +// to G6 alongside the parser. +// Copyright © 2026 Nightscout Foundation. MIT License. +// + +import XCTest +@testable import G6SensorCore + +/// Payloads follow the GS1 spec: a package Data Matrix = (01) GTIN, +/// (17) expiry, (10) lot, (21) serial, (240) additional product ID, with +/// FNC1 (\u{1D}) separating variable-length elements that aren't last. +final class GS1DataMatrixParserTests: XCTestCase { + private let fnc1 = "\u{1D}" + + // MARK: - Basic element extraction + + /// Real payload from a public G7 box image: (01) GTIN, (11) production + /// date, (17) expiry, (10) lot, (21) 12-char serial, (241) customer + /// part number. Note the box carries no (240): the pairing/sensor code + /// lives on the applicator label. + private var g7BoxPayload: String { + "01" + "00386270002839" + "11" + "230201" + "17" + "240731" + + "10" + "1523041787" + fnc1 + "21" + "448421319350" + fnc1 + "241" + "STP-AT-012301" + } + + func testParsesFullPayloadWithAIMPrefixAndFNC1() { + // ]d2 = AIM symbology identifier for GS1 Data Matrix + let elements = GS1DataMatrixParser.parse("]d2" + g7BoxPayload) + XCTAssertEqual(elements, [ + GS1Element(ai: "01", value: "00386270002839"), + GS1Element(ai: "11", value: "230201"), + GS1Element(ai: "17", value: "240731"), + GS1Element(ai: "10", value: "1523041787"), + GS1Element(ai: "21", value: "448421319350"), + GS1Element(ai: "241", value: "STP-AT-012301") + ]) + } + + func testParsesPayloadWithoutAIMPrefix() { + // VisionKit/Vision typically deliver the payload without "]d2". + let scan = G6PackageScan(payload: g7BoxPayload) + XCTAssertEqual(scan.gtin, "00386270002839") + XCTAssertEqual(scan.serial, "448421319350") + XCTAssertEqual(scan.value(forAI: "241"), "STP-AT-012301") + } + + func testStripsLeadingFNC1() { + // Some hardware scanners report the leading FNC1 of the first element. + let scan = G6PackageScan(payload: fnc1 + g7BoxPayload) + XCTAssertEqual(scan.gtin, "00386270002839") + XCTAssertEqual(scan.serial, "448421319350") + } + + // MARK: - Dexcom mapping + + func testG6PackageYieldsTransmitterIDCandidate() { + // G6 transmitter box: (21) serial is the 6-char transmitter ID. + let payload = "0100386270004070" + fnc1 + "218KAB12" + let scan = G6PackageScan(payload: payload) + + XCTAssertTrue(scan.isDexcomPackage) + XCTAssertEqual(scan.transmitterIDCandidate, "8KAB12") + } + + func testSensorPackageYieldsNoTransmitterIDCandidate() { + // G7 box (the public payload above): (21) is a 12-char sensor + // serial, not a transmitter ID. + let scan = G6PackageScan(payload: g7BoxPayload) + + XCTAssertTrue(scan.isDexcomPackage) + XCTAssertNil(scan.transmitterIDCandidate) + XCTAssertNil(scan.sensorCodeCandidate) // the box carries no (240) + } + + func testFNC1StrippedG7BoxYieldsNoCandidates() { + // The same public payload as scanners and pastes deliver it without + // separators: the dates still parse, nothing G6-usable falls out. + let payload = "0100386270002839112302011724073110152304178721448421319350241STP-AT-012301" + let scan = G6PackageScan(payload: payload) + + XCTAssertTrue(scan.isDexcomPackage) + XCTAssertEqual(scan.value(forAI: "11"), "230201") + XCTAssertEqual(scan.value(forAI: "17"), "240731") + XCTAssertNil(scan.transmitterIDCandidate) + XCTAssertNil(scan.sensorCodeCandidate) + } + + func testLowercaseSerialIsUppercased() { + let scan = G6PackageScan(payload: "0100386270004070" + fnc1 + "218kab12") + XCTAssertEqual(scan.transmitterIDCandidate, "8KAB12") + } + + func testNonDexcomGTINIsFlagged() { + // Another manufacturer's package: same GS1 shape, different company prefix. + let payload = "01" + "06991234567890" + fnc1 + "10LOT123" + fnc1 + "21991234ABCD5678" + let scan = G6PackageScan(payload: payload) + XCTAssertFalse(scan.isDexcomPackage) + XCTAssertEqual(scan.gtin, "06991234567890") + XCTAssertEqual(scan.lot, "LOT123") + XCTAssertEqual(scan.serial, "991234ABCD5678") + XCTAssertNil(scan.transmitterIDCandidate) + } + + // MARK: - G6 applicator sensor codes + + // The applicator payloads below are real, public G6 labels; the + // transmitter/sensor box structures mirror our own captures with + // serials, lots and dates anonymized. + + func testApplicatorYieldsSensorCodeCandidate() { + // Real public applicator labels: (10) 16-char lot glued to + // (240) + the 4-digit sensor code, FNC1 separators stripped. + let cases: [(payload: String, code: String)] = [ + ("10731863521434687D2405937", "5937"), + ("10527390421846477D2405931", "5931"), + ("10729148021365863F2409117", "9117") + ] + for (payload, code) in cases { + let scan = G6PackageScan(payload: payload) + XCTAssertEqual(scan.sensorCodeCandidate, code, payload) + XCTAssertNotNil(SensorCode(scan.sensorCodeCandidate), payload) + // No GTIN and no (21): an applicator label says nothing about the transmitter. + XCTAssertNil(scan.transmitterIDCandidate, payload) + XCTAssertFalse(scan.isDexcomPackage, payload) + } + } + + func testApplicatorWithFNC1YieldsSensorCodeCandidate() { + let payload = "10" + "731863521434687D" + fnc1 + "2405937" + let scan = G6PackageScan(payload: payload) + XCTAssertEqual(scan.lot, "731863521434687D") + XCTAssertEqual(scan.sensorCodeCandidate, "5937") + } + + func testApplicatorTailMustBeExactlyFourDigits() { + // "240" followed by 5 digits is not a sensor code. + let scan = G6PackageScan(payload: "10731863521434687D24059377") + XCTAssertNil(scan.sensorCodeCandidate) + } + + func testTransmitterBoxSerialWithTrailingPackagingData() { + // Transmitter box: (21) is the 6-char ID glued to "-". + let payload = "0100386270003072" + "241STT-GS-003" + fnc1 + + "10AB12CD34" + fnc1 + "218ZXY12-199270101" + let scan = G6PackageScan(payload: payload) + + XCTAssertTrue(scan.isDexcomPackage) + XCTAssertEqual(scan.transmitterIDCandidate, "8ZXY12") + XCTAssertNil(scan.sensorCodeCandidate) + } + + func testFNC1StrippedTransmitterBoxYieldsTransmitterID() { + // Same box with every FNC1 stripped: the strict parse cannot + // segment past (241), so the raw-payload fallback recovers the ID. + let payload = "0100386270003072241STT-GS-00310AB12CD34218ZXY12-199270101" + let scan = G6PackageScan(payload: payload) + + XCTAssertTrue(scan.isDexcomPackage) + XCTAssertEqual(scan.transmitterIDCandidate, "8ZXY12") + } + + func testTransmitterBoxSerialOnlyBarcode() { + // Real public G6 transmitter box: the small Data Matrix carries + // only (21) + the 6-char transmitter ID. + let scan = G6PackageScan(payload: "2188H03B") + + XCTAssertEqual(scan.transmitterIDCandidate, "88H03B") + XCTAssertNil(scan.sensorCodeCandidate) + XCTAssertFalse(scan.isDexcomPackage) + } + + func testTransmitterBoxFullDataMatrix() { + // Same box's large Data Matrix: (241) customer part number, (10) + // lot, (21) serial, (17) expiry. The GTIN is a separate linear + // barcode on the box, so no (01) appears here. + let payload = "241STT-OM-001" + fnc1 + "1018038762" + fnc1 + "2188H03B" + fnc1 + "17250226" + let scan = G6PackageScan(payload: payload) + + XCTAssertEqual(scan.elements, [ + GS1Element(ai: "241", value: "STT-OM-001"), + GS1Element(ai: "10", value: "18038762"), + GS1Element(ai: "21", value: "88H03B"), + GS1Element(ai: "17", value: "250226") + ]) + XCTAssertEqual(scan.transmitterIDCandidate, "88H03B") + XCTAssertNil(scan.sensorCodeCandidate) + XCTAssertFalse(scan.isDexcomPackage) + } + + func testSensorBoxYieldsNoCandidates() { + // Sensor box: GTIN, customer part number, dates; no code at all. + // The sensor code is only on the applicator label. + let payload = "0100386270000927" + "2419500-46107380885" + "11251207" + "17270630" + let scan = G6PackageScan(payload: payload) + + XCTAssertTrue(scan.isDexcomPackage) + XCTAssertNil(scan.transmitterIDCandidate) + XCTAssertNil(scan.sensorCodeCandidate) + } + + // MARK: - Robustness + + func testVariableLengthSerialAtEndOfPayloadWithoutFNC1() { + let payload = "0100386270004758" + fnc1 + "21ABCD12345678" + XCTAssertEqual(GS1DataMatrixParser.parse(payload).last, + GS1Element(ai: "21", value: "ABCD12345678")) + } + + func testStopsAtUnknownAIKeepingParsedPrefix() { + // (99) is not in the registry; parsing stops but keeps (01) and (21). + let payload = "0100386270004758" + fnc1 + "218KAB12" + fnc1 + "99JUNK" + let elements = GS1DataMatrixParser.parse(payload) + XCTAssertEqual(elements, [ + GS1Element(ai: "01", value: "00386270004758"), + GS1Element(ai: "21", value: "8KAB12") + ]) + } + + func testTruncatedFixedLengthFieldStopsParsing() { + let payload = "0100386" // truncated GTIN + XCTAssertTrue(GS1DataMatrixParser.parse(payload).isEmpty) + } + + func testGarbageYieldsNoElements() { + XCTAssertTrue(GS1DataMatrixParser.parse("hello world").isEmpty) + XCTAssertTrue(GS1DataMatrixParser.parse("").isEmpty) + } + + func testFourDigitAIIsNotMisreadAsTwoDigitAI() { + // "240..." must read as AI 240, not AI 24 + garbage. + let payload = "0100386270004758" + fnc1 + "2401249" + XCTAssertEqual(GS1DataMatrixParser.parse(payload).last, + GS1Element(ai: "240", value: "1249")) + } +} From 715549d45db4d44e3209b6de6857c8c63d46dda9 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Thu, 24 Sep 2026 12:44:59 +0200 Subject: [PATCH 03/13] feat(simulator): drain the command queue against state so End/Start Sensor work in the simulator Extract the pending-command logic into a pure CommandQueue value type (supersede-on-enqueue, 5-minute stale-calibration drop, raw-value persistence round-trip) with unit tests, and mirror didComplete into enqueue on the simulator, where no link will ever drain the queue. Also: stop simulated readings once no session is active, and mark Locked.mutate @discardableResult (both copies). --- Common/Locked.swift | 1 + G6SensorKit.xcodeproj/project.pbxproj | 700 +++++++++--------- .../xcschemes/G6SensorKit.xcscheme | 2 +- .../xcschemes/G6SensorKitPlugin.xcscheme | 2 +- .../xcschemes/G6SensorKitUI.xcscheme | 2 +- G6SensorKit/G6CGMManager.swift | 70 +- G6SensorKit/G6SimulatedSession.swift | 7 +- .../G6SensorCore/Session/CommandQueue.swift | 74 ++ Sources/G6SensorCore/Support/Locked.swift | 1 + .../G6SensorCoreTests/CommandQueueTests.swift | 95 +++ 10 files changed, 563 insertions(+), 391 deletions(-) create mode 100644 Sources/G6SensorCore/Session/CommandQueue.swift create mode 100644 Tests/G6SensorCoreTests/CommandQueueTests.swift diff --git a/Common/Locked.swift b/Common/Locked.swift index 206b2a5..849328d 100644 --- a/Common/Locked.swift +++ b/Common/Locked.swift @@ -31,6 +31,7 @@ public class Locked { } } + @discardableResult public func mutate(_ changes: (_ value: inout T) -> Void) -> T { os_unfair_lock_lock(&lock) defer { os_unfair_lock_unlock(&lock) } diff --git a/G6SensorKit.xcodeproj/project.pbxproj b/G6SensorKit.xcodeproj/project.pbxproj index c978d84..9a87e0e 100644 --- a/G6SensorKit.xcodeproj/project.pbxproj +++ b/G6SensorKit.xcodeproj/project.pbxproj @@ -7,82 +7,82 @@ objects = { /* Begin PBXBuildFile section */ - 0693C7476402404DE20D9B4F /* G6SensorKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7D03FEB69599D0AF52C22E7 /* G6SensorKitUI.framework */; }; - 08A233C9F8B1EEE650BF50FD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A05FE6FDE339FE9321E759CE /* Foundation.framework */; }; - 0DCAF3F659A2703E9CE24557 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A05FE6FDE339FE9321E759CE /* Foundation.framework */; }; - 113A6AADAEB5985A9833663C /* G6UICoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5028E90A753D82115E51BAB /* G6UICoordinator.swift */; }; - 1A031090C7910D3B4BF01246 /* G6ApplySensorViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4C8C72C6C5749880D0BD5C /* G6ApplySensorViews.swift */; }; - 1D75C9FD5B5D1798EA308C39 /* G6CGMManagerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70699BE714273A4BD5D45AC /* G6CGMManagerState.swift */; }; - 22BB2B2C62819EF28F71536C /* G6ShareCredentialStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DFA312ADF260746CCC9301B /* G6ShareCredentialStore.swift */; }; - 29A6CAB9D3F1429C79C19511 /* G6OnboardingViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E000DC9B3FDC9F2050CED65 /* G6OnboardingViews.swift */; }; - 2E65773EEED2B72034485C42 /* G6SensorKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DDAD343CEBAA70172F375006 /* G6SensorKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 3098352571C4019F26687C99 /* G6CGMManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0275C0BBB9440BE16CBDF2 /* G6CGMManager.swift */; }; - 37DEA0FE2BA2BF0AE14ADF13 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 9B5551B35D84DFE748E0B321 /* Localizable.xcstrings */; }; - 3AE0A4224E186716AD9B38BA /* G6CGMManager+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C499A8F2A45C5A5F2F6804C /* G6CGMManager+UI.swift */; }; - 47095EDB584677B51133FB55 /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CA1FD8713E9A195D3BEA65 /* TimeInterval.swift */; }; - 49DEA9F14CC66EE8CF7A1938 /* G6AlertEvaluator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5890F3F14505D20A3BF454AA /* G6AlertEvaluator.swift */; }; - 4B60FA598DDD83373BF9AF9A /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54F40591DF7546BD56902D34 /* LocalizedString.swift */; }; - 51E9F176C1D5B4D4C16A59A3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8951478AD4BD18A38807B735 /* Assets.xcassets */; }; - 52069C196E0860E1FCAA8146 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 119FBC1B7DA145CCFD8E17F3 /* LoopKitUI.framework */; }; - 56DB4016BF61B7A5DEE9F47F /* G6ActivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7732FACCE0CBE0F2F3B38C /* G6ActivityViewController.swift */; }; - 59206A3FBADAC02D985182A1 /* G6PackageScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA1B967C98FAF4A32CF34800 /* G6PackageScannerView.swift */; }; - 66AF27897E99EE1859962C21 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = CDEF209176738C95929680EC /* Localizable.xcstrings */; }; - 69F9DC12AEE8DB64C7D39D7E /* OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD71DF7E83AF717270ABEB4F /* OSLog.swift */; }; - 766AD55DDB016FA0D4CE7531 /* G6SensorKitPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FCA7C7B1082F4DB56383E62 /* G6SensorKitPlugin.swift */; }; - 779E0E2EFCD8988DB0D48E1E /* G6ReadingDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1C1DFABF454CD486038D23B /* G6ReadingDetailView.swift */; }; - 7C492DE3E17736DC551DA2EB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A05FE6FDE339FE9321E759CE /* Foundation.framework */; }; - 7F02F2A865E554B97A785906 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E87AE5D60C3B9C9E8C81472 /* LoopKit.framework */; }; - 81AF0901E0F6A16A4634AAF5 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE39687E90C268D1324F4928 /* LocalizedString.swift */; }; - 88F90B528970A11DC5A0D6A0 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E87AE5D60C3B9C9E8C81472 /* LoopKit.framework */; }; - 8955744E48E5793B6019A69D /* G6Graphics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BECD386214266280C635EF4 /* G6Graphics.swift */; }; - 90E1E35D64D8B5B905A2C2A4 /* G6SimulatedSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7D978600747DD5D213658C /* G6SimulatedSession.swift */; }; - 957A9D07764B7C40DFBBEF6A /* G6DetailViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B9AFCC06065A5816CF9B0D0 /* G6DetailViews.swift */; }; - 990AF949E54DE82A45F260E6 /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDAD343CEBAA70172F375006 /* G6SensorKit.framework */; }; - A8D7FD3BA2F4591BC1E043C5 /* G6Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32113D2719FEFFC866A296E /* G6Alert.swift */; }; - B07CE4D488047BAB8E73A5D5 /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDAD343CEBAA70172F375006 /* G6SensorKit.framework */; }; - B4312F20327B994F68EA3B2F /* Locked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4757E22C8DF1FFACB0F5FE55 /* Locked.swift */; }; - B74C908295343E4D9541421A /* G6SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 701FB5943D703C73F0914901 /* G6SettingsView.swift */; }; - BAB668D8A5161A2CFA99EE4F /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E87AE5D60C3B9C9E8C81472 /* LoopKit.framework */; }; - C156DFB9A7376B332B0A9090 /* G6CalibrationGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1400B7D723677F1F4E972C6 /* G6CalibrationGuideView.swift */; }; - C5A03437EB059CD181CD4931 /* G6SensorKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D7D03FEB69599D0AF52C22E7 /* G6SensorKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - CA78A9937F8B70F55524820B /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 868A9B29D7E79FF89C96DB5D /* HKUnit.swift */; }; - CBDC88F219D43D305FB343B0 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EFA396B891E4BDFE3D274C7 /* HKUnit.swift */; }; - F5B979D63490B082BA6EDAF6 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 119FBC1B7DA145CCFD8E17F3 /* LoopKitUI.framework */; }; + 032019A6EEC8573370EE4E4E /* G6SensorKitPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 737C6C35530CD8BB42B84DF0 /* G6SensorKitPlugin.swift */; }; + 03A90C3DAF1C15F423EBB537 /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D91984A1B779118EF08A4127 /* G6SensorKit.framework */; }; + 089143CB98FE2468E2B3D99A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6BF919306BACA2E97E323D4 /* Foundation.framework */; }; + 0B96FC48B098E283212D7434 /* G6ShareCredentialStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F673B89751D3C7E3998139B9 /* G6ShareCredentialStore.swift */; }; + 1443E4605DC4562A4C2A7BEC /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A76A719F98226D490448343A /* LoopKitUI.framework */; }; + 19DCE7B50E1D4DB6785C0764 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6BF919306BACA2E97E323D4 /* Foundation.framework */; }; + 1EFFB6CA1A4DD2702593640A /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B414B1B8987E102920EBB8 /* HKUnit.swift */; }; + 1F0E56CFDD57BC9269932E00 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 907230D65E10C39D822408AD /* LocalizedString.swift */; }; + 256CCEB29BA96551FCEC4B4A /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 17A6D5E4FD73994C5B1F06F5 /* Localizable.xcstrings */; }; + 325836DA81824456AC495CFF /* G6Graphics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47E75012965DC1C6990A2500 /* G6Graphics.swift */; }; + 3383256660F7228702BAA719 /* G6CGMManagerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CB151CF01D474F2595EF5CA /* G6CGMManagerState.swift */; }; + 38145114C2273AD696A3D633 /* G6AlertEvaluator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C23F573526681B9A23C06AB /* G6AlertEvaluator.swift */; }; + 38402F888769F9D025B8CE04 /* G6ApplySensorViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0DABEF600E765FA27D449C7 /* G6ApplySensorViews.swift */; }; + 388CA00B3F572757ADD0A58D /* G6OnboardingViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92908880134DF0809C232DA8 /* G6OnboardingViews.swift */; }; + 3A9FBCDBD2078C788E4D6A61 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 7F5C107F2A9FBB346DAC8840 /* Localizable.xcstrings */; }; + 3DAE7BECBFE06CFB97DDD196 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD562B4C4652CF07A6B07073 /* LocalizedString.swift */; }; + 3E90A28BA6A527167A190026 /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D91984A1B779118EF08A4127 /* G6SensorKit.framework */; }; + 428978D53D25A29DAAED79BB /* G6ActivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15B0EA77B0F64BDC3B3EEEC6 /* G6ActivityViewController.swift */; }; + 430C49804080723BD78C8DBA /* G6SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1009E258B325CFF8CFB4E87A /* G6SettingsView.swift */; }; + 43274E4597B3482D10EECF54 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 90F75E1970D7A80176F9FB9F /* LoopKit.framework */; }; + 504856D070F911796810BCC9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6BF919306BACA2E97E323D4 /* Foundation.framework */; }; + 5DB32B111CC9558D9D17F1DD /* OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02E433F3990FF78C38DC6551 /* OSLog.swift */; }; + 5E74E403BEF0BB27F23087A0 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 90F75E1970D7A80176F9FB9F /* LoopKit.framework */; }; + 6C3243405AE5D59AEF654CB7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A559C2D3AD9EBB43248B2199 /* Assets.xcassets */; }; + 829F7AA37876027EACE3A83C /* G6SensorKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 606033721DAAF7F6793184DB /* G6SensorKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 92984720FAB46BCCAB93C2F4 /* G6CalibrationGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F285089CA85DF822BC3527 /* G6CalibrationGuideView.swift */; }; + 94284FD983F0E91AE79A91B6 /* G6PackageScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704C5C6E0A049E4425DCDC45 /* G6PackageScannerView.swift */; }; + 96FE9CAA2BA79D899055E8B0 /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8541E3B5A43131113BCA24C3 /* TimeInterval.swift */; }; + A9A6EA0AADF90B3D2BC174BE /* G6CGMManager+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F317421564304E728293A980 /* G6CGMManager+UI.swift */; }; + AE16E074483DAC2574FA59C5 /* G6SensorKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 606033721DAAF7F6793184DB /* G6SensorKitUI.framework */; }; + BF338B66F1042236F4DBAAA0 /* G6Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B21A00EB9363194AD4E3DC4 /* G6Alert.swift */; }; + C1105244C23AE85D192C3C0D /* G6SensorKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D91984A1B779118EF08A4127 /* G6SensorKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + CF28F3F0F438EE53CD7CCEFE /* G6UICoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D0041A85C2E5CE22F9FB07 /* G6UICoordinator.swift */; }; + D389B8A224241FF1DC55A0B5 /* G6SimulatedSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1EFCFD2903EB844B045366 /* G6SimulatedSession.swift */; }; + D3B56173754CE3AA5CB8CEA6 /* G6CGMManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9097D3ECD4FB9E24FB170C75 /* G6CGMManager.swift */; }; + D5272301CD6F360B8E8F2D54 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A76A719F98226D490448343A /* LoopKitUI.framework */; }; + D5456F7B45319478DB67D043 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 90F75E1970D7A80176F9FB9F /* LoopKit.framework */; }; + D57D16D172751A2E34BCBE2D /* G6DetailViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = A236522437951B0C651E1483 /* G6DetailViews.swift */; }; + E2EF5851A11BCE61A474C191 /* Locked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 182061E2189A3DB8D5EC94F2 /* Locked.swift */; }; + EFC856B31EB45F398EF25CA6 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A7BA7FD280EA993E40E1D9A /* HKUnit.swift */; }; + F38D4C7E56F03FD1B2E7F924 /* G6ReadingDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B4FA59134AF1F66A4E60292 /* G6ReadingDetailView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 6DEB037B2C11C81B47415311 /* PBXContainerItemProxy */ = { + 1BBFE840668BC082C5C18328 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 7DEBAED43E1D4606FF3FD912 /* Project object */; + containerPortal = E00046664E8B19B1D108CD7E /* Project object */; proxyType = 1; - remoteGlobalIDString = 09335603AF5648226FC57BDD; + remoteGlobalIDString = 1FC930737F45A671AE16478F; remoteInfo = G6SensorKit; }; - AAE0E5C2368DE5F178EBA0A0 /* PBXContainerItemProxy */ = { + 23DF82B0A16EFF5164752461 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 7DEBAED43E1D4606FF3FD912 /* Project object */; + containerPortal = E00046664E8B19B1D108CD7E /* Project object */; proxyType = 1; - remoteGlobalIDString = 81F390A243C74FC62F2D96A1; + remoteGlobalIDString = 5FDFF54B3F109CF9EB807CE7; remoteInfo = G6SensorKitUI; }; - EEC597C8A44555CBC2C31860 /* PBXContainerItemProxy */ = { + E0A5C942CCB714A7E897F6AA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 7DEBAED43E1D4606FF3FD912 /* Project object */; + containerPortal = E00046664E8B19B1D108CD7E /* Project object */; proxyType = 1; - remoteGlobalIDString = 09335603AF5648226FC57BDD; + remoteGlobalIDString = 1FC930737F45A671AE16478F; remoteInfo = G6SensorKit; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 8DADB55D2D89E3F4C5997BF2 /* Embed Frameworks */ = { + EC6909781D72EEC70B1A43CA /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - 2E65773EEED2B72034485C42 /* G6SensorKit.framework in Embed Frameworks */, - C5A03437EB059CD181CD4931 /* G6SensorKitUI.framework in Embed Frameworks */, + C1105244C23AE85D192C3C0D /* G6SensorKit.framework in Embed Frameworks */, + 829F7AA37876027EACE3A83C /* G6SensorKitUI.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -90,196 +90,196 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 0E000DC9B3FDC9F2050CED65 /* G6OnboardingViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6OnboardingViews.swift; path = Views/G6OnboardingViews.swift; sourceTree = ""; }; - 119FBC1B7DA145CCFD8E17F3 /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 1FCA7C7B1082F4DB56383E62 /* G6SensorKitPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SensorKitPlugin.swift; sourceTree = ""; }; - 3B9AFCC06065A5816CF9B0D0 /* G6DetailViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6DetailViews.swift; path = Views/G6DetailViews.swift; sourceTree = ""; }; - 3C499A8F2A45C5A5F2F6804C /* G6CGMManager+UI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "G6CGMManager+UI.swift"; sourceTree = ""; }; - 4757E22C8DF1FFACB0F5FE55 /* Locked.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Locked.swift; sourceTree = ""; }; - 54F40591DF7546BD56902D34 /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; - 5890F3F14505D20A3BF454AA /* G6AlertEvaluator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6AlertEvaluator.swift; sourceTree = ""; }; - 701FB5943D703C73F0914901 /* G6SettingsView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6SettingsView.swift; path = Views/G6SettingsView.swift; sourceTree = ""; }; - 7BECD386214266280C635EF4 /* G6Graphics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6Graphics.swift; path = Views/G6Graphics.swift; sourceTree = ""; }; - 7E87AE5D60C3B9C9E8C81472 /* LoopKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 84CA1FD8713E9A195D3BEA65 /* TimeInterval.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TimeInterval.swift; sourceTree = ""; }; - 868A9B29D7E79FF89C96DB5D /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; - 8951478AD4BD18A38807B735 /* Assets.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 8DFA312ADF260746CCC9301B /* G6ShareCredentialStore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6ShareCredentialStore.swift; sourceTree = ""; }; - 8EFA396B891E4BDFE3D274C7 /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; - 98A7EC476C76B121A139FB05 /* G6SensorKitPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 9B5551B35D84DFE748E0B321 /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; - A05FE6FDE339FE9321E759CE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS26.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - AD71DF7E83AF717270ABEB4F /* OSLog.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OSLog.swift; sourceTree = ""; }; - B5028E90A753D82115E51BAB /* G6UICoordinator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6UICoordinator.swift; sourceTree = ""; }; - CDEF209176738C95929680EC /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; - CE0275C0BBB9440BE16CBDF2 /* G6CGMManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManager.swift; sourceTree = ""; }; - CE7D978600747DD5D213658C /* G6SimulatedSession.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SimulatedSession.swift; sourceTree = ""; }; - D70699BE714273A4BD5D45AC /* G6CGMManagerState.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManagerState.swift; sourceTree = ""; }; - D7D03FEB69599D0AF52C22E7 /* G6SensorKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - DDAD343CEBAA70172F375006 /* G6SensorKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - EA1B967C98FAF4A32CF34800 /* G6PackageScannerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6PackageScannerView.swift; path = Views/G6PackageScannerView.swift; sourceTree = ""; }; - EA4C8C72C6C5749880D0BD5C /* G6ApplySensorViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ApplySensorViews.swift; path = Views/G6ApplySensorViews.swift; sourceTree = ""; }; - EA7732FACCE0CBE0F2F3B38C /* G6ActivityViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ActivityViewController.swift; path = Views/G6ActivityViewController.swift; sourceTree = ""; }; - EE39687E90C268D1324F4928 /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; - F1400B7D723677F1F4E972C6 /* G6CalibrationGuideView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6CalibrationGuideView.swift; path = Views/G6CalibrationGuideView.swift; sourceTree = ""; }; - F1C1DFABF454CD486038D23B /* G6ReadingDetailView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ReadingDetailView.swift; path = Views/G6ReadingDetailView.swift; sourceTree = ""; }; - F32113D2719FEFFC866A296E /* G6Alert.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6Alert.swift; sourceTree = ""; }; + 02E433F3990FF78C38DC6551 /* OSLog.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OSLog.swift; sourceTree = ""; }; + 1009E258B325CFF8CFB4E87A /* G6SettingsView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6SettingsView.swift; path = Views/G6SettingsView.swift; sourceTree = ""; }; + 15B0EA77B0F64BDC3B3EEEC6 /* G6ActivityViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ActivityViewController.swift; path = Views/G6ActivityViewController.swift; sourceTree = ""; }; + 17A6D5E4FD73994C5B1F06F5 /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; + 182061E2189A3DB8D5EC94F2 /* Locked.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Locked.swift; sourceTree = ""; }; + 18B414B1B8987E102920EBB8 /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; + 2B21A00EB9363194AD4E3DC4 /* G6Alert.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6Alert.swift; sourceTree = ""; }; + 47E75012965DC1C6990A2500 /* G6Graphics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6Graphics.swift; path = Views/G6Graphics.swift; sourceTree = ""; }; + 51F285089CA85DF822BC3527 /* G6CalibrationGuideView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6CalibrationGuideView.swift; path = Views/G6CalibrationGuideView.swift; sourceTree = ""; }; + 5B4FA59134AF1F66A4E60292 /* G6ReadingDetailView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ReadingDetailView.swift; path = Views/G6ReadingDetailView.swift; sourceTree = ""; }; + 606033721DAAF7F6793184DB /* G6SensorKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 704C5C6E0A049E4425DCDC45 /* G6PackageScannerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6PackageScannerView.swift; path = Views/G6PackageScannerView.swift; sourceTree = ""; }; + 737C6C35530CD8BB42B84DF0 /* G6SensorKitPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SensorKitPlugin.swift; sourceTree = ""; }; + 7B1EFCFD2903EB844B045366 /* G6SimulatedSession.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SimulatedSession.swift; sourceTree = ""; }; + 7C23F573526681B9A23C06AB /* G6AlertEvaluator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6AlertEvaluator.swift; sourceTree = ""; }; + 7F5C107F2A9FBB346DAC8840 /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; + 8541E3B5A43131113BCA24C3 /* TimeInterval.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TimeInterval.swift; sourceTree = ""; }; + 8A7BA7FD280EA993E40E1D9A /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; + 8CB151CF01D474F2595EF5CA /* G6CGMManagerState.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManagerState.swift; sourceTree = ""; }; + 907230D65E10C39D822408AD /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; + 9097D3ECD4FB9E24FB170C75 /* G6CGMManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManager.swift; sourceTree = ""; }; + 90F75E1970D7A80176F9FB9F /* LoopKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 92908880134DF0809C232DA8 /* G6OnboardingViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6OnboardingViews.swift; path = Views/G6OnboardingViews.swift; sourceTree = ""; }; + A236522437951B0C651E1483 /* G6DetailViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6DetailViews.swift; path = Views/G6DetailViews.swift; sourceTree = ""; }; + A559C2D3AD9EBB43248B2199 /* Assets.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + A76A719F98226D490448343A /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A7D0041A85C2E5CE22F9FB07 /* G6UICoordinator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6UICoordinator.swift; sourceTree = ""; }; + CD562B4C4652CF07A6B07073 /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; + D91984A1B779118EF08A4127 /* G6SensorKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E6BF919306BACA2E97E323D4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS26.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + F0DABEF600E765FA27D449C7 /* G6ApplySensorViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ApplySensorViews.swift; path = Views/G6ApplySensorViews.swift; sourceTree = ""; }; + F317421564304E728293A980 /* G6CGMManager+UI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "G6CGMManager+UI.swift"; sourceTree = ""; }; + F673B89751D3C7E3998139B9 /* G6ShareCredentialStore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6ShareCredentialStore.swift; sourceTree = ""; }; + F9D12B501A84ED6C12CFFF6A /* G6SensorKitPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 0DADADB95F8B6B4EE8BBD291 /* Frameworks */ = { + 036BF4C74764238F023DA0E8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 7C492DE3E17736DC551DA2EB /* Foundation.framework in Frameworks */, - BAB668D8A5161A2CFA99EE4F /* LoopKit.framework in Frameworks */, + 089143CB98FE2468E2B3D99A /* Foundation.framework in Frameworks */, + D5456F7B45319478DB67D043 /* LoopKit.framework in Frameworks */, + 1443E4605DC4562A4C2A7BEC /* LoopKitUI.framework in Frameworks */, + 3E90A28BA6A527167A190026 /* G6SensorKit.framework in Frameworks */, + AE16E074483DAC2574FA59C5 /* G6SensorKitUI.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 7E51350C1DFCD8D28A2734F5 /* Frameworks */ = { + 3C582B67957BD8AC20A789A7 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0DCAF3F659A2703E9CE24557 /* Foundation.framework in Frameworks */, - 7F02F2A865E554B97A785906 /* LoopKit.framework in Frameworks */, - F5B979D63490B082BA6EDAF6 /* LoopKitUI.framework in Frameworks */, - 990AF949E54DE82A45F260E6 /* G6SensorKit.framework in Frameworks */, - 0693C7476402404DE20D9B4F /* G6SensorKitUI.framework in Frameworks */, + 504856D070F911796810BCC9 /* Foundation.framework in Frameworks */, + 5E74E403BEF0BB27F23087A0 /* LoopKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - B0308539A01D8375A0B43EF4 /* Frameworks */ = { + 95916C8AF6C891370D4B46A3 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 08A233C9F8B1EEE650BF50FD /* Foundation.framework in Frameworks */, - 88F90B528970A11DC5A0D6A0 /* LoopKit.framework in Frameworks */, - 52069C196E0860E1FCAA8146 /* LoopKitUI.framework in Frameworks */, - B07CE4D488047BAB8E73A5D5 /* G6SensorKit.framework in Frameworks */, + 19DCE7B50E1D4DB6785C0764 /* Foundation.framework in Frameworks */, + 43274E4597B3482D10EECF54 /* LoopKit.framework in Frameworks */, + D5272301CD6F360B8E8F2D54 /* LoopKitUI.framework in Frameworks */, + 03A90C3DAF1C15F423EBB537 /* G6SensorKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 1B6E3A15801163A7EDDC18B0 = { + 19A5E64B61E7B02E7A128E2A = { isa = PBXGroup; children = ( - 73C056E01BDF2C32C4010248 /* G6SensorKit */, - FE65C9531147916346925C03 /* Common */, - 86FEC5F564DA61606B5AAC38 /* G6SensorKitUI */, - 8735A9ACBBACA7E2C94847D0 /* G6SensorKitPlugin */, - 9306DFA63B200FA524EDB85D /* Products */, - D8EFE4C33EF051BAA9C3642E /* Frameworks */, + 7E3A0A5E82CBF0BEB5AC2BC6 /* G6SensorKit */, + 7EF5BB2F037C379D46B3D521 /* Common */, + 65A7A5C24641BA7AF03178DB /* G6SensorKitUI */, + 1E84BEF7FF7C5428825C9733 /* G6SensorKitPlugin */, + CB6896C5F55260956ACC3EAF /* Products */, + A6BF578ECCAF8B60CE3BB16F /* Frameworks */, ); sourceTree = ""; }; - 6A6E300163BCF6800DE164CC /* iOS */ = { + 1E84BEF7FF7C5428825C9733 /* G6SensorKitPlugin */ = { isa = PBXGroup; children = ( - A05FE6FDE339FE9321E759CE /* Foundation.framework */, + 737C6C35530CD8BB42B84DF0 /* G6SensorKitPlugin.swift */, ); - name = iOS; + name = G6SensorKitPlugin; + path = G6SensorKitPlugin; sourceTree = ""; }; - 73C056E01BDF2C32C4010248 /* G6SensorKit */ = { + 65A7A5C24641BA7AF03178DB /* G6SensorKitUI */ = { isa = PBXGroup; children = ( - F32113D2719FEFFC866A296E /* G6Alert.swift */, - 5890F3F14505D20A3BF454AA /* G6AlertEvaluator.swift */, - CE0275C0BBB9440BE16CBDF2 /* G6CGMManager.swift */, - D70699BE714273A4BD5D45AC /* G6CGMManagerState.swift */, - 8DFA312ADF260746CCC9301B /* G6ShareCredentialStore.swift */, - CE7D978600747DD5D213658C /* G6SimulatedSession.swift */, - 9B5551B35D84DFE748E0B321 /* Localizable.xcstrings */, + F317421564304E728293A980 /* G6CGMManager+UI.swift */, + A7D0041A85C2E5CE22F9FB07 /* G6UICoordinator.swift */, + 907230D65E10C39D822408AD /* LocalizedString.swift */, + 15B0EA77B0F64BDC3B3EEEC6 /* G6ActivityViewController.swift */, + F0DABEF600E765FA27D449C7 /* G6ApplySensorViews.swift */, + 51F285089CA85DF822BC3527 /* G6CalibrationGuideView.swift */, + A236522437951B0C651E1483 /* G6DetailViews.swift */, + 47E75012965DC1C6990A2500 /* G6Graphics.swift */, + 92908880134DF0809C232DA8 /* G6OnboardingViews.swift */, + 704C5C6E0A049E4425DCDC45 /* G6PackageScannerView.swift */, + 5B4FA59134AF1F66A4E60292 /* G6ReadingDetailView.swift */, + 1009E258B325CFF8CFB4E87A /* G6SettingsView.swift */, + 7F5C107F2A9FBB346DAC8840 /* Localizable.xcstrings */, + A559C2D3AD9EBB43248B2199 /* Assets.xcassets */, ); - name = G6SensorKit; - path = G6SensorKit; + name = G6SensorKitUI; + path = G6SensorKitUI; sourceTree = ""; }; - 86FEC5F564DA61606B5AAC38 /* G6SensorKitUI */ = { + 7E3A0A5E82CBF0BEB5AC2BC6 /* G6SensorKit */ = { isa = PBXGroup; children = ( - 3C499A8F2A45C5A5F2F6804C /* G6CGMManager+UI.swift */, - B5028E90A753D82115E51BAB /* G6UICoordinator.swift */, - 54F40591DF7546BD56902D34 /* LocalizedString.swift */, - EA7732FACCE0CBE0F2F3B38C /* G6ActivityViewController.swift */, - EA4C8C72C6C5749880D0BD5C /* G6ApplySensorViews.swift */, - F1400B7D723677F1F4E972C6 /* G6CalibrationGuideView.swift */, - 3B9AFCC06065A5816CF9B0D0 /* G6DetailViews.swift */, - 7BECD386214266280C635EF4 /* G6Graphics.swift */, - 0E000DC9B3FDC9F2050CED65 /* G6OnboardingViews.swift */, - EA1B967C98FAF4A32CF34800 /* G6PackageScannerView.swift */, - F1C1DFABF454CD486038D23B /* G6ReadingDetailView.swift */, - 701FB5943D703C73F0914901 /* G6SettingsView.swift */, - CDEF209176738C95929680EC /* Localizable.xcstrings */, - 8951478AD4BD18A38807B735 /* Assets.xcassets */, + 2B21A00EB9363194AD4E3DC4 /* G6Alert.swift */, + 7C23F573526681B9A23C06AB /* G6AlertEvaluator.swift */, + 9097D3ECD4FB9E24FB170C75 /* G6CGMManager.swift */, + 8CB151CF01D474F2595EF5CA /* G6CGMManagerState.swift */, + F673B89751D3C7E3998139B9 /* G6ShareCredentialStore.swift */, + 7B1EFCFD2903EB844B045366 /* G6SimulatedSession.swift */, + 17A6D5E4FD73994C5B1F06F5 /* Localizable.xcstrings */, ); - name = G6SensorKitUI; - path = G6SensorKitUI; + name = G6SensorKit; + path = G6SensorKit; sourceTree = ""; }; - 8735A9ACBBACA7E2C94847D0 /* G6SensorKitPlugin */ = { + 7EF5BB2F037C379D46B3D521 /* Common */ = { isa = PBXGroup; children = ( - 1FCA7C7B1082F4DB56383E62 /* G6SensorKitPlugin.swift */, + 18B414B1B8987E102920EBB8 /* HKUnit.swift */, + CD562B4C4652CF07A6B07073 /* LocalizedString.swift */, + 182061E2189A3DB8D5EC94F2 /* Locked.swift */, + 02E433F3990FF78C38DC6551 /* OSLog.swift */, + 8541E3B5A43131113BCA24C3 /* TimeInterval.swift */, + 8A7BA7FD280EA993E40E1D9A /* HKUnit.swift */, ); - name = G6SensorKitPlugin; - path = G6SensorKitPlugin; + name = Common; + path = Common; sourceTree = ""; }; - 9306DFA63B200FA524EDB85D /* Products */ = { + A6BF578ECCAF8B60CE3BB16F /* Frameworks */ = { isa = PBXGroup; children = ( - DDAD343CEBAA70172F375006 /* G6SensorKit.framework */, - D7D03FEB69599D0AF52C22E7 /* G6SensorKitUI.framework */, - 98A7EC476C76B121A139FB05 /* G6SensorKitPlugin.framework */, + 90F75E1970D7A80176F9FB9F /* LoopKit.framework */, + A76A719F98226D490448343A /* LoopKitUI.framework */, + DF2BE94BD2F3F23A12B6F7C4 /* iOS */, ); - name = Products; + name = Frameworks; sourceTree = ""; }; - D8EFE4C33EF051BAA9C3642E /* Frameworks */ = { + CB6896C5F55260956ACC3EAF /* Products */ = { isa = PBXGroup; children = ( - 7E87AE5D60C3B9C9E8C81472 /* LoopKit.framework */, - 119FBC1B7DA145CCFD8E17F3 /* LoopKitUI.framework */, - 6A6E300163BCF6800DE164CC /* iOS */, + D91984A1B779118EF08A4127 /* G6SensorKit.framework */, + 606033721DAAF7F6793184DB /* G6SensorKitUI.framework */, + F9D12B501A84ED6C12CFFF6A /* G6SensorKitPlugin.framework */, ); - name = Frameworks; + name = Products; sourceTree = ""; }; - FE65C9531147916346925C03 /* Common */ = { + DF2BE94BD2F3F23A12B6F7C4 /* iOS */ = { isa = PBXGroup; children = ( - 868A9B29D7E79FF89C96DB5D /* HKUnit.swift */, - EE39687E90C268D1324F4928 /* LocalizedString.swift */, - 4757E22C8DF1FFACB0F5FE55 /* Locked.swift */, - AD71DF7E83AF717270ABEB4F /* OSLog.swift */, - 84CA1FD8713E9A195D3BEA65 /* TimeInterval.swift */, - 8EFA396B891E4BDFE3D274C7 /* HKUnit.swift */, + E6BF919306BACA2E97E323D4 /* Foundation.framework */, ); - name = Common; - path = Common; + name = iOS; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 73AF5A35F193528B276B30B4 /* Headers */ = { + 60A6AA3FCCB11141F8B8C24E /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - B371086234D0EE811F02EC7D /* Headers */ = { + A7501DCDA29A942C68578914 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - BB4D67F09424EEBE210E689C /* Headers */ = { + B35B2AD03E597E11E2A0B16A /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( @@ -289,14 +289,14 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 09335603AF5648226FC57BDD /* G6SensorKit */ = { + 1FC930737F45A671AE16478F /* G6SensorKit */ = { isa = PBXNativeTarget; - buildConfigurationList = CCF0FF127493D98642A8659A /* Build configuration list for PBXNativeTarget "G6SensorKit" */; + buildConfigurationList = E6BECE0CEC895BB0D3C1EA93 /* Build configuration list for PBXNativeTarget "G6SensorKit" */; buildPhases = ( - 73AF5A35F193528B276B30B4 /* Headers */, - A7014F2B4A8E71778514B0ED /* Sources */, - 0DADADB95F8B6B4EE8BBD291 /* Frameworks */, - A14A0BEC872E5B61AAEF9C97 /* Resources */, + 60A6AA3FCCB11141F8B8C24E /* Headers */, + 444C5BA0EDD6B24D16C899CF /* Sources */, + 3C582B67957BD8AC20A789A7 /* Frameworks */, + A720A1114AADAE11791259CE /* Resources */, ); buildRules = ( ); @@ -304,62 +304,62 @@ ); name = G6SensorKit; packageProductDependencies = ( - D394DBFFF1C24A5BE57AD26C /* G6SensorCore */, + 99E200D18B601AFB565F1B5B /* G6SensorCore */, ); productName = G6SensorKit; - productReference = DDAD343CEBAA70172F375006 /* G6SensorKit.framework */; + productReference = D91984A1B779118EF08A4127 /* G6SensorKit.framework */; productType = "com.apple.product-type.framework"; }; - 350C634F69815B1C4E0D8ACC /* G6SensorKitPlugin */ = { + 5FDFF54B3F109CF9EB807CE7 /* G6SensorKitUI */ = { isa = PBXNativeTarget; - buildConfigurationList = BF1A336FAFA87AA5EAEAF56A /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */; + buildConfigurationList = CD0E963482CD3D2B5682140B /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */; buildPhases = ( - B371086234D0EE811F02EC7D /* Headers */, - B52E76D39F272FBFCA5CFC20 /* Sources */, - 7E51350C1DFCD8D28A2734F5 /* Frameworks */, - F94EE9C2A48DF3DA8B2F856E /* Resources */, - 8DADB55D2D89E3F4C5997BF2 /* Embed Frameworks */, + A7501DCDA29A942C68578914 /* Headers */, + 8417137A0C4F1F7F25185E61 /* Sources */, + 95916C8AF6C891370D4B46A3 /* Frameworks */, + A456440235B07EA3B55C3C44 /* Resources */, ); buildRules = ( ); dependencies = ( - 765B7BD50495DB444A1963DB /* PBXTargetDependency */, - 02D3824D7998AA7BB603E4B0 /* PBXTargetDependency */, + 43D4F281FBAD16F8FCAE2F77 /* PBXTargetDependency */, ); - name = G6SensorKitPlugin; - productName = G6SensorKitPlugin; - productReference = 98A7EC476C76B121A139FB05 /* G6SensorKitPlugin.framework */; + name = G6SensorKitUI; + productName = G6SensorKitUI; + productReference = 606033721DAAF7F6793184DB /* G6SensorKitUI.framework */; productType = "com.apple.product-type.framework"; }; - 81F390A243C74FC62F2D96A1 /* G6SensorKitUI */ = { + D59705DF2CF01716CBDBCA1E /* G6SensorKitPlugin */ = { isa = PBXNativeTarget; - buildConfigurationList = 46716CE46FCB498D573CFB95 /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */; + buildConfigurationList = 92650F7E6B063572AC79D169 /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */; buildPhases = ( - BB4D67F09424EEBE210E689C /* Headers */, - 645A1FC8D344F4493716F92A /* Sources */, - B0308539A01D8375A0B43EF4 /* Frameworks */, - BC0BD21D3B7639D7D9899099 /* Resources */, + B35B2AD03E597E11E2A0B16A /* Headers */, + E14BEE3FDC217ED133742420 /* Sources */, + 036BF4C74764238F023DA0E8 /* Frameworks */, + 1384F63BC3916A99F4309AD9 /* Resources */, + EC6909781D72EEC70B1A43CA /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( - 7B658B66EC05118906BACD6A /* PBXTargetDependency */, + 15B834AB9E65E9AFA58F1744 /* PBXTargetDependency */, + 7A4F1CA8724DC60FA58D2552 /* PBXTargetDependency */, ); - name = G6SensorKitUI; - productName = G6SensorKitUI; - productReference = D7D03FEB69599D0AF52C22E7 /* G6SensorKitUI.framework */; + name = G6SensorKitPlugin; + productName = G6SensorKitPlugin; + productReference = F9D12B501A84ED6C12CFFF6A /* G6SensorKitPlugin.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 7DEBAED43E1D4606FF3FD912 /* Project object */ = { + E00046664E8B19B1D108CD7E /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1600; LastUpgradeCheck = 1600; }; - buildConfigurationList = 5B553683CF19BBB44D32F54D /* Build configuration list for PBXProject "G6SensorKit" */; + buildConfigurationList = 1CB4E131373959E0BC530F1F /* Build configuration list for PBXProject "G6SensorKit" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = en; hasScannedForEncodings = 0; @@ -367,158 +367,122 @@ en, Base, ); - mainGroup = 1B6E3A15801163A7EDDC18B0; + mainGroup = 19A5E64B61E7B02E7A128E2A; minimizedProjectReferenceProxies = 0; packageReferences = ( - EDC1BC10B795C488BF680E84 /* XCLocalSwiftPackageReference "." */, + 459883F123D879CFB6DBB549 /* XCLocalSwiftPackageReference "." */, ); preferredProjectObjectVersion = 100; - productRefGroup = 9306DFA63B200FA524EDB85D /* Products */; + productRefGroup = CB6896C5F55260956ACC3EAF /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 09335603AF5648226FC57BDD /* G6SensorKit */, - 81F390A243C74FC62F2D96A1 /* G6SensorKitUI */, - 350C634F69815B1C4E0D8ACC /* G6SensorKitPlugin */, + 1FC930737F45A671AE16478F /* G6SensorKit */, + 5FDFF54B3F109CF9EB807CE7 /* G6SensorKitUI */, + D59705DF2CF01716CBDBCA1E /* G6SensorKitPlugin */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - A14A0BEC872E5B61AAEF9C97 /* Resources */ = { + 1384F63BC3916A99F4309AD9 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 37DEA0FE2BA2BF0AE14ADF13 /* Localizable.xcstrings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - BC0BD21D3B7639D7D9899099 /* Resources */ = { + A456440235B07EA3B55C3C44 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 66AF27897E99EE1859962C21 /* Localizable.xcstrings in Resources */, - 51E9F176C1D5B4D4C16A59A3 /* Assets.xcassets in Resources */, + 3A9FBCDBD2078C788E4D6A61 /* Localizable.xcstrings in Resources */, + 6C3243405AE5D59AEF654CB7 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - F94EE9C2A48DF3DA8B2F856E /* Resources */ = { + A720A1114AADAE11791259CE /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 256CCEB29BA96551FCEC4B4A /* Localizable.xcstrings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 645A1FC8D344F4493716F92A /* Sources */ = { + 444C5BA0EDD6B24D16C899CF /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3AE0A4224E186716AD9B38BA /* G6CGMManager+UI.swift in Sources */, - 113A6AADAEB5985A9833663C /* G6UICoordinator.swift in Sources */, - 4B60FA598DDD83373BF9AF9A /* LocalizedString.swift in Sources */, - 56DB4016BF61B7A5DEE9F47F /* G6ActivityViewController.swift in Sources */, - 1A031090C7910D3B4BF01246 /* G6ApplySensorViews.swift in Sources */, - C156DFB9A7376B332B0A9090 /* G6CalibrationGuideView.swift in Sources */, - 957A9D07764B7C40DFBBEF6A /* G6DetailViews.swift in Sources */, - 8955744E48E5793B6019A69D /* G6Graphics.swift in Sources */, - 29A6CAB9D3F1429C79C19511 /* G6OnboardingViews.swift in Sources */, - 59206A3FBADAC02D985182A1 /* G6PackageScannerView.swift in Sources */, - 779E0E2EFCD8988DB0D48E1E /* G6ReadingDetailView.swift in Sources */, - B74C908295343E4D9541421A /* G6SettingsView.swift in Sources */, - CBDC88F219D43D305FB343B0 /* HKUnit.swift in Sources */, + BF338B66F1042236F4DBAAA0 /* G6Alert.swift in Sources */, + 38145114C2273AD696A3D633 /* G6AlertEvaluator.swift in Sources */, + D3B56173754CE3AA5CB8CEA6 /* G6CGMManager.swift in Sources */, + 3383256660F7228702BAA719 /* G6CGMManagerState.swift in Sources */, + 0B96FC48B098E283212D7434 /* G6ShareCredentialStore.swift in Sources */, + D389B8A224241FF1DC55A0B5 /* G6SimulatedSession.swift in Sources */, + 1EFFB6CA1A4DD2702593640A /* HKUnit.swift in Sources */, + 3DAE7BECBFE06CFB97DDD196 /* LocalizedString.swift in Sources */, + E2EF5851A11BCE61A474C191 /* Locked.swift in Sources */, + 5DB32B111CC9558D9D17F1DD /* OSLog.swift in Sources */, + 96FE9CAA2BA79D899055E8B0 /* TimeInterval.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - A7014F2B4A8E71778514B0ED /* Sources */ = { + 8417137A0C4F1F7F25185E61 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A8D7FD3BA2F4591BC1E043C5 /* G6Alert.swift in Sources */, - 49DEA9F14CC66EE8CF7A1938 /* G6AlertEvaluator.swift in Sources */, - 3098352571C4019F26687C99 /* G6CGMManager.swift in Sources */, - 1D75C9FD5B5D1798EA308C39 /* G6CGMManagerState.swift in Sources */, - 22BB2B2C62819EF28F71536C /* G6ShareCredentialStore.swift in Sources */, - 90E1E35D64D8B5B905A2C2A4 /* G6SimulatedSession.swift in Sources */, - CA78A9937F8B70F55524820B /* HKUnit.swift in Sources */, - 81AF0901E0F6A16A4634AAF5 /* LocalizedString.swift in Sources */, - B4312F20327B994F68EA3B2F /* Locked.swift in Sources */, - 69F9DC12AEE8DB64C7D39D7E /* OSLog.swift in Sources */, - 47095EDB584677B51133FB55 /* TimeInterval.swift in Sources */, + A9A6EA0AADF90B3D2BC174BE /* G6CGMManager+UI.swift in Sources */, + CF28F3F0F438EE53CD7CCEFE /* G6UICoordinator.swift in Sources */, + 1F0E56CFDD57BC9269932E00 /* LocalizedString.swift in Sources */, + 428978D53D25A29DAAED79BB /* G6ActivityViewController.swift in Sources */, + 38402F888769F9D025B8CE04 /* G6ApplySensorViews.swift in Sources */, + 92984720FAB46BCCAB93C2F4 /* G6CalibrationGuideView.swift in Sources */, + D57D16D172751A2E34BCBE2D /* G6DetailViews.swift in Sources */, + 325836DA81824456AC495CFF /* G6Graphics.swift in Sources */, + 388CA00B3F572757ADD0A58D /* G6OnboardingViews.swift in Sources */, + 94284FD983F0E91AE79A91B6 /* G6PackageScannerView.swift in Sources */, + F38D4C7E56F03FD1B2E7F924 /* G6ReadingDetailView.swift in Sources */, + 430C49804080723BD78C8DBA /* G6SettingsView.swift in Sources */, + EFC856B31EB45F398EF25CA6 /* HKUnit.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - B52E76D39F272FBFCA5CFC20 /* Sources */ = { + E14BEE3FDC217ED133742420 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 766AD55DDB016FA0D4CE7531 /* G6SensorKitPlugin.swift in Sources */, + 032019A6EEC8573370EE4E4E /* G6SensorKitPlugin.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 02D3824D7998AA7BB603E4B0 /* PBXTargetDependency */ = { + 15B834AB9E65E9AFA58F1744 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = G6SensorKitUI; - target = 81F390A243C74FC62F2D96A1 /* G6SensorKitUI */; - targetProxy = AAE0E5C2368DE5F178EBA0A0 /* PBXContainerItemProxy */; + name = G6SensorKit; + target = 1FC930737F45A671AE16478F /* G6SensorKit */; + targetProxy = E0A5C942CCB714A7E897F6AA /* PBXContainerItemProxy */; }; - 765B7BD50495DB444A1963DB /* PBXTargetDependency */ = { + 43D4F281FBAD16F8FCAE2F77 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = G6SensorKit; - target = 09335603AF5648226FC57BDD /* G6SensorKit */; - targetProxy = 6DEB037B2C11C81B47415311 /* PBXContainerItemProxy */; + target = 1FC930737F45A671AE16478F /* G6SensorKit */; + targetProxy = 1BBFE840668BC082C5C18328 /* PBXContainerItemProxy */; }; - 7B658B66EC05118906BACD6A /* PBXTargetDependency */ = { + 7A4F1CA8724DC60FA58D2552 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = G6SensorKit; - target = 09335603AF5648226FC57BDD /* G6SensorKit */; - targetProxy = EEC597C8A44555CBC2C31860 /* PBXContainerItemProxy */; + name = G6SensorKitUI; + target = 5FDFF54B3F109CF9EB807CE7 /* G6SensorKitUI */; + targetProxy = 23DF82B0A16EFF5164752461 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 00710D3BA9DAD1A2388461E2 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUILD_LIBRARY_FOR_DISTRIBUTION = YES; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = NO; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = NO; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_MODULE_VERIFIER = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(BUILT_PRODUCTS_DIR)", - ); - GENERATE_INFOPLIST_FILE = NO; - INFOPLIST_FILE = G6SensorKitPlugin/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 17.6; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitPlugin; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.9; - TARGETED_DEVICE_FAMILY = 1; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WRAPPER_EXTENSION = loopplugin; - }; - name = Debug; - }; - 2BDD209E0CD6A5C0AEFACFA1 /* Release */ = { + 48313512C607D6345E05EA05 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -535,12 +499,12 @@ "$(inherited)", "$(BUILT_PRODUCTS_DIR)", ); - INFOPLIST_FILE = G6SensorKit/Info.plist; + INFOPLIST_FILE = G6SensorKitUI/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKit; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitUI; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; @@ -553,7 +517,7 @@ }; name = Release; }; - 77859602A5958F6C7636159C /* Debug */ = { + 5F47B21649870C5B6887C09E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -561,7 +525,7 @@ CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = NO; CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; + DEFINES_MODULE = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -570,12 +534,13 @@ "$(inherited)", "$(BUILT_PRODUCTS_DIR)", ); - INFOPLIST_FILE = G6SensorKitUI/Info.plist; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = G6SensorKitPlugin/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitUI; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitPlugin; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; @@ -584,10 +549,11 @@ TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WRAPPER_EXTENSION = loopplugin; }; name = Debug; }; - 9A188B7C6508D5BE865290DF /* Release */ = { + 6B7F966D3443B894BE4C93D1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -595,7 +561,7 @@ CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = NO; CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; + DEFINES_MODULE = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -604,12 +570,13 @@ "$(inherited)", "$(BUILT_PRODUCTS_DIR)", ); - INFOPLIST_FILE = G6SensorKitUI/Info.plist; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = G6SensorKitPlugin/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitUI; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitPlugin; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; @@ -619,10 +586,11 @@ VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WRAPPER_EXTENSION = loopplugin; }; name = Release; }; - A8C5BF1B01A31FCB77220DF6 /* Debug */ = { + 7309CF4E6FD8C75F7C6FC8D1 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -684,44 +652,7 @@ }; name = Debug; }; - B67CF6E49F25C51A744E1B8D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUILD_LIBRARY_FOR_DISTRIBUTION = YES; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = NO; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = NO; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_MODULE_VERIFIER = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(BUILT_PRODUCTS_DIR)", - ); - GENERATE_INFOPLIST_FILE = NO; - INFOPLIST_FILE = G6SensorKitPlugin/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 17.6; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitPlugin; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.9; - TARGETED_DEVICE_FAMILY = 1; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WRAPPER_EXTENSION = loopplugin; - }; - name = Release; - }; - BC493465B0E8800363FF8DAC /* Debug */ = { + 8B0271A75292B6CE385B7ABD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -750,12 +681,13 @@ SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.9; TARGETED_DEVICE_FAMILY = 1; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; - FD0873526D7652433984E911 /* Release */ = { + A3B0558276FC30AF2089ACE6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -811,41 +743,109 @@ }; name = Release; }; + BA27D1028CA339E51C052640 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = NO; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)", + ); + INFOPLIST_FILE = G6SensorKitUI/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitUI; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.9; + TARGETED_DEVICE_FAMILY = 1; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DCB9941481C5322FDDBB0801 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = NO; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(BUILT_PRODUCTS_DIR)", + ); + INFOPLIST_FILE = G6SensorKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKit; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.9; + TARGETED_DEVICE_FAMILY = 1; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 46716CE46FCB498D573CFB95 /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */ = { + 1CB4E131373959E0BC530F1F /* Build configuration list for PBXProject "G6SensorKit" */ = { isa = XCConfigurationList; buildConfigurations = ( - 9A188B7C6508D5BE865290DF /* Release */, - 77859602A5958F6C7636159C /* Debug */, + 7309CF4E6FD8C75F7C6FC8D1 /* Debug */, + A3B0558276FC30AF2089ACE6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 5B553683CF19BBB44D32F54D /* Build configuration list for PBXProject "G6SensorKit" */ = { + 92650F7E6B063572AC79D169 /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */ = { isa = XCConfigurationList; buildConfigurations = ( - A8C5BF1B01A31FCB77220DF6 /* Debug */, - FD0873526D7652433984E911 /* Release */, + 6B7F966D3443B894BE4C93D1 /* Release */, + 5F47B21649870C5B6887C09E /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - BF1A336FAFA87AA5EAEAF56A /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */ = { + CD0E963482CD3D2B5682140B /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */ = { isa = XCConfigurationList; buildConfigurations = ( - B67CF6E49F25C51A744E1B8D /* Release */, - 00710D3BA9DAD1A2388461E2 /* Debug */, + 48313512C607D6345E05EA05 /* Release */, + BA27D1028CA339E51C052640 /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - CCF0FF127493D98642A8659A /* Build configuration list for PBXNativeTarget "G6SensorKit" */ = { + E6BECE0CEC895BB0D3C1EA93 /* Build configuration list for PBXNativeTarget "G6SensorKit" */ = { isa = XCConfigurationList; buildConfigurations = ( - 2BDD209E0CD6A5C0AEFACFA1 /* Release */, - BC493465B0E8800363FF8DAC /* Debug */, + 8B0271A75292B6CE385B7ABD /* Release */, + DCB9941481C5322FDDBB0801 /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -853,18 +853,18 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - EDC1BC10B795C488BF680E84 /* XCLocalSwiftPackageReference "." */ = { + 459883F123D879CFB6DBB549 /* XCLocalSwiftPackageReference "." */ = { isa = XCLocalSwiftPackageReference; relativePath = .; }; /* End XCLocalSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - D394DBFFF1C24A5BE57AD26C /* G6SensorCore */ = { + 99E200D18B601AFB565F1B5B /* G6SensorCore */ = { isa = XCSwiftPackageProductDependency; productName = G6SensorCore; }; /* End XCSwiftPackageProductDependency section */ }; - rootObject = 7DEBAED43E1D4606FF3FD912 /* Project object */; + rootObject = E00046664E8B19B1D108CD7E /* Project object */; } diff --git a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme index dacccc3..6717617 100644 --- a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme +++ b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> diff --git a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme index cbfeedb..6c0d16d 100644 --- a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme +++ b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> diff --git a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme index 60e523c..ed560ca 100644 --- a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme +++ b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> diff --git a/G6SensorKit/G6CGMManager.swift b/G6SensorKit/G6CGMManager.swift index 93d4516..b446c18 100644 --- a/G6SensorKit/G6CGMManager.swift +++ b/G6SensorKit/G6CGMManager.swift @@ -69,7 +69,7 @@ public final class G6CGMManager: CGMManager { public private(set) var session: TransmitterSession? /// Commands queued for the next connection cycle. - private let lockedPendingCommands: Locked<[Command]> = Locked([]) + private let lockedCommandQueue: Locked = Locked(CommandQueue()) private var lastBatteryReadDate: Date? @@ -134,7 +134,7 @@ public final class G6CGMManager: CGMManager { public init(state: G6CGMManagerState) { self.lockedState = Locked(state) - lockedPendingCommands.mutate { $0 = state.pendingCommands.compactMap(Command.init(rawValue:)) } + lockedCommandQueue.mutate { $0 = CommandQueue(rawValues: state.pendingCommands) } startSession() } @@ -151,7 +151,7 @@ public final class G6CGMManager: CGMManager { } self.lockedState = Locked(state) - lockedPendingCommands.mutate { $0 = state.pendingCommands.compactMap(Command.init(rawValue:)) } + lockedCommandQueue.mutate { $0 = CommandQueue(rawValues: state.pendingCommands) } startSession() } @@ -304,11 +304,8 @@ public final class G6CGMManager: CGMManager { // is persisted, a stale code-less start could reach the transmitter // ahead of the one carrying the sensor code the user actually typed. var superseded = 0 - lockedPendingCommands.mutate { commands in - let before = commands.count - commands.removeAll { $0.supersededBy(command) } - superseded = before - commands.count - commands.append(command) + lockedCommandQueue.mutate { queue in + superseded = queue.enqueue(command) } if superseded > 0 { @@ -316,10 +313,7 @@ public final class G6CGMManager: CGMManager { } mutateState { state in - state.pendingCommands.removeAll { raw in - Command(rawValue: raw).map { $0.supersededBy(command) } ?? true - } - state.pendingCommands.append(command.rawValue) + state.pendingCommands = self.lockedCommandQueue.value.rawValues // Reflect the entered code straight away. Waiting until the // transmitter answered meant the screen said "Not used" for as @@ -332,6 +326,27 @@ public final class G6CGMManager: CGMManager { // Nudge the connection in case it is idle. session?.start() + + #if targetEnvironment(simulator) + // No link will ever drain the queue in the simulator; apply the + // command to state directly, mirroring didComplete on hardware, + // so End Sensor / Start New Sensor work end-to-end there. + lockedCommandQueue.mutate { _ = $0.dequeue() } + mutateState { state in + state.pendingCommands = self.lockedCommandQueue.value.rawValues + switch command { + case .stopSensor: + state.sensorStartDate = nil + state.sensorCode = nil + case .startSensor(let date, let sensorCode): + state.sensorCode = sensorCode.carriesParameters ? sensorCode.code : nil + state.sensorStartDate = date + .addingTimeInterval(-(state.warmupPeriod - G6CGMManager.simulatedWarmupRemaining)) + case .calibrateSensor, .resetTransmitter: + break + } + } + #endif } public func setSensorLifeDays(_ days: Int) { @@ -383,7 +398,7 @@ public final class G6CGMManager: CGMManager { if connectionPhase == .connected { log.default("Old transmitter still connected; sending session stop before switching") session?.commandSource = self - lockedPendingCommands.mutate { $0 = [.stopSensor(at: Date())] } + lockedCommandQueue.mutate { $0 = CommandQueue([.stopSensor(at: Date())]) } } else { log.default("Old transmitter not connected; its session is left as-is") } @@ -407,7 +422,7 @@ public final class G6CGMManager: CGMManager { // middle of the state reset. The session itself is kept and pointed at // the new transmitter — the radio does not need rebuilding for a swap. session?.stop() - lockedPendingCommands.mutate { $0.removeAll() } + lockedCommandQueue.mutate { $0.removeAll() } raisedAlerts = [] mutateState { state in @@ -846,36 +861,17 @@ extension G6CGMManager: TransmitterCommandSource { public func dequeuePendingCommand(for session: TransmitterSession) -> Command? { var next: Command? var dropped: [Command] = [] - lockedPendingCommands.mutate { commands in - // A calibration is only meaningful next to the fingerstick it came - // from; xDrip uses the same five-minute window. Sending a stale one - // would teach the sensor from a value that no longer holds. - while let candidate = commands.first { - commands.removeFirst() - if case .calibrateSensor(_, let date) = candidate, - Date().timeIntervalSince(date) > .minutes(5) { - dropped.append(candidate) - continue - } - next = candidate - break - } + lockedCommandQueue.mutate { queue in + (next, dropped) = queue.dequeue() } for command in dropped { log.default("Dropping stale command: %{public}@", String(describing: command)) - mutateState { state in - if !state.pendingCommands.isEmpty { - state.pendingCommands.removeFirst() - } - } } - if next != nil { + if next != nil || !dropped.isEmpty { mutateState { state in - if !state.pendingCommands.isEmpty { - state.pendingCommands.removeFirst() - } + state.pendingCommands = self.lockedCommandQueue.value.rawValues } } diff --git a/G6SensorKit/G6SimulatedSession.swift b/G6SensorKit/G6SimulatedSession.swift index cc886c3..30c4aac 100644 --- a/G6SensorKit/G6SimulatedSession.swift +++ b/G6SensorKit/G6SimulatedSession.swift @@ -43,7 +43,9 @@ extension G6CGMManager { // warming up. state.transmitterStartDate = now.addingTimeInterval(-.hours(24 * 12)) state.sensorStartDate = now.addingTimeInterval(-(state.warmupPeriod - Self.simulatedWarmupRemaining)) - state.transmitterExpiryInDays = 90 + // 180 days so the simulator presents as an Anubis, making the + // longer session length and expiry visible in the UI. + state.transmitterExpiryInDays = 180 state.firmwareVersion = "1.0.0.0 (simulated)" state.peripheralIdentifier = UUID() } @@ -64,6 +66,9 @@ extension G6CGMManager { } private func emitSimulatedReading() { + // No active session (ended, or not yet started): stay quiet. + guard state.sensorStartDate != nil else { return } + guard !state.isInWarmup else { // Still warming up: the state change alone refreshes the UI. notifySimulationObservers() diff --git a/Sources/G6SensorCore/Session/CommandQueue.swift b/Sources/G6SensorCore/Session/CommandQueue.swift new file mode 100644 index 0000000..dbf6c18 --- /dev/null +++ b/Sources/G6SensorCore/Session/CommandQueue.swift @@ -0,0 +1,74 @@ +// +// CommandQueue.swift +// G6SensorKit +// +// Copyright © 2026 Nightscout Foundation. MIT License. +// + +import Foundation + +/// A persisted queue of transmitter commands awaiting the next connection. +/// +/// Pure value logic, extracted from the G6 manager so the supersede and +/// stale-drop rules can be tested without LoopKit. The manager mirrors +/// `rawValues` into its persisted state so queued commands survive relaunch. +public struct CommandQueue: Equatable { + + public static let staleCalibrationInterval: TimeInterval = .minutes(5) + + public private(set) var commands: [Command] + + public init(_ commands: [Command] = []) { + self.commands = commands + } + + public init(rawValues: [Command.RawValue]) { + self.init(rawValues.compactMap(Command.init(rawValue:))) + } + + public var rawValues: [Command.RawValue] { + commands.map(\.rawValue) + } + + public var isEmpty: Bool { + commands.isEmpty + } + + /// Queues a command for the next connection cycle. Newest wins: any + /// queued command the new one supersedes is dropped first, so repeated + /// trips through setup cannot stack session starts. + /// + /// - Returns: the number of queued commands the new one replaced. + @discardableResult public mutating func enqueue(_ command: Command) -> Int { + let before = commands.count + commands.removeAll { $0.supersededBy(command) } + let superseded = before - commands.count + commands.append(command) + return superseded + } + + /// Pops the next command to send, silently dropping stale calibrations. + /// + /// - Returns: the command to send, plus any commands dropped as stale + /// (for logging). + public mutating func dequeue(now: Date = Date()) -> (next: Command?, dropped: [Command]) { + var dropped: [Command] = [] + var next: Command? + while let candidate = commands.first { + commands.removeFirst() + if case let .calibrateSensor(_, date) = candidate, + now.timeIntervalSince(date) > Self.staleCalibrationInterval + { + dropped.append(candidate) + continue + } + next = candidate + break + } + return (next, dropped) + } + + public mutating func removeAll() { + commands.removeAll() + } +} diff --git a/Sources/G6SensorCore/Support/Locked.swift b/Sources/G6SensorCore/Support/Locked.swift index fd6e35b..4a82830 100644 --- a/Sources/G6SensorCore/Support/Locked.swift +++ b/Sources/G6SensorCore/Support/Locked.swift @@ -31,6 +31,7 @@ internal class Locked { } } + @discardableResult func mutate(_ changes: (_ value: inout T) -> Void) -> T { os_unfair_lock_lock(&lock) defer { os_unfair_lock_unlock(&lock) } diff --git a/Tests/G6SensorCoreTests/CommandQueueTests.swift b/Tests/G6SensorCoreTests/CommandQueueTests.swift new file mode 100644 index 0000000..bdcb7cd --- /dev/null +++ b/Tests/G6SensorCoreTests/CommandQueueTests.swift @@ -0,0 +1,95 @@ +// +// CommandQueueTests.swift +// G6SensorKit +// +// Copyright © 2026 Nightscout Foundation. MIT License. +// + +import XCTest +@testable import G6SensorCore + +class CommandQueueTests: XCTestCase { + private let now = Date(timeIntervalSince1970: 1_700_000_000) + + func testEnqueueAppendsDistinctCommands() { + var queue = CommandQueue() + queue.enqueue(.startSensor(at: now, sensorCode: .none)) + queue.enqueue(.calibrateSensor(toMgDL: 120, at: now)) + + XCTAssertEqual(queue.commands.count, 2) + } + + func testEnqueueSupersedesSameKind() { + var queue = CommandQueue() + queue.enqueue(.startSensor(at: now, sensorCode: .none)) + queue.enqueue(.startSensor(at: now, sensorCode: .none)) + queue.enqueue(.calibrateSensor(toMgDL: 100, at: now)) + queue.enqueue(.calibrateSensor(toMgDL: 140, at: now)) + + XCTAssertEqual(queue.commands.count, 2) + guard case let .calibrateSensor(value, _) = queue.commands[1] else { + return XCTFail("expected calibration") + } + XCTAssertEqual(value, 140) + } + + func testEnqueueReturnsSupersededCount() { + var queue = CommandQueue() + queue.enqueue(.calibrateSensor(toMgDL: 100, at: now)) + queue.enqueue(.calibrateSensor(toMgDL: 110, at: now)) + // The 110 enqueue already superseded the 100 one, so a single queued + // calibration remains for the 120 to replace. + let superseded = queue.enqueue(.calibrateSensor(toMgDL: 120, at: now)) + XCTAssertEqual(superseded, 1) + XCTAssertEqual(queue.commands.count, 1) + } + + func testDequeueDropsStaleCalibrations() { + var queue = CommandQueue() + // 6 minutes old at dequeue time: beyond the 5-minute window. + queue.enqueue(.calibrateSensor(toMgDL: 120, at: now.addingTimeInterval(-360))) + queue.enqueue(.stopSensor(at: now)) + + let (next, dropped) = queue.dequeue(now: now) + + XCTAssertEqual(dropped.count, 1) + guard case .stopSensor? = next else { + return XCTFail("expected stopSensor, got \(String(describing: next))") + } + XCTAssertTrue(queue.isEmpty) + } + + func testDequeueKeepsFreshCalibration() { + var queue = CommandQueue() + queue.enqueue(.calibrateSensor(toMgDL: 120, at: now.addingTimeInterval(-60))) + + let (next, dropped) = queue.dequeue(now: now) + + XCTAssertTrue(dropped.isEmpty) + guard case .calibrateSensor? = next else { + return XCTFail("expected calibration, got \(String(describing: next))") + } + } + + func testDequeueEmptyReturnsNil() { + var queue = CommandQueue() + let (next, dropped) = queue.dequeue(now: now) + XCTAssertNil(next) + XCTAssertTrue(dropped.isEmpty) + } + + func testRawValuesRoundTrip() { + var queue = CommandQueue() + queue.enqueue(.startSensor(at: now, sensorCode: SensorCode("5931") ?? .none)) + queue.enqueue(.calibrateSensor(toMgDL: 123.4, at: now)) + queue.enqueue(.resetTransmitter) + + let restored = CommandQueue(rawValues: queue.rawValues) + XCTAssertEqual(restored, queue) + } + + func testRawValuesDropMalformedEntries() { + let queue = CommandQueue(rawValues: [["action": 99], [:]]) + XCTAssertTrue(queue.isEmpty) + } +} From 7762e90c0782de6dbff57bf2b8581786da33c0b5 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Thu, 24 Sep 2026 14:21:01 +0200 Subject: [PATCH 04/13] fix(session): notification routing, sensorEnd on user stop, expiry guard, discovery timeout PeripheralManager.didUpdateValueFor: bind the condition's characteristic and compare with == instead of shadowing the parameter (any characteristic's update could satisfy a pending command's condition), and forward unclaimed notifications to the delegate even while a command is in flight (backfill frames were dropped mid-command). didComplete(.stopSensor): emit a .sensorEnd persisted event before clearing the session dates; the simulator drain path mirrors it. transmitterExpirationDate stays nil until the first version read: the fallback lifetime is a guess and a 180-day Anubis would alert as expired at day 90. Service discovery timeout 2s -> 10s. Battery re-arm reads the persisted state.lastBatteryReadDate instead of a transient ivar that was nil after every relaunch. UInt16(clamping:) for the persisted expiry-days Int fallback, matching G6CGMManagerState. --- G6SensorKit/G6CGMManager.swift | 31 +++++++++++++++---- G6SensorKit/G6CGMManagerState.swift | 7 +++++ G6SensorKit/Localizable.xcstrings | 4 +++ .../Model/TransmitterManagerState.swift | 2 +- .../Transport/PeripheralManager.swift | 14 ++++++--- 5 files changed, 46 insertions(+), 12 deletions(-) diff --git a/G6SensorKit/G6CGMManager.swift b/G6SensorKit/G6CGMManager.swift index b446c18..364c12d 100644 --- a/G6SensorKit/G6CGMManager.swift +++ b/G6SensorKit/G6CGMManager.swift @@ -71,8 +71,6 @@ public final class G6CGMManager: CGMManager { /// Commands queued for the next connection cycle. private let lockedCommandQueue: Locked = Locked(CommandQueue()) - private var lastBatteryReadDate: Date? - /// Response code from a session start awaiting confirmation. The reply /// alone does not say whether a session began, so it is held until the /// transmitter's state settles the question. @@ -332,6 +330,17 @@ public final class G6CGMManager: CGMManager { // command to state directly, mirroring didComplete on hardware, // so End Sensor / Start New Sensor work end-to-end there. lockedCommandQueue.mutate { _ = $0.dequeue() } + if case .stopSensor = command, state.sensorStartDate != nil { + let sensorEnded = PersistedCgmEvent( + date: Date(), + type: .sensorEnd, + deviceIdentifier: state.transmitterID, + failureMessage: LocalizedString("Stopped by user", comment: "Reason recorded when a session ends because the user stopped it") + ) + delegate.notify { delegate in + delegate?.cgmManager(self, hasNew: [sensorEnded]) + } + } mutateState { state in state.pendingCommands = self.lockedCommandQueue.value.rawValues switch command { @@ -545,9 +554,9 @@ public final class G6CGMManager: CGMManager { } } - if let last = lastBatteryReadDate, Date().timeIntervalSince(last) < Self.batteryReadInterval { - // Battery was read recently. - } else { + let batteryReadRecently = state.lastBatteryReadDate + .map { Date().timeIntervalSince($0) < Self.batteryReadInterval } ?? false + if !batteryReadRecently { session?.shouldReadBattery = true } @@ -647,7 +656,6 @@ extension G6CGMManager: TransmitterSessionDelegate { } public func transmitterSession(_ session: TransmitterSession, didReadBattery message: BatteryStatusRxMessage) { - lastBatteryReadDate = Date() log.default("Battery: A %d, B %d, resist %d", Int(message.voltageA), Int(message.voltageB), Int(message.resist)) mutateState { state in @@ -907,6 +915,17 @@ extension G6CGMManager: TransmitterCommandSource { state.lastSessionStartFailure = nil } case .stopSensor: + if state.sensorStartDate != nil { + let sensorEnded = PersistedCgmEvent( + date: Date(), + type: .sensorEnd, + deviceIdentifier: state.transmitterID, + failureMessage: LocalizedString("Stopped by user", comment: "Reason recorded when a session ends because the user stopped it") + ) + delegate.notify { delegate in + delegate?.cgmManager(self, hasNew: [sensorEnded]) + } + } mutateState { state in state.sensorStartDate = nil state.sensorCode = nil diff --git a/G6SensorKit/G6CGMManagerState.swift b/G6SensorKit/G6CGMManagerState.swift index 40b6039..09606d4 100644 --- a/G6SensorKit/G6CGMManagerState.swift +++ b/G6SensorKit/G6CGMManagerState.swift @@ -308,7 +308,14 @@ public struct G6CGMManagerState: RawRepresentable { return sensorStartDate?.addingTimeInterval(sensorLife) } + /// Unknown until the first version read: the fallback constants in + /// `transmitterLifetime` are guesses (a 180-day Anubis would alert as + /// "expired" against the stock 90 days), so no expiry is reported before + /// the transmitter's own value is in. public var transmitterExpirationDate: Date? { + guard transmitterExpiryInDays != nil else { + return nil + } return transmitterStartDate?.addingTimeInterval(transmitterLifetime) } diff --git a/G6SensorKit/Localizable.xcstrings b/G6SensorKit/Localizable.xcstrings index ff7977d..8d6f1b6 100644 --- a/G6SensorKit/Localizable.xcstrings +++ b/G6SensorKit/Localizable.xcstrings @@ -120,6 +120,10 @@ "mg/dL": { "extractionState": "manual", "comment": "The short unit display string for milligrams of glucose per deciliter" + }, + "Stopped by user": { + "extractionState": "manual", + "comment": "Reason recorded when a session ends because the user stopped it" } }, "version": "1.0" diff --git a/Sources/G6SensorCore/Model/TransmitterManagerState.swift b/Sources/G6SensorCore/Model/TransmitterManagerState.swift index 6511a7e..cd57195 100644 --- a/Sources/G6SensorCore/Model/TransmitterManagerState.swift +++ b/Sources/G6SensorCore/Model/TransmitterManagerState.swift @@ -69,7 +69,7 @@ public struct TransmitterManagerState: RawRepresentable, Equatable { let sensorStartOffset = rawValue["sensorStartOffset"] as? UInt32 let transmitterExpiryInDays = (rawValue["transmitterExpiryInDays"] as? UInt16) - ?? (rawValue["transmitterExpiryInDays"] as? Int).map { UInt16($0) } + ?? (rawValue["transmitterExpiryInDays"] as? Int).map { UInt16(clamping: $0) } let sensorLifeDays = rawValue["sensorLifeDays"] as? Int ?? Self.defaultSensorLifeDays diff --git a/Sources/G6SensorCore/Transport/PeripheralManager.swift b/Sources/G6SensorCore/Transport/PeripheralManager.swift index 8239e10..834298b 100644 --- a/Sources/G6SensorCore/Transport/PeripheralManager.swift +++ b/Sources/G6SensorCore/Transport/PeripheralManager.swift @@ -147,7 +147,7 @@ extension PeripheralManager { } } - private func applyConfiguration(discoveryTimeout: TimeInterval = 2) throws { + private func applyConfiguration(discoveryTimeout: TimeInterval = 10) throws { try discoverServices(configuration.serviceCharacteristics.keys.map { $0 }, timeout: discoveryTimeout) for service in peripheral.services ?? [] { @@ -400,11 +400,13 @@ extension PeripheralManager: CBPeripheralDelegate { var notifyDelegate = false if let index = commandConditions.firstIndex(where: { (condition) -> Bool in - if case .valueUpdate(characteristic: characteristic, matching: let matching) = condition { - return matching?(characteristic.value) ?? true - } else { + guard case .valueUpdate(characteristic: let conditionCharacteristic, matching: let matching) = condition, + conditionCharacteristic == characteristic + else { return false } + + return matching?(characteristic.value) ?? true }) { commandConditions.remove(at: index) commandError = error @@ -414,7 +416,9 @@ extension PeripheralManager: CBPeripheralDelegate { } } else if let macro = configuration.valueUpdateMacros[characteristic.uuid] { macro(self) - } else if commandConditions.isEmpty { + } else { + // Unclaimed by any condition or macro: pass it along to the + // delegate even while an unrelated command is still pending. notifyDelegate = true // execute after the unlock } From 10cfa657c35c57a9a23f46ad84d06075124865c9 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Thu, 24 Sep 2026 14:50:31 +0200 Subject: [PATCH 05/13] fix(glucose): match the official trend-arrow bucketing, classify transmitter model in core The old thresholds (..<(-3) style) put a boundary rate like exactly -3.0 mg/dL/min on the single-down arrow where the official apps and CGMBLEKit put it on the steeper one, and mapped implausible rates (|rate| > 8, reachable over the wire as Int8 tenths) to a triple arrow where the apps show none. The bucketing now lives in G6SensorCore as G6TrendArrow (LoopKit-free, raw values matching GlucoseTrend for a one-line bridge) so it is covered by swift test, and all three call sites (glucoseTrend(for:), G6GlucoseDisplay.trendType, settings trend symbol) share it. Also moves the transmitter-model prefix classification (8.. G6, 5../C.. ONE) into core as G6TransmitterModel with TransmitterID.model, so the mapping is unit-tested; deviceModel keeps returning the display string. --- G6SensorKit.xcodeproj/project.pbxproj | 732 +++++++++--------- .../xcschemes/G6SensorKit.xcscheme | 2 +- .../xcschemes/G6SensorKitPlugin.xcscheme | 2 +- .../xcschemes/G6SensorKitUI.xcscheme | 2 +- G6SensorKit/G6CGMManager.swift | 33 +- G6SensorKit/G6CGMManagerState.swift | 8 +- G6SensorKitUI/Views/G6SettingsView.swift | 16 +- .../Auth/G6TransmitterModel.swift | 27 + Sources/G6SensorCore/Auth/TransmitterID.swift | 5 + Sources/G6SensorCore/Model/G6TrendArrow.swift | 50 ++ .../G6SensorCoreTests/G6TrendArrowTests.swift | 53 ++ .../TransmitterIDTests.swift | 15 +- 12 files changed, 534 insertions(+), 411 deletions(-) create mode 100644 Sources/G6SensorCore/Auth/G6TransmitterModel.swift create mode 100644 Sources/G6SensorCore/Model/G6TrendArrow.swift create mode 100644 Tests/G6SensorCoreTests/G6TrendArrowTests.swift diff --git a/G6SensorKit.xcodeproj/project.pbxproj b/G6SensorKit.xcodeproj/project.pbxproj index 9a87e0e..7fbbf6a 100644 --- a/G6SensorKit.xcodeproj/project.pbxproj +++ b/G6SensorKit.xcodeproj/project.pbxproj @@ -7,82 +7,82 @@ objects = { /* Begin PBXBuildFile section */ - 032019A6EEC8573370EE4E4E /* G6SensorKitPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 737C6C35530CD8BB42B84DF0 /* G6SensorKitPlugin.swift */; }; - 03A90C3DAF1C15F423EBB537 /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D91984A1B779118EF08A4127 /* G6SensorKit.framework */; }; - 089143CB98FE2468E2B3D99A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6BF919306BACA2E97E323D4 /* Foundation.framework */; }; - 0B96FC48B098E283212D7434 /* G6ShareCredentialStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F673B89751D3C7E3998139B9 /* G6ShareCredentialStore.swift */; }; - 1443E4605DC4562A4C2A7BEC /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A76A719F98226D490448343A /* LoopKitUI.framework */; }; - 19DCE7B50E1D4DB6785C0764 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6BF919306BACA2E97E323D4 /* Foundation.framework */; }; - 1EFFB6CA1A4DD2702593640A /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B414B1B8987E102920EBB8 /* HKUnit.swift */; }; - 1F0E56CFDD57BC9269932E00 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 907230D65E10C39D822408AD /* LocalizedString.swift */; }; - 256CCEB29BA96551FCEC4B4A /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 17A6D5E4FD73994C5B1F06F5 /* Localizable.xcstrings */; }; - 325836DA81824456AC495CFF /* G6Graphics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47E75012965DC1C6990A2500 /* G6Graphics.swift */; }; - 3383256660F7228702BAA719 /* G6CGMManagerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CB151CF01D474F2595EF5CA /* G6CGMManagerState.swift */; }; - 38145114C2273AD696A3D633 /* G6AlertEvaluator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C23F573526681B9A23C06AB /* G6AlertEvaluator.swift */; }; - 38402F888769F9D025B8CE04 /* G6ApplySensorViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0DABEF600E765FA27D449C7 /* G6ApplySensorViews.swift */; }; - 388CA00B3F572757ADD0A58D /* G6OnboardingViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92908880134DF0809C232DA8 /* G6OnboardingViews.swift */; }; - 3A9FBCDBD2078C788E4D6A61 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 7F5C107F2A9FBB346DAC8840 /* Localizable.xcstrings */; }; - 3DAE7BECBFE06CFB97DDD196 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD562B4C4652CF07A6B07073 /* LocalizedString.swift */; }; - 3E90A28BA6A527167A190026 /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D91984A1B779118EF08A4127 /* G6SensorKit.framework */; }; - 428978D53D25A29DAAED79BB /* G6ActivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15B0EA77B0F64BDC3B3EEEC6 /* G6ActivityViewController.swift */; }; - 430C49804080723BD78C8DBA /* G6SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1009E258B325CFF8CFB4E87A /* G6SettingsView.swift */; }; - 43274E4597B3482D10EECF54 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 90F75E1970D7A80176F9FB9F /* LoopKit.framework */; }; - 504856D070F911796810BCC9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6BF919306BACA2E97E323D4 /* Foundation.framework */; }; - 5DB32B111CC9558D9D17F1DD /* OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02E433F3990FF78C38DC6551 /* OSLog.swift */; }; - 5E74E403BEF0BB27F23087A0 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 90F75E1970D7A80176F9FB9F /* LoopKit.framework */; }; - 6C3243405AE5D59AEF654CB7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A559C2D3AD9EBB43248B2199 /* Assets.xcassets */; }; - 829F7AA37876027EACE3A83C /* G6SensorKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 606033721DAAF7F6793184DB /* G6SensorKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 92984720FAB46BCCAB93C2F4 /* G6CalibrationGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F285089CA85DF822BC3527 /* G6CalibrationGuideView.swift */; }; - 94284FD983F0E91AE79A91B6 /* G6PackageScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 704C5C6E0A049E4425DCDC45 /* G6PackageScannerView.swift */; }; - 96FE9CAA2BA79D899055E8B0 /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8541E3B5A43131113BCA24C3 /* TimeInterval.swift */; }; - A9A6EA0AADF90B3D2BC174BE /* G6CGMManager+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = F317421564304E728293A980 /* G6CGMManager+UI.swift */; }; - AE16E074483DAC2574FA59C5 /* G6SensorKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 606033721DAAF7F6793184DB /* G6SensorKitUI.framework */; }; - BF338B66F1042236F4DBAAA0 /* G6Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B21A00EB9363194AD4E3DC4 /* G6Alert.swift */; }; - C1105244C23AE85D192C3C0D /* G6SensorKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D91984A1B779118EF08A4127 /* G6SensorKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - CF28F3F0F438EE53CD7CCEFE /* G6UICoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D0041A85C2E5CE22F9FB07 /* G6UICoordinator.swift */; }; - D389B8A224241FF1DC55A0B5 /* G6SimulatedSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1EFCFD2903EB844B045366 /* G6SimulatedSession.swift */; }; - D3B56173754CE3AA5CB8CEA6 /* G6CGMManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9097D3ECD4FB9E24FB170C75 /* G6CGMManager.swift */; }; - D5272301CD6F360B8E8F2D54 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A76A719F98226D490448343A /* LoopKitUI.framework */; }; - D5456F7B45319478DB67D043 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 90F75E1970D7A80176F9FB9F /* LoopKit.framework */; }; - D57D16D172751A2E34BCBE2D /* G6DetailViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = A236522437951B0C651E1483 /* G6DetailViews.swift */; }; - E2EF5851A11BCE61A474C191 /* Locked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 182061E2189A3DB8D5EC94F2 /* Locked.swift */; }; - EFC856B31EB45F398EF25CA6 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A7BA7FD280EA993E40E1D9A /* HKUnit.swift */; }; - F38D4C7E56F03FD1B2E7F924 /* G6ReadingDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B4FA59134AF1F66A4E60292 /* G6ReadingDetailView.swift */; }; + 068F65E11AF1419388CBD953 /* G6SensorKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D531F0A53057A0235E7C192 /* G6SensorKitUI.framework */; }; + 14589281DC7760165D5590E3 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B0799EB2EDF3A7864F7C5C2 /* LoopKit.framework */; }; + 1BFC8B0012423024BCEE84C4 /* Locked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3695593AE5C331A21B37C828 /* Locked.swift */; }; + 226AE1C008E3432034691E58 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DAF739DBBA35C93627B2A12C /* Assets.xcassets */; }; + 25B13BDAFD609EC61E01ED42 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54CADE8EBD6A8DBD34E5F08E /* LocalizedString.swift */; }; + 2921FB176CBA1E3FACF8C998 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 8C69491E1F3F7F01BACF348A /* Localizable.xcstrings */; }; + 2A9D142A81AE191360B058B0 /* G6Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAFC51720925E26FFF9526D8 /* G6Alert.swift */; }; + 2C77CCC0A4FC873D451B1D9C /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 2803D463F94F749B9B4C4480 /* Localizable.xcstrings */; }; + 2E9270FAE984E3B653790956 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B0799EB2EDF3A7864F7C5C2 /* LoopKit.framework */; }; + 332BA57D80F0D8A629C0881A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F95502372EC14A32117B5F92 /* Foundation.framework */; }; + 3342E51E140EB78C3406DCFC /* G6SensorKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8B421AE8197339D306979939 /* G6SensorKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 39603B3649182CA37CE8237A /* G6CGMManager+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C2C05844010D28B27D4E02D /* G6CGMManager+UI.swift */; }; + 3A518597A56D377383B5D384 /* G6CGMManagerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 650CB121B3A64293DDF66491 /* G6CGMManagerState.swift */; }; + 3A7D53148400D95D5EBE9B20 /* G6Graphics.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC82866E887A9C466610864B /* G6Graphics.swift */; }; + 3B2B08D9C8ACC49731771581 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B0799EB2EDF3A7864F7C5C2 /* LoopKit.framework */; }; + 3D85A309CDAA70C948DB7D06 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = C199CCC759EB31B7459FAF02 /* HKUnit.swift */; }; + 405A216F8D1752F1421D4887 /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4847E689C846CC527559717B /* LocalizedString.swift */; }; + 4159FE6F9D1C67AA7D355705 /* G6SimulatedSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFB4FF079E0E059B0A2514C4 /* G6SimulatedSession.swift */; }; + 51AA80EED323BB1051CCF352 /* G6SensorKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9D531F0A53057A0235E7C192 /* G6SensorKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 5623B9849DDAC97251E7B413 /* G6CGMManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AB56C95B7CD81513D98B212 /* G6CGMManager.swift */; }; + 6C6A5725B781F8EC0283A2E3 /* G6ActivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A6B1AD620BB43E52CA138 /* G6ActivityViewController.swift */; }; + 77CD64A55933B10835781892 /* G6UICoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60451EC9CB88AAED72C7B4C0 /* G6UICoordinator.swift */; }; + 7A17394DCB757B79A35A9401 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93F66577CA895DC0539B94DB /* LoopKitUI.framework */; }; + 7B236774AE21607067257858 /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B421AE8197339D306979939 /* G6SensorKit.framework */; }; + 81CC3E50E4370774F5954A78 /* G6SensorKitPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = A15C3F478B37D28F487EA970 /* G6SensorKitPlugin.swift */; }; + 83FDE18A177B5C10B0504485 /* G6ShareCredentialStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9DBE6B77523AE6CF47FE179 /* G6ShareCredentialStore.swift */; }; + 84E98310287C4DAF8D376F5C /* G6SensorKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B421AE8197339D306979939 /* G6SensorKit.framework */; }; + 8587D2CC46C9C9CB94B2D3FA /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = E067B8007DAFB29BE2F03F48 /* HKUnit.swift */; }; + 85D8C77F66A1FF1AF57A8F17 /* G6ApplySensorViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D5C11477C372E423D1838A5 /* G6ApplySensorViews.swift */; }; + 9068DC2E9303B2620EC57AF2 /* G6AlertEvaluator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BFF9D322E96EE881F0910FD /* G6AlertEvaluator.swift */; }; + 9068DD5A9EB5430807D21AE5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F95502372EC14A32117B5F92 /* Foundation.framework */; }; + 934EFF804E6452CD19F40C04 /* G6CalibrationGuideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14F99764DE6442A33728920B /* G6CalibrationGuideView.swift */; }; + 9D23800E9E278C62602AAF06 /* G6SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB76778EA2C3FE465AE8FC8F /* G6SettingsView.swift */; }; + ABC18A66F55CAC750FAAA781 /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ED9872057F9AB73CCE989CF /* TimeInterval.swift */; }; + CF81E72F011FD1971AA15AA2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F95502372EC14A32117B5F92 /* Foundation.framework */; }; + D48D98C13312034AB8C11BA8 /* G6DetailViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABB63314B843491AD67FAFB8 /* G6DetailViews.swift */; }; + DA3B54D9184C892B5F9A7B96 /* G6OnboardingViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BCCCBFAEC5AC32DCB17C0E0 /* G6OnboardingViews.swift */; }; + E5928066DDD984FCE765E888 /* G6PackageScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F8E7A171900BF409A482908 /* G6PackageScannerView.swift */; }; + EE9148D1635A031059CB0474 /* OSLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B2202DFC274BBEC075ADF5E /* OSLog.swift */; }; + F3BF96B43DC44EAB997C9556 /* G6ReadingDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9773F6BB69F46104A715B09 /* G6ReadingDetailView.swift */; }; + F5B695198564172CA054D830 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93F66577CA895DC0539B94DB /* LoopKitUI.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 1BBFE840668BC082C5C18328 /* PBXContainerItemProxy */ = { + 1CA7CA75216CC94C77001C8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = E00046664E8B19B1D108CD7E /* Project object */; + containerPortal = 05E8929C0E445F2264A8A045 /* Project object */; proxyType = 1; - remoteGlobalIDString = 1FC930737F45A671AE16478F; - remoteInfo = G6SensorKit; + remoteGlobalIDString = 8F3461A960A54D2320B21FE4; + remoteInfo = G6SensorKitUI; }; - 23DF82B0A16EFF5164752461 /* PBXContainerItemProxy */ = { + 8C5FBFBE5966E33ED892663C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = E00046664E8B19B1D108CD7E /* Project object */; + containerPortal = 05E8929C0E445F2264A8A045 /* Project object */; proxyType = 1; - remoteGlobalIDString = 5FDFF54B3F109CF9EB807CE7; - remoteInfo = G6SensorKitUI; + remoteGlobalIDString = 215CD1147465A2E980A94D63; + remoteInfo = G6SensorKit; }; - E0A5C942CCB714A7E897F6AA /* PBXContainerItemProxy */ = { + AB91E4CF703C2153542F72B0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = E00046664E8B19B1D108CD7E /* Project object */; + containerPortal = 05E8929C0E445F2264A8A045 /* Project object */; proxyType = 1; - remoteGlobalIDString = 1FC930737F45A671AE16478F; + remoteGlobalIDString = 215CD1147465A2E980A94D63; remoteInfo = G6SensorKit; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - EC6909781D72EEC70B1A43CA /* Embed Frameworks */ = { + D0449C47C05DB7A8F1FC65C4 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - C1105244C23AE85D192C3C0D /* G6SensorKit.framework in Embed Frameworks */, - 829F7AA37876027EACE3A83C /* G6SensorKitUI.framework in Embed Frameworks */, + 3342E51E140EB78C3406DCFC /* G6SensorKit.framework in Embed Frameworks */, + 51AA80EED323BB1051CCF352 /* G6SensorKitUI.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -90,196 +90,196 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 02E433F3990FF78C38DC6551 /* OSLog.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OSLog.swift; sourceTree = ""; }; - 1009E258B325CFF8CFB4E87A /* G6SettingsView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6SettingsView.swift; path = Views/G6SettingsView.swift; sourceTree = ""; }; - 15B0EA77B0F64BDC3B3EEEC6 /* G6ActivityViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ActivityViewController.swift; path = Views/G6ActivityViewController.swift; sourceTree = ""; }; - 17A6D5E4FD73994C5B1F06F5 /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; - 182061E2189A3DB8D5EC94F2 /* Locked.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Locked.swift; sourceTree = ""; }; - 18B414B1B8987E102920EBB8 /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; - 2B21A00EB9363194AD4E3DC4 /* G6Alert.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6Alert.swift; sourceTree = ""; }; - 47E75012965DC1C6990A2500 /* G6Graphics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6Graphics.swift; path = Views/G6Graphics.swift; sourceTree = ""; }; - 51F285089CA85DF822BC3527 /* G6CalibrationGuideView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6CalibrationGuideView.swift; path = Views/G6CalibrationGuideView.swift; sourceTree = ""; }; - 5B4FA59134AF1F66A4E60292 /* G6ReadingDetailView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ReadingDetailView.swift; path = Views/G6ReadingDetailView.swift; sourceTree = ""; }; - 606033721DAAF7F6793184DB /* G6SensorKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 704C5C6E0A049E4425DCDC45 /* G6PackageScannerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6PackageScannerView.swift; path = Views/G6PackageScannerView.swift; sourceTree = ""; }; - 737C6C35530CD8BB42B84DF0 /* G6SensorKitPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SensorKitPlugin.swift; sourceTree = ""; }; - 7B1EFCFD2903EB844B045366 /* G6SimulatedSession.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SimulatedSession.swift; sourceTree = ""; }; - 7C23F573526681B9A23C06AB /* G6AlertEvaluator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6AlertEvaluator.swift; sourceTree = ""; }; - 7F5C107F2A9FBB346DAC8840 /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; - 8541E3B5A43131113BCA24C3 /* TimeInterval.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TimeInterval.swift; sourceTree = ""; }; - 8A7BA7FD280EA993E40E1D9A /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; - 8CB151CF01D474F2595EF5CA /* G6CGMManagerState.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManagerState.swift; sourceTree = ""; }; - 907230D65E10C39D822408AD /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; - 9097D3ECD4FB9E24FB170C75 /* G6CGMManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManager.swift; sourceTree = ""; }; - 90F75E1970D7A80176F9FB9F /* LoopKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 92908880134DF0809C232DA8 /* G6OnboardingViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6OnboardingViews.swift; path = Views/G6OnboardingViews.swift; sourceTree = ""; }; - A236522437951B0C651E1483 /* G6DetailViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6DetailViews.swift; path = Views/G6DetailViews.swift; sourceTree = ""; }; - A559C2D3AD9EBB43248B2199 /* Assets.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - A76A719F98226D490448343A /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - A7D0041A85C2E5CE22F9FB07 /* G6UICoordinator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6UICoordinator.swift; sourceTree = ""; }; - CD562B4C4652CF07A6B07073 /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; - D91984A1B779118EF08A4127 /* G6SensorKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E6BF919306BACA2E97E323D4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS26.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - F0DABEF600E765FA27D449C7 /* G6ApplySensorViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ApplySensorViews.swift; path = Views/G6ApplySensorViews.swift; sourceTree = ""; }; - F317421564304E728293A980 /* G6CGMManager+UI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "G6CGMManager+UI.swift"; sourceTree = ""; }; - F673B89751D3C7E3998139B9 /* G6ShareCredentialStore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6ShareCredentialStore.swift; sourceTree = ""; }; - F9D12B501A84ED6C12CFFF6A /* G6SensorKitPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 14F99764DE6442A33728920B /* G6CalibrationGuideView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6CalibrationGuideView.swift; path = Views/G6CalibrationGuideView.swift; sourceTree = ""; }; + 1B0799EB2EDF3A7864F7C5C2 /* LoopKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2803D463F94F749B9B4C4480 /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; + 2AB56C95B7CD81513D98B212 /* G6CGMManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManager.swift; sourceTree = ""; }; + 3695593AE5C331A21B37C828 /* Locked.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Locked.swift; sourceTree = ""; }; + 3B2202DFC274BBEC075ADF5E /* OSLog.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OSLog.swift; sourceTree = ""; }; + 3C2C05844010D28B27D4E02D /* G6CGMManager+UI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "G6CGMManager+UI.swift"; sourceTree = ""; }; + 4847E689C846CC527559717B /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; + 54CADE8EBD6A8DBD34E5F08E /* LocalizedString.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; + 5BFF9D322E96EE881F0910FD /* G6AlertEvaluator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6AlertEvaluator.swift; sourceTree = ""; }; + 60451EC9CB88AAED72C7B4C0 /* G6UICoordinator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6UICoordinator.swift; sourceTree = ""; }; + 650CB121B3A64293DDF66491 /* G6CGMManagerState.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6CGMManagerState.swift; sourceTree = ""; }; + 6BCCCBFAEC5AC32DCB17C0E0 /* G6OnboardingViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6OnboardingViews.swift; path = Views/G6OnboardingViews.swift; sourceTree = ""; }; + 6D5C11477C372E423D1838A5 /* G6ApplySensorViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ApplySensorViews.swift; path = Views/G6ApplySensorViews.swift; sourceTree = ""; }; + 6ED9872057F9AB73CCE989CF /* TimeInterval.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TimeInterval.swift; sourceTree = ""; }; + 7F8E7A171900BF409A482908 /* G6PackageScannerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6PackageScannerView.swift; path = Views/G6PackageScannerView.swift; sourceTree = ""; }; + 8B421AE8197339D306979939 /* G6SensorKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8C69491E1F3F7F01BACF348A /* Localizable.xcstrings */ = {isa = PBXFileReference; includeInIndex = 1; path = Localizable.xcstrings; sourceTree = ""; }; + 93F66577CA895DC0539B94DB /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9D531F0A53057A0235E7C192 /* G6SensorKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A15C3F478B37D28F487EA970 /* G6SensorKitPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SensorKitPlugin.swift; sourceTree = ""; }; + A1A4A5B6A02A6007C52230EE /* G6SensorKitPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = G6SensorKitPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + AAFC51720925E26FFF9526D8 /* G6Alert.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6Alert.swift; sourceTree = ""; }; + ABB63314B843491AD67FAFB8 /* G6DetailViews.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6DetailViews.swift; path = Views/G6DetailViews.swift; sourceTree = ""; }; + AFB4FF079E0E059B0A2514C4 /* G6SimulatedSession.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6SimulatedSession.swift; sourceTree = ""; }; + B9DBE6B77523AE6CF47FE179 /* G6ShareCredentialStore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = G6ShareCredentialStore.swift; sourceTree = ""; }; + BC82866E887A9C466610864B /* G6Graphics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6Graphics.swift; path = Views/G6Graphics.swift; sourceTree = ""; }; + C199CCC759EB31B7459FAF02 /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; + D20A6B1AD620BB43E52CA138 /* G6ActivityViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ActivityViewController.swift; path = Views/G6ActivityViewController.swift; sourceTree = ""; }; + DAF739DBBA35C93627B2A12C /* Assets.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + DB76778EA2C3FE465AE8FC8F /* G6SettingsView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6SettingsView.swift; path = Views/G6SettingsView.swift; sourceTree = ""; }; + E067B8007DAFB29BE2F03F48 /* HKUnit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; + E9773F6BB69F46104A715B09 /* G6ReadingDetailView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = G6ReadingDetailView.swift; path = Views/G6ReadingDetailView.swift; sourceTree = ""; }; + F95502372EC14A32117B5F92 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS26.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 036BF4C74764238F023DA0E8 /* Frameworks */ = { + 29459DDF79C2F6E84E026198 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 089143CB98FE2468E2B3D99A /* Foundation.framework in Frameworks */, - D5456F7B45319478DB67D043 /* LoopKit.framework in Frameworks */, - 1443E4605DC4562A4C2A7BEC /* LoopKitUI.framework in Frameworks */, - 3E90A28BA6A527167A190026 /* G6SensorKit.framework in Frameworks */, - AE16E074483DAC2574FA59C5 /* G6SensorKitUI.framework in Frameworks */, + 332BA57D80F0D8A629C0881A /* Foundation.framework in Frameworks */, + 3B2B08D9C8ACC49731771581 /* LoopKit.framework in Frameworks */, + F5B695198564172CA054D830 /* LoopKitUI.framework in Frameworks */, + 84E98310287C4DAF8D376F5C /* G6SensorKit.framework in Frameworks */, + 068F65E11AF1419388CBD953 /* G6SensorKitUI.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 3C582B67957BD8AC20A789A7 /* Frameworks */ = { + 7892D299DD1C4456611A5D26 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 504856D070F911796810BCC9 /* Foundation.framework in Frameworks */, - 5E74E403BEF0BB27F23087A0 /* LoopKit.framework in Frameworks */, + CF81E72F011FD1971AA15AA2 /* Foundation.framework in Frameworks */, + 2E9270FAE984E3B653790956 /* LoopKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 95916C8AF6C891370D4B46A3 /* Frameworks */ = { + CC4E9DF835B45B2D2994E5A0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 19DCE7B50E1D4DB6785C0764 /* Foundation.framework in Frameworks */, - 43274E4597B3482D10EECF54 /* LoopKit.framework in Frameworks */, - D5272301CD6F360B8E8F2D54 /* LoopKitUI.framework in Frameworks */, - 03A90C3DAF1C15F423EBB537 /* G6SensorKit.framework in Frameworks */, + 9068DD5A9EB5430807D21AE5 /* Foundation.framework in Frameworks */, + 14589281DC7760165D5590E3 /* LoopKit.framework in Frameworks */, + 7A17394DCB757B79A35A9401 /* LoopKitUI.framework in Frameworks */, + 7B236774AE21607067257858 /* G6SensorKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 19A5E64B61E7B02E7A128E2A = { + 35E638A87A48A6CBC246BF6B /* Products */ = { isa = PBXGroup; children = ( - 7E3A0A5E82CBF0BEB5AC2BC6 /* G6SensorKit */, - 7EF5BB2F037C379D46B3D521 /* Common */, - 65A7A5C24641BA7AF03178DB /* G6SensorKitUI */, - 1E84BEF7FF7C5428825C9733 /* G6SensorKitPlugin */, - CB6896C5F55260956ACC3EAF /* Products */, - A6BF578ECCAF8B60CE3BB16F /* Frameworks */, + 8B421AE8197339D306979939 /* G6SensorKit.framework */, + 9D531F0A53057A0235E7C192 /* G6SensorKitUI.framework */, + A1A4A5B6A02A6007C52230EE /* G6SensorKitPlugin.framework */, ); + name = Products; sourceTree = ""; }; - 1E84BEF7FF7C5428825C9733 /* G6SensorKitPlugin */ = { + 7CAD88E09B3DB8C98B60678D /* iOS */ = { isa = PBXGroup; children = ( - 737C6C35530CD8BB42B84DF0 /* G6SensorKitPlugin.swift */, + F95502372EC14A32117B5F92 /* Foundation.framework */, ); - name = G6SensorKitPlugin; - path = G6SensorKitPlugin; + name = iOS; sourceTree = ""; }; - 65A7A5C24641BA7AF03178DB /* G6SensorKitUI */ = { + 82F360FB55C90EC211EF8CA1 /* Common */ = { isa = PBXGroup; children = ( - F317421564304E728293A980 /* G6CGMManager+UI.swift */, - A7D0041A85C2E5CE22F9FB07 /* G6UICoordinator.swift */, - 907230D65E10C39D822408AD /* LocalizedString.swift */, - 15B0EA77B0F64BDC3B3EEEC6 /* G6ActivityViewController.swift */, - F0DABEF600E765FA27D449C7 /* G6ApplySensorViews.swift */, - 51F285089CA85DF822BC3527 /* G6CalibrationGuideView.swift */, - A236522437951B0C651E1483 /* G6DetailViews.swift */, - 47E75012965DC1C6990A2500 /* G6Graphics.swift */, - 92908880134DF0809C232DA8 /* G6OnboardingViews.swift */, - 704C5C6E0A049E4425DCDC45 /* G6PackageScannerView.swift */, - 5B4FA59134AF1F66A4E60292 /* G6ReadingDetailView.swift */, - 1009E258B325CFF8CFB4E87A /* G6SettingsView.swift */, - 7F5C107F2A9FBB346DAC8840 /* Localizable.xcstrings */, - A559C2D3AD9EBB43248B2199 /* Assets.xcassets */, + C199CCC759EB31B7459FAF02 /* HKUnit.swift */, + 54CADE8EBD6A8DBD34E5F08E /* LocalizedString.swift */, + 3695593AE5C331A21B37C828 /* Locked.swift */, + 3B2202DFC274BBEC075ADF5E /* OSLog.swift */, + 6ED9872057F9AB73CCE989CF /* TimeInterval.swift */, + E067B8007DAFB29BE2F03F48 /* HKUnit.swift */, ); - name = G6SensorKitUI; - path = G6SensorKitUI; + name = Common; + path = Common; sourceTree = ""; }; - 7E3A0A5E82CBF0BEB5AC2BC6 /* G6SensorKit */ = { + B59CE774003B80A203AAC25E /* G6SensorKitUI */ = { isa = PBXGroup; children = ( - 2B21A00EB9363194AD4E3DC4 /* G6Alert.swift */, - 7C23F573526681B9A23C06AB /* G6AlertEvaluator.swift */, - 9097D3ECD4FB9E24FB170C75 /* G6CGMManager.swift */, - 8CB151CF01D474F2595EF5CA /* G6CGMManagerState.swift */, - F673B89751D3C7E3998139B9 /* G6ShareCredentialStore.swift */, - 7B1EFCFD2903EB844B045366 /* G6SimulatedSession.swift */, - 17A6D5E4FD73994C5B1F06F5 /* Localizable.xcstrings */, + 3C2C05844010D28B27D4E02D /* G6CGMManager+UI.swift */, + 60451EC9CB88AAED72C7B4C0 /* G6UICoordinator.swift */, + 4847E689C846CC527559717B /* LocalizedString.swift */, + D20A6B1AD620BB43E52CA138 /* G6ActivityViewController.swift */, + 6D5C11477C372E423D1838A5 /* G6ApplySensorViews.swift */, + 14F99764DE6442A33728920B /* G6CalibrationGuideView.swift */, + ABB63314B843491AD67FAFB8 /* G6DetailViews.swift */, + BC82866E887A9C466610864B /* G6Graphics.swift */, + 6BCCCBFAEC5AC32DCB17C0E0 /* G6OnboardingViews.swift */, + 7F8E7A171900BF409A482908 /* G6PackageScannerView.swift */, + E9773F6BB69F46104A715B09 /* G6ReadingDetailView.swift */, + DB76778EA2C3FE465AE8FC8F /* G6SettingsView.swift */, + 8C69491E1F3F7F01BACF348A /* Localizable.xcstrings */, + DAF739DBBA35C93627B2A12C /* Assets.xcassets */, ); - name = G6SensorKit; - path = G6SensorKit; + name = G6SensorKitUI; + path = G6SensorKitUI; sourceTree = ""; }; - 7EF5BB2F037C379D46B3D521 /* Common */ = { + BF936AEBB1ADE9BD907B2665 /* G6SensorKit */ = { isa = PBXGroup; children = ( - 18B414B1B8987E102920EBB8 /* HKUnit.swift */, - CD562B4C4652CF07A6B07073 /* LocalizedString.swift */, - 182061E2189A3DB8D5EC94F2 /* Locked.swift */, - 02E433F3990FF78C38DC6551 /* OSLog.swift */, - 8541E3B5A43131113BCA24C3 /* TimeInterval.swift */, - 8A7BA7FD280EA993E40E1D9A /* HKUnit.swift */, + AAFC51720925E26FFF9526D8 /* G6Alert.swift */, + 5BFF9D322E96EE881F0910FD /* G6AlertEvaluator.swift */, + 2AB56C95B7CD81513D98B212 /* G6CGMManager.swift */, + 650CB121B3A64293DDF66491 /* G6CGMManagerState.swift */, + B9DBE6B77523AE6CF47FE179 /* G6ShareCredentialStore.swift */, + AFB4FF079E0E059B0A2514C4 /* G6SimulatedSession.swift */, + 2803D463F94F749B9B4C4480 /* Localizable.xcstrings */, ); - name = Common; - path = Common; + name = G6SensorKit; + path = G6SensorKit; sourceTree = ""; }; - A6BF578ECCAF8B60CE3BB16F /* Frameworks */ = { + C8A84B9B66E84F3EA74CEF1D /* Frameworks */ = { isa = PBXGroup; children = ( - 90F75E1970D7A80176F9FB9F /* LoopKit.framework */, - A76A719F98226D490448343A /* LoopKitUI.framework */, - DF2BE94BD2F3F23A12B6F7C4 /* iOS */, + 1B0799EB2EDF3A7864F7C5C2 /* LoopKit.framework */, + 93F66577CA895DC0539B94DB /* LoopKitUI.framework */, + 7CAD88E09B3DB8C98B60678D /* iOS */, ); name = Frameworks; sourceTree = ""; }; - CB6896C5F55260956ACC3EAF /* Products */ = { + CC1502118BD5CBA5F06AC98B /* G6SensorKitPlugin */ = { isa = PBXGroup; children = ( - D91984A1B779118EF08A4127 /* G6SensorKit.framework */, - 606033721DAAF7F6793184DB /* G6SensorKitUI.framework */, - F9D12B501A84ED6C12CFFF6A /* G6SensorKitPlugin.framework */, + A15C3F478B37D28F487EA970 /* G6SensorKitPlugin.swift */, ); - name = Products; + name = G6SensorKitPlugin; + path = G6SensorKitPlugin; sourceTree = ""; }; - DF2BE94BD2F3F23A12B6F7C4 /* iOS */ = { + D96C91ED9D8FC6BFCEDD36AC = { isa = PBXGroup; children = ( - E6BF919306BACA2E97E323D4 /* Foundation.framework */, + BF936AEBB1ADE9BD907B2665 /* G6SensorKit */, + 82F360FB55C90EC211EF8CA1 /* Common */, + B59CE774003B80A203AAC25E /* G6SensorKitUI */, + CC1502118BD5CBA5F06AC98B /* G6SensorKitPlugin */, + 35E638A87A48A6CBC246BF6B /* Products */, + C8A84B9B66E84F3EA74CEF1D /* Frameworks */, ); - name = iOS; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 60A6AA3FCCB11141F8B8C24E /* Headers */ = { + 07EAC52738A519CDC1D4C8D4 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - A7501DCDA29A942C68578914 /* Headers */ = { + 7ADBA84EA66B2BBAFD4A6288 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - B35B2AD03E597E11E2A0B16A /* Headers */ = { + FF4AC7DA0EA20F2B20BE3902 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( @@ -289,14 +289,14 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 1FC930737F45A671AE16478F /* G6SensorKit */ = { + 215CD1147465A2E980A94D63 /* G6SensorKit */ = { isa = PBXNativeTarget; - buildConfigurationList = E6BECE0CEC895BB0D3C1EA93 /* Build configuration list for PBXNativeTarget "G6SensorKit" */; + buildConfigurationList = DD280BDB51D34244226439F4 /* Build configuration list for PBXNativeTarget "G6SensorKit" */; buildPhases = ( - 60A6AA3FCCB11141F8B8C24E /* Headers */, - 444C5BA0EDD6B24D16C899CF /* Sources */, - 3C582B67957BD8AC20A789A7 /* Frameworks */, - A720A1114AADAE11791259CE /* Resources */, + 7ADBA84EA66B2BBAFD4A6288 /* Headers */, + CF5459A40A7FD204384A3827 /* Sources */, + 7892D299DD1C4456611A5D26 /* Frameworks */, + BBB2CD01CD25C8772A7D6484 /* Resources */, ); buildRules = ( ); @@ -304,62 +304,62 @@ ); name = G6SensorKit; packageProductDependencies = ( - 99E200D18B601AFB565F1B5B /* G6SensorCore */, + 0EC90A7F507FA56DA0FAAC1D /* G6SensorCore */, ); productName = G6SensorKit; - productReference = D91984A1B779118EF08A4127 /* G6SensorKit.framework */; + productReference = 8B421AE8197339D306979939 /* G6SensorKit.framework */; productType = "com.apple.product-type.framework"; }; - 5FDFF54B3F109CF9EB807CE7 /* G6SensorKitUI */ = { + 8F3461A960A54D2320B21FE4 /* G6SensorKitUI */ = { isa = PBXNativeTarget; - buildConfigurationList = CD0E963482CD3D2B5682140B /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */; + buildConfigurationList = 072C8C59C81653E06FA00EB4 /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */; buildPhases = ( - A7501DCDA29A942C68578914 /* Headers */, - 8417137A0C4F1F7F25185E61 /* Sources */, - 95916C8AF6C891370D4B46A3 /* Frameworks */, - A456440235B07EA3B55C3C44 /* Resources */, + 07EAC52738A519CDC1D4C8D4 /* Headers */, + 30F8F65AC6C7D52F848495B9 /* Sources */, + CC4E9DF835B45B2D2994E5A0 /* Frameworks */, + 6D20D7C6745342F8C65404B0 /* Resources */, ); buildRules = ( ); dependencies = ( - 43D4F281FBAD16F8FCAE2F77 /* PBXTargetDependency */, + 2B67866B45ABC4CCDF08A03B /* PBXTargetDependency */, ); name = G6SensorKitUI; productName = G6SensorKitUI; - productReference = 606033721DAAF7F6793184DB /* G6SensorKitUI.framework */; + productReference = 9D531F0A53057A0235E7C192 /* G6SensorKitUI.framework */; productType = "com.apple.product-type.framework"; }; - D59705DF2CF01716CBDBCA1E /* G6SensorKitPlugin */ = { + D09D95523AA824744122C1CB /* G6SensorKitPlugin */ = { isa = PBXNativeTarget; - buildConfigurationList = 92650F7E6B063572AC79D169 /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */; + buildConfigurationList = FCDA3AF29E0740002157A96C /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */; buildPhases = ( - B35B2AD03E597E11E2A0B16A /* Headers */, - E14BEE3FDC217ED133742420 /* Sources */, - 036BF4C74764238F023DA0E8 /* Frameworks */, - 1384F63BC3916A99F4309AD9 /* Resources */, - EC6909781D72EEC70B1A43CA /* Embed Frameworks */, + FF4AC7DA0EA20F2B20BE3902 /* Headers */, + D91BC325094ACAC7D108B6A0 /* Sources */, + 29459DDF79C2F6E84E026198 /* Frameworks */, + BE615E0FBD1840B4E6C34D02 /* Resources */, + D0449C47C05DB7A8F1FC65C4 /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( - 15B834AB9E65E9AFA58F1744 /* PBXTargetDependency */, - 7A4F1CA8724DC60FA58D2552 /* PBXTargetDependency */, + 627FBE52365C3C03931C7886 /* PBXTargetDependency */, + F6FFF5B09BC08B51699968C7 /* PBXTargetDependency */, ); name = G6SensorKitPlugin; productName = G6SensorKitPlugin; - productReference = F9D12B501A84ED6C12CFFF6A /* G6SensorKitPlugin.framework */; + productReference = A1A4A5B6A02A6007C52230EE /* G6SensorKitPlugin.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - E00046664E8B19B1D108CD7E /* Project object */ = { + 05E8929C0E445F2264A8A045 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1600; LastUpgradeCheck = 1600; }; - buildConfigurationList = 1CB4E131373959E0BC530F1F /* Build configuration list for PBXProject "G6SensorKit" */; + buildConfigurationList = 8B609048B49027655DD83E61 /* Build configuration list for PBXProject "G6SensorKit" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = en; hasScannedForEncodings = 0; @@ -367,122 +367,122 @@ en, Base, ); - mainGroup = 19A5E64B61E7B02E7A128E2A; + mainGroup = D96C91ED9D8FC6BFCEDD36AC; minimizedProjectReferenceProxies = 0; packageReferences = ( - 459883F123D879CFB6DBB549 /* XCLocalSwiftPackageReference "." */, + 222FDCD3CB726F70DF5E5FEA /* XCLocalSwiftPackageReference "." */, ); preferredProjectObjectVersion = 100; - productRefGroup = CB6896C5F55260956ACC3EAF /* Products */; + productRefGroup = 35E638A87A48A6CBC246BF6B /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 1FC930737F45A671AE16478F /* G6SensorKit */, - 5FDFF54B3F109CF9EB807CE7 /* G6SensorKitUI */, - D59705DF2CF01716CBDBCA1E /* G6SensorKitPlugin */, + 215CD1147465A2E980A94D63 /* G6SensorKit */, + 8F3461A960A54D2320B21FE4 /* G6SensorKitUI */, + D09D95523AA824744122C1CB /* G6SensorKitPlugin */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 1384F63BC3916A99F4309AD9 /* Resources */ = { + 6D20D7C6745342F8C65404B0 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2921FB176CBA1E3FACF8C998 /* Localizable.xcstrings in Resources */, + 226AE1C008E3432034691E58 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - A456440235B07EA3B55C3C44 /* Resources */ = { + BBB2CD01CD25C8772A7D6484 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3A9FBCDBD2078C788E4D6A61 /* Localizable.xcstrings in Resources */, - 6C3243405AE5D59AEF654CB7 /* Assets.xcassets in Resources */, + 2C77CCC0A4FC873D451B1D9C /* Localizable.xcstrings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - A720A1114AADAE11791259CE /* Resources */ = { + BE615E0FBD1840B4E6C34D02 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 256CCEB29BA96551FCEC4B4A /* Localizable.xcstrings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 444C5BA0EDD6B24D16C899CF /* Sources */ = { + 30F8F65AC6C7D52F848495B9 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - BF338B66F1042236F4DBAAA0 /* G6Alert.swift in Sources */, - 38145114C2273AD696A3D633 /* G6AlertEvaluator.swift in Sources */, - D3B56173754CE3AA5CB8CEA6 /* G6CGMManager.swift in Sources */, - 3383256660F7228702BAA719 /* G6CGMManagerState.swift in Sources */, - 0B96FC48B098E283212D7434 /* G6ShareCredentialStore.swift in Sources */, - D389B8A224241FF1DC55A0B5 /* G6SimulatedSession.swift in Sources */, - 1EFFB6CA1A4DD2702593640A /* HKUnit.swift in Sources */, - 3DAE7BECBFE06CFB97DDD196 /* LocalizedString.swift in Sources */, - E2EF5851A11BCE61A474C191 /* Locked.swift in Sources */, - 5DB32B111CC9558D9D17F1DD /* OSLog.swift in Sources */, - 96FE9CAA2BA79D899055E8B0 /* TimeInterval.swift in Sources */, + 39603B3649182CA37CE8237A /* G6CGMManager+UI.swift in Sources */, + 77CD64A55933B10835781892 /* G6UICoordinator.swift in Sources */, + 405A216F8D1752F1421D4887 /* LocalizedString.swift in Sources */, + 6C6A5725B781F8EC0283A2E3 /* G6ActivityViewController.swift in Sources */, + 85D8C77F66A1FF1AF57A8F17 /* G6ApplySensorViews.swift in Sources */, + 934EFF804E6452CD19F40C04 /* G6CalibrationGuideView.swift in Sources */, + D48D98C13312034AB8C11BA8 /* G6DetailViews.swift in Sources */, + 3A7D53148400D95D5EBE9B20 /* G6Graphics.swift in Sources */, + DA3B54D9184C892B5F9A7B96 /* G6OnboardingViews.swift in Sources */, + E5928066DDD984FCE765E888 /* G6PackageScannerView.swift in Sources */, + F3BF96B43DC44EAB997C9556 /* G6ReadingDetailView.swift in Sources */, + 9D23800E9E278C62602AAF06 /* G6SettingsView.swift in Sources */, + 8587D2CC46C9C9CB94B2D3FA /* HKUnit.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8417137A0C4F1F7F25185E61 /* Sources */ = { + CF5459A40A7FD204384A3827 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A9A6EA0AADF90B3D2BC174BE /* G6CGMManager+UI.swift in Sources */, - CF28F3F0F438EE53CD7CCEFE /* G6UICoordinator.swift in Sources */, - 1F0E56CFDD57BC9269932E00 /* LocalizedString.swift in Sources */, - 428978D53D25A29DAAED79BB /* G6ActivityViewController.swift in Sources */, - 38402F888769F9D025B8CE04 /* G6ApplySensorViews.swift in Sources */, - 92984720FAB46BCCAB93C2F4 /* G6CalibrationGuideView.swift in Sources */, - D57D16D172751A2E34BCBE2D /* G6DetailViews.swift in Sources */, - 325836DA81824456AC495CFF /* G6Graphics.swift in Sources */, - 388CA00B3F572757ADD0A58D /* G6OnboardingViews.swift in Sources */, - 94284FD983F0E91AE79A91B6 /* G6PackageScannerView.swift in Sources */, - F38D4C7E56F03FD1B2E7F924 /* G6ReadingDetailView.swift in Sources */, - 430C49804080723BD78C8DBA /* G6SettingsView.swift in Sources */, - EFC856B31EB45F398EF25CA6 /* HKUnit.swift in Sources */, + 2A9D142A81AE191360B058B0 /* G6Alert.swift in Sources */, + 9068DC2E9303B2620EC57AF2 /* G6AlertEvaluator.swift in Sources */, + 5623B9849DDAC97251E7B413 /* G6CGMManager.swift in Sources */, + 3A518597A56D377383B5D384 /* G6CGMManagerState.swift in Sources */, + 83FDE18A177B5C10B0504485 /* G6ShareCredentialStore.swift in Sources */, + 4159FE6F9D1C67AA7D355705 /* G6SimulatedSession.swift in Sources */, + 3D85A309CDAA70C948DB7D06 /* HKUnit.swift in Sources */, + 25B13BDAFD609EC61E01ED42 /* LocalizedString.swift in Sources */, + 1BFC8B0012423024BCEE84C4 /* Locked.swift in Sources */, + EE9148D1635A031059CB0474 /* OSLog.swift in Sources */, + ABC18A66F55CAC750FAAA781 /* TimeInterval.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - E14BEE3FDC217ED133742420 /* Sources */ = { + D91BC325094ACAC7D108B6A0 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 032019A6EEC8573370EE4E4E /* G6SensorKitPlugin.swift in Sources */, + 81CC3E50E4370774F5954A78 /* G6SensorKitPlugin.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 15B834AB9E65E9AFA58F1744 /* PBXTargetDependency */ = { + 2B67866B45ABC4CCDF08A03B /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = G6SensorKit; - target = 1FC930737F45A671AE16478F /* G6SensorKit */; - targetProxy = E0A5C942CCB714A7E897F6AA /* PBXContainerItemProxy */; + target = 215CD1147465A2E980A94D63 /* G6SensorKit */; + targetProxy = 8C5FBFBE5966E33ED892663C /* PBXContainerItemProxy */; }; - 43D4F281FBAD16F8FCAE2F77 /* PBXTargetDependency */ = { + 627FBE52365C3C03931C7886 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = G6SensorKit; - target = 1FC930737F45A671AE16478F /* G6SensorKit */; - targetProxy = 1BBFE840668BC082C5C18328 /* PBXContainerItemProxy */; + target = 215CD1147465A2E980A94D63 /* G6SensorKit */; + targetProxy = AB91E4CF703C2153542F72B0 /* PBXContainerItemProxy */; }; - 7A4F1CA8724DC60FA58D2552 /* PBXTargetDependency */ = { + F6FFF5B09BC08B51699968C7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = G6SensorKitUI; - target = 5FDFF54B3F109CF9EB807CE7 /* G6SensorKitUI */; - targetProxy = 23DF82B0A16EFF5164752461 /* PBXContainerItemProxy */; + target = 8F3461A960A54D2320B21FE4 /* G6SensorKitUI */; + targetProxy = 1CA7CA75216CC94C77001C8A /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 48313512C607D6345E05EA05 /* Release */ = { + 3A87E12D403C48B6C4E16BCA /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -490,7 +490,7 @@ CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = NO; CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; + DEFINES_MODULE = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -499,12 +499,13 @@ "$(inherited)", "$(BUILT_PRODUCTS_DIR)", ); - INFOPLIST_FILE = G6SensorKitUI/Info.plist; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = G6SensorKitPlugin/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitUI; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitPlugin; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; @@ -514,10 +515,73 @@ VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WRAPPER_EXTENSION = loopplugin; }; name = Release; }; - 5F47B21649870C5B6887C09E /* Debug */ = { + 3B66BBA892E68EDF726B4480 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.9; + }; + name = Debug; + }; + 6965477C499968CA83551725 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -525,7 +589,7 @@ CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = NO; CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = NO; + DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -534,13 +598,12 @@ "$(inherited)", "$(BUILT_PRODUCTS_DIR)", ); - GENERATE_INFOPLIST_FILE = NO; - INFOPLIST_FILE = G6SensorKitPlugin/Info.plist; + INFOPLIST_FILE = G6SensorKit/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitPlugin; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKit; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; @@ -549,11 +612,10 @@ TARGETED_DEVICE_FAMILY = 1; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; - WRAPPER_EXTENSION = loopplugin; }; name = Debug; }; - 6B7F966D3443B894BE4C93D1 /* Release */ = { + 6EC800F9252B079EBE43E8D0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -561,7 +623,7 @@ CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = NO; CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = NO; + DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -570,13 +632,12 @@ "$(inherited)", "$(BUILT_PRODUCTS_DIR)", ); - GENERATE_INFOPLIST_FILE = NO; - INFOPLIST_FILE = G6SensorKitPlugin/Info.plist; + INFOPLIST_FILE = G6SensorKitUI/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitPlugin; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitUI; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; @@ -586,73 +647,45 @@ VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; - WRAPPER_EXTENSION = loopplugin; }; name = Release; }; - 7309CF4E6FD8C75F7C6FC8D1 /* Debug */ = { + 9342504C39FA6A5C36B3F153 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", + CLANG_ENABLE_OBJC_WEAK = NO; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", + "$(BUILT_PRODUCTS_DIR)", ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = G6SensorKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 17.6; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKit; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.9; + TARGETED_DEVICE_FAMILY = 1; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; - 8B0271A75292B6CE385B7ABD /* Release */ = { + C2EF29AC766E13A496E2D70A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -660,7 +693,7 @@ CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = NO; CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; + DEFINES_MODULE = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -669,25 +702,26 @@ "$(inherited)", "$(BUILT_PRODUCTS_DIR)", ); - INFOPLIST_FILE = G6SensorKit/Info.plist; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = G6SensorKitPlugin/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 17.6; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKit; + PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKitPlugin; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.9; TARGETED_DEVICE_FAMILY = 1; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WRAPPER_EXTENSION = loopplugin; }; - name = Release; + name = Debug; }; - A3B0558276FC30AF2089ACE6 /* Release */ = { + E1A1853C1186E503AB2BC172 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -743,7 +777,7 @@ }; name = Release; }; - BA27D1028CA339E51C052640 /* Debug */ = { + F3ADA5588B68CDB0DC02C9F6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUILD_LIBRARY_FOR_DISTRIBUTION = YES; @@ -777,75 +811,41 @@ }; name = Debug; }; - DCB9941481C5322FDDBB0801 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUILD_LIBRARY_FOR_DISTRIBUTION = YES; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = NO; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_MODULE_VERIFIER = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(BUILT_PRODUCTS_DIR)", - ); - INFOPLIST_FILE = G6SensorKit/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 17.6; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = org.nightscout.G6SensorKit; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.9; - TARGETED_DEVICE_FAMILY = 1; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 1CB4E131373959E0BC530F1F /* Build configuration list for PBXProject "G6SensorKit" */ = { + 072C8C59C81653E06FA00EB4 /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */ = { isa = XCConfigurationList; buildConfigurations = ( - 7309CF4E6FD8C75F7C6FC8D1 /* Debug */, - A3B0558276FC30AF2089ACE6 /* Release */, + 6EC800F9252B079EBE43E8D0 /* Release */, + F3ADA5588B68CDB0DC02C9F6 /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 92650F7E6B063572AC79D169 /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */ = { + 8B609048B49027655DD83E61 /* Build configuration list for PBXProject "G6SensorKit" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6B7F966D3443B894BE4C93D1 /* Release */, - 5F47B21649870C5B6887C09E /* Debug */, + 3B66BBA892E68EDF726B4480 /* Debug */, + E1A1853C1186E503AB2BC172 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - CD0E963482CD3D2B5682140B /* Build configuration list for PBXNativeTarget "G6SensorKitUI" */ = { + DD280BDB51D34244226439F4 /* Build configuration list for PBXNativeTarget "G6SensorKit" */ = { isa = XCConfigurationList; buildConfigurations = ( - 48313512C607D6345E05EA05 /* Release */, - BA27D1028CA339E51C052640 /* Debug */, + 9342504C39FA6A5C36B3F153 /* Release */, + 6965477C499968CA83551725 /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - E6BECE0CEC895BB0D3C1EA93 /* Build configuration list for PBXNativeTarget "G6SensorKit" */ = { + FCDA3AF29E0740002157A96C /* Build configuration list for PBXNativeTarget "G6SensorKitPlugin" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8B0271A75292B6CE385B7ABD /* Release */, - DCB9941481C5322FDDBB0801 /* Debug */, + 3A87E12D403C48B6C4E16BCA /* Release */, + C2EF29AC766E13A496E2D70A /* Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -853,18 +853,18 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 459883F123D879CFB6DBB549 /* XCLocalSwiftPackageReference "." */ = { + 222FDCD3CB726F70DF5E5FEA /* XCLocalSwiftPackageReference "." */ = { isa = XCLocalSwiftPackageReference; relativePath = .; }; /* End XCLocalSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 99E200D18B601AFB565F1B5B /* G6SensorCore */ = { + 0EC90A7F507FA56DA0FAAC1D /* G6SensorCore */ = { isa = XCSwiftPackageProductDependency; productName = G6SensorCore; }; /* End XCSwiftPackageProductDependency section */ }; - rootObject = E00046664E8B19B1D108CD7E /* Project object */; + rootObject = 05E8929C0E445F2264A8A045 /* Project object */; } diff --git a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme index 6717617..2a070a1 100644 --- a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme +++ b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKit.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> diff --git a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme index 6c0d16d..aacd34c 100644 --- a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme +++ b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitPlugin.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> diff --git a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme index ed560ca..1c91f21 100644 --- a/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme +++ b/G6SensorKit.xcodeproj/xcshareddata/xcschemes/G6SensorKitUI.xcscheme @@ -14,7 +14,7 @@ buildForAnalyzing = "YES"> diff --git a/G6SensorKit/G6CGMManager.swift b/G6SensorKit/G6CGMManager.swift index 364c12d..48707f7 100644 --- a/G6SensorKit/G6CGMManager.swift +++ b/G6SensorKit/G6CGMManager.swift @@ -837,27 +837,10 @@ extension G6CGMManager: TransmitterSessionDelegate { } private func glucoseTrend(for glucose: Glucose) -> GlucoseTrend? { - guard let rate = glucose.trendRateMgDLPerMinute else { + guard let arrow = G6TrendArrow(dexcomRateMgDLPerMinute: glucose.trendRateMgDLPerMinute) else { return nil } - - // Standard Dexcom trend arrow thresholds in (mg/dL)/min. - switch rate { - case ..<(-3): - return .downDownDown - case ..<(-2): - return .downDown - case ..<(-1): - return .down - case ..<1: - return .flat - case ..<2: - return .up - case ..<3: - return .upUp - default: - return .upUpUp - } + return GlucoseTrend(rawValue: arrow.rawValue) } } @@ -948,18 +931,10 @@ struct G6GlucoseDisplay: GlucoseDisplayable { } var trendType: GlucoseTrend? { - guard let rate = reading.trendRateMgDLPerMinute else { + guard let arrow = G6TrendArrow(dexcomRateMgDLPerMinute: reading.trendRateMgDLPerMinute) else { return nil } - switch rate { - case ..<(-3): return .downDownDown - case ..<(-2): return .downDown - case ..<(-1): return .down - case ..<1: return .flat - case ..<2: return .up - case ..<3: return .upUp - default: return .upUpUp - } + return GlucoseTrend(rawValue: arrow.rawValue) } var trendRate: HKQuantity? { diff --git a/G6SensorKit/G6CGMManagerState.swift b/G6SensorKit/G6CGMManagerState.swift index 09606d4..d96eb22 100644 --- a/G6SensorKit/G6CGMManagerState.swift +++ b/G6SensorKit/G6CGMManagerState.swift @@ -345,11 +345,9 @@ public struct G6CGMManagerState: RawRepresentable { /// The device model implied by the transmitter ID prefix. G6 transmitters /// use `8…`; Dexcom ONE uses `5…` or `C…`. public var deviceModel: String { - switch transmitterID.first { - case "5", "C", "c": - return "Dexcom ONE" - default: - return "Dexcom G6" + switch G6TransmitterModel(transmitterID: transmitterID) { + case .g6: return "Dexcom G6" + case .one: return "Dexcom ONE" } } } diff --git a/G6SensorKitUI/Views/G6SettingsView.swift b/G6SensorKitUI/Views/G6SettingsView.swift index 1cc7742..ddbcc27 100644 --- a/G6SensorKitUI/Views/G6SettingsView.swift +++ b/G6SensorKitUI/Views/G6SettingsView.swift @@ -151,15 +151,17 @@ final class G6SettingsViewModel: ObservableObject, G6CGMManagerObserver { } var trendSymbol: String? { - guard let rate = state.latestReading?.trendRateMgDLPerMinute, !isSignalLost else { + guard !isSignalLost, + let arrow = G6TrendArrow(dexcomRateMgDLPerMinute: state.latestReading?.trendRateMgDLPerMinute) + else { return nil } - switch rate { - case ..<(-3): return "arrow.down" - case ..<(-1): return "arrow.down.right" - case ..<1: return "arrow.right" - case ..<3: return "arrow.up.right" - default: return "arrow.up" + switch arrow { + case .downDownDown, .downDown: return "arrow.down" + case .down: return "arrow.down.right" + case .flat: return "arrow.right" + case .up, .upUp: return "arrow.up.right" + case .upUpUp: return "arrow.up" } } diff --git a/Sources/G6SensorCore/Auth/G6TransmitterModel.swift b/Sources/G6SensorCore/Auth/G6TransmitterModel.swift new file mode 100644 index 0000000..0558c08 --- /dev/null +++ b/Sources/G6SensorCore/Auth/G6TransmitterModel.swift @@ -0,0 +1,27 @@ +// +// G6TransmitterModel.swift +// G6SensorKit +// +// Copyright © 2026 Nightscout Foundation. MIT License. +// + +import Foundation + +/// The G6-family model, classified from the transmitter ID the user entered. +public enum G6TransmitterModel: CaseIterable { + case g6 + case one + + /// Dexcom ONE transmitters use `5…` or `C…`; G6 uses `8…`. An unrecognized + /// prefix falls back to G6, the stock case. + public init(transmitterID: String) { + switch transmitterID.first { + case "5", + "c", + "C": + self = .one + default: + self = .g6 + } + } +} diff --git a/Sources/G6SensorCore/Auth/TransmitterID.swift b/Sources/G6SensorCore/Auth/TransmitterID.swift index f81a1eb..cebeffe 100644 --- a/Sources/G6SensorCore/Auth/TransmitterID.swift +++ b/Sources/G6SensorCore/Auth/TransmitterID.swift @@ -21,6 +21,11 @@ public struct TransmitterID { self.id = id } + /// The G6-family model, classified from the transmitter ID prefix. + public var model: G6TransmitterModel { + return G6TransmitterModel(transmitterID: id) + } + private var cryptKey: Data? { return "00\(id)00\(id)".data(using: .utf8) } diff --git a/Sources/G6SensorCore/Model/G6TrendArrow.swift b/Sources/G6SensorCore/Model/G6TrendArrow.swift new file mode 100644 index 0000000..95ad0e7 --- /dev/null +++ b/Sources/G6SensorCore/Model/G6TrendArrow.swift @@ -0,0 +1,50 @@ +// +// G6TrendArrow.swift +// G6SensorKit +// +// Copyright © 2026 Nightscout Foundation. MIT License. +// + +import Foundation + +/// The Dexcom trend arrow for a reported rate of change. +/// +/// The raw values match LoopKit's `GlucoseTrend` so the integration layer +/// can bridge with `GlucoseTrend(rawValue:)`. +public enum G6TrendArrow: Int, CaseIterable { + case upUpUp = 1 + case upUp = 2 + case up = 3 + case flat = 4 + case down = 5 + case downDown = 6 + case downDownDown = 7 + + /// Beyond this the official apps show no arrow at all. Reachable: the + /// rate arrives as Int8 tenths (0x7F is the "no trend" sentinel), so + /// roughly -12.8 to +12.6 comes in over the wire. + private static let dexcomArrowLimit = 8.0 + + /// The Dexcom arrow for the rate the transmitter reported, in + /// (mg/dL)/min. + /// + /// Thresholds match the apps' shared trend-arrow table: every threshold + /// belongs to the steeper arrow, `flat` excludes both of its ends, and + /// |rate| above 8 is no arrow. The transmitter sends the rate; the + /// receiver only buckets it. + public init?(dexcomRateMgDLPerMinute rate: Double?) { + guard let rate = rate, + (-Self.dexcomArrowLimit ... Self.dexcomArrowLimit).contains(rate) + else { return nil } + + switch rate { + case ...(-3): self = .downDownDown + case ...(-2): self = .downDown + case ...(-1): self = .down + case ..<1: self = .flat + case ..<2: self = .up + case ..<3: self = .upUp + default: self = .upUpUp + } + } +} diff --git a/Tests/G6SensorCoreTests/G6TrendArrowTests.swift b/Tests/G6SensorCoreTests/G6TrendArrowTests.swift new file mode 100644 index 0000000..9062794 --- /dev/null +++ b/Tests/G6SensorCoreTests/G6TrendArrowTests.swift @@ -0,0 +1,53 @@ +// +// G6TrendArrowTests.swift +// G6SensorKit +// +// Copyright © 2026 Nightscout Foundation. MIT License. +// + +import XCTest +@testable import G6SensorCore + +/// Rates are integer tenths on the wire, so every case here is reachable. +class G6TrendArrowTests: XCTestCase { + func testNoRateHasNoArrow() { + XCTAssertNil(G6TrendArrow(dexcomRateMgDLPerMinute: nil)) + } + + func testArrowsByRate() { + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: -4), .downDownDown) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: -2.5), .downDown) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: -1.5), .down) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: 0), .flat) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: 1.5), .up) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: 2.5), .upUp) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: 4), .upUpUp) + } + + /// Every threshold belongs to the steeper arrow, on both sides. + /// The old `..<(-3)` bucketing gave a single-down arrow at exactly -3.0. + func testThresholdsTakeTheSteeperArrow() { + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: -3), .downDownDown) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: 3), .upUpUp) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: -2), .downDown) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: 2), .upUp) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: -1), .down) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: 1), .up) + } + + /// Flat excludes both of its ends, so it is the narrowest bucket. + func testFlatIsOnlyBetweenTheUnitThresholds() { + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: -0.9), .flat) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: 0.9), .flat) + } + + /// Past +/-8 the official apps show no arrow rather than a triple one. + /// The wire carries Int8 tenths, so this reaches roughly +/-12.6. + func testImplausibleRatesHaveNoArrow() { + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: -8), .downDownDown) + XCTAssertEqual(G6TrendArrow(dexcomRateMgDLPerMinute: 8), .upUpUp) + XCTAssertNil(G6TrendArrow(dexcomRateMgDLPerMinute: -8.1)) + XCTAssertNil(G6TrendArrow(dexcomRateMgDLPerMinute: 8.1)) + XCTAssertNil(G6TrendArrow(dexcomRateMgDLPerMinute: 12.6)) + } +} diff --git a/Tests/G6SensorCoreTests/TransmitterIDTests.swift b/Tests/G6SensorCoreTests/TransmitterIDTests.swift index 59aedba..c807053 100644 --- a/Tests/G6SensorCoreTests/TransmitterIDTests.swift +++ b/Tests/G6SensorCoreTests/TransmitterIDTests.swift @@ -16,5 +16,18 @@ class TransmitterIDTests: XCTestCase { XCTAssertEqual("e60d4a7999b0fbb2", id.computeHash(of: Data(hexadecimalString: "0123456789abcdef")!)!.hexadecimalString) } - + + /// The prefix decides the model: 8… is G6, 5… and C… are Dexcom ONE. + func testModelByPrefix() { + XCTAssertEqual(TransmitterID(id: "8ZXY12").model, .g6) + XCTAssertEqual(TransmitterID(id: "5ZXY12").model, .one) + XCTAssertEqual(TransmitterID(id: "CZXY12").model, .one) + XCTAssertEqual(TransmitterID(id: "cZXY12").model, .one) + } + + /// An unrecognized prefix is the stock case, not a failure. + func testUnknownPrefixFallsBackToG6() { + XCTAssertEqual(TransmitterID(id: "9ZXY12").model, .g6) + } + } From 4347d139693322ff909d09fad65f9623dcfed498 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Thu, 24 Sep 2026 15:57:08 +0200 Subject: [PATCH 06/13] feat(calibration): show current reading, gate on fresh flat reading, warn on large deviations The calibration screen now shows the current sensor reading next to the entry field and only allows sending a calibration when it can be compared fairly: the latest reading must be fresh (one missed 5-minute reading closes the gate, with 30 s of jitter tolerance) and the trend must be flat (|rate| < 1 mg/dL/min, via the shared G6TrendArrow bucketing). Blocked states explain themselves with a callout; the Send button greys out. A change of 40 mg/dL or more from the current reading asks for confirmation before sending. A new G6CalibrationViewModel observes manager state so the reading updates live; a 30 s tick lets the freshness gate expire while the screen is open (state updates only arrive with a reading). Entry parsing is now a single computed property shared by the deviation math and submit, so the warned-about value is exactly the value sent. --- G6SensorKitUI/Localizable.xcstrings | 32 +++++ G6SensorKitUI/Views/G6DetailViews.swift | 183 ++++++++++++++++++++++-- 2 files changed, 206 insertions(+), 9 deletions(-) diff --git a/G6SensorKitUI/Localizable.xcstrings b/G6SensorKitUI/Localizable.xcstrings index 309d047..07fa8e4 100644 --- a/G6SensorKitUI/Localizable.xcstrings +++ b/G6SensorKitUI/Localizable.xcstrings @@ -898,6 +898,38 @@ "The camera couldn't start. Try again or type the code manually.": { "extractionState": "manual", "comment": "Scanner failed to start" + }, + "Current sensor reading": { + "extractionState": "manual", + "comment": "Calibration: current reading label" + }, + "Large calibration change": { + "extractionState": "manual", + "comment": "Calibration deviation warning title" + }, + "Send Anyway": { + "extractionState": "manual", + "comment": "Confirm calibration despite large deviation" + }, + "This is %1$@ away from the current sensor reading. A change this large can be bad for sensor accuracy; try to limit each calibration to at most %2$@ at a time.": { + "extractionState": "manual", + "comment": "Calibration deviation warning (1: deviation with unit, 2: recommended maximum with unit)" + }, + "No recent sensor reading": { + "extractionState": "manual", + "comment": "Calibration unavailable: title" + }, + "Calibrating compares your fingerstick to what the sensor reads right now, so it needs a recent reading. Wait for the next reading, then calibrate.": { + "extractionState": "manual", + "comment": "Calibration unavailable: explanation" + }, + "Glucose is changing": { + "extractionState": "manual", + "comment": "Calibration unavailable while trend is not flat: title" + }, + "Calibrating compares your fingerstick to the current reading, which only works when your glucose is steady. Wait for a flat trend arrow (→), then calibrate.": { + "extractionState": "manual", + "comment": "Calibration unavailable while trend is not flat: explanation" } }, "version": "1.1" diff --git a/G6SensorKitUI/Views/G6DetailViews.swift b/G6SensorKitUI/Views/G6DetailViews.swift index d8edcc3..fe94996 100644 --- a/G6SensorKitUI/Views/G6DetailViews.swift +++ b/G6SensorKitUI/Views/G6DetailViews.swift @@ -17,20 +17,99 @@ import G6SensorCore // MARK: - Calibration +/// Keeps the calibration screen's "current reading" live. State updates +/// alone are not enough: they only arrive WITH a reading, so without the +/// tick a disconnected transmitter would leave an old reading looking +/// fresh forever. +final class G6CalibrationViewModel: ObservableObject, G6CGMManagerObserver { + @Published private(set) var latestReading: G6StoredReading? + @Published private(set) var now = Date() + + private var tick: Timer? + + init(cgmManager: G6CGMManager) { + latestReading = cgmManager.state.latestReading + cgmManager.addStateObserver(self) + + let timer = Timer(timeInterval: 30, repeats: true) { [weak self] _ in + self?.now = Date() + } + RunLoop.main.add(timer, forMode: .common) + tick = timer + } + + deinit { + tick?.invalidate() + } + + func g6CGMManagerDidUpdateState(_ manager: G6CGMManager) { + DispatchQueue.main.async { + self.latestReading = manager.state.latestReading + } + } + + /// Readings arrive every 5 minutes; one missed reading closes the gate. + /// The extra 30 seconds absorb delivery jitter so a slightly late reading + /// does not flicker the gate. + static let readingFreshnessInterval: TimeInterval = .minutes(5.5) + + /// Why calibration is or is not currently possible. + enum Readiness { + case ready + case noFreshReading + case notFlat + } + + var freshReading: G6StoredReading? { + guard let reading = latestReading, + now.timeIntervalSince(reading.date) <= Self.readingFreshnessInterval + else { + return nil + } + return reading + } + + /// Calibrating teaches the sensor from the difference between the + /// fingerstick and the current reading; a reading that is moving cannot + /// be compared fairly, so calibration requires a flat trend. + var readiness: Readiness { + guard let reading = freshReading else { + return .noFreshReading + } + guard G6TrendArrow(dexcomRateMgDLPerMinute: reading.trendRateMgDLPerMinute) == .flat else { + return .notFlat + } + return .ready + } +} + struct G6CalibrationView: View { let cgmManager: G6CGMManager let didSubmit: () -> Void + @StateObject private var viewModel: G6CalibrationViewModel + @State private var entry: String = "" @State private var validationMessage: String? @State private var showingGuide = false + @State private var showingDeviationWarning = false @EnvironmentObject private var displayGlucosePreference: DisplayGlucosePreference private static let minimumMgDL: Double = 40 private static let maximumMgDL: Double = 400 + /// Deviation from the current reading at or beyond which the big-change + /// warning shows (mg/dL). + private static let largeDeviationWarningMgDL: Double = 40 + + init(cgmManager: G6CGMManager, didSubmit: @escaping () -> Void) { + self.cgmManager = cgmManager + self.didSubmit = didSubmit + _viewModel = StateObject(wrappedValue: G6CalibrationViewModel(cgmManager: cgmManager)) + } + private var unit: HKUnit { return displayGlucosePreference.unit } @@ -47,6 +126,38 @@ struct G6CalibrationView: View { return HKQuantity(unit: .milligramsPerDeciliter, doubleValue: value) } + private func formatted(mgdl value: Double) -> String { + return displayGlucosePreference.format(quantity(fromMgDL: value)) + } + + /// Latest sensor reading in mg/dL, if one exists and is fresh enough to + /// calibrate against. + private var currentValueMgDL: Double? { + return viewModel.freshReading?.glucoseMgDL + } + + private var isCalibrationBlocked: Bool { + return viewModel.readiness != .ready + } + + private var enteredMgDL: Double? { + let normalized = entry.replacingOccurrences(of: decimalSeparator, with: ".") + return Double(normalized).map { + HKQuantity(unit: unit, doubleValue: $0).doubleValue(for: .milligramsPerDeciliter) + } + } + + private var deviationMgDL: Double? { + guard let entered = enteredMgDL, let current = currentValueMgDL else { + return nil + } + return abs(entered - current) + } + + private var showsLargeDeviationWarning: Bool { + return (deviationMgDL ?? 0) >= Self.largeDeviationWarningMgDL + } + private func sanitize(_ input: String) -> String { guard usesDecimals else { return String(input.filter(\.isNumber).prefix(3)) @@ -84,13 +195,26 @@ struct G6CalibrationView: View { } } + HStack { + Text(LocalizedString("Current sensor reading", comment: "Calibration: current reading label")) + Spacer() + if let current = currentValueMgDL { + Text(formatted(mgdl: current)) + .foregroundColor(.secondary) + } else { + Text(LocalizedString("—", comment: "Placeholder for missing value")) + .foregroundColor(.secondary) + } + } + .font(.subheadline) + TextField(unit.localizedShortUnitString, text: $entry) .keyboardType(usesDecimals ? .decimalPad : .numberPad) .font(.title3.monospaced()) .padding() .background(Color(.secondarySystemBackground)) .cornerRadius(10) - .onChange(of: entry) { newValue in + .onChange(of: entry) { _, newValue in let sanitized = sanitize(newValue) if sanitized != newValue { entry = sanitized @@ -112,34 +236,75 @@ struct G6CalibrationView: View { body: LocalizedString("The calibration is sent the next time your transmitter connects, which can be up to 5 minutes away. The transmitter may accept it, ask for a second value, or reject it — this screen's status will tell you which.", comment: "Calibration callout body about delivery timing") ) + switch viewModel.readiness { + case .ready: + EmptyView() + case .noFreshReading: + G6CalloutBox( + symbolName: "exclamationmark.triangle.fill", + tint: .orange, + title: LocalizedString("No recent sensor reading", comment: "Calibration unavailable: title"), + body: LocalizedString("Calibrating compares your fingerstick to what the sensor reads right now, so it needs a recent reading. Wait for the next reading, then calibrate.", comment: "Calibration unavailable: explanation") + ) + case .notFlat: + G6CalloutBox( + symbolName: "exclamationmark.triangle.fill", + tint: .orange, + title: LocalizedString("Glucose is changing", comment: "Calibration unavailable while trend is not flat: title"), + body: LocalizedString("Calibrating compares your fingerstick to the current reading, which only works when your glucose is steady. Wait for a flat trend arrow (→), then calibrate.", comment: "Calibration unavailable while trend is not flat: explanation") + ) + } + } .padding() } - Button(action: submit) { + Button(action: submitTapped) { Text(LocalizedString("Send Calibration", comment: "Calibration submit button")) .frame(maxWidth: .infinity, minHeight: 44) } .buttonStyle(G6PrimaryButtonStyle()) - .disabled(entry.isEmpty) + .disabled(entry.isEmpty || isCalibrationBlocked) .padding() } .sheet(isPresented: $showingGuide) { G6CalibrationGuideView(onDone: { showingGuide = false }) } + .alert( + Text(LocalizedString("Large calibration change", comment: "Calibration deviation warning title")), + isPresented: $showingDeviationWarning + ) { + Button(role: .cancel, action: {}) { + Text(LocalizedString("Cancel", comment: "Cancel button")) + } + Button(action: submit) { + Text(LocalizedString("Send Anyway", comment: "Confirm calibration despite large deviation")) + } + } message: { + Text(String( + format: LocalizedString("This is %1$@ away from the current sensor reading. A change this large can be bad for sensor accuracy; try to limit each calibration to at most %2$@ at a time.", comment: "Calibration deviation warning (1: deviation with unit, 2: recommended maximum with unit)"), + formatted(mgdl: deviationMgDL ?? 0), + formatted(mgdl: Self.largeDeviationWarningMgDL) + )) + } } - private func submit() { - let normalized = entry.replacingOccurrences(of: decimalSeparator, with: ".") + private func submitTapped() { + // A large jump from the current reading gets a confirmation first; + // big corrections can teach the sensor the wrong thing. + guard showsLargeDeviationWarning else { + submit() + return + } + showingDeviationWarning = true + } - guard let entered = Double(normalized) else { + private func submit() { + guard let valueMgDL = enteredMgDL else { validationMessage = LocalizedString("Enter a number.", comment: "Validation message for non-numeric calibration entry") return } - let valueMgDL = HKQuantity(unit: unit, doubleValue: entered) - .doubleValue(for: .milligramsPerDeciliter) - guard (Self.minimumMgDL...Self.maximumMgDL).contains(valueMgDL) else { validationMessage = String( format: LocalizedString("Calibrations must be between %1$@ and %2$@. If your meter reads outside that range, treat it and follow your care team's guidance instead of calibrating.", comment: "Validation message for out-of-range calibration (1: minimum with unit, 2: maximum with unit)"), From 3b27853af616542e643133041fac053146753a9e Mon Sep 17 00:00:00 2001 From: ETolboom Date: Thu, 24 Sep 2026 16:59:56 +0200 Subject: [PATCH 07/13] feat(settings): battery status view, Anubis branding, wheel picker for session length --- G6SensorKit/G6CGMManagerState.swift | 18 ++ G6SensorKit/G6SimulatedSession.swift | 8 + .../anubis.imageset/Contents.json | 12 ++ .../anubis.imageset/anubis.png | Bin 0 -> 475811 bytes G6SensorKitUI/G6UICoordinator.swift | 11 ++ G6SensorKitUI/Localizable.xcstrings | 26 ++- G6SensorKitUI/Views/G6DetailViews.swift | 161 +++++++++++------- G6SensorKitUI/Views/G6Graphics.swift | 3 +- G6SensorKitUI/Views/G6SettingsView.swift | 40 ++++- 9 files changed, 213 insertions(+), 66 deletions(-) create mode 100644 G6SensorKitUI/Assets.xcassets/anubis.imageset/Contents.json create mode 100644 G6SensorKitUI/Assets.xcassets/anubis.imageset/anubis.png diff --git a/G6SensorKit/G6CGMManagerState.swift b/G6SensorKit/G6CGMManagerState.swift index d96eb22..0d57d5e 100644 --- a/G6SensorKit/G6CGMManagerState.swift +++ b/G6SensorKit/G6CGMManagerState.swift @@ -131,6 +131,24 @@ public struct G6CGMManagerState: RawRepresentable { return millivolts <= Self.batteryVeryLowMillivolts } + /// Headline battery level for the settings row. + public enum BatteryLevel { + case unknown, high, low, veryLow + } + + public var batteryLevel: BatteryLevel { + guard let millivolts = batteryVoltageBMillivolts else { + return .unknown + } + if millivolts <= Self.batteryVeryLowMillivolts { + return .veryLow + } + if millivolts <= Self.batteryLowMillivolts { + return .low + } + return .high + } + public init( transmitterID: String, peripheralIdentifier: UUID? = nil, diff --git a/G6SensorKit/G6SimulatedSession.swift b/G6SensorKit/G6SimulatedSession.swift index 30c4aac..c9df672 100644 --- a/G6SensorKit/G6SimulatedSession.swift +++ b/G6SensorKit/G6SimulatedSession.swift @@ -48,6 +48,14 @@ extension G6CGMManager { state.transmitterExpiryInDays = 180 state.firmwareVersion = "1.0.0.0 (simulated)" state.peripheralIdentifier = UUID() + // A healthy battery, so the settings row renders and no + // low-battery alert fires. + state.batteryVoltageA = 295 + state.batteryVoltageB = 282 + state.batteryResistance = 700 + state.batteryRuntimeDays = 12 + state.batteryTemperature = 31 + state.lastBatteryReadDate = now } self.scheduleSimulatedReadings() diff --git a/G6SensorKitUI/Assets.xcassets/anubis.imageset/Contents.json b/G6SensorKitUI/Assets.xcassets/anubis.imageset/Contents.json new file mode 100644 index 0000000..7f5dd38 --- /dev/null +++ b/G6SensorKitUI/Assets.xcassets/anubis.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "anubis.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/G6SensorKitUI/Assets.xcassets/anubis.imageset/anubis.png b/G6SensorKitUI/Assets.xcassets/anubis.imageset/anubis.png new file mode 100644 index 0000000000000000000000000000000000000000..b6f481d8ec0e23431b28cbda420ebc8a8f2c6a51 GIT binary patch literal 475811 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 uJAxIpooLX1gYonzU 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

HW1AzCD= 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≧j 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

GX_^2H0rY0{{@O5YDk=NI6}fR9ou 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

I<|9#iGQMKK6TNI;z8CZ^10rnOaK9RSGv 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 literal 0 HcmV?d00001 diff --git a/G6SensorKitUI/G6UICoordinator.swift b/G6SensorKitUI/G6UICoordinator.swift index 7c44fc5..af168e1 100644 --- a/G6SensorKitUI/G6UICoordinator.swift +++ b/G6SensorKitUI/G6UICoordinator.swift @@ -30,6 +30,7 @@ enum G6UIScreen { case settings case calibration case transmitterDetails + case batteryDetails case sensorLifeSettings case shareUpload case readingDetail @@ -408,6 +409,7 @@ public class G6UICoordinator: UINavigationController, CGMManagerOnboarding, Comp cgmManager: cgmManager, toCalibration: { [weak self] in self?.navigateTo(.calibration) }, toTransmitterDetails: { [weak self] in self?.navigateTo(.transmitterDetails) }, + toBatteryDetails: { [weak self] in self?.navigateTo(.batteryDetails) }, toSensorLifeSettings: { [weak self] in self?.navigateTo(.sensorLifeSettings) }, toShareUpload: { [weak self] in self?.navigateTo(.shareUpload) }, toReadingDetail: { [weak self] in self?.navigateTo(.readingDetail) }, @@ -458,6 +460,15 @@ public class G6UICoordinator: UINavigationController, CGMManagerOnboarding, Comp title: LocalizedString("Transmitter", comment: "Navigation title for transmitter details") ) + case .batteryDetails: + guard let cgmManager = cgmManager else { + return UIViewController() + } + return hostingController( + rootView: G6BatteryDetailsView(cgmManager: cgmManager), + title: LocalizedString("Battery", comment: "Navigation title for battery details") + ) + case .sensorLifeSettings: guard let cgmManager = cgmManager else { return UIViewController() diff --git a/G6SensorKitUI/Localizable.xcstrings b/G6SensorKitUI/Localizable.xcstrings index 07fa8e4..9a46cf6 100644 --- a/G6SensorKitUI/Localizable.xcstrings +++ b/G6SensorKitUI/Localizable.xcstrings @@ -124,7 +124,7 @@ "extractionState": "manual" }, "Battery": { - "comment": "Transmitter details section header for battery", + "comment": "Navigation title for battery details", "extractionState": "manual" }, "Battery B is the cell that runs down first and determines whether the transmitter can finish a session.": { @@ -587,10 +587,6 @@ "comment": "Navigation title for sensor life settings", "extractionState": "manual" }, - "Session length: %d days": { - "comment": "Session length value (1: day count)", - "extractionState": "manual" - }, "Session stopped": { "comment": "Algorithm state: stopped", "extractionState": "manual" @@ -930,6 +926,26 @@ "Calibrating compares your fingerstick to the current reading, which only works when your glucose is steady. Wait for a flat trend arrow (→), then calibrate.": { "extractionState": "manual", "comment": "Calibration unavailable while trend is not flat: explanation" + }, + "Session length": { + "extractionState": "manual", + "comment": "Session length picker label" + }, + "High": { + "extractionState": "manual", + "comment": "Battery level: high" + }, + "Low": { + "extractionState": "manual", + "comment": "Battery level: low" + }, + "Replace Now": { + "extractionState": "manual", + "comment": "Battery level: very low, replace transmitter" + }, + "Save": { + "extractionState": "manual", + "comment": "Save session length button" } }, "version": "1.1" diff --git a/G6SensorKitUI/Views/G6DetailViews.swift b/G6SensorKitUI/Views/G6DetailViews.swift index fe94996..c54858e 100644 --- a/G6SensorKitUI/Views/G6DetailViews.swift +++ b/G6SensorKitUI/Views/G6DetailViews.swift @@ -4,8 +4,8 @@ // // Copyright © 2026 Nightscout Foundation. MIT License. // -// Calibration entry, transmitter details, Anubis session-length settings, -// and optional Dexcom Share upload configuration. +// Calibration entry, transmitter and battery details, Anubis session-length +// settings, and optional Dexcom Share upload configuration. // import SwiftUI @@ -353,7 +353,10 @@ struct G6TransmitterDetailsView: View { } Section { - row(LocalizedString("Model", comment: "Transmitter detail label for model"), cgmManager.state.deviceModel) + row( + LocalizedString("Model", comment: "Transmitter detail label for model"), + cgmManager.state.isAnubis ? "Anubis" : cgmManager.state.deviceModel + ) row(LocalizedString("Transmitter ID", comment: "Transmitter detail label for ID"), cgmManager.state.transmitterID) row( LocalizedString("Firmware", comment: "Transmitter detail label for firmware"), @@ -390,56 +393,72 @@ struct G6TransmitterDetailsView: View { } } - batterySection } .listStyle(.insetGrouped) } - @ViewBuilder - private var batterySection: some View { - if let voltageA = cgmManager.state.batteryVoltageAMillivolts, - let voltageB = cgmManager.state.batteryVoltageBMillivolts { - Section { - row( - LocalizedString("Voltage A", comment: "Transmitter detail label for battery A"), - String(format: LocalizedString("%d mV", comment: "Voltage in millivolts (1: millivolts)"), voltageA) - ) - HStack { - Text(LocalizedString("Voltage B", comment: "Transmitter detail label for battery B")) - Spacer() - Text(String(format: LocalizedString("%d mV", comment: "Voltage in millivolts (1: millivolts)"), voltageB)) - .foregroundColor(cgmManager.state.isBatteryLow ? .orange : .secondary) - } - if let resistance = cgmManager.state.batteryResistance { - row( - LocalizedString("Resistance", comment: "Transmitter detail label for battery resistance"), - String(Int(resistance)) - ) - } - if let temperature = cgmManager.state.batteryTemperature { - row( - LocalizedString("Temperature", comment: "Transmitter detail label for temperature"), - String(format: LocalizedString("%d °C", comment: "Temperature in Celsius (1: degrees)"), temperature) - ) - } - if let read = cgmManager.state.lastBatteryReadDate { + private func row(_ label: String, _ value: String) -> some View { + HStack { + Text(label) + Spacer() + Text(value).foregroundColor(.secondary) + } + } +} + +// MARK: - Battery details + +struct G6BatteryDetailsView: View { + + let cgmManager: G6CGMManager + + var body: some View { + List { + if let voltageA = cgmManager.state.batteryVoltageAMillivolts, + let voltageB = cgmManager.state.batteryVoltageBMillivolts { + Section { row( - LocalizedString("Last checked", comment: "Transmitter detail label for last battery read"), - read.formatted(date: .abbreviated, time: .shortened) + LocalizedString("Voltage A", comment: "Transmitter detail label for battery A"), + String(format: LocalizedString("%d mV", comment: "Voltage in millivolts (1: millivolts)"), voltageA) ) - } - } header: { - Text(LocalizedString("Battery", comment: "Transmitter details section header for battery")) - } footer: { - if cgmManager.state.isBatteryVeryLow { - Text(LocalizedString("Voltage B is very low. This transmitter may stop sending readings at any time, even during a session. Replace it as soon as you can.", comment: "Footer shown when battery B is very low")) - } else if cgmManager.state.isBatteryLow { - Text(LocalizedString("Voltage B is getting low. The transmitter should finish the sensor you are wearing, but order a replacement now.", comment: "Footer shown when battery B is low")) - } else { - Text(LocalizedString("Battery B is the cell that runs down first and determines whether the transmitter can finish a session.", comment: "Footer explaining what battery B means")) + HStack { + Text(LocalizedString("Voltage B", comment: "Transmitter detail label for battery B")) + Spacer() + Text(String(format: LocalizedString("%d mV", comment: "Voltage in millivolts (1: millivolts)"), voltageB)) + .foregroundColor(cgmManager.state.isBatteryLow ? .orange : .secondary) + } + if let resistance = cgmManager.state.batteryResistance { + row( + LocalizedString("Resistance", comment: "Transmitter detail label for battery resistance"), + String(Int(resistance)) + ) + } + if let temperature = cgmManager.state.batteryTemperature { + row( + LocalizedString("Temperature", comment: "Transmitter detail label for temperature"), + String(format: LocalizedString("%d °C", comment: "Temperature in Celsius (1: degrees)"), temperature) + ) + } + if let read = cgmManager.state.lastBatteryReadDate { + row( + LocalizedString("Last checked", comment: "Transmitter detail label for last battery read"), + read.formatted(date: .abbreviated, time: .shortened) + ) + } + } header: { + Text(LocalizedString("Battery", comment: "Transmitter details section header for battery")) + } footer: { + if cgmManager.state.isBatteryVeryLow { + Text(LocalizedString("Voltage B is very low. This transmitter may stop sending readings at any time, even during a session. Replace it as soon as you can.", comment: "Footer shown when battery B is very low")) + } else if cgmManager.state.isBatteryLow { + Text(LocalizedString("Voltage B is getting low. The transmitter should finish the sensor you are wearing, but order a replacement now.", comment: "Footer shown when battery B is low")) + } else { + Text(LocalizedString("Battery B is the cell that runs down first and determines whether the transmitter can finish a session.", comment: "Footer explaining what battery B means")) + } } } } + .listStyle(.insetGrouped) } private func row(_ label: String, _ value: String) -> some View { @@ -457,42 +476,66 @@ struct G6SensorLifeSettingsView: View { let cgmManager: G6CGMManager - @State private var days: Double + @State private var days: Int + @State private var savedDays: Int init(cgmManager: G6CGMManager) { self.cgmManager = cgmManager - _days = State(initialValue: Double(cgmManager.state.sensorLifeDays)) + let initial = cgmManager.state.sensorLifeDays + _days = State(initialValue: initial) + _savedDays = State(initialValue: initial) } - private var range: ClosedRange { - let bounds = TransmitterManagerState.sensorLifeDaysRange - return Double(bounds.lowerBound)...Double(bounds.upperBound) + private var isDirty: Bool { + return days != savedDays } var body: some View { List { Section { - VStack(alignment: .leading, spacing: 12) { + HStack { + Text(LocalizedString("Session length", comment: "Session length picker label")) + Spacer() Text(String( - format: LocalizedString("Session length: %d days", comment: "Session length value (1: day count)"), - Int(days) + format: LocalizedString("%d days", comment: "Session length value (1: day count)"), + savedDays )) - .font(.headline) + .foregroundColor(.secondary) + } - Slider(value: $days, in: range, step: 1) { editing in - if !editing { - cgmManager.setSensorLifeDays(Int(days)) - } + Picker(selection: $days) { + ForEach(TransmitterManagerState.sensorLifeDaysRange, id: \.self) { value in + Text(String( + format: LocalizedString("%d days", comment: "Session length option (1: day count)"), + value + )) + .tag(value) } + } label: { + Text(LocalizedString("Session length", comment: "Session length picker label")) } - } header: { - Text(LocalizedString("Session Length", comment: "Section header for session length")) + .pickerStyle(.wheel) + .labelsHidden() } footer: { Text(LocalizedString("Modified transmitters can keep a sensor running past the standard 10 days. This setting only changes when this app treats the session as finished; it does not change the sensor's accuracy. Sensor readings can drift the longer a sensor is worn, so check against a fingerstick meter if a reading does not match how you feel.", comment: "Footer explaining extended session length and its accuracy caveat")) } + + // Applied explicitly: a wheel picker fires intermediate values + // while scrolling, and each write hits persistent state. + Button(action: save) { + Text(LocalizedString("Save", comment: "Save session length button")) + } + .disabled(!isDirty) + .buttonStyle(G6PrimaryButtonStyle()) + .listRowInsets(EdgeInsets()) } .listStyle(.insetGrouped) } + + private func save() { + cgmManager.setSensorLifeDays(days) + savedDays = days + } } // MARK: - Dexcom Share upload diff --git a/G6SensorKitUI/Views/G6Graphics.swift b/G6SensorKitUI/Views/G6Graphics.swift index d91efa4..29c8cb6 100644 --- a/G6SensorKitUI/Views/G6Graphics.swift +++ b/G6SensorKitUI/Views/G6Graphics.swift @@ -411,9 +411,10 @@ struct G6SensorCodeLabelGlyph: View { struct G6TransmitterImage: View { var size: CGFloat = 88 var isActive: Bool = true + var assetName: String = "G6Transmitter" var body: some View { - if let image = UIImage(named: "G6Transmitter", in: Bundle(for: G6UICoordinator.self), compatibleWith: nil) { + if let image = UIImage(named: assetName, in: Bundle(for: G6UICoordinator.self), compatibleWith: nil) { Image(uiImage: image) .resizable() .scaledToFit() diff --git a/G6SensorKitUI/Views/G6SettingsView.swift b/G6SensorKitUI/Views/G6SettingsView.swift index ddbcc27..cfba3d4 100644 --- a/G6SensorKitUI/Views/G6SettingsView.swift +++ b/G6SensorKitUI/Views/G6SettingsView.swift @@ -22,6 +22,7 @@ final class G6SettingsViewModel: ObservableObject, G6CGMManagerObserver { let toCalibration: () -> Void let toTransmitterDetails: () -> Void + let toBatteryDetails: () -> Void let toSensorLifeSettings: () -> Void let toShareUpload: () -> Void let toReadingDetail: () -> Void @@ -35,6 +36,7 @@ final class G6SettingsViewModel: ObservableObject, G6CGMManagerObserver { cgmManager: G6CGMManager, toCalibration: @escaping () -> Void, toTransmitterDetails: @escaping () -> Void, + toBatteryDetails: @escaping () -> Void, toSensorLifeSettings: @escaping () -> Void, toShareUpload: @escaping () -> Void, toReadingDetail: @escaping () -> Void, @@ -46,6 +48,7 @@ final class G6SettingsViewModel: ObservableObject, G6CGMManagerObserver { state = cgmManager.state self.toCalibration = toCalibration self.toTransmitterDetails = toTransmitterDetails + self.toBatteryDetails = toBatteryDetails self.toSensorLifeSettings = toSensorLifeSettings self.toShareUpload = toShareUpload self.toReadingDetail = toReadingDetail @@ -180,6 +183,22 @@ final class G6SettingsViewModel: ObservableObject, G6CGMManagerObserver { state.sensorStartDate != nil && !state.isInWarmup } + /// Headline battery level for the settings row; nil until the first + /// battery read, so the row stays hidden for transmitters we have + /// never heard battery from. + var batteryLevelText: String? { + switch state.batteryLevel { + case .unknown: + return nil + case .high: + return LocalizedString("High", comment: "Battery level: high") + case .low: + return LocalizedString("Low", comment: "Battery level: low") + case .veryLow: + return LocalizedString("Replace Now", comment: "Battery level: very low, replace transmitter") + } + } + var canStartSensor: Bool { state.sensorStartDate == nil } @@ -252,7 +271,11 @@ struct G6SettingsView: View { Section { HStack { Spacer() - G6TransmitterImage(size: 200, isActive: viewModel.phase == .active) + G6TransmitterImage( + size: 200, + isActive: viewModel.phase == .active, + assetName: viewModel.state.isAnubis ? "anubis" : "G6Transmitter" + ) Spacer() } .listRowBackground(Color.clear) @@ -458,6 +481,21 @@ struct G6SettingsView: View { navRow(LocalizedString("Transmitter Details", comment: "Row to transmitter details"), "cpu", viewModel.toTransmitterDetails) + if let batteryLevel = viewModel.batteryLevelText { + Button(action: viewModel.toBatteryDetails) { + HStack { + Label(LocalizedString("Battery", comment: "Row to transmitter battery details"), systemImage: "battery.75") + Spacer() + Text(batteryLevel) + .foregroundColor(.secondary) + Image(systemName: "chevron.right") + .font(.footnote.weight(.semibold)) + .foregroundStyle(.tertiary) + } + } + .buttonStyle(G6RowButtonStyle()) + } + if viewModel.state.isAnubis { navRow(LocalizedString("Session Length", comment: "Row to session length settings"), "calendar", viewModel.toSensorLifeSettings) } From b78e81fe14f9c4d736f0947dc69dc99fcfbf8f85 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 25 Sep 2026 13:55:19 +0200 Subject: [PATCH 08/13] feat(core): add a passive session that observes the Dexcom app's traffic PassiveTransmitterSession connects alongside another client on the same phone, subscribes once to the authentication, control and backfill characteristics, and decodes the notification traffic that client's session generates. It never writes: no auth, no bonding, no commands. Only one client may talk to the transmitter from a phone; two interfere. Decoding lives in PassiveMessageHandler, a pure type adapted from CGMBLEKit's passive path so it can be unit-tested. Glucose and backfill wait for an observed time frame, because the sensor session start comes from it. The handler sits behind a lock since retarget swaps it while frames decode on the Bluetooth queue. Frames it cannot use are logged, not reported as session errors, since the link itself is fine. TransmitterSessioning is the surface both session kinds share, and the delegate now takes it instead of TransmitterSession. TransmitterConnection forwards unclaimed control and authentication values to the delegate. --- .../Model/TransmitterManagerState.swift | 6 +- .../Session/PassiveMessageHandler.swift | 218 ++++++++++++++++ .../Session/PassiveTransmitterSession.swift | 232 +++++++++++++++++ .../Session/TransmitterSession.swift | 84 +++++-- .../Transport/PeripheralManager+G5.swift | 11 + .../Transport/TransmitterConnection.swift | 38 ++- .../PassiveMessageHandlerTests.swift | 236 ++++++++++++++++++ 7 files changed, 789 insertions(+), 36 deletions(-) create mode 100644 Sources/G6SensorCore/Session/PassiveMessageHandler.swift create mode 100644 Sources/G6SensorCore/Session/PassiveTransmitterSession.swift create mode 100644 Tests/G6SensorCoreTests/PassiveMessageHandlerTests.swift diff --git a/Sources/G6SensorCore/Model/TransmitterManagerState.swift b/Sources/G6SensorCore/Model/TransmitterManagerState.swift index cd57195..6497c97 100644 --- a/Sources/G6SensorCore/Model/TransmitterManagerState.swift +++ b/Sources/G6SensorCore/Model/TransmitterManagerState.swift @@ -5,8 +5,10 @@ // Adapted for G6SensorKit from CGMBLEKit, created by Pete Schwamb on 9/11/23. // Copyright © 2023 LoopKit Authors. All rights reserved. (MIT License) // -// Adaptations: LoopKit-free (RawValue is a plain [String: Any]); -// `passiveModeEnabled` removed — G6SensorKit is active/native mode only. +// Adaptations: LoopKit-free (RawValue is a plain [String: Any]). +// `passiveModeEnabled` lives in G6CGMManagerState (the integration layer's +// persisted state); this struct keeps CGMBLEKit's key names so its rawValue +// doubles as the legacy-state reference shape for migration. // import Foundation diff --git a/Sources/G6SensorCore/Session/PassiveMessageHandler.swift b/Sources/G6SensorCore/Session/PassiveMessageHandler.swift new file mode 100644 index 0000000..0f814c3 --- /dev/null +++ b/Sources/G6SensorCore/Session/PassiveMessageHandler.swift @@ -0,0 +1,218 @@ +// +// PassiveMessageHandler.swift +// G6SensorKit +// +// Adapted for G6SensorKit from CGMBLEKit (Transmitter.swift's passive +// control-response dispatcher), originally xDripG5, created by Nathan +// Racklyeft on 11/22/15. +// Copyright © 2015 Nathan Racklyeft. (MIT License) +// Copyright © 2026 Nightscout Foundation. MIT License. +// +// Adaptation: the opcode switch, time-message caching and backfill frame +// validation follow CGMBLEKit's passive path, restructured into a pure type +// with no CoreBluetooth so the whole decode path is unit-testable. +// + +import Foundation +import os.log + + +/// What an observed frame turned into. Forwarded to the session delegate. +enum PassiveEvent { + /// Another client completed the auth exchange. Informational: control + /// subscription is not gated on this (CGMBLEKit's `dec4ff0` gating was a + /// workaround for toggling subscriptions mid-exchange, which this design + /// avoids by subscribing everything once at connect). + case observedAuthentication(isAuthenticated: Bool, isBonded: Bool) + + /// A time frame was observed; carries the derived activation date. + case transmitterTime(activationDate: Date) + + case glucose(Glucose) + + case backfill([Glucose]) + + case transmitterVersion(TransmitterVersionRxMessage) + + case unknown(Data) + + case error(TransmitterError) +} + + +/// Stateful decoder for observed traffic. A glucose frame cannot be dated +/// until a time frame has been observed (the glucose timestamp is seconds +/// since transmitter activation), so time frames are cached; frames arriving +/// before the first one are dropped with an observation error. +final class PassiveMessageHandler { + + private let transmitterID: String + + /// Seeded from persisted state and corrected by every observed time + /// frame. The seed alone does not let a reading through: the sensor + /// session start only comes from a time frame, and a reading without one + /// would look like the session ended. Frames before the first time frame + /// are therefore still dropped. + private(set) var activationDate: Date? + + private var lastTimeMessage: TransmitterTimeRxMessage? + + private var lastCalibration: CalibrationDataRxMessage? + + /// Frames accumulate whenever they arrive; the acknowledgement on the + /// control characteristic is what validates and triggers decoding. + private var backfillBuffer: GlucoseBackfillFrameBuffer? + + private let log = OSLog(category: "PassiveMessageHandler") + + init(transmitterID: String, activationDate: Date? = nil) { + self.transmitterID = transmitterID + self.activationDate = activationDate + } + + // MARK: - Authentication characteristic + + func handleAuthentication(_ data: Data) -> [PassiveEvent] { + // Only the challenge response carries anything worth reporting; the + // rest of the auth exchange is ignored. + guard let message = AuthChallengeRxMessage(data: data) else { + return [] + } + + return [.observedAuthentication(isAuthenticated: message.isAuthenticated, isBonded: message.isBonded)] + } + + // MARK: - Control characteristic + + func handleControl(_ data: Data, at date: Date = Date()) -> [PassiveEvent] { + guard let first = data.first, let opcode = Opcode(rawValue: first) else { + return [.unknown(data)] + } + + switch opcode { + case .transmitterTimeRx: + guard let message = TransmitterTimeRxMessage(data: data) else { + return [.unknown(data)] + } + + lastTimeMessage = message + let activation = date.addingTimeInterval(-TimeInterval(message.currentTime)) + activationDate = activation + return [.transmitterTime(activationDate: activation)] + + case .glucoseRx, .glucoseG6Rx: + guard let message = GlucoseRxMessage(data: data) else { + return [.unknown(data)] + } + + guard let timeMessage = lastTimeMessage, let activationDate = activationDate else { + return [.error(.observationError( + "Glucose frame observed before any time frame; cannot date it, dropping"))] + } + + let glucose = Glucose( + transmitterID: transmitterID, + glucoseMessage: message, + timeMessage: timeMessage, + calibrationMessage: lastCalibration, + activationDate: activationDate + ) + return [.glucose(glucose)] + + case .glucoseBackfillRx: + guard let ack = GlucoseBackfillRxMessage(data: data) else { + return [.unknown(data)] + } + return handleBackfillAcknowledgement(ack) + + case .calibrationDataRx: + guard let message = CalibrationDataRxMessage(data: data) else { + return [.unknown(data)] + } + lastCalibration = message + return [] + + case .transmitterVersionRx: + guard let message = TransmitterVersionRxMessage(data: data) else { + return [.unknown(data)] + } + return [.transmitterVersion(message)] + + default: + return [.unknown(data)] + } + } + + // MARK: - Backfill characteristic + + /// Appends an observed frame to the buffer. Decoding happens when the + /// acknowledgement arrives on the control characteristic. + func handleBackfill(_ data: Data) { + guard data.count > 2 else { + return + } + + // Byte 0 is the frame index, byte 1 the buffer identifier. + if data[0] == 1 { + log.default("Starting new observed backfill buffer with ID %d", data[1]) + backfillBuffer = GlucoseBackfillFrameBuffer(identifier: data[1]) + } + + backfillBuffer?.append(data) + } + + // MARK: - Private + + private func handleBackfillAcknowledgement(_ ack: GlucoseBackfillRxMessage) -> [PassiveEvent] { + defer { backfillBuffer = nil } + + guard let buffer = backfillBuffer, buffer.count > 0 else { + // Nothing observed for the window: an empty result, not a failure. + if ack.bufferLength == 0 { + return [] + } + return [.error(.observationError( + "Backfill acknowledged \(ack.bufferLength) bytes but no frames were observed"))] + } + + let complete = buffer.count == Int(ack.bufferLength) + + if complete { + guard ack.bufferCRC == buffer.crc16 else { + return [.error(.observationError( + "Backfill expected CRC \(String(format: "%04x", ack.bufferCRC)), but was \(String(format: "%04x", buffer.crc16))"))] + } + } else { + // The CRC covers the whole buffer, so it cannot check a prefix. + log.default("Observed backfill incomplete: %{public}@ of %{public}@ bytes; delivering what arrived", + String(buffer.count), String(ack.bufferLength)) + } + + guard let timeMessage = lastTimeMessage, let activationDate = activationDate else { + return [.error(.observationError( + "Backfill observed before any time frame; cannot date it, dropping"))] + } + + let glucose = buffer.glucose.map { + Glucose(transmitterID: transmitterID, status: ack.status, glucoseMessage: $0, timeMessage: timeMessage, activationDate: activationDate) + } + + guard !glucose.isEmpty else { + return [] + } + + guard glucose.first!.glucoseMessage.timestamp <= glucose.last!.glucoseMessage.timestamp else { + return [.error(.observationError( + "Backfill timestamps out of order: \(glucose.first!.glucoseMessage.timestamp) - \(glucose.last!.glucoseMessage.timestamp)"))] + } + + var events: [PassiveEvent] = [.backfill(glucose)] + + if !complete { + events.append(.error(.observationError( + "Backfill delivered \(glucose.count) readings but was incomplete"))) + } + + return events + } +} diff --git a/Sources/G6SensorCore/Session/PassiveTransmitterSession.swift b/Sources/G6SensorCore/Session/PassiveTransmitterSession.swift new file mode 100644 index 0000000..b276d19 --- /dev/null +++ b/Sources/G6SensorCore/Session/PassiveTransmitterSession.swift @@ -0,0 +1,232 @@ +// +// PassiveTransmitterSession.swift +// G6SensorKit +// +// Adapted for G6SensorKit from CGMBLEKit (Transmitter.swift, passive path), +// originally xDripG5, created by Nathan Racklyeft on 11/22/15. +// Copyright © 2015 Nathan Racklyeft. (MIT License) +// Copyright © 2026 Nightscout Foundation. MIT License. +// +// Adaptations: +// - All three subscriptions happen once, at connect, and are never toggled. +// CGMBLEKit subscribes to control only after observing an authenticated +// session (commit dec4ff0) because toggling subscriptions mid-exchange +// confused CoreBluetooth; subscribing everything up front sidesteps that +// entirely. If field testing shows missed traffic, gate the control +// subscription on `PassiveEvent.observedAuthentication` — the handler +// already parses it. +// - There is no write API in scope here at all: no auth, no bonding, no +// commands, no active reads, no disconnect request. The link drops when +// the driving client is done, and TransmitterConnection's reconnect loop +// picks the transmitter up again on its next cycle. +// +// A passive session never writes a request to the transmitter. It connects, +// subscribes to the authentication, control and backfill characteristics +// once, and decodes the notification traffic another client on the same +// phone (the Dexcom app, or the transmitter's bonded session) generates. +// iOS shares the system-level connection between apps, so the Dexcom app's +// five-minute polling drives the exchange and this session observes it. +// +// Because nothing here writes, passive mode cannot start or stop sessions, +// calibrate, read battery status, or request backfill. +// + +import Foundation +import CoreBluetooth +import os.log + + +public final class PassiveTransmitterSession: TransmitterSessioning { + + /// The ID of the transmitter to connect to + public var ID: String { + return id.id + } + + private var id: TransmitterID + + public weak var delegate: TransmitterSessionDelegate? + + /// Frames are decoded on the Bluetooth queue while `retarget` swaps the + /// handler from the caller's thread, so every access goes through here. + private let handler: Locked + + private let log = OSLog(category: "PassiveTransmitterSession") + + private let connection: TransmitterConnection + + private let delegateQueue = DispatchQueue(label: "org.nightscout.G6SensorKit.passiveSessionDelegateQueue", qos: .unspecified) + + /// - Parameter activationDate: the persisted transmitter start date. It + /// seeds the decoder, but readings still wait for an observed time + /// frame (see `PassiveMessageHandler.activationDate`). + public init(id: String, peripheralIdentifier: UUID? = nil, activationDate: Date? = nil) { + self.id = TransmitterID(id: id) + self.handler = Locked(PassiveMessageHandler(transmitterID: id, activationDate: activationDate)) + self.connection = TransmitterConnection(peripheralIdentifier: peripheralIdentifier) + + connection.delegate = self + } + + /// Starts (or resumes) looking for the transmitter. Idempotent. + public func start() { + connection.stayConnected = true + connection.scanForPeripheral() + } + + /// Stops the reconnect loop and drops any live connection. + public func stop() { + connection.stayConnected = false + connection.disconnect() + } + + /// Points this session at a different transmitter, keeping the existing + /// connection and its central manager. + public func retarget(id newID: String) { + log.default("Retargeting session to transmitter %{public}@", newID) + + connection.stayConnected = false + connection.disconnect() + + self.id = TransmitterID(id: newID) + handler.value = PassiveMessageHandler(transmitterID: newID) + connection.peripheralIdentifier = nil + + start() + } + + public var peripheralIdentifier: UUID? { + get { + return connection.peripheralIdentifier + } + set { + connection.peripheralIdentifier = newValue + } + } + + // MARK: - Event forwarding + + private func forward(_ events: [PassiveEvent]) { + guard !events.isEmpty else { + return + } + + delegateQueue.async { + for event in events { + switch event { + case .observedAuthentication(let isAuthenticated, let isBonded): + self.log.default("Observed authentication exchange (authenticated: %{public}@, bonded: %{public}@)", + String(describing: isAuthenticated), String(describing: isBonded)) + case .transmitterTime(let activationDate): + self.delegate?.transmitterSession(self, didReadTransmitterTime: activationDate) + case .glucose(let glucose): + self.delegate?.transmitterSession(self, didRead: glucose) + case .backfill(let glucose): + self.delegate?.transmitterSession(self, didReadBackfill: glucose) + case .transmitterVersion(let message): + self.delegate?.transmitterSession(self, didReadTransmitterVersion: message) + case .unknown(let data): + self.delegate?.transmitterSession(self, didReadUnknownData: data) + case .error(let error): + // A frame this session could not use — seen before a time + // frame, or a partial backfill — says nothing about the + // link, which the other client is still driving. Reporting + // it as a session error would flip the UI to searching + // and raise CGM errors in the host while all is well. + self.log.error("Observation: %{public}@", String(describing: error)) + } + } + } + } +} + + +extension PassiveTransmitterSession: TransmitterConnectionDelegate { + + func transmitterConnection(_ connection: TransmitterConnection, peripheralManager: PeripheralManager, isReadyWithError error: Error?) { + if let error = error { + delegateQueue.async { + self.delegate?.transmitterSession(self, didError: error) + } + return + } + + delegateQueue.async { + self.delegate?.transmitterSessionDidConnect(self) + } + + peripheralManager.perform { (peripheral) in + do { + // The whole setup: subscribe and get out of the way. No + // writes, and crucially no disconnect — the link belongs to + // the client driving the exchange. + try peripheral.listenToCharacteristic(.authentication) + try peripheral.listenToCharacteristic(.control) + try peripheral.listenToCharacteristic(.backfill) + self.log.default("Listening for another client's session traffic") + } catch let error { + self.delegateQueue.async { + self.delegate?.transmitterSession(self, didError: error) + } + } + } + } + + func transmitterConnection(_ connection: TransmitterConnection, shouldConnectPeripheral peripheral: CBPeripheral, advertisementData: [String: Any]) -> Bool { + // G6/ONE transmitters advertise a name of "DexcomXX", where "XX" is + // the last two characters of the transmitter ID. Unlike the active + // session there is no auth handshake to reject a wrong transmitter, + // so this name match is the only identity check. + let advertisedName = advertisementData[CBAdvertisementDataLocalNameKey] as? String + let expected = id.id.suffix(2).uppercased() + + if let name = advertisedName ?? peripheral.name { + let matches = name.suffix(2).uppercased() == expected + if matches { + log.default("Matched transmitter %{public}@", name) + } else { + log.info("Ignoring peripheral %{public}@ (expected suffix %{public}@)", name, String(expected)) + } + return matches + } + + // No name from either source. The scan is already filtered to the + // Dexcom advertisement service, and a system-connected peripheral on + // the user's own phone is virtually always their transmitter, so + // attempt the connection rather than stranding setup. + log.default("Peripheral advertised no name; attempting connection anyway (passive mode has no auth check)") + return true + } + + func transmitterConnection(_ connection: TransmitterConnection, didUpdatePeripheralIdentifier identifier: UUID?) { + delegateQueue.async { + self.delegate?.transmitterSession(self, didUpdatePeripheralIdentifier: identifier) + } + } + + func transmitterConnection(_ connection: TransmitterConnection, didReceiveAuthenticationResponse response: Data) { + var events: [PassiveEvent] = [] + handler.mutate { events = $0.handleAuthentication(response) } + forward(events) + } + + func transmitterConnection(_ connection: TransmitterConnection, didReceiveControlResponse response: Data) { + var events: [PassiveEvent] = [] + handler.mutate { events = $0.handleControl(response) } + forward(events) + } + + func transmitterConnection(_ connection: TransmitterConnection, didReceiveBackfillResponse response: Data) { + handler.mutate { $0.handleBackfill(response) } + } +} + + +extension PassiveTransmitterSession: CustomDebugStringConvertible { + public var debugDescription: String { + return [ + "## PassiveTransmitterSession", + String(reflecting: connection), + ].joined(separator: "\n") + } +} diff --git a/Sources/G6SensorCore/Session/TransmitterSession.swift b/Sources/G6SensorCore/Session/TransmitterSession.swift index 17d77a9..20d3e09 100644 --- a/Sources/G6SensorCore/Session/TransmitterSession.swift +++ b/Sources/G6SensorCore/Session/TransmitterSession.swift @@ -7,8 +7,9 @@ // Copyright © 2015 Nathan Racklyeft. All rights reserved. (MIT License) // // Adaptations (behavioural reference: xDrip4iOS — no code copied): -// - Active/native mode ONLY: the passive "observe another app's session" -// path is removed by design. G6SensorKit owns the transmitter. +// - Active/native mode: this session owns the transmitter. The passive +// "observe another app's session" mode lives separately in +// PassiveTransmitterSession. // - Per-connection flow follows the Firefly ordering: authenticate → // bond if needed → subscribe control + backfill → time → pending // commands (session stop / session start / calibrate / reset) → @@ -25,42 +26,70 @@ import CoreBluetooth import os.log +/// The surface shared by the active (`TransmitterSession`) and passive +/// (`PassiveTransmitterSession`) sessions, so the integration layer can hold +/// either without knowing which one is driving the radio. +public protocol TransmitterSessioning: AnyObject { + /// The ID of the transmitter the session connects to. + var ID: String { get } + + /// Called on a private background queue. It is the responsibility of the + /// client to ensure thread-safety. + var delegate: TransmitterSessionDelegate? { get set } + + /// The known peripheral identifier; persist it to skip rediscovery. + var peripheralIdentifier: UUID? { get set } + + /// Starts (or resumes) looking for the transmitter. Idempotent. + func start() + + /// Stops the reconnect loop and drops any live connection. + func stop() + + /// Points the session at a different transmitter, keeping the existing + /// connection and its central manager. + func retarget(id: String) +} + +/// These methods are called on a private background queue. It is the responsibility of the client to ensure thread-safety. public protocol TransmitterSessionDelegate: AnyObject { - func transmitterSessionDidConnect(_ session: TransmitterSession) + func transmitterSessionDidConnect(_ session: any TransmitterSessioning) - func transmitterSession(_ session: TransmitterSession, didError error: Error) + func transmitterSession(_ session: any TransmitterSessioning, didError error: Error) - func transmitterSession(_ session: TransmitterSession, didRead glucose: Glucose) + func transmitterSession(_ session: any TransmitterSessioning, didRead glucose: Glucose) - func transmitterSession(_ session: TransmitterSession, didReadBackfill glucose: [Glucose]) + func transmitterSession(_ session: any TransmitterSessioning, didReadBackfill glucose: [Glucose]) - func transmitterSession(_ session: TransmitterSession, didReadTransmitterVersion message: TransmitterVersionRxMessage) + func transmitterSession(_ session: any TransmitterSessioning, didReadTransmitterVersion message: TransmitterVersionRxMessage) - func transmitterSession(_ session: TransmitterSession, didReadBattery message: BatteryStatusRxMessage) + func transmitterSession(_ session: any TransmitterSessioning, didReadBattery message: BatteryStatusRxMessage) /// The transmitter's clock was read, which means authentication - /// succeeded. Reported separately from glucose because a stopped or + /// succeeded — or, in a passive session, that another client's time read + /// was observed. Reported separately from glucose because a stopped or /// failed sensor produces no usable reading, and the app still needs to /// know it is talking to the transmitter. - func transmitterSession(_ session: TransmitterSession, didReadTransmitterTime activationDate: Date) + func transmitterSession(_ session: any TransmitterSessioning, didReadTransmitterTime activationDate: Date) - func transmitterSession(_ session: TransmitterSession, didReadUnknownData data: Data) + func transmitterSession(_ session: any TransmitterSessioning, didReadUnknownData data: Data) /// The known peripheral identifier changed; persist it. - func transmitterSession(_ session: TransmitterSession, didUpdatePeripheralIdentifier identifier: UUID?) + func transmitterSession(_ session: any TransmitterSessioning, didUpdatePeripheralIdentifier identifier: UUID?) /// A bond request was sent; the user must accept the iOS pairing prompt - /// within the keep-alive window (~60 s). - func transmitterSessionDidRequestBond(_ session: TransmitterSession) + /// within the keep-alive window (~60 s). Active sessions only — a + /// passive session never writes, so it never bonds. + func transmitterSessionDidRequestBond(_ session: any TransmitterSessioning) } /// These methods are called on a private background queue. It is the responsibility of the client to ensure thread-safety. public protocol TransmitterCommandSource: AnyObject { - func dequeuePendingCommand(for session: TransmitterSession) -> Command? + func dequeuePendingCommand(for session: any TransmitterSessioning) -> Command? - func transmitterSession(_ session: TransmitterSession, didFail command: Command, with error: Error) + func transmitterSession(_ session: any TransmitterSessioning, didFail command: Command, with error: Error) - func transmitterSession(_ session: TransmitterSession, didComplete command: Command, response: TransmitterRxMessage?) + func transmitterSession(_ session: any TransmitterSessioning, didComplete command: Command, response: TransmitterRxMessage?) } public enum TransmitterError: Error { @@ -83,7 +112,7 @@ extension TransmitterError: CustomStringConvertible { } -public final class TransmitterSession: TransmitterConnectionDelegate { +public final class TransmitterSession: TransmitterSessioning, TransmitterConnectionDelegate { /// Seconds the transmitter is asked to keep the link alive while the user /// responds to the iOS pairing prompt. @@ -401,11 +430,20 @@ public final class TransmitterSession: TransmitterConnectionDelegate { } + func transmitterConnection(_ connection: TransmitterConnection, didReceiveControlResponse response: Data) { + // Control responses to this session's own requests are claimed by + // the peripheral manager's conditions. Anything arriving here is + // another client's traffic, which an active session has no use for. + } + + func transmitterConnection(_ connection: TransmitterConnection, didReceiveAuthenticationResponse response: Data) { + // See didReceiveControlResponse. + } + func transmitterConnection(_ connection: TransmitterConnection, didReceiveBackfillResponse response: Data) { guard response.count > 2 else { return } - backfillLock.lock() defer { backfillLock.broadcast() @@ -703,12 +741,4 @@ fileprivate extension PeripheralManager { } catch { } } - - func listenToCharacteristic(_ characteristic: CGMServiceCharacteristicUUID) throws { - do { - try setNotifyValue(true, for: characteristic) - } catch let error { - throw TransmitterError.controlError("Error enabling notification for \(characteristic): \(error)") - } - } } diff --git a/Sources/G6SensorCore/Transport/PeripheralManager+G5.swift b/Sources/G6SensorCore/Transport/PeripheralManager+G5.swift index c1caac4..e23c98c 100644 --- a/Sources/G6SensorCore/Transport/PeripheralManager+G5.swift +++ b/Sources/G6SensorCore/Transport/PeripheralManager+G5.swift @@ -187,6 +187,17 @@ extension PeripheralManager { try writeValue(message.data, for: characteristic, type: type, timeout: timeout) } + + /// Subscribes to a characteristic's notifications without expecting a + /// response to anything — the passive session's only use of the radio. + /// - Throws: TransmitterError.controlError + func listenToCharacteristic(_ characteristic: CGMServiceCharacteristicUUID) throws { + do { + try setNotifyValue(true, for: characteristic) + } catch let error { + throw TransmitterError.controlError("Error enabling notification for \(characteristic): \(error)") + } + } } diff --git a/Sources/G6SensorCore/Transport/TransmitterConnection.swift b/Sources/G6SensorCore/Transport/TransmitterConnection.swift index 94bd855..ef56657 100644 --- a/Sources/G6SensorCore/Transport/TransmitterConnection.swift +++ b/Sources/G6SensorCore/Transport/TransmitterConnection.swift @@ -22,8 +22,11 @@ // // The central is owned by this instance, as CGMBLEKit does it. // -// There is no passive mode. This connection owns the transmitter; it never -// observes another app's session. +// Both session types share this connection: an active session drives the +// exchange with writes, a passive session only subscribes and observes +// another app's traffic. Unsolicited values on all three notify +// characteristics are forwarded to the delegate; which of them matter +// depends on the session. // import CoreBluetooth @@ -49,6 +52,16 @@ protocol TransmitterConnectionDelegate: AnyObject { /// notifications rather than as a command response, so it comes through /// here rather than the peripheral manager's condition machinery. func transmitterConnection(_ connection: TransmitterConnection, didReceiveBackfillResponse response: Data) + + /// Unsolicited data on the control characteristic. In an active session + /// control responses are consumed by the peripheral manager's condition + /// machinery, so anything arriving here is traffic generated by someone + /// else's session — the raw material of passive mode. + func transmitterConnection(_ connection: TransmitterConnection, didReceiveControlResponse response: Data) + + /// Unsolicited data on the authentication characteristic. Only passive + /// sessions listen to this, to observe another client authenticating. + func transmitterConnection(_ connection: TransmitterConnection, didReceiveAuthenticationResponse response: Data) } @@ -339,15 +352,26 @@ extension TransmitterConnection: PeripheralManagerDelegate { } func peripheralManager(_ manager: PeripheralManager, didUpdateValueFor characteristic: CBCharacteristic) { - // Control and authentication responses are consumed by the peripheral - // manager's condition machinery as part of the active command flow. - // Only backfill arrives unsolicited. + // Control and authentication responses to our own requests are + // consumed by the peripheral manager's condition machinery as part + // of the active command flow. Everything arriving here was not + // claimed by a condition: backfill frames (unsolicited by design) + // and, for a passive session, another client's session traffic. guard let value = characteristic.value, - case .backfill? = CGMServiceCharacteristicUUID(rawValue: characteristic.uuid.uuidString.uppercased()) + let characteristicID = CGMServiceCharacteristicUUID(rawValue: characteristic.uuid.uuidString.uppercased()) else { return } - delegate?.transmitterConnection(self, didReceiveBackfillResponse: value) + switch characteristicID { + case .backfill: + delegate?.transmitterConnection(self, didReceiveBackfillResponse: value) + case .control: + delegate?.transmitterConnection(self, didReceiveControlResponse: value) + case .authentication: + delegate?.transmitterConnection(self, didReceiveAuthenticationResponse: value) + default: + break + } } } diff --git a/Tests/G6SensorCoreTests/PassiveMessageHandlerTests.swift b/Tests/G6SensorCoreTests/PassiveMessageHandlerTests.swift new file mode 100644 index 0000000..64091e5 --- /dev/null +++ b/Tests/G6SensorCoreTests/PassiveMessageHandlerTests.swift @@ -0,0 +1,236 @@ +// +// PassiveMessageHandlerTests.swift +// G6SensorKitTests +// +// Copyright © 2026 Nightscout Foundation. MIT License. +// +// The captured-traffic fixtures come from CGMBLEKit's test suite +// (GlucoseTests, GlucoseBackfillMessageTests), originally xDripG5. +// Copyright © 2016-2018 LoopKit Authors. (MIT License) +// + +import XCTest +@testable import G6SensorCore + +class PassiveMessageHandlerTests: XCTestCase { + + // Captured G6 traffic, same fixtures as the codec tests. + let timeFrame = Data(hexadecimalString: "2500470272007cff710001000000fa1d")! + let glucoseFrame = Data(hexadecimalString: "3100680a00008a715700cc0006ffc42a")! + let calibrationFrame = Data(hexadecimalString: "33002b290090012900ae00800050e929001225")! + let versionFrame = Data(hexadecimalString: "4b0001000011df2900005100037000f00009b6")! + let backfillAck = Data(hexadecimalString: "51000100b7ff52006604530032000000e6cb9805")! + let backfillFrames = [ + Data(hexadecimalString: "0100bc460000b7ff52008b0006eee30053008500")!, + Data(hexadecimalString: "020006eb0f025300800006ee3a0353007e0006f5")!, + Data(hexadecimalString: "030066045300790006f8")!, + ] + + let now = Date(timeIntervalSince1970: 1_700_000_000) + + private func handler(seedActivation: Bool = false) -> PassiveMessageHandler { + PassiveMessageHandler( + transmitterID: "123456", + activationDate: seedActivation ? now.addingTimeInterval(-1_000_000) : nil + ) + } + + // MARK: - Authentication + + func testAuthChallengeIsReported() { + let events = handler().handleAuthentication(Data(hexadecimalString: "050101")!) + + guard case .observedAuthentication(let isAuthenticated, let isBonded) = events.first else { + return XCTFail("Expected observedAuthentication, got \(events)") + } + XCTAssertTrue(isAuthenticated) + XCTAssertTrue(isBonded) + } + + func testOtherAuthTrafficIsIgnored() { + // AuthRequestRx (0x03) carries nothing worth reporting. + XCTAssertTrue(handler().handleAuthentication(Data(hexadecimalString: "0300a1b2c3d4e5f6a7b8")!).isEmpty) + } + + // MARK: - Time and glucose + + func testGlucoseDroppedBeforeAnyTimeFrame() { + let events = handler().handleControl(glucoseFrame, at: now) + + guard case .error(let error) = events.first, events.count == 1 else { + return XCTFail("Expected a single error, got \(events)") + } + guard case .observationError = error else { + return XCTFail("Expected observationError, got \(error)") + } + } + + func testSeededActivationDateAloneCannotDateGlucose() { + // The session start time comes from the time message, not the + // activation date, so a seeded date alone is not enough. + let events = handler(seedActivation: true).handleControl(glucoseFrame, at: now) + + guard case .error = events.first, events.count == 1 else { + return XCTFail("Expected a single error, got \(events)") + } + } + + func testTimeFrameDerivesActivationDate() { + let handler = handler() + let events = handler.handleControl(timeFrame, at: now) + + let currentTime = TransmitterTimeRxMessage(data: timeFrame)!.currentTime + let expected = now.addingTimeInterval(-TimeInterval(currentTime)) + + guard case .transmitterTime(let activationDate) = events.first, events.count == 1 else { + return XCTFail("Expected transmitterTime, got \(events)") + } + XCTAssertEqual(expected, activationDate) + XCTAssertEqual(expected, handler.activationDate) + } + + func testGlucoseAfterTimeFrame() { + let handler = handler() + handler.handleControl(timeFrame, at: now) + let events = handler.handleControl(glucoseFrame, at: now) + + guard case .glucose(let glucose) = events.first, events.count == 1 else { + return XCTFail("Expected glucose, got \(events)") + } + XCTAssertEqual(204, glucose.glucoseMgDL) + XCTAssertEqual(.known(.ok), glucose.state) + XCTAssertTrue(glucose.hasValidSensorSession) + XCTAssertNil(glucose.lastCalibration) + } + + // MARK: - Calibration + + func testCalibrationIsCachedAndAttachedToLaterReadings() { + let handler = handler() + XCTAssertTrue(handler.handleControl(calibrationFrame, at: now).isEmpty) + + handler.handleControl(timeFrame, at: now) + let events = handler.handleControl(glucoseFrame, at: now) + + guard case .glucose(let glucose) = events.first else { + return XCTFail("Expected glucose, got \(events)") + } + XCTAssertNotNil(glucose.lastCalibration) + } + + // MARK: - Transmitter version + + func testTransmitterVersionIsForwarded() { + let events = handler().handleControl(versionFrame, at: now) + + guard case .transmitterVersion(let message) = events.first, events.count == 1 else { + return XCTFail("Expected transmitterVersion, got \(events)") + } + XCTAssertEqual(112, message.transmitterExpiryInDays) + } + + // MARK: - Backfill + + private func primedHandler() -> PassiveMessageHandler { + let handler = handler() + handler.handleControl(timeFrame, at: now) + return handler + } + + func testCompleteBackfill() { + let handler = primedHandler() + for frame in backfillFrames { + handler.handleBackfill(frame) + } + let events = handler.handleControl(backfillAck, at: now) + + guard case .backfill(let readings) = events.first, events.count == 1 else { + return XCTFail("Expected backfill, got \(events)") + } + XCTAssertEqual(5, readings.count) + XCTAssertEqual(139, readings.first?.glucoseMgDL) + XCTAssertEqual(121, readings.last?.glucoseMgDL) + } + + func testBackfillAckWithoutFramesIsAnError() { + let events = primedHandler().handleControl(backfillAck, at: now) + + guard case .error = events.first, events.count == 1 else { + return XCTFail("Expected a single error, got \(events)") + } + } + + func testBackfillEmptyWindowIsNotAnError() { + // An ack reporting zero bytes stored is an empty result. + var ack = Data([0x51, 0x00, 0x00, 0x00]) + ack.append(UInt32(1000)) + ack.append(UInt32(2000)) + ack.append(UInt32(0)) + ack.append(UInt16(0)) + ack = ack.appendingCRC() + + XCTAssertTrue(primedHandler().handleControl(ack, at: now).isEmpty) + } + + func testBackfillCRCMismatch() { + let handler = primedHandler() + for frame in backfillFrames { + handler.handleBackfill(frame) + } + + // Same ack but a corrupted buffer CRC (message CRC recomputed so the + // ack itself still parses). + var bytes = [UInt8](backfillAck) + bytes[16] ^= 0xff + let corrupted = Data(bytes[0..<18]).appendingCRC() + + let events = handler.handleControl(corrupted, at: now) + + guard case .error = events.first, events.count == 1 else { + return XCTFail("Expected a single error, got \(events)") + } + } + + func testPartialBackfillDeliversPrefixWithError() { + let handler = primedHandler() + // Two of the three frames; the buffer is a valid prefix. + handler.handleBackfill(backfillFrames[0]) + handler.handleBackfill(backfillFrames[1]) + let events = handler.handleControl(backfillAck, at: now) + + guard case .backfill(let readings) = events.first else { + return XCTFail("Expected backfill, got \(events)") + } + // Each full frame carries two 8-byte sub-messages past the header. + XCTAssertEqual(4, readings.count) + guard case .error = events.last, events.count == 2 else { + return XCTFail("Expected a trailing incompleteness error, got \(events)") + } + } + + func testBackfillDroppedBeforeAnyTimeFrame() { + let handler = handler() + for frame in backfillFrames { + handler.handleBackfill(frame) + } + let events = handler.handleControl(backfillAck, at: now) + + guard case .error = events.first, events.count == 1 else { + return XCTFail("Expected a single error, got \(events)") + } + } + + // MARK: - Unknown traffic + + func testUnknownOpcode() { + // 0x09 (disconnectTx) is a known opcode but meaningless as observed + // traffic; 0x7f is not an opcode at all. + for hex in ["0900aa55", "7f00aa55"] { + let events = handler().handleControl(Data(hexadecimalString: hex)!, at: now) + guard case .unknown(let data) = events.first, events.count == 1 else { + return XCTFail("Expected unknown for \(hex), got \(events)") + } + XCTAssertEqual(hex, data.hexadecimalString) + } + } +} From a869ab93161227f77ca4ca9ed888e29004827e4b Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 25 Sep 2026 13:55:19 +0200 Subject: [PATCH 09/13] feat(passive): passive mode in the CGM manager, onboarding and settings The manager holds either session kind and persists passiveModeEnabled. Direct stays the default. Switching modes rebuilds the session and clears queued commands, which passive mode cannot deliver and which must not replay against a session the Dexcom app has since started. Settings saved by CGMBLEKit (no sensorLifeDays, no passiveModeEnabled) migrate into passive mode with onboarding complete, and their sensorStartOffset becomes a sensorStartDate. Onboarding gains a connection-mode screen after the transmitter ID. The manager is created in passive mode until the user chooses, so it never logs in or pairs with a transmitter the Dexcom app already holds. Passive mode skips the sensor code screen, and settings hide session, calibration and session-length actions the Dexcom app owns there. --- G6SensorKit/G6CGMManager.swift | 136 +++++++++++++------ G6SensorKit/G6CGMManagerState.swift | 40 +++++- G6SensorKitUI/G6UICoordinator.swift | 44 +++++- G6SensorKitUI/Localizable.xcstrings | 64 +++++++++ G6SensorKitUI/Views/G6DetailViews.swift | 23 ++++ G6SensorKitUI/Views/G6Graphics.swift | 3 +- G6SensorKitUI/Views/G6OnboardingViews.swift | 140 +++++++++++++++++--- G6SensorKitUI/Views/G6SettingsView.swift | 10 +- 8 files changed, 393 insertions(+), 67 deletions(-) diff --git a/G6SensorKit/G6CGMManager.swift b/G6SensorKit/G6CGMManager.swift index 48707f7..c84270c 100644 --- a/G6SensorKit/G6CGMManager.swift +++ b/G6SensorKit/G6CGMManager.swift @@ -4,11 +4,11 @@ // // Copyright © 2026 Nightscout Foundation. MIT License. // -// LoopKit CGMManager conformance over G6SensorCore's owned, active -// transmitter session. Unlike CGMBLEKit (which in Loop always piggybacks -// the Dexcom app's session) this manager owns the transmitter: it -// authenticates, starts and stops sessions, sends calibrations, and -// requests backfill. +// LoopKit CGMManager conformance over G6SensorCore's transmitter sessions. +// Two modes: direct (the manager owns the transmitter — it authenticates, +// starts and stops sessions, sends calibrations, requests backfill) and +// passive (the manager observes the session another client, such as the +// Dexcom app, drives — like CGMBLEKit). // import Foundation @@ -66,7 +66,7 @@ public final class G6CGMManager: CGMManager { private let lockedState: Locked - public private(set) var session: TransmitterSession? + public private(set) var session: (any TransmitterSessioning)? /// Commands queued for the next connection cycle. private let lockedCommandQueue: Locked = Locked(CommandQueue()) @@ -186,6 +186,7 @@ public final class G6CGMManager: CGMManager { "## G6CGMManager", "transmitterID: \(state.transmitterID)", "model: \(state.deviceModel)", + "mode: \(state.passiveModeEnabled ? "passive" : "direct")", "firmware: \(state.firmwareVersion ?? "unknown")", "isAnubis: \(state.isAnubis)", "sensorStartDate: \(String(describing: state.sensorStartDate))", @@ -287,9 +288,19 @@ public final class G6CGMManager: CGMManager { return #else connectionPhase = .searching - let session = TransmitterSession(id: state.transmitterID, peripheralIdentifier: state.peripheralIdentifier) + let session: any TransmitterSessioning + if state.passiveModeEnabled { + session = PassiveTransmitterSession( + id: state.transmitterID, + peripheralIdentifier: state.peripheralIdentifier, + activationDate: state.transmitterStartDate + ) + } else { + let active = TransmitterSession(id: state.transmitterID, peripheralIdentifier: state.peripheralIdentifier) + active.commandSource = self + session = active + } session.delegate = self - session.commandSource = self self.session = session session.start() #endif @@ -297,6 +308,14 @@ public final class G6CGMManager: CGMManager { /// Queues a device command for the next connection cycle. public func enqueue(_ command: Command) { + // A passive session never writes, so a command could never be + // delivered. The UI hides the command rows in passive mode; this is + // the backstop. + guard !state.passiveModeEnabled else { + log.error("Dropping command %{public}@: passive mode cannot write to the transmitter", String(describing: command)) + return + } + // Newest wins. Repeated trips through setup used to stack session // starts — seven went out in one connection — and because the queue // is persisted, a stale code-less start could reach the transmitter @@ -376,6 +395,33 @@ public final class G6CGMManager: CGMManager { } } + /// Switches between passive (observe the Dexcom app's session) and direct + /// (own the transmitter) mode. The live session can't change nature, so + /// it is torn down and rebuilt as the other kind. + public func setPassiveModeEnabled(_ enabled: Bool) { + guard enabled != state.passiveModeEnabled else { + return + } + + log.default("Switching to %{public}@ mode", enabled ? "passive" : "direct") + + session?.stop() + session = nil + + // Queued commands belong to the mode they were queued in. Passive + // mode can't deliver them, and carrying them back into direct mode + // would replay a stale stop or start — possibly days later, against + // a session the Dexcom app has since started. + lockedCommandQueue.mutate { $0.removeAll() } + + mutateState { state in + state.passiveModeEnabled = enabled + state.pendingCommands = [] + } + + startSession() + } + /// Switches to a different transmitter without tearing down the CGM. /// /// Everything scoped to the old transmitter is cleared — its clock, @@ -403,10 +449,11 @@ public final class G6CGMManager: CGMManager { // Best effort: if the old transmitter happens to be connected // right now, tell it to stop. Once it is off the sensor there is - // nothing to send to, so this is not worth waiting on. - if connectionPhase == .connected { + // nothing to send to, so this is not worth waiting on. A passive + // session cannot send anything at all. + if !state.passiveModeEnabled, connectionPhase == .connected, let active = session as? TransmitterSession { log.default("Old transmitter still connected; sending session stop before switching") - session?.commandSource = self + active.commandSource = self lockedCommandQueue.mutate { $0 = CommandQueue([.stopSensor(at: Date())]) } } else { log.default("Old transmitter not connected; its session is left as-is") @@ -488,10 +535,12 @@ public final class G6CGMManager: CGMManager { // MARK: - CGMManager public var providesBLEHeartbeat: Bool { - // The owned connection wakes the app roughly every 5 minutes. + // Direct mode: the owned connection wakes the app roughly every + // 5 minutes. Passive mode: the Dexcom app drives the cadence, so the + // host's own timer must keep ticking. // Loop uses this to suppress the pump's timer tick; Trio dev reads it // through FetchGlucoseManager. - return true + return !state.passiveModeEnabled } public var shouldSyncToRemoteService: Bool { @@ -545,19 +594,24 @@ public final class G6CGMManager: CGMManager { // session delegate on BLE events. session?.start() - if let lastDate = state.latestReading?.date { - let gap = Date().timeIntervalSince(lastDate) - if gap > Self.backfillGapThreshold { - let end = Date() - let start = max(lastDate, end.addingTimeInterval(-Self.backfillWindow)) - session?.requestedBackfillWindow = DateInterval(start: start, end: end) + // Backfill requests and battery reads are writes; passive mode + // cannot perform them and picks up whatever the driving client asks + // for instead. + if let session = session as? TransmitterSession { + if let lastDate = state.latestReading?.date { + let gap = Date().timeIntervalSince(lastDate) + if gap > Self.backfillGapThreshold { + let end = Date() + let start = max(lastDate, end.addingTimeInterval(-Self.backfillWindow)) + session.requestedBackfillWindow = DateInterval(start: start, end: end) + } } - } - let batteryReadRecently = state.lastBatteryReadDate - .map { Date().timeIntervalSince($0) < Self.batteryReadInterval } ?? false - if !batteryReadRecently { - session?.shouldReadBattery = true + let batteryReadRecently = state.lastBatteryReadDate + .map { Date().timeIntervalSince($0) < Self.batteryReadInterval } ?? false + if !batteryReadRecently { + session.shouldReadBattery = true + } } completion(.noData) @@ -586,7 +640,7 @@ public final class G6CGMManager: CGMManager { extension G6CGMManager: TransmitterSessionDelegate { - public func transmitterSessionDidConnect(_ session: TransmitterSession) { + public func transmitterSessionDidConnect(_ session: any TransmitterSessioning) { log.default("Connected to transmitter") connectionPhase = .connected // Expiry and signal loss are time-based: without this they would only @@ -594,7 +648,7 @@ extension G6CGMManager: TransmitterSessionDelegate { evaluateAlerts() } - public func transmitterSession(_ session: TransmitterSession, didError error: Error) { + public func transmitterSession(_ session: any TransmitterSessioning, didError error: Error) { log.error("Session error: %{public}@", String(describing: error)) connectionPhase = .searching delegate.notify { delegate in @@ -602,7 +656,7 @@ extension G6CGMManager: TransmitterSessionDelegate { } } - public func transmitterSession(_ session: TransmitterSession, didRead glucose: Glucose) { + public func transmitterSession(_ session: any TransmitterSessioning, didRead glucose: Glucose) { reconcileSession(with: glucose) guard let sample = newGlucoseSample(from: glucose) else { @@ -619,7 +673,7 @@ extension G6CGMManager: TransmitterSessionDelegate { deliver([sample]) } - public func transmitterSession(_ session: TransmitterSession, didReadBackfill glucose: [Glucose]) { + public func transmitterSession(_ session: any TransmitterSessioning, didReadBackfill glucose: [Glucose]) { let samples = glucose.compactMap { newGlucoseSample(from: $0) } guard !samples.isEmpty else { @@ -630,7 +684,7 @@ extension G6CGMManager: TransmitterSessionDelegate { deliver(samples) } - public func transmitterSession(_ session: TransmitterSession, didReadTransmitterVersion message: TransmitterVersionRxMessage) { + public func transmitterSession(_ session: any TransmitterSessioning, didReadTransmitterVersion message: TransmitterVersionRxMessage) { let firmware = message.firmwareVersion.map(String.init).joined(separator: ".") let wasAnubis = state.isAnubis @@ -644,10 +698,12 @@ extension G6CGMManager: TransmitterSessionDelegate { } } - public func transmitterSession(_ session: TransmitterSession, didReadTransmitterTime activationDate: Date) { - // Authentication succeeded. Record it now rather than waiting for a - // glucose reading: a stopped or failed sensor never produces one, and - // pairing would appear to hang even though the transmitter is talking. + public func transmitterSession(_ session: any TransmitterSessioning, didReadTransmitterTime activationDate: Date) { + // In direct mode this is the proof authentication succeeded; in + // passive mode it is the first observed time frame. Record it now + // rather than waiting for a glucose reading: a stopped or failed + // sensor never produces one, and pairing would appear to hang even + // though the transmitter is talking. log.default("Transmitter clock read; activation %{public}@", String(describing: activationDate)) mutateState { state in @@ -655,7 +711,7 @@ extension G6CGMManager: TransmitterSessionDelegate { } } - public func transmitterSession(_ session: TransmitterSession, didReadBattery message: BatteryStatusRxMessage) { + public func transmitterSession(_ session: any TransmitterSessioning, didReadBattery message: BatteryStatusRxMessage) { log.default("Battery: A %d, B %d, resist %d", Int(message.voltageA), Int(message.voltageB), Int(message.resist)) mutateState { state in @@ -670,17 +726,17 @@ extension G6CGMManager: TransmitterSessionDelegate { evaluateAlerts() } - public func transmitterSession(_ session: TransmitterSession, didReadUnknownData data: Data) { + public func transmitterSession(_ session: any TransmitterSessioning, didReadUnknownData data: Data) { log.error("Unknown data received (%d bytes)", data.count) } - public func transmitterSession(_ session: TransmitterSession, didUpdatePeripheralIdentifier identifier: UUID?) { + public func transmitterSession(_ session: any TransmitterSessioning, didUpdatePeripheralIdentifier identifier: UUID?) { mutateState { state in state.peripheralIdentifier = identifier } } - public func transmitterSessionDidRequestBond(_ session: TransmitterSession) { + public func transmitterSessionDidRequestBond(_ session: any TransmitterSessioning) { log.default("Bond requested; user must accept the pairing prompt") connectionPhase = .awaitingPairing } @@ -849,7 +905,7 @@ extension G6CGMManager: TransmitterSessionDelegate { extension G6CGMManager: TransmitterCommandSource { - public func dequeuePendingCommand(for session: TransmitterSession) -> Command? { + public func dequeuePendingCommand(for session: any TransmitterSessioning) -> Command? { var next: Command? var dropped: [Command] = [] lockedCommandQueue.mutate { queue in @@ -869,7 +925,7 @@ extension G6CGMManager: TransmitterCommandSource { return next } - public func transmitterSession(_ session: TransmitterSession, didFail command: Command, with error: Error) { + public func transmitterSession(_ session: any TransmitterSessioning, didFail command: Command, with error: Error) { log.error("Command failed: %{public}@ — %{public}@", String(describing: command), String(describing: error)) if case .startSensor = command { @@ -882,7 +938,7 @@ extension G6CGMManager: TransmitterCommandSource { } } - public func transmitterSession(_ session: TransmitterSession, didComplete command: Command, response: TransmitterRxMessage?) { + public func transmitterSession(_ session: any TransmitterSessioning, didComplete command: Command, response: TransmitterRxMessage?) { log.default("Command completed: %{public}@", String(describing: command)) switch command { diff --git a/G6SensorKit/G6CGMManagerState.swift b/G6SensorKit/G6CGMManagerState.swift index 0d57d5e..85e84ba 100644 --- a/G6SensorKit/G6CGMManagerState.swift +++ b/G6SensorKit/G6CGMManagerState.swift @@ -19,6 +19,7 @@ import G6SensorCore /// cannot live in memory. public enum G6SetupStep: String { case transmitterID + case connectionMode case placement case sensorCode case pairing @@ -56,6 +57,12 @@ public struct G6CGMManagerState: RawRepresentable { public var shouldSyncToRemoteService: Bool + /// Passive mode observes the Dexcom app's session instead of owning the + /// transmitter: no auth, no bonding, no commands, no active reads. Direct + /// (active) mode is the default; passive is chosen by the user or by + /// migration from CGMBLEKit, which ran passive-only. + public var passiveModeEnabled: Bool + /// Transmitter-reported lifetime in days (90 stock, 180 Anubis); nil until /// the first version-rx frame arrives. public var transmitterExpiryInDays: UInt16? @@ -156,6 +163,7 @@ public struct G6CGMManagerState: RawRepresentable { sensorStartDate: Date? = nil, sensorCode: String? = nil, shouldSyncToRemoteService: Bool = true, + passiveModeEnabled: Bool = false, transmitterExpiryInDays: UInt16? = nil, sensorLifeDays: Int = TransmitterManagerState.defaultSensorLifeDays, latestReading: G6StoredReading? = nil, @@ -174,6 +182,7 @@ public struct G6CGMManagerState: RawRepresentable { self.sensorStartDate = sensorStartDate self.sensorCode = sensorCode self.shouldSyncToRemoteService = shouldSyncToRemoteService + self.passiveModeEnabled = passiveModeEnabled self.transmitterExpiryInDays = transmitterExpiryInDays self.sensorLifeDays = TransmitterManagerState.clampedSensorLifeDays(sensorLifeDays) self.latestReading = latestReading @@ -192,24 +201,45 @@ public struct G6CGMManagerState: RawRepresentable { return nil } + // Migration from CGMBLEKit: its TransmitterManagerState persists + // `sensorStartOffset` and never `sensorLifeDays` or + // `passiveModeEnabled`, while every G6SensorKit state carries + // `sensorLifeDays`. CGMBLEKit ran passive-only, so a legacy-shaped + // state migrates into passive mode with onboarding already complete. + let isLegacyCGMBLEKitState = rawValue["sensorLifeDays"] == nil && rawValue["passiveModeEnabled"] == nil + // UInt16 cannot round-trip through a property list, so accept Int too. let expiry = (rawValue["transmitterExpiryInDays"] as? UInt16) ?? (rawValue["transmitterExpiryInDays"] as? Int).map { UInt16(clamping: $0) } + let transmitterStartDate = rawValue["transmitterStartDate"] as? Date + + // CGMBLEKit stores the session start as an offset from transmitter + // activation; G6SensorKit stores the date itself. + var sensorStartDate = rawValue["sensorStartDate"] as? Date + if sensorStartDate == nil, let transmitterStartDate = transmitterStartDate { + let offset = (rawValue["sensorStartOffset"] as? UInt32) + ?? (rawValue["sensorStartOffset"] as? Int).map { UInt32(clamping: $0) } + if let offset = offset { + sensorStartDate = transmitterStartDate.addingTimeInterval(TimeInterval(offset)) + } + } + self.init( transmitterID: transmitterID, peripheralIdentifier: (rawValue["peripheralIdentifier"] as? String).flatMap(UUID.init(uuidString:)), - transmitterStartDate: rawValue["transmitterStartDate"] as? Date, - sensorStartDate: rawValue["sensorStartDate"] as? Date, + transmitterStartDate: transmitterStartDate, + sensorStartDate: sensorStartDate, sensorCode: rawValue["sensorCode"] as? String, shouldSyncToRemoteService: rawValue["shouldSyncToRemoteService"] as? Bool ?? true, + passiveModeEnabled: rawValue["passiveModeEnabled"] as? Bool ?? isLegacyCGMBLEKitState, transmitterExpiryInDays: expiry, sensorLifeDays: rawValue["sensorLifeDays"] as? Int ?? TransmitterManagerState.defaultSensorLifeDays, latestReading: (rawValue["latestReading"] as? G6StoredReading.RawValue).flatMap(G6StoredReading.init(rawValue:)), recentReadings: (rawValue["recentReadings"] as? [G6StoredReading.RawValue])?.compactMap(G6StoredReading.init(rawValue:)) ?? [], firmwareVersion: rawValue["firmwareVersion"] as? String, shareUploadEnabled: rawValue["shareUploadEnabled"] as? Bool ?? false, - isOnboarded: rawValue["isOnboarded"] as? Bool ?? false, + isOnboarded: rawValue["isOnboarded"] as? Bool ?? isLegacyCGMBLEKitState, setupStep: (rawValue["setupStep"] as? String).flatMap(G6SetupStep.init(rawValue:)), pendingCommands: rawValue["pendingCommands"] as? [Command.RawValue] ?? [], lastSessionStartFailure: rawValue["lastSessionStartFailure"] as? String, @@ -229,6 +259,9 @@ public struct G6CGMManagerState: RawRepresentable { "transmitterID": transmitterID, "shouldSyncToRemoteService": shouldSyncToRemoteService, "sensorLifeDays": sensorLifeDays, + // Written unconditionally: its absence is the migration signal + // for CGMBLEKit-shaped states (see init?(rawValue:)). + "passiveModeEnabled": passiveModeEnabled, ] raw["peripheralIdentifier"] = peripheralIdentifier?.uuidString @@ -439,6 +472,7 @@ extension G6CGMManagerState: Equatable { && lhs.sensorStartDate == rhs.sensorStartDate && lhs.sensorCode == rhs.sensorCode && lhs.shouldSyncToRemoteService == rhs.shouldSyncToRemoteService + && lhs.passiveModeEnabled == rhs.passiveModeEnabled && lhs.transmitterExpiryInDays == rhs.transmitterExpiryInDays && lhs.sensorLifeDays == rhs.sensorLifeDays && lhs.latestReading == rhs.latestReading diff --git a/G6SensorKitUI/G6UICoordinator.swift b/G6SensorKitUI/G6UICoordinator.swift index af168e1..98f74c2 100644 --- a/G6SensorKitUI/G6UICoordinator.swift +++ b/G6SensorKitUI/G6UICoordinator.swift @@ -21,6 +21,7 @@ enum G6UIScreen { // Onboarding case introduction case transmitterIDEntry + case connectionMode case sensorCodeEntry case placementGuide case pairing @@ -39,6 +40,7 @@ enum G6UIScreen { var setupStep: G6SetupStep? { switch self { case .transmitterIDEntry: return .transmitterID + case .connectionMode: return .connectionMode case .placementGuide: return .placement case .sensorCodeEntry: return .sensorCode case .pairing: return .pairing @@ -50,6 +52,7 @@ enum G6UIScreen { init?(setupStep: G6SetupStep) { switch setupStep { case .transmitterID: self = .transmitterIDEntry + case .connectionMode: self = .connectionMode case .placement: self = .placementGuide case .sensorCode: self = .sensorCodeEntry case .pairing: self = .pairing @@ -60,7 +63,8 @@ enum G6UIScreen { var next: G6UIScreen? { switch self { case .introduction: return .transmitterIDEntry - case .transmitterIDEntry: return .placementGuide + case .transmitterIDEntry: return .connectionMode + case .connectionMode: return .placementGuide case .placementGuide: return .sensorCodeEntry case .sensorCodeEntry: return .pairing case .pairing: return .warmup @@ -98,6 +102,10 @@ public class G6UICoordinator: UINavigationController, CGMManagerOnboarding, Comp /// Transmitter ID collected during onboarding, before a manager exists. private var pendingTransmitterID: String? + /// Whether the user has answered the connection-mode screen in this flow. + /// Until then the manager's passive flag is a placeholder, not a choice. + private var hasChosenConnectionMode = false + private var screenStack: [G6UIScreen] = [] private var flowMode: G6FlowMode = .onboarding @@ -209,17 +217,24 @@ public class G6UICoordinator: UINavigationController, CGMManagerOnboarding, Comp } private func nextScreen(after screen: G6UIScreen) -> G6UIScreen? { + // Sensor codes are entered in the Dexcom app in passive mode, so the + // code screen has no meaning there. + let isPassive = cgmManager?.state.passiveModeEnabled ?? false + switch flowMode { case .onboarding: if screen == .pairing, !shouldShowWarmup { return nil } + if screen == .placementGuide, isPassive { + return .pairing + } return screen.next case .replacingTransmitter: // No introduction, and no placement guide: the sensor is already // worn, only the transmitter changed. switch screen { - case .transmitterIDEntry: return .sensorCodeEntry + case .transmitterIDEntry: return isPassive ? .pairing : .sensorCodeEntry case .sensorCodeEntry: return .pairing case .pairing: return shouldShowWarmup ? .warmup : nil default: return nil @@ -329,7 +344,11 @@ public class G6UICoordinator: UINavigationController, CGMManagerOnboarding, Comp return } - let state = G6CGMManagerState(transmitterID: transmitterID) + // Start passive until the user picks a mode on the next screen. A + // direct session would connect straight away and, if the Dexcom app + // already holds this transmitter, authenticate and try to pair with + // it before the user has said they want to listen instead. + let state = G6CGMManagerState(transmitterID: transmitterID, passiveModeEnabled: true) let manager = G6CGMManager(state: state) cgmManager = manager manager.recordSetupStep(.transmitterID) @@ -364,6 +383,25 @@ public class G6UICoordinator: UINavigationController, CGMManagerOnboarding, Comp title: LocalizedString("Transmitter ID", comment: "Navigation title for transmitter ID entry") ) + case .connectionMode: + return hostingController( + rootView: G6ConnectionModeView( + // The manager sits in passive mode until a choice is + // made, so only show its mode once it reflects one. + initialPassive: hasChosenConnectionMode ? (cgmManager?.state.passiveModeEnabled ?? false) : false, + didContinue: { [weak self] passive in + guard let self = self else { return } + self.hasChosenConnectionMode = true + if let manager = self.cgmManager { + manager.logSetupEvent(passive ? "Chose passive mode" : "Chose direct mode") + manager.setPassiveModeEnabled(passive) + } + self.stepFinished() + } + ), + title: LocalizedString("Connection Mode", comment: "Navigation title for connection mode screen") + ) + case .sensorCodeEntry: return hostingController( rootView: G6SensorCodeEntryView( diff --git a/G6SensorKitUI/Localizable.xcstrings b/G6SensorKitUI/Localizable.xcstrings index 9a46cf6..ed91009 100644 --- a/G6SensorKitUI/Localizable.xcstrings +++ b/G6SensorKitUI/Localizable.xcstrings @@ -946,6 +946,70 @@ "Save": { "extractionState": "manual", "comment": "Save session length button" + }, + "Listening to the Dexcom app": { + "extractionState": "manual", + "comment": "Pairing callout title in passive mode" + }, + "Passive mode never pairs with the transmitter itself. The Dexcom G6 or ONE app must be installed and connected to this transmitter — this app listens to its session.": { + "extractionState": "manual", + "comment": "Pairing callout body in passive mode" + }, + "Check that the Dexcom app is installed and connected to this transmitter, that the transmitter ID is exactly right, and that your phone is next to it. Bluetooth must be on.": { + "extractionState": "manual", + "comment": "Pairing troubleshooting body in passive mode" + }, + "Passive Mode": { + "extractionState": "manual", + "comment": "Toggle label for passive (listen-only) mode" + }, + "Connection": { + "extractionState": "manual", + "comment": "Transmitter details section header for connection mode" + }, + "Passive mode listens to the Dexcom G6 or ONE app on this phone, which must be installed and running a sensor session with this transmitter. Start, stop and calibrate from the Dexcom app.": { + "extractionState": "manual", + "comment": "Footer explaining passive mode" + }, + "Direct mode talks to the transmitter itself, which allows starting, stopping and calibrating sessions here. The Dexcom app must not be connected to this transmitter while direct mode is on.": { + "extractionState": "manual", + "comment": "Footer explaining direct mode" + }, + "Sessions and calibrations are managed in the Dexcom app while passive mode is on.": { + "extractionState": "manual", + "comment": "Explanation replacing the session action buttons in passive mode" + }, + "Connection Mode": { + "extractionState": "manual", + "comment": "Navigation title for connection mode screen" + }, + "%1$@ reads glucose from your G6 or Dexcom ONE transmitter over Bluetooth — either by talking to the transmitter itself, or by listening to the Dexcom app's session. You choose on the next screens.": { + "extractionState": "manual", + "comment": "Introduction: what the driver does (1: app name)" + }, + "Choose how to connect": { + "extractionState": "manual", + "comment": "Connection mode screen heading" + }, + "Direct": { + "extractionState": "manual", + "comment": "Connection mode option: direct" + }, + "Recommended": { + "extractionState": "manual", + "comment": "Badge on the recommended connection mode" + }, + "This app talks to the transmitter itself: start and stop sensor sessions, enter sensor codes and calibrations here. The Dexcom app must not be connected to this transmitter.": { + "extractionState": "manual", + "comment": "Direct mode explanation" + }, + "Listen to the Dexcom app": { + "extractionState": "manual", + "comment": "Connection mode option: passive" + }, + "This app listens to the session the Dexcom G6 or ONE app drives on this phone. The Dexcom app is required, and sessions, sensor codes and calibrations are managed there.": { + "extractionState": "manual", + "comment": "Passive mode explanation" } }, "version": "1.1" diff --git a/G6SensorKitUI/Views/G6DetailViews.swift b/G6SensorKitUI/Views/G6DetailViews.swift index c54858e..f84fcad 100644 --- a/G6SensorKitUI/Views/G6DetailViews.swift +++ b/G6SensorKitUI/Views/G6DetailViews.swift @@ -328,6 +328,10 @@ struct G6TransmitterDetailsView: View { @State private var showingPairConfirmation = false + /// Mirrors the persisted mode; writes go through the manager, which + /// rebuilds the session as the other kind. + @State private var passiveModeEnabled = false + var body: some View { List { // Top of the transmitter screen, matching where the @@ -352,6 +356,24 @@ struct G6TransmitterDetailsView: View { } } + Section { + Toggle(LocalizedString("Passive Mode", comment: "Toggle label for passive (listen-only) mode"), isOn: $passiveModeEnabled) + .onChange(of: passiveModeEnabled) { newValue in + guard newValue != cgmManager.state.passiveModeEnabled else { + return + } + cgmManager.setPassiveModeEnabled(newValue) + } + } header: { + Text(LocalizedString("Connection", comment: "Transmitter details section header for connection mode")) + } footer: { + if passiveModeEnabled { + Text(LocalizedString("Passive mode listens to the Dexcom G6 or ONE app on this phone, which must be installed and running a sensor session with this transmitter. Start, stop and calibrate from the Dexcom app.", comment: "Footer explaining passive mode")) + } else { + Text(LocalizedString("Direct mode talks to the transmitter itself, which allows starting, stopping and calibrating sessions here. The Dexcom app must not be connected to this transmitter while direct mode is on.", comment: "Footer explaining direct mode")) + } + } + Section { row( LocalizedString("Model", comment: "Transmitter detail label for model"), @@ -395,6 +417,7 @@ struct G6TransmitterDetailsView: View { } .listStyle(.insetGrouped) + .onAppear { passiveModeEnabled = cgmManager.state.passiveModeEnabled } } private func row(_ label: String, _ value: String) -> some View { diff --git a/G6SensorKitUI/Views/G6Graphics.swift b/G6SensorKitUI/Views/G6Graphics.swift index 29c8cb6..4f1041c 100644 --- a/G6SensorKitUI/Views/G6Graphics.swift +++ b/G6SensorKitUI/Views/G6Graphics.swift @@ -328,11 +328,12 @@ struct G6AssetImage: View { struct G6FindCodeCard: View { let assetName: String let caption: String + var imageHeight: CGFloat = 170 @ViewBuilder var fallback: () -> Fallback var body: some View { VStack(alignment: .leading, spacing: 10) { - G6AssetImage(name: assetName, height: 170, fallback: fallback) + G6AssetImage(name: assetName, height: imageHeight, fallback: fallback) .frame(maxWidth: .infinity) .padding(10) .background( diff --git a/G6SensorKitUI/Views/G6OnboardingViews.swift b/G6SensorKitUI/Views/G6OnboardingViews.swift index 34a81ae..c59eae6 100644 --- a/G6SensorKitUI/Views/G6OnboardingViews.swift +++ b/G6SensorKitUI/Views/G6OnboardingViews.swift @@ -161,9 +161,10 @@ struct G6CodeBoxField: View { // MARK: - 1. Introduction /// Product hero, in the shape G7SensorKit uses: name, device, a short -/// statement of what this driver does, then Continue. The wording is the -/// inverse of G7's — that one piggybacks the manufacturer's app, this one -/// replaces it, and getting that distinction wrong would be dangerous. +/// statement of what this driver does, then Continue. The mode distinction +/// (direct vs. listening to the Dexcom app) is introduced here and chosen on +/// the connection-mode screen — getting that distinction wrong in the copy +/// would be dangerous. struct G6IntroductionView: View { let didContinue: () -> Void @@ -181,12 +182,9 @@ struct G6IntroductionView: View { VStack(spacing: 14) { Text(String( - format: LocalizedString("%1$@ talks to your G6 or Dexcom ONE transmitter directly. It starts and stops sensor sessions, sends your calibrations, and fills in readings it missed.", comment: "Introduction: what the native driver does (1: app name)"), + format: LocalizedString("%1$@ reads glucose from your G6 or Dexcom ONE transmitter over Bluetooth — either by talking to the transmitter itself, or by listening to the Dexcom app's session. You choose on the next screens.", comment: "Introduction: what the driver does (1: app name)"), appName )) - - Text(LocalizedString("You do not need the Dexcom app — and you must not let it use the same transmitter at the same time.", comment: "Introduction: single-app requirement")) - .foregroundStyle(.secondary) } .font(.body) .multilineTextAlignment(.leading) @@ -248,6 +246,94 @@ struct G6CalloutBox: View { } } +// MARK: - 3. Connection mode + +/// Lets the user choose between owning the transmitter (direct) and +/// listening to the Dexcom app's session (passive). Direct is presented as +/// the recommendation; passive exists for people who want to keep the +/// manufacturer's app running. +struct G6ConnectionModeView: View { + @State private var usePassive: Bool + let didContinue: (Bool) -> Void + + init(initialPassive: Bool, didContinue: @escaping (Bool) -> Void) { + _usePassive = State(initialValue: initialPassive) + self.didContinue = didContinue + } + + var body: some View { + VStack(spacing: 0) { + ScrollView { + VStack(alignment: .leading, spacing: 18) { + Text(LocalizedString("Choose how to connect", comment: "Connection mode screen heading")) + .font(.title2.bold()) + + modeCard( + title: LocalizedString("Direct", comment: "Connection mode option: direct"), + badge: LocalizedString("Recommended", comment: "Badge on the recommended connection mode"), + description: LocalizedString("This app talks to the transmitter itself: start and stop sensor sessions, enter sensor codes and calibrations here. The Dexcom app must not be connected to this transmitter.", comment: "Direct mode explanation"), + symbolName: "antenna.radiowaves.left.and.right", + isSelected: !usePassive + ) { + usePassive = false + } + + modeCard( + title: LocalizedString("Listen to the Dexcom app", comment: "Connection mode option: passive"), + badge: nil, + description: LocalizedString("This app listens to the session the Dexcom G6 or ONE app drives on this phone. The Dexcom app is required, and sessions, sensor codes and calibrations are managed there.", comment: "Passive mode explanation"), + symbolName: "ear.badge.waveform", + isSelected: usePassive + ) { + usePassive = true + } + } + .padding() + } + + G6ContinueButton(action: { didContinue(usePassive) }) + } + } + + private func modeCard(title: String, badge: String?, description: String, symbolName: String, isSelected: Bool, action: @escaping () -> Void) -> some View { + Button(action: action) { + VStack(alignment: .leading, spacing: 8) { + HStack(spacing: 8) { + Image(systemName: symbolName) + .foregroundColor(isSelected ? Color.accentColor : .secondary) + Text(title) + .font(.headline) + .foregroundColor(.primary) + if let badge = badge { + Text(badge) + .font(.caption.weight(.semibold)) + .foregroundColor(.white) + .padding(.horizontal, 8) + .padding(.vertical, 2) + .background(Color.accentColor) + .cornerRadius(6) + } + Spacer() + Image(systemName: isSelected ? "checkmark.circle.fill" : "circle") + .foregroundColor(isSelected ? Color.accentColor : Color(.separator)) + } + Text(description) + .font(.subheadline) + .foregroundColor(.secondary) + .fixedSize(horizontal: false, vertical: true) + } + .padding() + .background(Color(.secondarySystemGroupedBackground)) + .cornerRadius(10) + .overlay( + RoundedRectangle(cornerRadius: 10, style: .continuous) + .stroke(isSelected ? Color.accentColor : Color.clear, lineWidth: 2) + ) + } + .buttonStyle(.plain) + } +} + // MARK: - 2. Transmitter ID struct G6TransmitterIDEntryView: View { @@ -324,6 +410,10 @@ struct G6TransmitterIDEntryView: View { Text(LocalizedString("Scan package code", comment: "Scan package barcode button")) } .font(.subheadline.weight(.semibold)) + .foregroundColor(.white) + .padding(.horizontal, 16) + .padding(.vertical, 8) + .background(Capsule().fill(Color.accentColor)) } .frame(maxWidth: .infinity) } @@ -465,7 +555,7 @@ struct G6TransmitterIDEntryView: View { } } -// MARK: - 3. Sensor code +// MARK: - 4. Sensor code struct G6SensorCodeEntryView: View { /// Passes nil when the user chooses to start without a code. @@ -488,9 +578,10 @@ struct G6SensorCodeEntryView: View { G6FindCodeCard( assetName: "G6SensorCodeLocation", - caption: LocalizedString("The 4-digit code is on the applicator’s adhesive label, and is unique to that sensor. Use the code from the applicator you are about to insert — a code from a different one will make readings inaccurate.", comment: "Sensor code: where to find it") + caption: LocalizedString("The 4-digit code is on the applicator’s adhesive label, and is unique to that sensor. Use the code from the applicator you are about to insert — a code from a different one will make readings inaccurate.", comment: "Sensor code: where to find it"), + imageHeight: 110 ) { - G6SensorCodeLabelGlyph(size: 150) + G6SensorCodeLabelGlyph(size: 110) } G6CodeBoxField( @@ -528,6 +619,10 @@ struct G6SensorCodeEntryView: View { Text(LocalizedString("Scan applicator code", comment: "Scan applicator barcode button")) } .font(.subheadline.weight(.semibold)) + .foregroundColor(.white) + .padding(.horizontal, 16) + .padding(.vertical, 8) + .background(Capsule().fill(Color.accentColor)) } .frame(maxWidth: .infinity) } @@ -536,7 +631,7 @@ struct G6SensorCodeEntryView: View { symbolName: "drop.fill", tint: .blue, title: LocalizedString("No code on your sensor?", comment: "Sensor code callout title"), - body: LocalizedString("You can start without one. The transmitter will then ask you for two fingerstick glucose values after warm-up, and for one more each day. \"Calibration\" means telling the sensor what your meter reads, so it can correct itself.", comment: "Sensor code callout body explaining calibration") + body: LocalizedString("You can start without one. The transmitter will then ask you for two fingerstick glucose values after warm-up, and for one more each day.", comment: "Sensor code callout body explaining calibration") ) } @@ -690,7 +785,7 @@ struct G6SensorCodeEntryView: View { } } -// MARK: - 5. Pairing +// MARK: - 6. Pairing /// Observes the manager so the screen reflects the radio live. Without this /// the view read `manager.state` once and never updated, so a successful @@ -701,6 +796,7 @@ final class G6PairingViewModel: ObservableObject, G6CGMManagerObserver { @Published private(set) var phase: G6ConnectionPhase = .searching @Published private(set) var isPaired = false @Published private(set) var hasSession = false + @Published private(set) var isPassive = false @Published private(set) var searchingLongerThanExpected = false private let startedAt = Date() @@ -738,11 +834,12 @@ final class G6PairingViewModel: ObservableObject, G6CGMManagerObserver { let phase = cgmManager.connectionPhase let paired = cgmManager.isPaired let session = cgmManager.state.sensorStartDate != nil + let passive = cgmManager.state.passiveModeEnabled if Thread.isMainThread { - self.phase = phase; isPaired = paired; hasSession = session + self.phase = phase; isPaired = paired; hasSession = session; isPassive = passive } else { DispatchQueue.main.async { - self.phase = phase; self.isPaired = paired; self.hasSession = session + self.phase = phase; self.isPaired = paired; self.hasSession = session; self.isPassive = passive } } } @@ -800,7 +897,14 @@ struct G6PairingView: View { Text(LocalizedString("Your transmitter only talks to your phone about once every 5 minutes, so this can take a few minutes. Keep your phone nearby.", comment: "Pairing: explanation of the 5-minute cycle")) } - if viewModel.phase == .awaitingPairing { + if viewModel.isPassive, !viewModel.isPaired { + G6CalloutBox( + symbolName: "ear.badge.waveform", + tint: .blue, + title: LocalizedString("Listening to the Dexcom app", comment: "Pairing callout title in passive mode"), + body: LocalizedString("Passive mode never pairs with the transmitter itself. The Dexcom G6 or ONE app must be installed and connected to this transmitter — this app listens to its session.", comment: "Pairing callout body in passive mode") + ) + } else if viewModel.phase == .awaitingPairing { G6CalloutBox( symbolName: "lock.shield.fill", tint: .orange, @@ -829,7 +933,9 @@ struct G6PairingView: View { symbolName: "exclamationmark.triangle.fill", tint: .orange, title: LocalizedString("Still looking", comment: "Pairing troubleshooting title"), - body: LocalizedString("Check that the Dexcom app is not connected to this transmitter, that the transmitter ID is exactly right, and that your phone is next to it. Bluetooth must be on.", comment: "Pairing troubleshooting body") + body: viewModel.isPassive + ? LocalizedString("Check that the Dexcom app is installed and connected to this transmitter, that the transmitter ID is exactly right, and that your phone is next to it. Bluetooth must be on.", comment: "Pairing troubleshooting body in passive mode") + : LocalizedString("Check that the Dexcom app is not connected to this transmitter, that the transmitter ID is exactly right, and that your phone is next to it. Bluetooth must be on.", comment: "Pairing troubleshooting body") ) Button { @@ -878,7 +984,7 @@ struct G6PairingView: View { } } -// MARK: - 6. Warm-up +// MARK: - 7. Warm-up struct G6WarmupView: View { let manager: G6CGMManager? diff --git a/G6SensorKitUI/Views/G6SettingsView.swift b/G6SensorKitUI/Views/G6SettingsView.swift index cfba3d4..e9b9afa 100644 --- a/G6SensorKitUI/Views/G6SettingsView.swift +++ b/G6SensorKitUI/Views/G6SettingsView.swift @@ -423,7 +423,11 @@ struct G6SettingsView: View { private var actionsSection: some View { Section { - if viewModel.canStartSensor { + if viewModel.state.passiveModeEnabled { + Label(LocalizedString("Sessions and calibrations are managed in the Dexcom app while passive mode is on.", comment: "Explanation replacing the session action buttons in passive mode"), systemImage: "info.circle") + .font(.footnote) + .foregroundStyle(.secondary) + } else if viewModel.canStartSensor { Button { viewModel.toPlacementGuide() } label: { @@ -465,7 +469,7 @@ struct G6SettingsView: View { } } } footer: { - if viewModel.state.isInWarmup { + if viewModel.state.isInWarmup, !viewModel.state.passiveModeEnabled { Text(LocalizedString("Calibration becomes available once warm-up finishes. Do not make insulin decisions from early readings — use a fingerstick meter and follow your care team's guidance.", comment: "Footer explaining warm-up restrictions")) } } @@ -496,7 +500,7 @@ struct G6SettingsView: View { .buttonStyle(G6RowButtonStyle()) } - if viewModel.state.isAnubis { + if viewModel.state.isAnubis, !viewModel.state.passiveModeEnabled { navRow(LocalizedString("Session Length", comment: "Row to session length settings"), "calendar", viewModel.toSensorLifeSettings) } From 71d0cd100c2613249443140b21aeee227a449a1a Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 25 Sep 2026 13:55:19 +0200 Subject: [PATCH 10/13] feat(settings): confirm before turning passive mode off Direct mode connects straight away, and two clients talking to the transmitter from one phone interfere. Turning passive mode off now asks first and tells the user to close the Dexcom app and turn off its Bluetooth access, or delete it. Turning passive mode on is immediate, since listening cannot interfere. --- G6SensorKitUI/Localizable.xcstrings | 12 +++++++++ G6SensorKitUI/Views/G6DetailViews.swift | 34 +++++++++++++++++++++---- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/G6SensorKitUI/Localizable.xcstrings b/G6SensorKitUI/Localizable.xcstrings index ed91009..05b0738 100644 --- a/G6SensorKitUI/Localizable.xcstrings +++ b/G6SensorKitUI/Localizable.xcstrings @@ -975,6 +975,18 @@ "extractionState": "manual", "comment": "Footer explaining direct mode" }, + "Switch to direct mode?": { + "extractionState": "manual", + "comment": "Confirmation title for turning passive mode off" + }, + "Switch to Direct Mode": { + "extractionState": "manual", + "comment": "Confirm turning passive mode off" + }, + "Close the Dexcom app and turn off its Bluetooth access, or delete it, before switching. Only one app on this phone can talk to the transmitter; if the Dexcom app is still connected, the two will interfere and readings can be lost.": { + "extractionState": "manual", + "comment": "Warning shown before turning passive mode off" + }, "Sessions and calibrations are managed in the Dexcom app while passive mode is on.": { "extractionState": "manual", "comment": "Explanation replacing the session action buttons in passive mode" diff --git a/G6SensorKitUI/Views/G6DetailViews.swift b/G6SensorKitUI/Views/G6DetailViews.swift index f84fcad..7bb19ce 100644 --- a/G6SensorKitUI/Views/G6DetailViews.swift +++ b/G6SensorKitUI/Views/G6DetailViews.swift @@ -332,6 +332,8 @@ struct G6TransmitterDetailsView: View { /// rebuilds the session as the other kind. @State private var passiveModeEnabled = false + @State private var showingDirectModeConfirmation = false + var body: some View { List { // Top of the transmitter screen, matching where the @@ -357,13 +359,30 @@ struct G6TransmitterDetailsView: View { } Section { - Toggle(LocalizedString("Passive Mode", comment: "Toggle label for passive (listen-only) mode"), isOn: $passiveModeEnabled) - .onChange(of: passiveModeEnabled) { newValue in - guard newValue != cgmManager.state.passiveModeEnabled else { - return + // Turning passive off is confirmed before the switch: a direct + // session connects straight away, and two clients talking to + // the transmitter from one phone interfere with each other. + Toggle(LocalizedString("Passive Mode", comment: "Toggle label for passive (listen-only) mode"), isOn: Binding( + get: { passiveModeEnabled }, + set: { newValue in + if newValue { + setPassiveModeEnabled(true) + } else { + showingDirectModeConfirmation = true } - cgmManager.setPassiveModeEnabled(newValue) } + )) + .confirmationDialog( + LocalizedString("Switch to direct mode?", comment: "Confirmation title for turning passive mode off"), + isPresented: $showingDirectModeConfirmation, + titleVisibility: .visible + ) { + Button(LocalizedString("Switch to Direct Mode", comment: "Confirm turning passive mode off")) { + setPassiveModeEnabled(false) + } + } message: { + Text(LocalizedString("Close the Dexcom app and turn off its Bluetooth access, or delete it, before switching. Only one app on this phone can talk to the transmitter; if the Dexcom app is still connected, the two will interfere and readings can be lost.", comment: "Warning shown before turning passive mode off")) + } } header: { Text(LocalizedString("Connection", comment: "Transmitter details section header for connection mode")) } footer: { @@ -420,6 +439,11 @@ struct G6TransmitterDetailsView: View { .onAppear { passiveModeEnabled = cgmManager.state.passiveModeEnabled } } + private func setPassiveModeEnabled(_ enabled: Bool) { + passiveModeEnabled = enabled + cgmManager.setPassiveModeEnabled(enabled) + } + private func row(_ label: String, _ value: String) -> some View { HStack { Text(label) From fdf065a11f0bc6125d1f986afe9e5ffbfee41c3a Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 25 Sep 2026 13:55:19 +0200 Subject: [PATCH 11/13] fix(harness): add the Info.plist project.yml points at, target iOS 17 The harness project referenced Sources/Info.plist, which was never committed. It carries the Bluetooth usage description and background modes the harness needs. The deployment target moves to iOS 17 to match the package. --- Apps/G6SensorHarness/Sources/Info.plist | 30 +++++++++++++++++++++++++ Apps/G6SensorHarness/project.yml | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 Apps/G6SensorHarness/Sources/Info.plist diff --git a/Apps/G6SensorHarness/Sources/Info.plist b/Apps/G6SensorHarness/Sources/Info.plist new file mode 100644 index 0000000..d244bb4 --- /dev/null +++ b/Apps/G6SensorHarness/Sources/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSBluetoothAlwaysUsageDescription + G6SensorHarness connects to your Dexcom transmitter over Bluetooth to read glucose values. + UIBackgroundModes + + bluetooth-central + + UILaunchScreen + + + diff --git a/Apps/G6SensorHarness/project.yml b/Apps/G6SensorHarness/project.yml index 6c95f82..de16e5d 100644 --- a/Apps/G6SensorHarness/project.yml +++ b/Apps/G6SensorHarness/project.yml @@ -8,7 +8,7 @@ name: G6SensorHarness options: bundleIdPrefix: org.nightscout deploymentTarget: - iOS: "15.0" + iOS: "17.0" settings: TARGETED_DEVICE_FAMILY: "1" SWIFT_VERSION: "5.9" From 0ea0f8ecc3e355e70feedd2d7450f80c13e230a1 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 25 Sep 2026 13:55:19 +0200 Subject: [PATCH 12/13] feat(harness): passive mode toggle The harness can run a passive session next to the Dexcom app. Battery, backfill and command actions are hidden or refused in passive mode, since that session cannot write. --- .../G6SensorHarness/Sources/ContentView.swift | 37 +++++----- .../Sources/HarnessViewModel.swift | 71 +++++++++++++------ 2 files changed, 70 insertions(+), 38 deletions(-) diff --git a/Apps/G6SensorHarness/Sources/ContentView.swift b/Apps/G6SensorHarness/Sources/ContentView.swift index 8cd93c6..28d7abd 100644 --- a/Apps/G6SensorHarness/Sources/ContentView.swift +++ b/Apps/G6SensorHarness/Sources/ContentView.swift @@ -21,6 +21,9 @@ struct ContentView: View { .textInputAutocapitalization(.characters) .disabled(model.isRunning) + Toggle("Passive mode (listen to Dexcom app)", isOn: $model.passiveModeEnabled) + .disabled(model.isRunning) + if model.isRunning { Button("Stop", role: .destructive) { model.stop() } } else { @@ -31,26 +34,28 @@ struct ContentView: View { row("Last connect", model.lastConnect.map { $0.formatted(date: .omitted, time: .standard) } ?? "—") } - Section("Session commands (sent on next connection)") { - HStack { - TextField("Sensor code (blank = no code)", text: $sensorCode) - .keyboardType(.numberPad) - Button("Start sensor") { - model.enqueueStartSensor(code: sensorCode.isEmpty ? nil : sensorCode) + if !model.passiveModeEnabled { + Section("Session commands (sent on next connection)") { + HStack { + TextField("Sensor code (blank = no code)", text: $sensorCode) + .keyboardType(.numberPad) + Button("Start sensor") { + model.enqueueStartSensor(code: sensorCode.isEmpty ? nil : sensorCode) + } } - } - Button("Stop sensor") { model.enqueueStopSensor() } - HStack { - TextField("Calibration mg/dL", text: $calibrationValue) - .keyboardType(.numberPad) - Button("Calibrate") { - if let value = Double(calibrationValue) { - model.enqueueCalibration(mgDL: value) + Button("Stop sensor") { model.enqueueStopSensor() } + HStack { + TextField("Calibration mg/dL", text: $calibrationValue) + .keyboardType(.numberPad) + Button("Calibrate") { + if let value = Double(calibrationValue) { + model.enqueueCalibration(mgDL: value) + } } } + Button("Read battery") { model.requestBattery() } + Button("Backfill last 3h") { model.requestBackfill(hours: 3) } } - Button("Read battery") { model.requestBattery() } - Button("Backfill last 3h") { model.requestBackfill(hours: 3) } } Section("Log") { diff --git a/Apps/G6SensorHarness/Sources/HarnessViewModel.swift b/Apps/G6SensorHarness/Sources/HarnessViewModel.swift index c31d1ab..9ca3d0b 100644 --- a/Apps/G6SensorHarness/Sources/HarnessViewModel.swift +++ b/Apps/G6SensorHarness/Sources/HarnessViewModel.swift @@ -4,10 +4,11 @@ // // Copyright © 2026 Nightscout Foundation. MIT License. // -// Drives a TransmitterSession directly for on-device validation of the +// Drives a transmitter session directly for on-device validation of the // core: pairing, per-cycle reads, session start/stop with sensor codes, -// calibration, battery, and backfill — with an in-app event log so -// background behavior can be inspected without a debugger. +// calibration, battery, and backfill in direct mode — or passive listening +// alongside the Dexcom app — with an in-app event log so background +// behavior can be inspected without a debugger. // import Foundation @@ -23,13 +24,14 @@ struct LogLine: Identifiable { final class HarnessViewModel: ObservableObject, TransmitterSessionDelegate, TransmitterCommandSource { @Published var transmitterID: String = UserDefaults.standard.string(forKey: "harness.transmitterID") ?? "" + @Published var passiveModeEnabled: Bool = UserDefaults.standard.bool(forKey: "harness.passiveModeEnabled") @Published var isRunning = false @Published var latestReading: String = "—" @Published var lastConnect: Date? @Published var log: [LogLine] = [] @Published var pendingCommands: [Command] = [] - private var session: TransmitterSession? + private var session: (any TransmitterSessioning)? private var peripheralIdentifier: UUID? { get { UserDefaults.standard.string(forKey: "harness.peripheralIdentifier").flatMap(UUID.init) } @@ -49,14 +51,23 @@ final class HarnessViewModel: ObservableObject, TransmitterSessionDelegate, Tran } UserDefaults.standard.set(transmitterID, forKey: "harness.transmitterID") - - let session = TransmitterSession(id: transmitterID, peripheralIdentifier: peripheralIdentifier) + UserDefaults.standard.set(passiveModeEnabled, forKey: "harness.passiveModeEnabled") + + let session: any TransmitterSessioning + if passiveModeEnabled { + session = PassiveTransmitterSession(id: transmitterID, peripheralIdentifier: peripheralIdentifier) + } else { + let active = TransmitterSession(id: transmitterID, peripheralIdentifier: peripheralIdentifier) + active.commandSource = self + session = active + } session.delegate = self - session.commandSource = self self.session = session session.start() isRunning = true - append("Session armed for \(transmitterID); waiting for transmitter advertisement (~5 min cycle)") + append(passiveModeEnabled + ? "Passive session armed for \(transmitterID); listening for the Dexcom app's traffic" + : "Session armed for \(transmitterID); waiting for transmitter advertisement (~5 min cycle)") } func stop() { @@ -87,17 +98,29 @@ final class HarnessViewModel: ObservableObject, TransmitterSessionDelegate, Tran } func requestBattery() { - session?.shouldReadBattery = true + guard let session = session as? TransmitterSession else { + append("Battery reads require direct mode") + return + } + session.shouldReadBattery = true append("Battery read queued for next connection") } func requestBackfill(hours: Double) { + guard let session = session as? TransmitterSession else { + append("Backfill requests require direct mode") + return + } let end = Date() - session?.requestedBackfillWindow = DateInterval(start: end.addingTimeInterval(-hours * 3600), end: end) + session.requestedBackfillWindow = DateInterval(start: end.addingTimeInterval(-hours * 3600), end: end) append("Backfill queued for last \(Int(hours))h") } private func enqueue(_ command: Command) { + guard !passiveModeEnabled else { + append("Commands require direct mode") + return + } DispatchQueue.main.async { self.pendingCommands.append(command) self.append("Queued: \(String(describing: command))") @@ -115,49 +138,53 @@ final class HarnessViewModel: ObservableObject, TransmitterSessionDelegate, Tran // MARK: - TransmitterSessionDelegate (background queue) - func transmitterSessionDidConnect(_ session: TransmitterSession) { + func transmitterSessionDidConnect(_ session: any TransmitterSessioning) { DispatchQueue.main.async { self.lastConnect = Date() } append("Connected") } - func transmitterSession(_ session: TransmitterSession, didError error: Error) { + func transmitterSession(_ session: any TransmitterSessioning, didError error: Error) { append("Error: \(error)") } - func transmitterSession(_ session: TransmitterSession, didRead glucose: Glucose) { + func transmitterSession(_ session: any TransmitterSessioning, didRead glucose: Glucose) { let value = glucose.glucoseMgDL.map { "\(Int($0)) mg/dL" } ?? "unreliable (\(glucose.state))" DispatchQueue.main.async { self.latestReading = value } append("Glucose: \(value), state: \(glucose.state), trend: \(glucose.trend)") } - func transmitterSession(_ session: TransmitterSession, didReadBackfill glucose: [Glucose]) { + func transmitterSession(_ session: any TransmitterSessioning, didReadBackfill glucose: [Glucose]) { append("Backfill: \(glucose.count) readings") } - func transmitterSession(_ session: TransmitterSession, didReadTransmitterVersion message: TransmitterVersionRxMessage) { + func transmitterSession(_ session: any TransmitterSessioning, didReadTransmitterVersion message: TransmitterVersionRxMessage) { append("Version: fw \(message.firmwareVersion.map(String.init).joined(separator: ".")), expiry \(message.transmitterExpiryInDays)d\(message.isAnubis ? " (Anubis)" : "")") } - func transmitterSession(_ session: TransmitterSession, didReadBattery message: BatteryStatusRxMessage) { + func transmitterSession(_ session: any TransmitterSessioning, didReadBattery message: BatteryStatusRxMessage) { append("Battery: A \(Double(message.voltageA)/100)V, B \(Double(message.voltageB)/100)V") } - func transmitterSession(_ session: TransmitterSession, didReadUnknownData data: Data) { + func transmitterSession(_ session: any TransmitterSessioning, didReadTransmitterTime activationDate: Date) { + append("Transmitter clock: activation \(activationDate.formatted(date: .abbreviated, time: .standard))") + } + + func transmitterSession(_ session: any TransmitterSessioning, didReadUnknownData data: Data) { append("Unknown data: \(data.map { String(format: "%02x", $0) }.joined())") } - func transmitterSession(_ session: TransmitterSession, didUpdatePeripheralIdentifier identifier: UUID?) { + func transmitterSession(_ session: any TransmitterSessioning, didUpdatePeripheralIdentifier identifier: UUID?) { DispatchQueue.main.async { self.peripheralIdentifier = identifier } append("Peripheral identifier: \(identifier?.uuidString ?? "nil")") } - func transmitterSessionDidRequestBond(_ session: TransmitterSession) { + func transmitterSessionDidRequestBond(_ session: any TransmitterSessioning) { append("⚠️ Accept the iOS pairing prompt within 60 seconds") } // MARK: - TransmitterCommandSource (background queue) - func dequeuePendingCommand(for session: TransmitterSession) -> Command? { + func dequeuePendingCommand(for session: any TransmitterSessioning) -> Command? { var command: Command? DispatchQueue.main.sync { if !pendingCommands.isEmpty { @@ -167,11 +194,11 @@ final class HarnessViewModel: ObservableObject, TransmitterSessionDelegate, Tran return command } - func transmitterSession(_ session: TransmitterSession, didFail command: Command, with error: Error) { + func transmitterSession(_ session: any TransmitterSessioning, didFail command: Command, with error: Error) { append("Command failed: \(String(describing: command)) — \(error)") } - func transmitterSession(_ session: TransmitterSession, didComplete command: Command, response: TransmitterRxMessage?) { + func transmitterSession(_ session: any TransmitterSessioning, didComplete command: Command, response: TransmitterRxMessage?) { append("Command completed: \(String(describing: command))") } } From 2ef7f20d42734f3bf5c837abce242ca5ade356b2 Mon Sep 17 00:00:00 2001 From: ETolboom Date: Fri, 25 Sep 2026 13:55:19 +0200 Subject: [PATCH 13/13] docs: describe passive mode and CGMBLEKit migration README lists both connection modes. HostIntegration documents the persisted passiveModeEnabled key and how CGMBLEKit settings migrate. CGMBLEKitDeviations records passive mode's return and how it differs from CGMBLEKit's. --- Docs/CGMBLEKitDeviations.md | 50 +++++++++++++++++++++++++++------- Docs/HostIntegration.md | 54 ++++++++++++++++++++++++++++++++----- README.md | 34 ++++++++++++++--------- 3 files changed, 110 insertions(+), 28 deletions(-) diff --git a/Docs/CGMBLEKitDeviations.md b/Docs/CGMBLEKitDeviations.md index 87073e6..e54c56d 100644 --- a/Docs/CGMBLEKitDeviations.md +++ b/Docs/CGMBLEKitDeviations.md @@ -18,9 +18,10 @@ Nothing in the BLE layer comes from xDrip4iOS. | Ours | From | Changed | |---|---|---| | `Transport/PeripheralManager.swift` | `PeripheralManager.swift` | **0 lines of 471** — byte-identical | -| `Transport/PeripheralManager+G5.swift` | `PeripheralManager+G5.swift` | +61 lines, **0 deletions** — purely additive | -| `Transport/TransmitterConnection.swift` | `BluetoothManager.swift` | 350 → 352 lines; mostly renames, 2 substantive | -| `Session/TransmitterSession.swift` | `Transmitter.swift` | heavily restructured — see below | +| `Transport/PeripheralManager+G5.swift` | `PeripheralManager+G5.swift` | +75 lines, **0 deletions** — purely additive | +| `Transport/TransmitterConnection.swift` | `BluetoothManager.swift` | mostly renames, 3 substantive deviations | +| `Session/TransmitterSession.swift` | `Transmitter.swift` (active path) | heavily restructured — see below | +| `Session/PassiveTransmitterSession.swift` | `Transmitter.swift` (passive path) | clean-room reimplementation — see below | `PeripheralManager.swift` is where the connection intricacies actually live — `runCommand`, the condition list, `commandLock`, the delegate callbacks. It @@ -50,7 +51,7 @@ refreshes displayed text and touches nothing BLE-related. For reference, CGMBLEKit itself does use a `DispatchSourceTimer`, in `TransmitterManager`'s simulated sample generator. That file is not vendored. -## The two deviations in `TransmitterConnection` +## The deviations in `TransmitterConnection` Everything else in that file is a rename (`BluetoothManager` → `TransmitterConnection` and its delegate methods) or added logging. @@ -75,6 +76,14 @@ match can fall back to `CBAdvertisementDataLocalNameKey` when persisted and passed back into `init`, so a known transmitter can be reconnected directly across launches. +**3. Unsolicited control and authentication values reach the delegate.** +CGMBLEKit routes them to `Transmitter`'s passive listener. Here they were +initially dropped (only backfill was forwarded); passive mode re-adds two +delegate callbacks, `didReceiveControlResponse` and +`didReceiveAuthenticationResponse`. Values claimed by the condition +machinery — an active session's own request/response traffic — still never +reach these callbacks. + Also: the configuration constant changed from `.dexcomG5` to `.dexcomG6`, and the authentication-response delegate callback was dropped because auth responses are now awaited inline (below). @@ -131,23 +140,46 @@ left on the characteristic could otherwise satisfy a bare type match. ## The session layer `TransmitterSession` is where the real divergence is, and it is policy rather -than connection handling. +than connection handling. It covers the **active** path only; the passive +path is a separate class (below). -- **Removed:** the passive path entirely. G6SensorKit always owns the - transmitter; it never observes another app's session. Also gone: +- **Removed:** the passive path from this class (it lives in + `PassiveTransmitterSession` now). Also gone: `resumeScanning`, `stopScanning`, `transmitterDidConnect`; `computeHash` moved to `TransmitterID`. - **Added:** `start`/`stop`/`retarget`, `requestBackfill`/`drainBackfill`, `readBatteryStatus`. - **Kept:** `authenticate`, `requestBond`, `enableNotify`, - `listenToCharacteristic`, `sendCommand`, `dequeuePendingCommand`, + `listenToCharacteristic` (moved to `PeripheralManager+G5.swift`, shared + with the passive session), `sendCommand`, `dequeuePendingCommand`, `readGlucose`, `readTimeMessage`, `readCalibrationData`, `readTransmitterVersion`, `disconnect`. -Backfill is a request in our version. In CGMBLEKit backfill arrives as +Backfill is a request in the active session. In CGMBLEKit backfill arrives as notifications and there is no request function, because the Dexcom app drives the session. +## The passive session + +`PassiveTransmitterSession` + `PassiveMessageHandler` reimplement CGMBLEKit's +passive path without its accumulated workarounds: + +- **Subscribing is done once, at connect, for all three characteristics** + (authentication, control, backfill), and subscriptions are never toggled + for the life of the connection. CGMBLEKit subscribes to control only after + observing an authenticated session (commit `dec4ff0`), because toggling + subscriptions mid-exchange confused CoreBluetooth — a workaround this + design sidesteps rather than replicates. If field testing shows missed + traffic, the fallback is to gate the control subscription on the observed + `AuthChallengeRxMessage`, which the handler already parses. +- **No writes exist in scope at all** — no auth, bond, commands, active reads + or disconnect request. CGMBLEKit's passive path shares a class with the + active path, so writes were reachable from it. +- Message handling is a pure type (`PassiveMessageHandler`, no CoreBluetooth) + that turns observed frames into events, so the whole decode path — + time-frame caching, glucose dating, backfill frame reassembly and CRC + validation against the observed acknowledgement — is unit-tested. + ## What came from xDrip4iOS Four things, none of them code, none in the BLE layer: diff --git a/Docs/HostIntegration.md b/Docs/HostIntegration.md index e557db9..b04861a 100644 --- a/Docs/HostIntegration.md +++ b/Docs/HostIntegration.md @@ -86,12 +86,52 @@ building against `LoopKit/LoopKit`. Fork differences belong in `Common/` shims — never in `G6SensorCore`, which imports no LoopKit at all. A CI matrix building against both hosts at pinned SHAs is the only reliable guard. +## Connection modes + +The manager runs in one of two modes, persisted as `passiveModeEnabled` in the +manager state, chosen during onboarding and switchable afterwards under +Transmitter details: + +- **Direct (default)**: G6SensorKit owns the transmitter — authentication, + bonding, session start/stop, calibrations, active backfill requests. The + manufacturer's app must not be connected to the same transmitter. +- **Passive**: G6SensorKit never writes to the transmitter. It subscribes to + the authentication/control/backfill characteristics and decodes the traffic + of the session the manufacturer's app (or another bonded client on the same + phone) drives. Session commands, calibrations, battery reads and backfill + requests are unavailable; `enqueue(_:)` drops commands. + +`providesBLEHeartbeat` is `true` in direct mode and `false` in passive mode: +in passive the manufacturer's app drives the cadence, so the host's own fetch +timer must keep ticking. + +## Migration from CGMBLEKit + +`G6CGMManager.init?(rawState:)` accepts a rawState dictionary persisted by +CGMBLEKit's `TransmitterManagerState` directly. A state is recognized as +CGMBLEKit-shaped when `passiveModeEnabled` and `sensorLifeDays` are both +absent (every G6SensorKit state carries both). Legacy key handling: + +| CGMBLEKit key | Handling | +|---|---| +| `transmitterID` | Required, same key | +| `transmitterStartDate` | Same key | +| `sensorStartOffset` (seconds since activation) | Mapped to `sensorStartDate = transmitterStartDate + offset` | +| `transmitterExpiryInDays` | Same key (Int) | +| `shouldSyncToRemoteService` | Same key | +| *(absent)* | `passiveModeEnabled = true`, `isOnboarded = true` — CGMBLEKit ran passive-only, so migrated users keep exactly the behavior they had and never see onboarding | + +`peripheralIdentifier` starts nil and is learned on first connection, so the +first launch after migration does one name-filtered scan. + ## Safety notes for host maintainers -- G6SensorKit owns the transmitter connection. Users must not run the - manufacturer's app against the same transmitter. -- The manufacturer's app is not watching glucose while this driver is in use, - so high/low alerting is entirely the host's responsibility. Do not ship this - plugin in a host without working glucose alerts. -- `providesBLEHeartbeat` is `true`. In Loop this suppresses the pump's timer - tick, so regressions in BLE wake-up affect loop cadence, not just CGM data. +- In direct mode G6SensorKit owns the transmitter connection. Users must not + run the manufacturer's app against the same transmitter. In passive mode the + manufacturer's app is **required** on the same phone. +- The manufacturer's app is not watching glucose while this driver is in use + in direct mode, so high/low alerting is entirely the host's responsibility. + Do not ship this plugin in a host without working glucose alerts. +- `providesBLEHeartbeat` is `true` in direct mode. In Loop this suppresses + the pump's timer tick, so regressions in BLE wake-up affect loop cadence, + not just CGM data. diff --git a/README.md b/README.md index c5e96d2..8e46dbb 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,32 @@ # G6SensorKit -A [LoopKit](https://github.com/LoopKit/LoopKit) CGMManager plugin that connects -**directly and natively** to Dexcom G6 and Dexcom ONE transmitters over -Bluetooth — an owning, active connection (authentication, session start/stop, -sensor codes, calibration, backfill), usable by both +A [LoopKit](https://github.com/LoopKit/LoopKit) CGMManager plugin for Dexcom G6 +and Dexcom ONE transmitters over Bluetooth, usable by both [Loop](https://github.com/LoopKit/Loop) and [Trio](https://github.com/nightscout/Trio) -from this single repository. +from this single repository. Two connection modes: + +- **Direct (default)** — an owning, active connection: authentication, + session start/stop, sensor codes, calibration, backfill. +- **Passive** — listens to the session the official Dexcom app drives on the + same phone, like CGMBLEKit does in Loop. Users migrated from CGMBLEKit land + here automatically (see [Docs/HostIntegration.md](Docs/HostIntegration.md)). > **Status: pre-alpha, under active development. Do not use for therapy.** ## What "native" means -Unlike existing drivers that passively read alongside the official Dexcom app, -G6SensorKit *owns* the transmitter relationship: it performs the authentication -handshake keyed on the transmitter ID, starts and stops sensor sessions -(including 4-digit sensor codes), sends calibrations, and backfills missed -readings after connectivity gaps. The official Dexcom app must **not** be used -at the same time. +In the default **direct** mode, G6SensorKit *owns* the transmitter +relationship: it performs the authentication handshake keyed on the +transmitter ID, starts and stops sensor sessions (including 4-digit sensor +codes), sends calibrations, and backfills missed readings after connectivity +gaps. The official Dexcom app must **not** be used at the same time. + +In **passive** mode the plugin never writes to the transmitter: it connects +alongside the official Dexcom app and decodes the notification traffic of the +session that app drives. Sessions, calibrations and sensor codes are then +managed in the Dexcom app, and the Dexcom app is **required** — without it +there is no traffic to observe. Backfill arrives only when the Dexcom app +requests it. Supported: Dexcom G6 (`8…` transmitter IDs), Dexcom ONE (`5…`/`C…`), and Anubis-modified G6 transmitters (auto-detected, extended session length). @@ -31,7 +41,7 @@ Not supported: Dexcom G5 (`4…` IDs — no longer in circulation), G7/ONE+ | `G6SensorKit.framework` | LoopKit `CGMManager` conformance, state persistence, sample conversion | | `G6SensorKitUI.framework` | `CGMManagerUI`, onboarding and settings UI | | `G6SensorKitPlugin.loopplugin` | Plugin bundle discovered by Loop at runtime | -| `Apps/G6SensorHarness` | Standalone proof-of-concept app exercising the core on a live transmitter | +| `Apps/G6SensorHarness` | Standalone proof-of-concept app exercising both session modes on a live transmitter | ## License