Pārlūkot izejas kodu

Merge pull request #67 from josep1972/dev

Pull Data From Dexcom Share
jonfawcett 6 gadi atpakaļ
vecāks
revīzija
a40ef6f009

+ 12 - 0
LoopFollow.xcodeproj/project.pbxproj

@@ -8,6 +8,7 @@
 
 /* Begin PBXBuildFile section */
 		3F1335F351590E573D8E6962 /* Pods_LoopFollow.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7D55B42A22051DAD69E89D0 /* Pods_LoopFollow.framework */; };
+		DD98F54424BCEFEE0007425A /* ShareClientExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD98F54324BCEFEE0007425A /* ShareClientExtension.swift */; };
 		FC16A97A24996673003D6245 /* NightScout.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC16A97924996673003D6245 /* NightScout.swift */; };
 		FC16A97B249966A3003D6245 /* AlarmSound.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7CE589248ABEA3001F83B8 /* AlarmSound.swift */; };
 		FC16A97D24996747003D6245 /* Alarms.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC16A97C24996747003D6245 /* Alarms.swift */; };
@@ -162,6 +163,7 @@
 /* Begin PBXFileReference section */
 		059B0FA59AABFE72FE13DDDA /* Pods-LoopFollow.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LoopFollow.release.xcconfig"; path = "Target Support Files/Pods-LoopFollow/Pods-LoopFollow.release.xcconfig"; sourceTree = "<group>"; };
 		A7D55B42A22051DAD69E89D0 /* Pods_LoopFollow.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LoopFollow.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		DD98F54324BCEFEE0007425A /* ShareClientExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareClientExtension.swift; sourceTree = "<group>"; };
 		ECA3EFB4037410B4973BB632 /* Pods-LoopFollow.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LoopFollow.debug.xcconfig"; path = "Target Support Files/Pods-LoopFollow/Pods-LoopFollow.debug.xcconfig"; sourceTree = "<group>"; };
 		FC16A97924996673003D6245 /* NightScout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightScout.swift; sourceTree = "<group>"; };
 		FC16A97C24996747003D6245 /* Alarms.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alarms.swift; sourceTree = "<group>"; };
@@ -350,6 +352,14 @@
 			path = Pods;
 			sourceTree = "<group>";
 		};
+		DD98F54224BCEF190007425A /* Extensions */ = {
+			isa = PBXGroup;
+			children = (
+				DD98F54324BCEFEE0007425A /* ShareClientExtension.swift */,
+			);
+			path = Extensions;
+			sourceTree = "<group>";
+		};
 		FC16A97624995FEE003D6245 /* Application */ = {
 			isa = PBXGroup;
 			children = (
@@ -513,6 +523,7 @@
 				FC8DEEE62485D1ED0075863F /* Info.plist */,
 				FC7CE59A248D334B001F83B8 /* Resources */,
 				FCC68871248A736700A0279D /* ViewControllers */,
+				DD98F54224BCEF190007425A /* Extensions */,
 				FC16A9782499657E003D6245 /* Controllers */,
 				FCC688542489367300A0279D /* helpers */,
 				FCC68872248A748A00A0279D /* Models */,
@@ -841,6 +852,7 @@
 				FCC0FAC224922A22003E610E /* DictionaryKeyPath.swift in Sources */,
 				FC9788182485969B00A7906C /* AppDelegate.swift in Sources */,
 				FCC6886B24898FD800A0279D /* ObservationToken.swift in Sources */,
+				DD98F54424BCEFEE0007425A /* ShareClientExtension.swift in Sources */,
 				FCC6886D2489909D00A0279D /* AnyConvertible.swift in Sources */,
 				FC97881A2485969B00A7906C /* SceneDelegate.swift in Sources */,
 				FCD49B6C24AA536E007879DC /* DebugViewController.swift in Sources */,

+ 33 - 18
LoopFollow/Application/Base.lproj/Main.storyboard

@@ -139,7 +139,7 @@
                                                                         <nil key="highlightedColor"/>
                                                                     </label>
                                                                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TzL-hn-9qu">
-                                                                        <rect key="frame" x="13" y="18" width="66.666666666666671" height="27"/>
+                                                                        <rect key="frame" x="14.333333333333329" y="18" width="64" height="27"/>
                                                                         <fontDescription key="fontDescription" type="system" pointSize="15"/>
                                                                         <nil key="textColor"/>
                                                                         <nil key="highlightedColor"/>
@@ -156,7 +156,7 @@
                                                                         <nil key="highlightedColor"/>
                                                                     </label>
                                                                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7mH-Np-j0L">
-                                                                        <rect key="frame" x="13.333333333333343" y="18" width="66" height="27"/>
+                                                                        <rect key="frame" x="14.333333333333343" y="18" width="64" height="27"/>
                                                                         <fontDescription key="fontDescription" type="system" pointSize="15"/>
                                                                         <nil key="textColor"/>
                                                                         <nil key="highlightedColor"/>
@@ -167,13 +167,13 @@
                                                                 <rect key="frame" x="205.33333333333331" y="0.0" width="92.666666666666686" height="45"/>
                                                                 <subviews>
                                                                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="High:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0Zq-6s-y8B">
-                                                                        <rect key="frame" x="28.333333333333371" y="0.0" width="36.333333333333343" height="18"/>
+                                                                        <rect key="frame" x="28.333333333333375" y="0.0" width="36.333333333333343" height="18"/>
                                                                         <fontDescription key="fontDescription" type="system" pointSize="15"/>
                                                                         <nil key="textColor"/>
                                                                         <nil key="highlightedColor"/>
                                                                     </label>
                                                                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HON-rt-8pC">
-                                                                        <rect key="frame" x="13" y="18" width="66.666666666666671" height="27"/>
+                                                                        <rect key="frame" x="14.333333333333371" y="18" width="64" height="27"/>
                                                                         <fontDescription key="fontDescription" type="system" pointSize="15"/>
                                                                         <nil key="textColor"/>
                                                                         <nil key="highlightedColor"/>
@@ -182,45 +182,59 @@
                                                             </stackView>
                                                         </subviews>
                                                     </stackView>
-                                                    <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="jwr-iC-EjI">
+                                                    <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="top" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="K8G-Ph-ZNA">
                                                         <rect key="frame" x="0.0" y="55" width="298" height="45"/>
                                                         <subviews>
-                                                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="mhQ-v3-Rex">
+                                                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="0aR-E9-gpC">
                                                                 <rect key="frame" x="0.0" y="0.0" width="92.666666666666671" height="45"/>
                                                                 <subviews>
-                                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Avg BG:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tpy-y3-B9A">
-                                                                        <rect key="frame" x="19.333333333333329" y="0.0" width="54.333333333333343" height="18"/>
+                                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Avg BG:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Rrh-Zo-cis" userLabel="Avg BG:">
+                                                                        <rect key="frame" x="19.333333333333332" y="0.0" width="54.333333333333343" height="18"/>
                                                                         <fontDescription key="fontDescription" type="system" pointSize="15"/>
                                                                         <nil key="textColor"/>
                                                                         <nil key="highlightedColor"/>
                                                                     </label>
-                                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cDE-hR-Tao">
-                                                                        <rect key="frame" x="6.6666666666666714" y="18" width="79.333333333333329" height="27"/>
+                                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jpA-Nb-pU7" userLabel="Stats AvBG">
+                                                                        <rect key="frame" x="21.333333333333343" y="18" width="50" height="27"/>
                                                                         <fontDescription key="fontDescription" type="system" pointSize="15"/>
                                                                         <nil key="textColor"/>
                                                                         <nil key="highlightedColor"/>
                                                                     </label>
                                                                 </subviews>
                                                             </stackView>
-                                                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="xCG-CQ-HvH">
+                                                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="xGF-Pj-QE0">
                                                                 <rect key="frame" x="102.66666666666666" y="0.0" width="92.666666666666657" height="45"/>
                                                                 <subviews>
-                                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Est A1C:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BSh-qP-ZnD">
-                                                                        <rect key="frame" x="18.333333333333343" y="0.0" width="56.333333333333343" height="18"/>
+                                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Est A1C:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WV0-Jy-FPs" userLabel="Est A1C:">
+                                                                        <rect key="frame" x="18.333333333333346" y="0.0" width="56.333333333333343" height="18"/>
                                                                         <fontDescription key="fontDescription" type="system" pointSize="15"/>
                                                                         <nil key="textColor"/>
                                                                         <nil key="highlightedColor"/>
                                                                     </label>
-                                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Vxv-1M-W8k">
-                                                                        <rect key="frame" x="6.3333333333333428" y="18" width="80" height="27"/>
+                                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7Jx-XF-1vS" userLabel="Stas EstA1C">
+                                                                        <rect key="frame" x="21.333333333333343" y="18" width="50" height="27"/>
                                                                         <fontDescription key="fontDescription" type="system" pointSize="15"/>
                                                                         <nil key="textColor"/>
                                                                         <nil key="highlightedColor"/>
                                                                     </label>
                                                                 </subviews>
                                                             </stackView>
-                                                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="par-v0-OMA">
+                                                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="ohT-Dn-cjf">
                                                                 <rect key="frame" x="205.33333333333331" y="0.0" width="92.666666666666686" height="45"/>
+                                                                <subviews>
+                                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Std Dev:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iXC-Mz-I09">
+                                                                        <rect key="frame" x="16.999999999999996" y="0.0" width="58.666666666666657" height="18"/>
+                                                                        <fontDescription key="fontDescription" type="system" pointSize="15"/>
+                                                                        <nil key="textColor"/>
+                                                                        <nil key="highlightedColor"/>
+                                                                    </label>
+                                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wAI-Tp-784" userLabel="Stats StdDev">
+                                                                        <rect key="frame" x="21.333333333333371" y="18" width="50" height="27"/>
+                                                                        <fontDescription key="fontDescription" type="system" pointSize="15"/>
+                                                                        <nil key="textColor"/>
+                                                                        <nil key="highlightedColor"/>
+                                                                    </label>
+                                                                </subviews>
                                                             </stackView>
                                                         </subviews>
                                                     </stackView>
@@ -273,12 +287,13 @@
                         <outlet property="MinAgoText" destination="UkG-hw-DVo" id="Xd2-fL-qYC"/>
                         <outlet property="PredictionLabel" destination="oiR-SM-6sg" id="2Sw-TR-SFo"/>
                         <outlet property="infoTable" destination="kTs-7g-lp9" id="Khq-sV-EZ1"/>
-                        <outlet property="statsAvgBG" destination="cDE-hR-Tao" id="SGK-z7-di4"/>
-                        <outlet property="statsEstA1C" destination="Vxv-1M-W8k" id="CpH-4t-haS"/>
+                        <outlet property="statsAvgBG" destination="jpA-Nb-pU7" id="Uo8-a4-Aus"/>
+                        <outlet property="statsEstA1C" destination="7Jx-XF-1vS" id="4RD-nm-JxO"/>
                         <outlet property="statsHighPercent" destination="HON-rt-8pC" id="283-3S-PCR"/>
                         <outlet property="statsInRangePercent" destination="7mH-Np-j0L" id="vUp-Pv-Mva"/>
                         <outlet property="statsLowPercent" destination="TzL-hn-9qu" id="0QR-Mz-KJe"/>
                         <outlet property="statsPieChart" destination="Hhh-F1-s1p" id="Rhh-Up-Kr0"/>
+                        <outlet property="statsStdDev" destination="wAI-Tp-784" id="BUZ-lS-JfA"/>
                     </connections>
                 </viewController>
                 <placeholder placeholderIdentifier="IBFirstResponder" id="W5J-7L-Pyd" sceneMemberID="firstResponder"/>

+ 8 - 2
LoopFollow/Controllers/Stats.swift

@@ -20,6 +20,7 @@ class StatsData {
     var totalGlucose: Int
     var avgBG: Float
     var a1C: Float
+    var stdDev: Float
     var pie: [DataStructs.pieData]
     
     init(bgData: [DataStructs.sgvData]) {
@@ -54,8 +55,6 @@ class StatsData {
             DataStructs.pieData(name: "range", value: Double(percentRange)),
             DataStructs.pieData(name: "high", value: Double(percentHigh))]
         
-        
-        
         // Set Average
         avgBG = Float(totalGlucose / bgData.count)
         
@@ -67,6 +66,13 @@ class StatsData {
             // https://github.com/nightscout/nightguard/pull/72
             // a1C = (((46.7 + Float(avgBG)) / 28.7) - 2.152) / 0.09148
         }
+         
+        // compute std dev (sigma)
+        var partialSum: Float = 0;
+        for i in 0..<bgData.count {
+            partialSum += (Float(bgData[i].sgv) - avgBG) * ( Float(bgData[i].sgv) - avgBG)
+        }
+        stdDev = sqrt(partialSum / Float(bgData.count))
     }
 
 }

+ 2 - 1
LoopFollow/Controllers/StatsView.swift

@@ -16,13 +16,14 @@ extension MainViewController {
     func updateStats()
     {
         if bgData.count > 0 {
-           var stats = StatsData(bgData: bgData)
+           let stats = StatsData(bgData: bgData)
             
             statsLowPercent.text = String(format:"%.1f%", stats.percentLow) + "%"
             statsInRangePercent.text = String(format:"%.1f%", stats.percentRange) + "%"
             statsHighPercent.text = String(format:"%.1f%", stats.percentHigh) + "%"
             statsAvgBG.text = bgUnits.toDisplayUnits(String(format:"%.0f%", stats.avgBG))
             statsEstA1C.text = String(format:"%.1f%", stats.a1C)
+            statsStdDev.text = String(format:"%.2f%", stats.stdDev)
             
             createStatsPie(pieData: stats.pie)
         }

+ 58 - 0
LoopFollow/Extensions/ShareClientExtension.swift

@@ -0,0 +1,58 @@
+//
+//  ShareClientExtension.swift
+//  LoopFollow
+//
+//  Created by Jose Paredes on 7/13/20.
+//  Copyright © 2020 Jon Fawcett. All rights reserved.
+//
+
+import Foundation
+import ShareClient
+
+public struct ShareGlucoseData: Codable {
+   var sgv: Int
+   var date: TimeInterval
+   var direction: String?
+}
+
+private var TrendTable: [String] = [
+   "NONE",            // 0
+   "DoubleUp",        // 1
+   "SingleUp",        // 2
+   "FourtyFiveUp",    // 3
+   "Flat",            // 4
+   "FourtyFiveDown",  // 5
+   "SingleDown",      // 6
+   "DoubleDown"       // 7
+]
+
+// TODO: probably better to make this an inherited class rather than an extension
+extension ShareClient {
+
+    public func fetchData(_ entries: Int, callback: @escaping (ShareError?, [ShareGlucoseData]?) -> Void) {
+        
+        self.fetchLast(entries) { (error, result) -> () in
+            guard error == nil || result != nil else {
+                return callback(error, nil)
+            }
+            
+            // parse data to conanical form
+            var shareData = [ShareGlucoseData]()
+            for i in 0..<result!.count {
+                
+                var trend = Int(result![i].trend)
+                if(trend < 0 || trend > TrendTable.count-1) {
+                    trend = 0
+                }
+            
+                let newShareData = ShareGlucoseData(
+                    sgv: Int(result![i].glucose),
+                    date: result![i].timestamp.timeIntervalSince1970,
+                    direction: TrendTable[trend]
+                )
+                shareData.append(newShareData)
+            }
+            callback(nil,shareData)
+         }
+    }
+}

+ 33 - 7
LoopFollow/ViewControllers/MainViewController.swift

@@ -9,6 +9,7 @@
 import UIKit
 import Charts
 import EventKit
+import ShareClient
 
 
 class MainViewController: UIViewController, UITableViewDataSource, ChartViewDelegate, UNUserNotificationCenterDelegate {
@@ -30,6 +31,7 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
     @IBOutlet weak var statsHighPercent: UILabel!
     @IBOutlet weak var statsAvgBG: UILabel!
     @IBOutlet weak var statsEstA1C: UILabel!
+    @IBOutlet weak var statsStdDev: UILabel!
     
     
     // Data Table Struct
@@ -75,6 +77,7 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
     var calTimer = Timer()
     
     // Info Table Setup
+    // TODO: make this selectable
     var tableData = [
         infoData(name: "IOB", value: ""), //0
         infoData(name: "COB", value: ""), //1
@@ -108,6 +111,10 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
     var lastOverrideStartTime: TimeInterval = 0
     var lastOverrideEndTime: TimeInterval = 0
     
+    // share
+    var bgDataShare: [ShareGlucoseData] = []
+    var dexShare: ShareClient?;
+    
     // calendar setup
     let store = EKEventStore()
     
@@ -116,16 +123,21 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
     override func viewDidLoad() {
         super.viewDidLoad()
         
+        // TODO: look for username and password in the UserDefaultsRepo ?
+        // TODO: need non-us server ?
+        let shareUserName = UserDefaultsRepository.shareUserName.value
+        let sharePassword = UserDefaultsRepository.sharePassword.value
+        let shareServer = UserDefaultsRepository.shareServer.value == "US" ?KnownShareServers.US.rawValue : KnownShareServers.NON_US.rawValue
+        dexShare = ShareClient(username: shareUserName, password: sharePassword, shareServer: shareServer )
+        
+        //print("Share: \(dexShare)")
+        
         // Start Log Timer if needed
         if UserDefaultsRepository.debugLog.value {
             guard let debug = self.tabBarController!.viewControllers?[5] as? debugViewController else { return }
             debug.loadViewIfNeeded()
         } else {
-            do {
-                try self.tabBarController?.viewControllers?.remove(at: 5)
-            } catch {
-                
-            }
+            self.tabBarController?.viewControllers?.remove(at: 5)
         }
         
         BGChart.delegate = self
@@ -164,8 +176,15 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
         // Load Data
         if UserDefaultsRepository.url.value != "" && firstGraphLoad {
             nightscoutLoader()
+          
+            // TODO: move this to MainViewController extension ?
+            dexShare?.fetchData(262) { (err, result) -> () in
+                
+                // TODO: add error checking
+                self.bgDataShare = result!
+                // print("\(self.bgDataShare)")
+            }
         }
-        
     }
     
     override func viewWillAppear(_ animated: Bool) {
@@ -174,7 +193,6 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
         
     }
     
-    
     // Info Table Functions
     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
         return tableData.count
@@ -289,6 +307,14 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
 //        if UserDefaultsRepository.debugLog.value { self.writeDebugLog(value: "Main timer ended") }
         updateMinAgo()
         nightscoutLoader()
+        
+        // TODO: move this to MainViewController extension ?
+        dexShare?.fetchData(262) { (err, result) -> () in
+            
+            // TODO: add error checking
+            self.bgDataShare = result!
+            // print("\(self.bgDataShare)")
+        }
     }
 
     //update Min Ago Text. We need to call this separately because it updates between readings

+ 34 - 0
LoopFollow/ViewControllers/SettingsViewController.swift

@@ -67,6 +67,40 @@ class SettingsViewController: FormViewController {
             guard let value = row.value else { return }
             UserDefaultsRepository.units.value = value
         }
+        +++ Section("Dexcom Settings")
+        <<< TextRow(){ row in
+            row.title = "User Name"
+            row.value = UserDefaultsRepository.shareUserName.value
+        }.cellSetup { (cell, row) in
+            cell.textField.autocorrectionType = .no
+        }.onChange { row in
+            if row.value == nil {
+                UserDefaultsRepository.shareUserName.value = ""
+            }
+            guard let value = row.value else { return }
+            UserDefaultsRepository.shareUserName.value = value
+        }
+        <<< TextRow(){ row in
+            row.title = "Password"
+            row.value = UserDefaultsRepository.sharePassword.value
+        }.cellSetup { (cell, row) in
+            cell.textField.autocorrectionType = .no
+            cell.textField.isSecureTextEntry = true
+        }.onChange { row in
+            if row.value == nil {
+                UserDefaultsRepository.sharePassword.value = ""
+            }
+            guard let value = row.value else { return }
+            UserDefaultsRepository.sharePassword.value = value
+        }
+        <<< SegmentedRow<String>("shareServer") { row in
+            row.title = "Server"
+            row.options = ["US", "NON-US"]
+            row.value = UserDefaultsRepository.shareServer.value
+        }.onChange { row in
+            guard let value = row.value else { return }
+            UserDefaultsRepository.shareServer.value = value
+        }
         
         
         buildGeneralSettings()

+ 6 - 0
LoopFollow/repository/UserDefaults.swift

@@ -11,11 +11,17 @@ import UIKit
 
 class UserDefaultsRepository {
     
+    
     //Nightscout Settings
     static let url = UserDefaultsValue<String>(key: "url", default: "")
     static let token = UserDefaultsValue<String>(key: "token", default: "")
     static let units = UserDefaultsValue<String>(key: "units", default: "mg/dL")
     
+    //Dexcom Share Settings
+    static let shareUserName = UserDefaultsValue<String>(key: "shareUserName", default: "")
+    static let sharePassword = UserDefaultsValue<String>(key: "sharePassword", default: "")
+    static let shareServer = UserDefaultsValue<String>(key: "shareServer", default: "US")
+    
     // Graph Settings
     static let showDots = UserDefaultsValue<Bool>(key: "showDots", default: true)
     static let showLines = UserDefaultsValue<Bool>(key: "showLines", default: true)

+ 3 - 2
Podfile

@@ -3,5 +3,6 @@ target 'LoopFollow' do
 
   pod 'Charts'
   pod 'Eureka'
-
-  end
+  pod 'ShareClient', :git => 'https://github.com/josep1972/dexcom-share-client-swift.git', :branch => 'dev' 
+  
+end

+ 14 - 1
Podfile.lock

@@ -3,20 +3,33 @@ PODS:
     - Charts/Core (= 3.5.0)
   - Charts/Core (3.5.0)
   - Eureka (5.2.1)
+  - ShareClient (1.2)
 
 DEPENDENCIES:
   - Charts
   - Eureka
+  - ShareClient (from `https://github.com/josep1972/dexcom-share-client-swift.git`, branch `dev`)
 
 SPEC REPOS:
   trunk:
     - Charts
     - Eureka
 
+EXTERNAL SOURCES:
+  ShareClient:
+    :branch: dev
+    :git: https://github.com/josep1972/dexcom-share-client-swift.git
+
+CHECKOUT OPTIONS:
+  ShareClient:
+    :commit: 815a1dbddd970a563e3b7fd22d88b23c164b026e
+    :git: https://github.com/josep1972/dexcom-share-client-swift.git
+
 SPEC CHECKSUMS:
   Charts: 40a08591df1f8ad5c223ddedfb1a06da92f24f7c
   Eureka: c883105488e05bc65539f583246ecf9657cabbfe
+  ShareClient: 5937ff69b57c85c2004c915812f73cf7ae86549e
 
-PODFILE CHECKSUM: 7665842405edac4f27ad84d4b66d6d57d5a4e5aa
+PODFILE CHECKSUM: b5ee540f0ef2120e92d3b71909453c335d659552
 
 COCOAPODS: 1.9.3

+ 14 - 1
Pods/Manifest.lock

@@ -3,20 +3,33 @@ PODS:
     - Charts/Core (= 3.5.0)
   - Charts/Core (3.5.0)
   - Eureka (5.2.1)
+  - ShareClient (1.2)
 
 DEPENDENCIES:
   - Charts
   - Eureka
+  - ShareClient (from `https://github.com/josep1972/dexcom-share-client-swift.git`, branch `dev`)
 
 SPEC REPOS:
   trunk:
     - Charts
     - Eureka
 
+EXTERNAL SOURCES:
+  ShareClient:
+    :branch: dev
+    :git: https://github.com/josep1972/dexcom-share-client-swift.git
+
+CHECKOUT OPTIONS:
+  ShareClient:
+    :commit: 815a1dbddd970a563e3b7fd22d88b23c164b026e
+    :git: https://github.com/josep1972/dexcom-share-client-swift.git
+
 SPEC CHECKSUMS:
   Charts: 40a08591df1f8ad5c223ddedfb1a06da92f24f7c
   Eureka: c883105488e05bc65539f583246ecf9657cabbfe
+  ShareClient: 5937ff69b57c85c2004c915812f73cf7ae86549e
 
-PODFILE CHECKSUM: 7665842405edac4f27ad84d4b66d6d57d5a4e5aa
+PODFILE CHECKSUM: b5ee540f0ef2120e92d3b71909453c335d659552
 
 COCOAPODS: 1.9.3

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 965 - 774
Pods/Pods.xcodeproj/project.pbxproj


+ 25 - 0
Pods/Target Support Files/Pods-LoopFollow/Pods-LoopFollow-acknowledgements.markdown

@@ -231,4 +231,29 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 
+
+## ShareClient
+
+The MIT License (MIT)
+
+Copyright (c) 2016 Mark Wilson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
 Generated by CocoaPods - https://cocoapods.org

+ 31 - 0
Pods/Target Support Files/Pods-LoopFollow/Pods-LoopFollow-acknowledgements.plist

@@ -257,6 +257,37 @@ SOFTWARE.
 		</dict>
 		<dict>
 			<key>FooterText</key>
+			<string>The MIT License (MIT)
+
+Copyright (c) 2016 Mark Wilson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+</string>
+			<key>License</key>
+			<string>MIT</string>
+			<key>Title</key>
+			<string>ShareClient</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
+		<dict>
+			<key>FooterText</key>
 			<string>Generated by CocoaPods - https://cocoapods.org</string>
 			<key>Title</key>
 			<string></string>

+ 2 - 1
Pods/Target Support Files/Pods-LoopFollow/Pods-LoopFollow-frameworks-Debug-input-files.xcfilelist

@@ -1,3 +1,4 @@
 ${PODS_ROOT}/Target Support Files/Pods-LoopFollow/Pods-LoopFollow-frameworks.sh
 ${BUILT_PRODUCTS_DIR}/Charts/Charts.framework
-${BUILT_PRODUCTS_DIR}/Eureka/Eureka.framework
+${BUILT_PRODUCTS_DIR}/Eureka/Eureka.framework
+${BUILT_PRODUCTS_DIR}/ShareClient/ShareClient.framework

+ 2 - 1
Pods/Target Support Files/Pods-LoopFollow/Pods-LoopFollow-frameworks-Debug-output-files.xcfilelist

@@ -1,2 +1,3 @@
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Charts.framework
-${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Eureka.framework
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Eureka.framework
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ShareClient.framework

+ 2 - 1
Pods/Target Support Files/Pods-LoopFollow/Pods-LoopFollow-frameworks-Release-input-files.xcfilelist

@@ -1,3 +1,4 @@
 ${PODS_ROOT}/Target Support Files/Pods-LoopFollow/Pods-LoopFollow-frameworks.sh
 ${BUILT_PRODUCTS_DIR}/Charts/Charts.framework
-${BUILT_PRODUCTS_DIR}/Eureka/Eureka.framework
+${BUILT_PRODUCTS_DIR}/Eureka/Eureka.framework
+${BUILT_PRODUCTS_DIR}/ShareClient/ShareClient.framework

+ 2 - 1
Pods/Target Support Files/Pods-LoopFollow/Pods-LoopFollow-frameworks-Release-output-files.xcfilelist

@@ -1,2 +1,3 @@
 ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Charts.framework
-${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Eureka.framework
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Eureka.framework
+${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ShareClient.framework

+ 2 - 0
Pods/Target Support Files/Pods-LoopFollow/Pods-LoopFollow-frameworks.sh

@@ -199,10 +199,12 @@ fi
 if [[ "$CONFIGURATION" == "Debug" ]]; then
   install_framework "${BUILT_PRODUCTS_DIR}/Charts/Charts.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/Eureka/Eureka.framework"
+  install_framework "${BUILT_PRODUCTS_DIR}/ShareClient/ShareClient.framework"
 fi
 if [[ "$CONFIGURATION" == "Release" ]]; then
   install_framework "${BUILT_PRODUCTS_DIR}/Charts/Charts.framework"
   install_framework "${BUILT_PRODUCTS_DIR}/Eureka/Eureka.framework"
+  install_framework "${BUILT_PRODUCTS_DIR}/ShareClient/ShareClient.framework"
 fi
 if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
   wait

+ 3 - 3
Pods/Target Support Files/Pods-LoopFollow/Pods-LoopFollow.debug.xcconfig

@@ -1,9 +1,9 @@
 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
-FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Charts" "${PODS_CONFIGURATION_BUILD_DIR}/Eureka"
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Charts" "${PODS_CONFIGURATION_BUILD_DIR}/Eureka" "${PODS_CONFIGURATION_BUILD_DIR}/ShareClient"
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Charts/Charts.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Eureka/Eureka.framework/Headers"
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Charts/Charts.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Eureka/Eureka.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ShareClient/ShareClient.framework/Headers"
 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
-OTHER_LDFLAGS = $(inherited) -framework "Charts" -framework "Eureka" -framework "Foundation" -framework "UIKit"
+OTHER_LDFLAGS = $(inherited) -framework "Charts" -framework "Eureka" -framework "Foundation" -framework "ShareClient" -framework "UIKit"
 OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
 PODS_BUILD_DIR = ${BUILD_DIR}
 PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

+ 3 - 3
Pods/Target Support Files/Pods-LoopFollow/Pods-LoopFollow.release.xcconfig

@@ -1,9 +1,9 @@
 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
-FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Charts" "${PODS_CONFIGURATION_BUILD_DIR}/Eureka"
+FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Charts" "${PODS_CONFIGURATION_BUILD_DIR}/Eureka" "${PODS_CONFIGURATION_BUILD_DIR}/ShareClient"
 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Charts/Charts.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Eureka/Eureka.framework/Headers"
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Charts/Charts.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Eureka/Eureka.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ShareClient/ShareClient.framework/Headers"
 LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
-OTHER_LDFLAGS = $(inherited) -framework "Charts" -framework "Eureka" -framework "Foundation" -framework "UIKit"
+OTHER_LDFLAGS = $(inherited) -framework "Charts" -framework "Eureka" -framework "Foundation" -framework "ShareClient" -framework "UIKit"
 OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
 PODS_BUILD_DIR = ${BUILD_DIR}
 PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)