Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
filePath = "GlucoseBar/SettingsView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "260"
endingLineNumber = "260"
startingLineNumber = "259"
endingLineNumber = "259"
landmarkName = "body"
landmarkType = "24">
</BreakpointContent>
Expand All @@ -30,8 +30,8 @@
filePath = "GlucoseBar/SettingsView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "292"
endingLineNumber = "292"
startingLineNumber = "291"
endingLineNumber = "291"
landmarkName = "body"
landmarkType = "24">
</BreakpointContent>
Expand Down
8 changes: 3 additions & 5 deletions GlucoseBar/GlucoseBarApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,11 @@ struct GlucoseBarApp: App {
applyColor = true
}

var configuration: NSImage.SymbolConfiguration
let configuration = NSImage.SymbolConfiguration(pointSize: 16, weight: .light)
if applyColor {
configuration = NSImage.SymbolConfiguration(pointSize: 16, weight: .light)
.applying(.init(paletteColors: [color]))
} else {
configuration = NSImage.SymbolConfiguration(pointSize: 16, weight: .light)
configuration.applying(.init(paletteColors: [color]))
}

let image = NSImage(systemSymbolName: symbol, accessibilityDescription: accessibilityDescription)
let titleImage = image?.withSymbolConfiguration(configuration) ?? NSImage(systemSymbolName: symbol, accessibilityDescription: accessibilityDescription)!

