Skip to content

Commit d797bc7

Browse files
committedDec 17, 2024
Merge remote-tracking branch 'upstream/main' into fix-merge
2 parents 4dc9a8a + 47bec3a commit d797bc7

File tree

10 files changed

+44
-44
lines changed

10 files changed

+44
-44
lines changed
 

‎App/App.swift

+4-7
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ import SwiftUI
1313
// MARK: - GlucoseDirectApp
1414

1515
@main
16-
final class GlucoseDirectApp: App {
16+
struct GlucoseDirectApp: App {
1717
// MARK: Lifecycle
1818

1919
init() {
2020
#if targetEnvironment(simulator)
2121
DirectLog.info("Application directory: \(NSHomeDirectory())")
2222
#endif
2323

24-
GlucoseDirectApp.store.dispatch(.startup)
24+
store.dispatch(.startup)
2525
}
2626

2727
// MARK: Internal
@@ -36,16 +36,13 @@ final class GlucoseDirectApp: App {
3636
var body: some Scene {
3737
WindowGroup {
3838
ContentView()
39-
.environmentObject(GlucoseDirectApp.store)
39+
.environmentObject(self.store)
4040
}
4141
}
4242

4343
// MARK: Private
4444

45-
46-
public static var store: DirectStore = {
47-
return createStore()
48-
}()
45+
private let store: DirectStore = createStore()
4946
}
5047

5148
// MARK: - GlucoseDirectAppDelegate

‎App/Modules/SensorConnector/LibreConnection/LibreLinkUpConnection.swift

+19-21
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,18 @@ class LibreLinkUpConnection: SensorBluetoothConnection, IsSensor {
151151

152152
// MARK: Private
153153

154+
private var throttleDelay: Double {
155+
(Double(sensorInterval) / 1.5) * 60
156+
}
157+
154158
private var lastLogin: LibreLinkLogin?
155159
private let oneMinuteReadingUUID = CBUUID(string: "0898177A-EF89-11E9-81B4-2A2AE2DBCCE4")
156160
private var oneMinuteReadingCharacteristic: CBCharacteristic?
157161
private let requestHeaders = [
158162
"User-Agent": "Mozilla/5.0",
159163
"Content-Type": "application/json",
160164
"product": "llu.ios",
161-
"version": "4.8.0",
165+
"version": "4.12.0",
162166
"Accept-Encoding": "gzip, deflate, br",
163167
"Connection": "keep-alive",
164168
"Pragma": "no-cache",
@@ -179,13 +183,9 @@ class LibreLinkUpConnection: SensorBluetoothConnection, IsSensor {
179183
return decoder
180184
}()
181185

182-
private var throttleDelay: Double {
183-
(Double(sensorInterval) / 1.5) * 60
184-
}
185-
186186
private func processLogin(apiRegion: String? = nil) async throws {
187187
if lastLogin == nil || lastLogin!.authExpires <= Date() {
188-
DirectLog.info("LibreLinkUp processLogin")
188+
DirectLog.info("LibreLinkUp processLogin, starts working, \(Date().debugDescription)")
189189

190190
var loginResponse = try await login(apiRegion: apiRegion)
191191
if loginResponse.status == 4 {
@@ -223,7 +223,7 @@ class LibreLinkUpConnection: SensorBluetoothConnection, IsSensor {
223223
DirectLog.info("LibreLinkUp processLogin, apiRegion: \(apiRegion)")
224224
DirectLog.info("LibreLinkUp processLogin, authExpires: \(authExpires)")
225225

226-
let connectResponse = try await connect(apiRegion: apiRegion, authToken: authToken)
226+
let connectResponse = try await connect(userID: userID, apiRegion: apiRegion, authToken: authToken)
227227

228228
guard let patientID = connectResponse.data?.first(where: { $0.patientID == userID })?.patientID ?? connectResponse.data?.first?.patientID else {
229229
disconnectConnection()
@@ -233,12 +233,12 @@ class LibreLinkUpConnection: SensorBluetoothConnection, IsSensor {
233233

234234
DirectLog.info("LibreLinkUp processLogin, patientID: \(patientID)")
235235

236-
lastLogin = LibreLinkLogin(patientID: patientID, apiRegion: apiRegion, authToken: authToken, authExpires: authExpires)
236+
lastLogin = LibreLinkLogin(userID: userID, patientID: patientID, apiRegion: apiRegion, authToken: authToken, authExpires: authExpires)
237237
}
238238
}
239239

240240
private func processFetch() async throws {
241-
DirectLog.info("LibreLinkUp processFetch")
241+
DirectLog.info("LibreLinkUp processFetch, starts working, \(Date().debugDescription)")
242242

243243
try await processLogin()
244244

@@ -375,7 +375,7 @@ class LibreLinkUpConnection: SensorBluetoothConnection, IsSensor {
375375
throw LibreLinkError.unknownError
376376
}
377377

378-
private func connect(apiRegion: String, authToken: String) async throws -> LibreLinkResponse<[LibreLinkResponseConnect]> {
378+
private func connect(userID: String, apiRegion: String, authToken: String) async throws -> LibreLinkResponse<[LibreLinkResponseConnect]> {
379379
DirectLog.info("LibreLinkUp connect")
380380

381381
guard let url = URL(string: "https://api-\(apiRegion).libreview.io/llu/connections") else {
@@ -386,6 +386,7 @@ class LibreLinkUpConnection: SensorBluetoothConnection, IsSensor {
386386

387387
var request = URLRequest(url: url)
388388
request.setValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization")
389+
request.setValue(userID.toSha256(), forHTTPHeaderField: "Account-Id")
389390

390391
for (header, value) in requestHeaders {
391392
request.setValue(value, forHTTPHeaderField: header)
@@ -422,6 +423,7 @@ class LibreLinkUpConnection: SensorBluetoothConnection, IsSensor {
422423

423424
var request = URLRequest(url: url)
424425
request.setValue("Bearer \(lastLogin.authToken)", forHTTPHeaderField: "Authorization")
426+
request.setValue(lastLogin.userID.toSha256(), forHTTPHeaderField: "Account-Id")
425427

426428
for (header, value) in requestHeaders {
427429
request.setValue(value, forHTTPHeaderField: header)
@@ -526,9 +528,7 @@ private struct LibreLinkResponseActiveSensors: Codable {
526528
// MARK: - LibreLinkResponseDevice
527529

528530
private struct LibreLinkResponseDevice: Codable {
529-
enum CodingKeys: String, CodingKey { case dtid
530-
case version = "v"
531-
}
531+
enum CodingKeys: String, CodingKey { case dtid, version = "v" }
532532

533533
let dtid: Int
534534
let version: String
@@ -537,9 +537,7 @@ private struct LibreLinkResponseDevice: Codable {
537537
// MARK: - LibreLinkResponseSensor
538538

539539
private struct LibreLinkResponseSensor: Codable {
540-
enum CodingKeys: String, CodingKey { case sn
541-
case activation = "a"
542-
}
540+
enum CodingKeys: String, CodingKey { case sn, activation = "a" }
543541

544542
let sn: String
545543
let activation: Double
@@ -559,9 +557,7 @@ private extension LibreLinkResponseSensor {
559557
// MARK: - LibreLinkResponseGlucose
560558

561559
private struct LibreLinkResponseGlucose: Codable {
562-
enum CodingKeys: String, CodingKey { case timestamp = "Timestamp"
563-
case value = "ValueInMgPerDl"
564-
}
560+
enum CodingKeys: String, CodingKey { case timestamp = "Timestamp", value = "ValueInMgPerDl" }
565561

566562
let timestamp: Date
567563
let value: Double
@@ -580,7 +576,7 @@ private extension LibreLinkResponseUser {
580576
return country.lowercased()
581577
}
582578

583-
if country.lowercased() == "gb" {
579+
if (country.lowercased() == "gb") {
584580
return "eu2"
585581
}
586582

@@ -600,7 +596,8 @@ private struct LibreLinkResponseAuthentication: Codable {
600596
private struct LibreLinkLogin {
601597
// MARK: Lifecycle
602598

603-
init(patientID: String, apiRegion: String, authToken: String, authExpires: Double) {
599+
init(userID: String, patientID: String, apiRegion: String, authToken: String, authExpires: Double) {
600+
self.userID = userID
604601
self.patientID = patientID
605602
self.apiRegion = apiRegion.lowercased()
606603
self.authToken = authToken
@@ -609,6 +606,7 @@ private struct LibreLinkLogin {
609606

610607
// MARK: Internal
611608

609+
let userID: String
612610
let patientID: String
613611
let apiRegion: String
614612
let authToken: String

‎FAQ.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
## Glucose Direct keeps losing the connection to the sensor
44

5-
Check if other apps (such as LibreLink) are allowed to use Bluetooth, and thus take away Glucose Direct's connection to the sensor !
5+
Check if other apps (such as LibreLink) are allowed to use Bluetooth, and thus take away Glucose Direct's connection to the sensor.
66

77
This can be done under the iOS app "Settings" > "LibreLink" (or other app that can connect sensors), disable Bluetooth there.
88

99
## No more minute-by-minute notifications, but glucose alarms continue to sound
1010
Go to Settings, disable the Glucose Badge under "Other Settings", but leave all alarms enabled. With the glucose badge also minutely notifications disappear. Without the notifications, however, it is also unfortunately not possible to display mmol values on the app icon.
1111

12-
## Display glucose values on the Apple Watch !
12+
## Display glucose values on the Apple Watch
1313
Create a new calendar in the Apple "Calendar" app, e.g. "Glucose Direct". Activate the calendar export in the Glucose Direct app, also select the created calendar there.
1414

1515
On the Apple Watch, activate a complication with the calendar selection "Your Schedule" on your Watch Face.

‎GlucoseDirect.xcodeproj/project.pbxproj

+4-4
Original file line numberDiff line numberDiff line change
@@ -970,7 +970,7 @@
970970
attributes = {
971971
BuildIndependentTargetsInParallel = YES;
972972
LastSwiftUpdateCheck = 1400;
973-
LastUpgradeCheck = 1400;
973+
LastUpgradeCheck = 1600;
974974
TargetAttributes = {
975975
E20B8539266F4A9800AA4224 = {
976976
CreatedOnToolsVersion = 12.5;
@@ -1396,6 +1396,7 @@
13961396
DEBUG_INFORMATION_FORMAT = dwarf;
13971397
ENABLE_STRICT_OBJC_MSGSEND = YES;
13981398
ENABLE_TESTABILITY = YES;
1399+
ENABLE_USER_SCRIPT_SANDBOXING = YES;
13991400
GCC_C_LANGUAGE_STANDARD = gnu11;
14001401
GCC_DYNAMIC_NO_PIC = NO;
14011402
GCC_NO_COMMON_BLOCKS = YES;
@@ -1459,6 +1460,7 @@
14591460
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
14601461
ENABLE_NS_ASSERTIONS = NO;
14611462
ENABLE_STRICT_OBJC_MSGSEND = YES;
1463+
ENABLE_USER_SCRIPT_SANDBOXING = YES;
14621464
GCC_C_LANGUAGE_STANDARD = gnu11;
14631465
GCC_NO_COMMON_BLOCKS = YES;
14641466
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -1483,7 +1485,6 @@
14831485
isa = XCBuildConfiguration;
14841486
baseConfigurationReference = E247D8E426B7D70A00BDAF89 /* GlucoseDirect.xcconfig */;
14851487
buildSettings = {
1486-
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
14871488
APP_GROUP_ID = "$(APP_GROUP_ID)";
14881489
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
14891490
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
@@ -1515,7 +1516,6 @@
15151516
isa = XCBuildConfiguration;
15161517
baseConfigurationReference = E247D8E426B7D70A00BDAF89 /* GlucoseDirect.xcconfig */;
15171518
buildSettings = {
1518-
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
15191519
APP_GROUP_ID = "$(APP_GROUP_ID)";
15201520
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
15211521
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
@@ -1647,7 +1647,7 @@
16471647
repositoryURL = "https://github.com/groue/GRDB.swift";
16481648
requirement = {
16491649
kind = exactVersion;
1650-
version = 6.15.0;
1650+
version = 6.29.3;
16511651
};
16521652
};
16531653
F45270802ACE690C00DB1611 /* XCRemoteSwiftPackageReference "toast-swift" */ = {

‎GlucoseDirect.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
2+
"originHash" : "1608ac12fdffe7fac9708cd1c5ae519dcab3a5d88dd62c53deb1c399a2e8dbf1",
23
"pins" : [
34
{
45
"identity" : "grdb.swift",
56
"kind" : "remoteSourceControl",
67
"location" : "https://github.com/groue/GRDB.swift",
78
"state" : {
8-
"revision" : "57aa4c30bfa0fe6a1913f83042937c4fb943e79c",
9-
"version" : "6.15.0"
9+
"revision" : "2cf6c756e1e5ef6901ebae16576a7e4e4b834622",
10+
"version" : "6.29.3"
1011
}
1112
},
1213
{
@@ -19,5 +20,5 @@
1920
}
2021
}
2122
],
22-
"version" : 2
23+
"version" : 3
2324
}

‎GlucoseDirect.xcodeproj/xcshareddata/xcschemes/GlucoseDirectApp.xcscheme

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1400"
3+
LastUpgradeVersion = "1600"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"

‎GlucoseDirect.xcodeproj/xcshareddata/xcschemes/GlucoseDirectWidget.xcscheme

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1400"
3+
LastUpgradeVersion = "1600"
44
wasCreatedForAppExtension = "YES"
55
version = "2.0">
66
<BuildAction

‎GlucoseDirectOverride.xcconfig

-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,4 @@
33
// LibreDirect
44
//
55

6-
PRODUCT_BUNDLE_IDENTIFIER = name.${DEVELOPMENT_TEAM}.libre-direct
76
DEVELOPMENT_TEAM = 9JNYW2DG9D
8-
9-
APP_AUTHOR = Reimar Metzen
10-
APP_SUPPORT_MAIL = glucosedirect@icloud.com

‎Library/Extensions/String.swift

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import CommonCrypto
77
import Foundation
8+
import CryptoKit
89

910
extension String {
1011
func capitalizingFirstLetter() -> String {
@@ -14,6 +15,13 @@ extension String {
1415
func asMinuteChange() -> String {
1516
return String(format: LocalizedString("%1$@/min."), self)
1617
}
18+
19+
func toSha256() -> String {
20+
let data = Data(self.utf8)
21+
22+
let hashedData = SHA256.hash(data: data)
23+
return hashedData.map { String(format: "%02hhx", $0) }.joined()
24+
}
1725

1826
func toSha1() -> String {
1927
let data = Data(self.utf8)

‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Glucose Direct App
1+
## Glucose Direct
22

33
*** Warning ***, This project is highly experimental! Please use this app with caution and extreme care. Do not make careless decisions based on software. Do not use this software if you are unsure.***
44

0 commit comments

Comments
 (0)
Please sign in to comment.