Skip to content
Open
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
22 changes: 17 additions & 5 deletions FreeAPS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,8 @@
E013D872273AC6FE0014109C /* GlucoseSimulatorSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E013D871273AC6FE0014109C /* GlucoseSimulatorSource.swift */; };
E06B911A275B5EEA003C04B6 /* Array+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E06B9119275B5EEA003C04B6 /* Array+Extension.swift */; };
E0CC2C5C275B9F0F00A7BC71 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E0CC2C5B275B9DAE00A7BC71 /* HealthKit.framework */; };
E0D4F80527513ECF00BDF1FE /* HealthKitSample.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0D4F80427513ECF00BDF1FE /* HealthKitSample.swift */; };
E0D4F80527513ECF00BDF1FE /* HealthKitSamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0D4F80427513ECF00BDF1FE /* HealthKitSamples.swift */; };
E0E9DB9727F051E700614A3F /* CarbsSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E9DB9627F051E700614A3F /* CarbsSource.swift */; };
E13B7DAB2A435F57066AF02E /* TargetsEditorStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36F58DDD71F0E795464FA3F0 /* TargetsEditorStateModel.swift */; };
E25073BC86C11C3D6A42F5AC /* CalibrationsStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47DFCE895C930F784EF11843 /* CalibrationsStateModel.swift */; };
E39E418C56A5A46B61D960EE /* ConfigEditorStateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D5B4F8B4194BB7E260EF251 /* ConfigEditorStateModel.swift */; };
Expand Down Expand Up @@ -729,7 +730,8 @@
E013D871273AC6FE0014109C /* GlucoseSimulatorSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseSimulatorSource.swift; sourceTree = "<group>"; };
E06B9119275B5EEA003C04B6 /* Array+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Extension.swift"; sourceTree = "<group>"; };
E0CC2C5B275B9DAE00A7BC71 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; };
E0D4F80427513ECF00BDF1FE /* HealthKitSample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthKitSample.swift; sourceTree = "<group>"; };
E0D4F80427513ECF00BDF1FE /* HealthKitSamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthKitSamples.swift; sourceTree = "<group>"; };
E0E9DB9627F051E700614A3F /* CarbsSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbsSource.swift; sourceTree = "<group>"; };
E26904AACA8D9C15D229D675 /* SnoozeStateModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SnoozeStateModel.swift; sourceTree = "<group>"; };
E2EBA7C03C26FCC67E16D798 /* LibreConfigProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LibreConfigProvider.swift; sourceTree = "<group>"; };
E625985B47742D498CB1681A /* NotificationsConfigProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NotificationsConfigProvider.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1131,6 +1133,7 @@
38A43597262E0E4900E80935 /* FetchAnnouncementsManager.swift */,
38DAB289260D349500F74C1A /* FetchGlucoseManager.swift */,
38192E06261BA9960094D973 /* FetchTreatmentsManager.swift */,
E0E9DB9527F051C300614A3F /* Carbs */,
3856933F270B57A00002C50D /* CGM */,
38A504F625DDA0E200C5B9E8 /* Extensions */,
388E5A5825B6F0070019842D /* OpenAPS */,
Expand Down Expand Up @@ -1308,7 +1311,7 @@
38A0364125ED069400FCBB52 /* TempBasal.swift */,
3871F39B25ED892B0013ECB5 /* TempTarget.swift */,
3811DE8E25C9D80400A708ED /* User.swift */,
E0D4F80427513ECF00BDF1FE /* HealthKitSample.swift */,
E0D4F80427513ECF00BDF1FE /* HealthKitSamples.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -1802,6 +1805,14 @@
path = Assemblies;
sourceTree = "<group>";
};
E0E9DB9527F051C300614A3F /* Carbs */ = {
isa = PBXGroup;
children = (
E0E9DB9627F051E700614A3F /* CarbsSource.swift */,
);
path = Carbs;
sourceTree = "<group>";
};
E42231DBF0DBE2B4B92D1B15 /* CREditor */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1945,11 +1956,11 @@
buildConfigurationList = 388E596725AD948E0019842D /* Build configuration list for PBXNativeTarget "FreeAPS" */;
buildPhases = (
3811DEF525CA169200A708ED /* Swiftformat */,
388E595425AD948C0019842D /* Sources */,
388E595525AD948C0019842D /* Frameworks */,
388E595625AD948C0019842D /* Resources */,
3821ECD025DC703C00BC42AD /* Embed Frameworks */,
38E8753D27554D5900975559 /* Embed Watch Content */,
388E595425AD948C0019842D /* Sources */,
);
buildRules = (
);
Expand Down Expand Up @@ -2361,7 +2372,7 @@
D2165E9D78EFF692C1DED1C6 /* AddTempTargetDataFlow.swift in Sources */,
38E4451E274DB04600EC9A94 /* AppDelegate.swift in Sources */,
5BFA1C2208114643B77F8CEB /* AddTempTargetProvider.swift in Sources */,
E0D4F80527513ECF00BDF1FE /* HealthKitSample.swift in Sources */,
E0D4F80527513ECF00BDF1FE /* HealthKitSamples.swift in Sources */,
919DBD08F13BAFB180DF6F47 /* AddTempTargetStateModel.swift in Sources */,
8BC2F5A29AD1ED08AC0EE013 /* AddTempTargetRootView.swift in Sources */,
38A00B1F25FC00F7006BC0B0 /* Autotune.swift in Sources */,
Expand Down Expand Up @@ -2402,6 +2413,7 @@
B7C465E9472624D8A2BE2A6A /* CalibrationsDataFlow.swift in Sources */,
320D030F724170A637F06D50 /* CalibrationsProvider.swift in Sources */,
E25073BC86C11C3D6A42F5AC /* CalibrationsStateModel.swift in Sources */,
E0E9DB9727F051E700614A3F /* CarbsSource.swift in Sources */,
BA90041DC8991147E5C8C3AA /* CalibrationsRootView.swift in Sources */,
E3A08AAE59538BC8A8ABE477 /* NotificationsConfigDataFlow.swift in Sources */,
0F7A65FBD2CD8D6477ED4539 /* NotificationsConfigProvider.swift in Sources */,
Expand Down
8 changes: 8 additions & 0 deletions FreeAPS.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
4 changes: 4 additions & 0 deletions FreeAPS/Sources/APS/APSManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ final class BaseAPSManager: APSManager, Injectable {
@Injected() private var deviceDataManager: DeviceDataManager!
@Injected() private var nightscout: NightscoutManager!
@Injected() private var settingsManager: SettingsManager!
@Injected() private var healthKitManager: HealthKitManager!
@Injected() private var broadcaster: Broadcaster!
@Persisted(key: "lastAutotuneDate") private var lastAutotuneDate = Date()
@Persisted(key: "lastLoopDate") var lastLoopDate: Date = .distantPast {
Expand Down Expand Up @@ -178,6 +179,9 @@ final class BaseAPSManager: APSManager, Injectable {
} else {
self.loopCompleted()
}
// upload insulin to healthKit (from pump history)
let events = self.pumpHistoryStorage.recent()
self.healthKitManager.saveIfNeeded(pumpEvents: events)
} receiveValue: {}
.store(in: &lifetime)
}
Expand Down
5 changes: 5 additions & 0 deletions FreeAPS/Sources/APS/Carbs/CarbsSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Combine