Expand Down
2 changes: 1 addition & 1 deletion GlucoseBar/GlucoseEntry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public struct GlucoseEntry: Hashable {
case .downDownDown:
return "↓↓"
case .notComputable:
return "?"
return ""
case .rateOutOfRange:
return "?"
}
Expand Down
23 changes: 11 additions & 12 deletions GlucoseBar/GraphView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,20 @@ struct GraphView: View {
func getGraphData() -> [GraphEntry] {
var data: [GraphEntry] = [];
if (g.entries != nil) {
for entry in g.entries! {
// Check if entry!.date is longer in the past than s.graphMinutes
if -1 * entry.date.timeIntervalSinceNow > Double(s.graphMinutes) * 60 {
continue
}

let entryCount = s.graphMinutes/5-1

for i in 0..<entryCount {
if (g.entries!.count > i) {
let entry = g.entries![i]
let glu = convertGlucose(s, glucose: entry.glucose)
let glu = convertGlucose(s, glucose: entry.glucose)

var delta = 0.0
if entry.changeRate != nil {
delta = entry.changeRate!
}

data.append(GraphEntry(date: entry.date, value: glu, trend: entry.trend ?? .notComputable, delta: delta))
var delta = 0.0
if entry.changeRate != nil {
delta = entry.changeRate!
}

data.append(GraphEntry(date: entry.date, value: glu, trend: entry.trend ?? .notComputable, delta: delta))
}
}

Expand Down
6 changes: 5 additions & 1 deletion GlucoseBar/MainAppView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,12 @@ struct MainAppView: View {
if g.error != "" && s.validSettings && vs.isOnline {
VStack {
Text("Error").font(.headline).frame(maxWidth: .infinity, alignment: .leading).padding(.top, 10).foregroundColor(.red)
// Text("\(g.error)").padding(.top, 10).fixedSize(horizontal: false, vertical: true).foregroundColor(.red).fontWeight(.heavy).padding(.bottom, 10)
Text("Check the settings and make sure your CGM source (\(s.cgmProvider.presentable)) is responding.").fixedSize(horizontal: false, vertical: true)

if g.provider.providerIssue != nil {
Text("Additional Info: \(g.provider.providerIssue!)").fixedSize(horizontal: false, vertical: true).padding(.top)
}

Spacer()
HStack {
SettingsButton()
Expand Down
208 changes: 112 additions & 96 deletions GlucoseBar/Providers/LibreLinkUp/LibreLinkUp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,9 @@ class LibreLinkUp: Provider {

if !isAuthValid() {
logger.debug("calling authenticate from fetch")
authenticate(completion: { success, _ in
if success {
Task {
await self.fetch()
}
}
})
if await authenticate() {
await self.fetch()
}
return
}

Expand Down Expand Up @@ -350,7 +346,7 @@ class LibreLinkUp: Provider {
//
// }

private func getConnections() async {
private func getConnections() async -> (connections: [LibreLinkUp.LibreLinkUpConnectionsResponse], success: Bool) {
self.logger.debug("LibreLinkUp.getConnections")

let path = "/connections"
Expand All @@ -363,41 +359,53 @@ class LibreLinkUp: Provider {

if res.statusCode > 499 {
// TODO: Handle error
return
self.logger.error("High status code, not yet handled")
return (connections: [], success: false)
}

do {
let result = try JSONDecoder().decode(LibreLinkUpResponse<[LibreLinkUpConnectionsResponse]>.self, from: data)

switch result.status {
case 0:
self.logger.info("Status 0, updating values")
// TODO: Success
self.logger.info("Connection count: \(self.connections.count)")
self.connections = result.data!
self.connectionID = self.connections.first!.patientID
self.logger.debug("got connections: \(self.connections)")
return
// DispatchQueue.main.async {
self.logger.info("Status 0, updating values")
// TODO: Success
self.logger.info("Connection count: \(self.connections.count)")
self.connections = result.data!
self.connectionID = result.data!.first?.patientID ?? ""// self.connections.first?.patientID ?? ""
self.logger.debug("got connections: \(self.connections)")
// }
return (connections: result.data!, success: true)
// return true
case 920: // Version bump needed
// self.logger.info("Version too low, bumping and retrying")
// self.lluVersion = result.data!.minimumVersion ?? "0"
// completion(false, true)
return
return (connections: [], success: false)
// return false
default:
self.logger.debug("Default case triggered for status: \(result.status)")
}
} catch {
self.logger.error("failed handling decode and actions from response \(String(describing: error))")
self.logger.debug("DEBUG: \(String(data: data, encoding: .utf8)!)")
return
self.logger.error("DEBUG: \(String(data: data, encoding: .utf8)!)")
return (connections: [], success: false)
// return false
}
} catch {

self.logger.error("Catastrophic failure creating request.")
return (connections: [], success: false)
// return false
}

return (connections: [], success: false)
// return false
}

private func authenticate(completion: @escaping (_ success: Bool, _ tryAgain: Bool?) -> Void) {
private func authenticate() async -> Bool {
self.logger.debug("LibreLinkUp.authenticate")
self.providerIssue = nil

let path = "/auth/login"
let requestBody = LibreLinkUpAuthRequest(email: self.username, password: self.password)
Expand All @@ -408,95 +416,103 @@ class LibreLinkUp: Provider {
request.httpBody = jsonData
} catch {
logger.info("failed marshalling json, aborting authenticate")
completion(false, false)
return
return false
}

let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
self.logger.error("authenitcation error: \(String(describing: error))")
completion(false, false)
return
}
do {
let (data, response) = try await URLSession.shared.data(for: request)
self.logger.error("DEBUG: \(String(data: data, encoding: .utf8)!)")

let res = response as! HTTPURLResponse
if res.statusCode > 499 {
// TODO: Handle error
completion(false, false)
return
self.logger.error("Response code in 500 range. Dunno what to do! Code: \(res.statusCode)")
return false
}

do {
let result = try JSONDecoder().decode(LibreLinkUpResponse<LibreLinkUpAuthResponse>.self, from: data)
if res.statusCode > 399 {
self.logger.error("Response code in 400 range. Something wrong? Rate limiting? Code: \(res.statusCode)")
if res.statusCode == 430 || res.statusCode == 429 {
self.logger.error("Rate limited, surfacing to user.")
self.providerIssue = "Libre LinkUp is rate limiting you. Please close GlucoseBar try again in 5 minutes or more."
}
return false
}

switch result.status {
case 0:
// TODO: Success
// Check if redirect
if let redirect = result.data!.redirect, let region = result.data!.region, redirect, !region.isEmpty {
self.apiRegion = result.data!.region!
self.authenticate(completion: completion)
return
}

guard let authToken = result.data!.authTicket?.token,
!authToken.isEmpty else {
self.logger.error("auth response did not satisfy requirements")
completion(false, false)
return
}

// COMPLETED AUTH
self.auth = result.data!.authTicket!

// Getting connections
Task {
await self.getConnections()
completion(true, false)
}
return
case 2:
// Bad credentials?
self.logger.info("Bad credentials")
completion(false, false)
return
case 4:
// TODO: Request TOU
self.logger.info("TOU needs calling")
completion(false, true)
return
case 920: // Version bump needed
self.logger.info("Version too low, bumping and retrying")
self.lluVersion = result.data!.data?.minimumVersion ?? "0"
completion(false, true)
return
default:
self.logger.debug("Default case triggered for status: \(result.status)")

let result = try JSONDecoder().decode(LibreLinkUpResponse<LibreLinkUpAuthResponse>.self, from: data)

switch result.status {
case 0:
// TODO: Success
// Check if redirect
if let redirect = result.data!.redirect, let region = result.data!.region, redirect, !region.isEmpty {
self.apiRegion = result.data!.region!
return await self.authenticate()
}
} catch {
self.logger.error("failed handling decode and actions from response: \(String(describing: error))")
completion(false, false)
return

guard let authToken = result.data!.authTicket?.token,
!authToken.isEmpty else {
self.logger.error("auth response did not satisfy requirements")
return false
}

// COMPLETED AUTH
self.auth = result.data!.authTicket!

// Getting connections
// Task {
let conns = await self.getConnections()
self.connections = conns.connections
return conns.success
// return await self.getConnections()
// }
case 2:
// Bad credentials?
self.logger.info("Bad credentials")
return false
case 4:
// TODO: Request TOU
self.logger.info("TOU needs calling")
// return await self.authenticate()
return false

case 920: // Version bump needed
self.logger.info("Version too low, bumping and retrying")
self.lluVersion = result.data!.data?.minimumVersion ?? "0"
return await self.authenticate()
default:
self.logger.debug("Default case triggered for status: \(result.status)")

}
} catch {
self.logger.error("failed handling decode and actions from response: \(String(describing: error))")
}
task.resume()

return false
}

// override internal func verifyCredentials(completion: @escaping (_ result: Bool) -> Void) {
// self.logger.debug("librelinkup.verifyCredentials")
// self.authenticate(completion: {authSuccess, tryAgain in
// if authSuccess {
// self.logger.debug("librelinkup auth success: \(self.connectionID)")
// completion(true)
// return
// }
//
// self.logger.debug("librelinkup auth failure")
// completion(false)
// return
// })
// }
override internal func verifyCredentials() async -> Bool {
self.logger.debug("librelinkup.verifyCredentials")
let authSuccess = await self.authenticate()

if authSuccess {
self.logger.debug("librelinkup auth success: \(self.connectionID)")

let conns = await self.getConnections()
// let connectionSuccess = await self.getConnections()
if conns.success {
self.connections = conns.connections
self.logger.debug("librelinkup got connections successfully")
return true
}

return false
}

self.logger.debug("librelinkup auth failure")
return false

}

override public func isAuthValid() -> Bool {
if auth == nil {
Expand Down
Loading