protocol CarbsSource: SourceInfoProvider {
func fetchCarbs() -> AnyPublisher<[CarbsEntry], Never>
}
9 changes: 6 additions & 3 deletions FreeAPS/Sources/APS/FetchTreatmentsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ protocol FetchTreatmentsManager {}
final class BaseFetchTreatmentsManager: FetchTreatmentsManager, Injectable {
private let processQueue = DispatchQueue(label: "BaseFetchTreatmentsManager.processQueue")
@Injected() var nightscoutManager: NightscoutManager!
@Injected() var healthKitManager: HealthKitManager!
@Injected() var tempTargetsStorage: TempTargetsStorage!
@Injected() var carbsStorage: CarbsStorage!

Expand All @@ -22,15 +23,17 @@ final class BaseFetchTreatmentsManager: FetchTreatmentsManager, Injectable {
private func subscribe() {
timer.publisher
.receive(on: processQueue)
.flatMap { _ -> AnyPublisher<([CarbsEntry], [TempTarget]), Never> in
.flatMap { _ -> AnyPublisher<([CarbsEntry], [CarbsEntry], [TempTarget]), Never> in
debug(.nightscout, "FetchTreatmentsManager heartbeat")
debug(.nightscout, "Start fetching carbs and temptargets")
return Publishers.CombineLatest(
return Publishers.CombineLatest3(
self.nightscoutManager.fetchCarbs(),
self.healthKitManager.fetchCarbs(),
self.nightscoutManager.fetchTempTargets()
).eraseToAnyPublisher()
}
.sink { carbs, targets in
.sink { carbsFromNS, carbsFromAH, targets in
let carbs = carbsFromAH + carbsFromNS
let filteredCarbs = carbs.filter { !($0.enteredBy?.contains(CarbsEntry.manual) ?? false) }
if filteredCarbs.isNotEmpty {
self.carbsStorage.storeCarbs(filteredCarbs)
Expand Down
2 changes: 1 addition & 1 deletion FreeAPS/Sources/APS/Storage/CarbsStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ final class BaseCarbsStorage: CarbsStorage, Injectable {
func nightscoutTretmentsNotUploaded() -> [NigtscoutTreatment] {
let uploaded = storage.retrieve(OpenAPS.Nightscout.uploadedPumphistory, as: [NigtscoutTreatment].self) ?? []

let eventsManual = recent().filter { $0.enteredBy == CarbsEntry.manual }
let eventsManual = recent().filter { $0.enteredBy == CarbsEntry.manual || $0.enteredBy == CarbsEntry.applehealth }
let treatments = eventsManual.map {
NigtscoutTreatment(
duration: nil,
Expand Down
5 changes: 3 additions & 2 deletions FreeAPS/Sources/Application/FreeAPSApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ import Swinject

var body: some Scene {
WindowGroup {
Main.RootView(resolver: resolver)
.onOpenURL(perform: handleURL)
rootView
.animation(.easeIn(duration: 0.75), value: self.loadingIsEnded)
}
.onChange(of: scenePhase) { newScenePhase in
debug(.default, "APPLICATION PHASE: \(newScenePhase)")
Expand All @@ -68,6 +68,7 @@ import Swinject
}

// Migration is temporary disabled

@ViewBuilder private var rootView: some View {
if !loadingIsEnded {
Screen.migration.view(resolver: resolver)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -943,11 +943,8 @@ Enact a temp Basal or a temp target */
/* */
"Connect to Apple Health" = "Connect to Apple Health";

/* Show when have not permissions for writing to Health */
"For write data to Apple Health you must give permissions in Settings > Health > Data Access" = "For write data to Apple Health you must give permissions in Settings > Health > Data Access";

/* */
"After you create glucose records in the Health app, please open FreeAPS X to help us guaranteed transfer changed data" = "After you create glucose records in the Health app, please open FreeAPS X to help us guaranteed transfer changed data";
"After you create records in the Health app, please open FreeAPS X to help us guaranteed transfer changed data" = "After you create records in the Health app, please open FreeAPS X to help us guaranteed transfer changed data";
/* --------------------------------------------
*/
/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -943,11 +943,8 @@ Enact a temp Basal or a temp target */
/* */
"Connect to Apple Health" = "Подключить к Apple Health";

/* Show when have not permissions for writing to Health */
"For write data to Apple Health you must give permissions in Settings > Health > Data Access" = "Чтобы записывать данные в Apple Health вам необходимо дать соответствующие разрешения, перейдя к меню Настройки > Здоровье > Доступ к данным";

/* */
"After you create glucose records in the Health app, please open FreeAPS X to help us guaranteed transfer changed data" = "После ручного создания записей о глюкозы в программе Здоровье пожалуйста откройте FreeAPS X, чтобы помочь нам гарантированно загрузить измененные данные";
"After you create records in the Health app, please open FreeAPS X to help us guaranteed transfer changed data" = "После ручного создания записей в программе Здоровье пожалуйста откройте FreeAPS X, чтобы помочь нам гарантированно загрузить измененные данные";
/* --------------------------------------------


Expand Down
30 changes: 30 additions & 0 deletions FreeAPS/Sources/Models/CarbsEntry.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import Foundation

struct CarbsEntry: JSON, Equatable, Hashable {
var id = UUID().uuidString
let createdAt: Date
let carbs: Decimal
let enteredBy: String?

static let manual = "freeaps-x"
static let applehealth = "applehealth"

static func == (lhs: CarbsEntry, rhs: CarbsEntry) -> Bool {
lhs.createdAt == rhs.createdAt
Expand All @@ -17,6 +19,34 @@ struct CarbsEntry: JSON, Equatable, Hashable {
}

extension CarbsEntry {
private enum CodingKeys: String, CodingKey {
case id = "_id"
case createdAt = "created_at"
case carbs
case enteredBy
}
}

// MARK: CarbsEntry till 0.2.6

// At this version was add id propery for working with Apple Health
struct CarbsEntryTill026: JSON, Equatable, Hashable {
let createdAt: Date
let carbs: Decimal
let enteredBy: String?

static let manual = "freeaps-x"

static func == (lhs: CarbsEntryTill026, rhs: CarbsEntryTill026) -> Bool {
lhs.createdAt == rhs.createdAt
}

func hash(into hasher: inout Hasher) {
hasher.combine(createdAt)
}
}

extension CarbsEntryTill026 {
private enum CodingKeys: String, CodingKey {
case createdAt = "created_at"
case carbs
Expand Down
19 changes: 0 additions & 19 deletions FreeAPS/Sources/Models/HealthKitSample.swift

This file was deleted.

41 changes: 41 additions & 0 deletions FreeAPS/Sources/Models/HealthKitSamples.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import Foundation

// MARK: - Blood glucose

struct HealthKitBGSample: JSON, Hashable, Equatable {
var healthKitId: String
var date: Date
var glucose: Int

static func == (lhs: HealthKitBGSample, rhs: HealthKitBGSample) -> Bool {
lhs.healthKitId == rhs.healthKitId
}
}

extension HealthKitBGSample {
private enum CodingKeys: String, CodingKey {
case healthKitId = "healthkit_id"
case date
case glucose
}
}

// MARK: - Carbs

struct HealthKitCarbsSample: JSON, Hashable, Equatable {
var healthKitId: String
var date: Date
var carbs: Decimal

static func == (lhs: HealthKitCarbsSample, rhs: HealthKitCarbsSample) -> Bool {
lhs.healthKitId == rhs.healthKitId
}
}

extension HealthKitCarbsSample {
private enum CodingKeys: String, CodingKey {
case healthKitId = "healthkit_id"
case date
case carbs
}
}
22 changes: 20 additions & 2 deletions FreeAPS/Sources/Modules/DataTable/DataTableDataFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ enum DataTable {
}

class Treatment: Identifiable, Hashable, Equatable {
let id = UUID()
var id = UUID()
let units: GlucoseUnits
let type: DataType
let date: Date
Expand All @@ -67,6 +67,24 @@ enum DataTable {
return formatter
}

init(
id: UUID,
units: GlucoseUnits,
type: DataType,
date: Date,
amount: Decimal? = nil,
secondAmount: Decimal? = nil,
duration: Decimal? = nil
) {
self.id = id
self.units = units
self.type = type
self.date = date
self.amount = amount
self.secondAmount = secondAmount
self.duration = duration
}

init(
units: GlucoseUnits,
type: DataType,
Expand Down Expand Up @@ -172,6 +190,6 @@ protocol DataTableProvider: Provider {
func tempTargets() -> [TempTarget]
func carbs() -> [CarbsEntry]
func glucose() -> [BloodGlucose]
func deleteCarbs(at date: Date)
func deleteCarbs(_ treatment: DataTable.Treatment)
func deleteGlucose(id: String)
}
7 changes: 4 additions & 3 deletions FreeAPS/Sources/Modules/DataTable/DataTableProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ extension DataTable {
carbsStorage.recent()
}

func deleteCarbs(at date: Date) {
nightscoutManager.deleteCarbs(at: date)
func deleteCarbs(_ treatment: Treatment) {
nightscoutManager.deleteCarbs(at: treatment.date)
healthkitManager.deleteCarbs(syncID: treatment.id.uuidString)
}

func glucose() -> [BloodGlucose] {
Expand All @@ -31,7 +32,7 @@ extension DataTable {

func deleteGlucose(id: String) {
glucoseStorage.removeGlucose(ids: [id])
healthkitManager.deleteGlucise(syncID: id)
healthkitManager.deleteGlucose(syncID: id)
}
}
}
12 changes: 9 additions & 3 deletions FreeAPS/Sources/Modules/DataTable/DataTableStateModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ extension DataTable {
let units = self.settingsManager.settings.units

let carbs = self.provider.carbs().map {
Treatment(units: units, type: .carbs, date: $0.createdAt, amount: $0.carbs)
Treatment(
id: UUID(uuidString: $0.id) ?? UUID(),
units: units,
type: .carbs,
date: $0.createdAt,
amount: $0.carbs
)
}

let boluses = self.provider.pumpHistory()
Expand Down Expand Up @@ -88,8 +94,8 @@ extension DataTable {
}
}

func deleteCarbs(at date: Date) {
provider.deleteCarbs(at: date)
func deleteCarbs(_ treatment: Treatment) {
provider.deleteCarbs(treatment)
}

func deleteGlucose(at index: Int) {
Expand Down
Loading