Jelajahi Sumber

Merge pull request #2 from nightscout/dev

Trio Release 0.2.0
Mike Plante 1 tahun lalu
induk
melakukan
6433d947ac
100 mengubah file dengan 732 tambahan dan 5218 penghapusan
  1. 2 0
      .github/CODEOWNERS
  2. 0 3
      .github/FUNDING.yml
  3. 52 0
      .github/ISSUE_TEMPLATE/bug-report.md
  4. 5 0
      .github/ISSUE_TEMPLATE/config.yml
  5. 27 0
      .github/ISSUE_TEMPLATE/feature-request.md
  6. 27 14
      .github/workflows/add_identifiers.yml
  7. 22 0
      .github/workflows/add_to_project.yml
  8. 0 71
      .github/workflows/build_iAPS.yml
  9. 302 0
      .github/workflows/build_trio.yml
  10. 26 13
      .github/workflows/create_certs.yml
  11. 48 0
      .github/workflows/stale_issues.yml
  12. 159 36
      .github/workflows/validate_secrets.yml
  13. 0 2
      .gitignore
  14. 40 0
      .gitmodules
  15. 8 0
      BuildDetails.plist
  16. 1 0
      CGMBLEKit
  17. 3 3
      CODE_OF_CONDUCT.md
  18. 6 7
      Config.xcconfig
  19. 4 3
      Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents
  20. 0 36
      Dependencies/CGMBLEKit/.gitignore
  21. 0 13
      Dependencies/CGMBLEKit/.travis.yml
  22. 0 140
      Dependencies/CGMBLEKit/CGMBLEKit Example/AppDelegate.swift
  23. 0 98
      Dependencies/CGMBLEKit/CGMBLEKit Example/Assets.xcassets/AppIcon.appiconset/Contents.json
  24. 0 25
      Dependencies/CGMBLEKit/CGMBLEKit Example/Base.lproj/LaunchScreen.storyboard
  25. 0 172
      Dependencies/CGMBLEKit/CGMBLEKit Example/Base.lproj/Main.storyboard
  26. 0 34
      Dependencies/CGMBLEKit/CGMBLEKit Example/CommandQueue.swift
  27. 0 49
      Dependencies/CGMBLEKit/CGMBLEKit Example/Info.plist
  28. 0 39
      Dependencies/CGMBLEKit/CGMBLEKit Example/NSUserDefaults.swift
  29. 0 200
      Dependencies/CGMBLEKit/CGMBLEKit Example/ViewController.swift
  30. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/da.lproj/InfoPlist.strings
  31. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/da.lproj/Localizable.strings
  32. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/da.lproj/Main.strings
  33. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/de.lproj/InfoPlist.strings
  34. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/de.lproj/Localizable.strings
  35. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/de.lproj/Main.strings
  36. 0 8
      Dependencies/CGMBLEKit/CGMBLEKit Example/en.lproj/Localizable.strings
  37. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/en.lproj/Main.strings
  38. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/es.lproj/InfoPlist.strings
  39. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/es.lproj/Localizable.strings
  40. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/es.lproj/Main.strings
  41. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/fi.lproj/InfoPlist.strings
  42. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/fi.lproj/Localizable.strings
  43. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/fi.lproj/Main.strings
  44. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/fr.lproj/InfoPlist.strings
  45. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/fr.lproj/Localizable.strings
  46. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/fr.lproj/Main.strings
  47. 0 1
      Dependencies/CGMBLEKit/CGMBLEKit Example/he.lproj/LaunchScreen.strings
  48. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/he.lproj/Localizable.strings
  49. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/he.lproj/Main.strings
  50. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/it.lproj/InfoPlist.strings
  51. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/it.lproj/Localizable.strings
  52. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/it.lproj/Main.strings
  53. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/ja.lproj/Localizable.strings
  54. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/ja.lproj/Main.strings
  55. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/nb.lproj/InfoPlist.strings
  56. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/nb.lproj/Localizable.strings
  57. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/nb.lproj/Main.strings
  58. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/nl.lproj/InfoPlist.strings
  59. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/nl.lproj/Localizable.strings
  60. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/nl.lproj/Main.strings
  61. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/pl.lproj/InfoPlist.strings
  62. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/pl.lproj/Localizable.strings
  63. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/pl.lproj/Main.strings
  64. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/pt-BR.lproj/Localizable.strings
  65. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/pt-BR.lproj/Main.strings
  66. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/ro.lproj/InfoPlist.strings
  67. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/ro.lproj/Localizable.strings
  68. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/ro.lproj/Main.strings
  69. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/ru.lproj/InfoPlist.strings
  70. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/ru.lproj/Localizable.strings
  71. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/ru.lproj/Main.strings
  72. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/sk.lproj/InfoPlist.strings
  73. 0 6
      Dependencies/CGMBLEKit/CGMBLEKit Example/sk.lproj/Localizable.strings
  74. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/sk.lproj/Main.strings
  75. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/sv.lproj/InfoPlist.strings
  76. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/sv.lproj/Localizable.strings
  77. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/sv.lproj/Main.strings
  78. 0 3
      Dependencies/CGMBLEKit/CGMBLEKit Example/tr.lproj/InfoPlist.strings
  79. 0 1
      Dependencies/CGMBLEKit/CGMBLEKit Example/tr.lproj/LaunchScreen.strings
  80. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/tr.lproj/Localizable.strings
  81. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/tr.lproj/Main.strings
  82. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/vi.lproj/Localizable.strings
  83. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/vi.lproj/Main.strings
  84. 0 9
      Dependencies/CGMBLEKit/CGMBLEKit Example/zh-Hans.lproj/Localizable.strings
  85. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit Example/zh-Hans.lproj/Main.strings
  86. 0 2493
      Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.pbxproj
  87. 0 7
      Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  88. 0 19
      Dependencies/CGMBLEKit/CGMBLEKit/AESCrypt.h
  89. 0 33
      Dependencies/CGMBLEKit/CGMBLEKit/AESCrypt.m
  90. 0 41
      Dependencies/CGMBLEKit/CGMBLEKit/Base.lproj/Localizable.strings
  91. 0 350
      Dependencies/CGMBLEKit/CGMBLEKit/BluetoothManager.swift
  92. 0 87
      Dependencies/CGMBLEKit/CGMBLEKit/BluetoothServices.swift
  93. 0 45
      Dependencies/CGMBLEKit/CGMBLEKit/CBPeripheral.swift
  94. 0 17
      Dependencies/CGMBLEKit/CGMBLEKit/CGMBLEKit.h
  95. 0 27
      Dependencies/CGMBLEKit/CGMBLEKit/Calibration.swift
  96. 0 106
      Dependencies/CGMBLEKit/CGMBLEKit/CalibrationState.swift
  97. 0 79
      Dependencies/CGMBLEKit/CGMBLEKit/Command.swift
  98. 0 85
      Dependencies/CGMBLEKit/CGMBLEKit/Glucose+SensorDisplayable.swift
  99. 0 111
      Dependencies/CGMBLEKit/CGMBLEKit/Glucose.swift
  100. 0 0
      Dependencies/CGMBLEKit/CGMBLEKit/Info.plist

+ 2 - 0
.github/CODEOWNERS

@@ -0,0 +1,2 @@
+*    @dnzxy @bjornoleh @MikePlante1 @aug0211 @AndreasStokholm @Sjoerd-Bo3 @t1dude
+*.js @dnzxy @bjornoleh @MikePlante1 @aug0211 @AndreasStokholm @Sjoerd-Bo3 @t1dude @jeremystorring

+ 0 - 3
.github/FUNDING.yml

@@ -1,3 +0,0 @@
-# These are supported funding model platforms
-
-custom: ["https://paypal.me/jonbm78", "https://www.paypal.com/paypalme/jonbm78"]

+ 52 - 0
.github/ISSUE_TEMPLATE/bug-report.md

@@ -0,0 +1,52 @@
+---
+name: "\U0001F41B Bug report"
+about: Create a report to help us fix things
+title: ''
+labels: ['bug', 'needs-triage']
+assignees: ''
+projects: ['nightscout/2']
+
+---
+## Describe the bug
+*A clear and concise description of what the bug is. Describe what you see versus what you expect to see.*
+
+## Attach a Log
+*Tap the Trio settings icon at the bottom of the screen, then tap 'Share logs' on the bottom of the list and attach it to this ticket.*
+
+## To Reproduce
+*Steps to reproduce the behavior:*
+1. *Go to '...'*
+2. *Click on '....'*
+3. *Scroll down to '....'*
+4. *See error*
+
+## Expected behavior
+*A clear and concise description of what you expected to happen.*
+
+## Screenshots
+*If applicable, add screenshots to help explain your problem.*
+
+## Setup Information (please complete the following information):
+
+### Smartphone:
+* Hardware: *[e.g. iPhone 15 Pro]*
+* OS Version: *[e.g. iOS 17.5]*
+
+### Pump:
+* Manufacturer: *[e.g. Insulet]*
+* Model: *[e.g. Omnipod Dash or Eros]*
+
+### CGM:
+* Device: *[e.g. Dexcom G7]*
+* Manager app: *[e.g. Dexcom App or xDrip4iOS]*
+
+### Trio Version:
+* Version Number: *[e.g. 1.9.2]*
+* Repo: *nightscout/trio*
+* Git Reference: *[e.g. commit hash]*
+
+## Technical Details
+*If applicable, provide any technical details that might help in diagnosing the problem. This could include logs, error messages, or relevant configuration details.*
+
+## Additional context
+*Add any other context about the problem here.*

+ 5 - 0
.github/ISSUE_TEMPLATE/config.yml

@@ -0,0 +1,5 @@
+blank_issues_enabled: false
+contact_links:
+  - name: "🆘 Individual troubleshooting help: Please go to the Discord Trio Server"
+    url: https://discord.com/invite/FnwFEFUwXE
+    about: Are you having an issue with your individual setup? Please first go to the Discord Trio Server and post there, with details of your setup (App version, pump, CGM, and CGM app) and the issue you are observing

+ 27 - 0
.github/ISSUE_TEMPLATE/feature-request.md

@@ -0,0 +1,27 @@
+---
+name: "\U0001F4A1 Feature request \U0001F4A1"
+about: Suggest an idea for this project
+title: ''
+labels: ['enhancement', 'needs-triage']
+assignees: ''
+projects: ['nightscout/2']
+
+---
+
+## Is your feature request related to a problem? Please describe.
+*Provide a clear and concise description of the problem. Explain how this issue affects your experience with the Trio app and any specific scenarios where it occurs.*
+
+## Describe the solution you'd like
+*Detail the desired change or feature you'd like to see implemented in the Trio app. Be specific about how this solution would improve your experience and address the problem described above.*
+
+## Describe alternatives you've considered
+*List and describe any alternative solutions or features you've considered that could also address the problem. Explain why you believe the proposed solution is the best option.*
+
+## Additional context
+*Include any other context, screenshots, or relevant information that might help in understanding the issue or the proposed solution. If applicable, describe any previous discussions or decisions that relate to this feature request.*
+
+## Technical Details
+*If applicable, provide any technical details or considerations that might impact the implementation of this feature. This could include dependencies, potential risks, or required changes to existing functionalities.*
+
+## User Impact
+*(Optional) Describe the impact of this issue on your use of the Trio app. Include any specific examples or data that demonstrate how widespread or severe the problem is.*

+ 27 - 14
.github/workflows/add_identifiers.yml

@@ -1,36 +1,49 @@
 name: 2. Add Identifiers
-run-name: Add Identifiers
+run-name: Add Identifiers (${{ github.ref_name }})
 on:
   workflow_dispatch:
 
 jobs:
-  secrets:
+  validate:
+    name: Validate
     uses: ./.github/workflows/validate_secrets.yml
     secrets: inherit
-
+  
   identifiers:
-    needs: secrets
-    runs-on: macos-13
+    name: Add Identifiers
+    needs: validate
+    runs-on: macos-14
     steps:
-      # Uncomment to manually select Xcode version if needed
-      #- name: Select Xcode version
-      #  run: "sudo xcode-select --switch /Applications/Xcode_14.1.app/Contents/Developer"
+      # Uncomment to manually select latest Xcode if needed
+      #- name: Select Latest Xcode
+      #  run: "sudo xcode-select --switch /Applications/Xcode_13.0.app/Contents/Developer"
       
       # Checks-out the repo
       - name: Checkout Repo
-        uses: actions/checkout@v3
-        
+        uses: actions/checkout@v4
+      
       # Patch Fastlane Match to not print tables
       - name: Patch Match Tables
-        run: find /usr/local/lib/ruby/gems -name table_printer.rb | xargs sed -i "" "/puts(Terminal::Table.new(params))/d"
-        
+        run: |
+          TABLE_PRINTER_PATH=$(ruby -e 'puts Gem::Specification.find_by_name("fastlane").gem_dir')/match/lib/match/table_printer.rb
+          if [ -f "$TABLE_PRINTER_PATH" ]; then
+            sed -i "" "/puts(Terminal::Table.new(params))/d" "$TABLE_PRINTER_PATH"
+          else
+            echo "table_printer.rb not found"
+            exit 1
+          fi
+
+      # Install project dependencies
+      - name: Install Project Dependencies
+        run: bundle install
+
       # Sync the GitHub runner clock with the Windows time server (workaround as suggested in https://github.com/actions/runner/issues/2996)
       - name: Sync clock
         run: sudo sntp -sS time.windows.com
-
+      
       # Create or update identifiers for app
       - name: Fastlane Provision
-        run: fastlane identifiers
+        run: bundle exec fastlane identifiers
         env:
           TEAMID: ${{ secrets.TEAMID }}
           GH_PAT: ${{ secrets.GH_PAT }}

+ 22 - 0
.github/workflows/add_to_project.yml

@@ -0,0 +1,22 @@
+name: 8. DONT RUN Add bugs to bugs project
+
+on:
+  issues:
+    types:
+      - opened
+
+jobs:
+  add-to-project:
+    name: Add issue to project
+    runs-on: ubuntu-latest
+    if: github.repository_owner == 'nightscout'
+    steps:
+      - uses: actions/add-to-project@v1.0.2
+        with:
+          # You can target a project in a different organization
+          # to the issue
+          project-url: https://github.com/orgs/nightscout/projects/2
+          github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
+          labeled: bug, needs-triage
+          label-operator: OR
+

+ 0 - 71
.github/workflows/build_iAPS.yml

@@ -1,71 +0,0 @@
-name: 4. Build iAPS
-run-name: Build iAPS (${{ github.ref_name }})
-on:
-  workflow_dispatch:
-  
-  ## Remove the "#" sign from the beginning of the line below to get automated builds on push (code changes in your repository)
-  #push:
-  
-  ## Remove the "#" sign from the beginning of the two lines below to get automated builds every two months
-  #schedule:
-    #- cron: '0 17 1 */2 *' # Runs at 17:00 UTC on the 1st in Jan, Mar, May, Jul, Sep and Nov.
-
-
-jobs:
-  secrets:
-    uses: ./.github/workflows/validate_secrets.yml
-    secrets: inherit
-
-  build:
-    needs: secrets
-    runs-on: macos-13
-    steps:
-      # Uncomment to manually select Xcode version if needed
-      - name: Select Xcode version
-        run: "sudo xcode-select --switch /Applications/Xcode_15.0.1.app/Contents/Developer"
-
-      # Checks-out the repo
-      - name: Checkout Repo
-        uses: actions/checkout@v3
-        with:
-          submodules: recursive
-      
-      # Patch Fastlane Match to not print tables
-      - name: Patch Match Tables
-        run: find /usr/local/lib/ruby/gems -name table_printer.rb | xargs sed -i "" "/puts(Terminal::Table.new(params))/d"
-      
-      # Sync the GitHub runner clock with the Windows time server (workaround as suggested in https://github.com/actions/runner/issues/2996)
-      - name: Sync clock
-        run: sudo sntp -sS time.windows.com
-
-      # Build signed iAPS IPA file
-      - name: Fastlane Build & Archive
-        run: fastlane build_iAPS
-        env:
-          TEAMID: ${{ secrets.TEAMID }}
-          GH_PAT: ${{ secrets.GH_PAT }}
-          FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }}
-          FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }}
-          FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }}
-          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
-      
-      # Upload to TestFlight
-      - name: Fastlane upload to TestFlight
-        run: fastlane release
-        env:
-          TEAMID: ${{ secrets.TEAMID }}
-          GH_PAT: ${{ secrets.GH_PAT }}
-          FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }}
-          FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }}
-          FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }}
-          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
-
-      # Upload Build artifacts
-      - name: Upload build log, IPA and Symbol artifacts
-        if: always()
-        uses: actions/upload-artifact@v3
-        with:
-          name: build-artifacts
-          path: |
-            artifacts
-            buildlog

+ 302 - 0
.github/workflows/build_trio.yml

@@ -0,0 +1,302 @@
+name: 4. Build Trio
+run-name: Build Trio (${{ github.ref_name }})
+on:
+  workflow_dispatch:
+
+  ## Remove the "#" sign from the beginning of the line below to get automated builds on push (code changes in your repository)
+  #push:
+
+  schedule:
+    - cron: "0 8 * * 3" # Checks for updates at 08:00 UTC every Wednesday
+    - cron: "0 6 1 * *" # Builds the app on the 1st of every month at 06:00 UTC
+
+env:  
+  UPSTREAM_REPO: nightscout/Trio
+  UPSTREAM_BRANCH: ${{ github.ref_name }} # branch on upstream repository to sync from (replace with specific branch name if needed)
+  TARGET_BRANCH: ${{ github.ref_name }} # target branch on fork to be kept in sync, and target branch on upstream to be kept alive (replace with specific branch name if needed)
+  ALIVE_BRANCH_MAIN: alive-main
+  ALIVE_BRANCH_DEV: alive-dev
+
+jobs:
+  validate:
+    name: Validate
+    uses: ./.github/workflows/validate_secrets.yml
+    secrets: inherit
+
+  # Checks if GH_PAT holds workflow permissions
+  # Checks for existence of alive branch; if non-existent creates it
+  check_alive_and_permissions:
+    needs: validate
+    runs-on: ubuntu-latest
+    name: Check alive branch and permissions
+    permissions:
+      contents: write
+    outputs:
+      WORKFLOW_PERMISSION: ${{ steps.workflow-permission.outputs.has_permission }}
+
+    steps:
+      - name: Check for workflow permissions
+        id: workflow-permission
+        env:
+          TOKEN_TO_CHECK: ${{ secrets.GH_PAT }}
+        run: |
+          PERMISSIONS=$(curl -sS -f -I -H "Authorization: token ${{ env.TOKEN_TO_CHECK }}" https://api.github.com | grep ^x-oauth-scopes: | cut -d' ' -f2-);
+
+          if [[ $PERMISSIONS =~ "workflow" || $PERMISSIONS == "" ]]; then
+            echo "GH_PAT holds workflow permissions or is fine-grained PAT."
+            echo "has_permission=true" >> $GITHUB_OUTPUT # Set WORKFLOW_PERMISSION to false.
+          else 
+            echo "GH_PAT lacks workflow permissions."
+            echo "Automated build features will be skipped!"
+            echo "has_permission=false" >> $GITHUB_OUTPUT # Set WORKFLOW_PERMISSION to false.
+          fi
+
+      - name: Check for alive branches
+        if: steps.workflow-permission.outputs.has_permission == 'true'
+        env:
+          GITHUB_TOKEN: ${{ secrets.GH_PAT }}
+        run: |
+          if [[ $(gh api -H "Accept: application/vnd.github+json" /repos/${{ github.repository_owner }}/Trio/branches | jq --raw-output '[.[] | select(.name == "alive-main" or .name == "alive-dev")] | length > 0') == "true" ]]; then
+            echo "Branches 'alive-main' or 'alive-dev' exist."
+            echo "ALIVE_BRANCH_EXISTS=true" >> $GITHUB_ENV
+          else
+            echo "Branches 'alive-main' and 'alive-dev' do not exist."
+            echo "ALIVE_BRANCH_EXISTS=false" >> $GITHUB_ENV
+          fi
+
+      - name: Create alive branches
+        if: env.ALIVE_BRANCH_EXISTS == 'false'
+        env:
+          GITHUB_TOKEN: ${{ secrets.GH_PAT }}
+        run: |
+          # Get ref for UPSTREAM_REPO:main
+          SHA_MAIN=$(curl -sS -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/repos/${{ env.UPSTREAM_REPO }}/git/refs/heads/main | jq -r '.object.sha')
+
+          # Get ref for UPSTREAM_REPO:dev
+          SHA_DEV=$(curl -sS -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/repos/${{ env.UPSTREAM_REPO }}/git/refs/heads/dev | jq -r '.object.sha')
+
+          # Create alive-main branch in Trio fork based on UPSTREAM_REPO:main
+          gh api \
+            --method POST \
+            -H "Authorization: token $GITHUB_TOKEN" \
+            -H "Accept: application/vnd.github.v3+json" \
+            /repos/${{ github.repository_owner }}/Trio/git/refs \
+            -f ref='refs/heads/alive-main' \
+            -f sha=$SHA_MAIN
+
+          # Create alive-dev branch in Trio fork based on UPSTREAM_REPO:dev
+          gh api \
+            --method POST \
+            -H "Authorization: token $GITHUB_TOKEN" \
+            -H "Accept: application/vnd.github.v3+json" \
+            /repos/${{ github.repository_owner }}/Trio/git/refs \
+            -f ref='refs/heads/alive-dev' \
+            -f sha=$SHA_DEV
+
+  # Checks for changes in upstream repository; if changes exist prompts sync for build
+  # Performs keepalive to avoid stale fork
+  check_latest_from_upstream:
+    needs: [validate, check_alive_and_permissions]
+    runs-on: ubuntu-latest
+    name: Check upstream and keep alive
+    outputs:
+      NEW_COMMITS: ${{ steps.sync.outputs.has_new_commits }}
+      ABORT_SYNC: ${{ steps.check_branch.outputs.ABORT_SYNC }}
+
+    steps:
+      - name: Check if running on main or dev branch
+        if: |
+          needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
+          (vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false')
+        id: check_branch
+        run: |
+          if [ "${GITHUB_REF##*/}" = "main" ]; then
+            echo "Running on main branch"
+            echo "ALIVE_BRANCH=${ALIVE_BRANCH_MAIN}" >> $GITHUB_OUTPUT
+            echo "ABORT_SYNC=false" >> $GITHUB_OUTPUT
+          elif [ "${GITHUB_REF##*/}" = "dev" ]; then
+            echo "Running on dev branch"
+            echo "ALIVE_BRANCH=${ALIVE_BRANCH_DEV}" >> $GITHUB_OUTPUT
+            echo "ABORT_SYNC=false" >> $GITHUB_OUTPUT
+          else
+            echo "Not running on main or dev branch"
+            echo "ABORT_SYNC=true" >> $GITHUB_OUTPUT
+          fi
+
+      - name: Checkout target repo
+        if: |
+          needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
+          (vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false')
+        uses: actions/checkout@v4
+        with:
+          token: ${{ secrets.GH_PAT }}
+          ref: ${{ steps.check_branch.outputs.ALIVE_BRANCH }}
+
+      - name: Sync upstream changes
+        if: | # do not run the upstream sync action on the upstream repository
+          needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
+          vars.SCHEDULED_SYNC != 'false' && github.repository_owner != 'nightscout' && steps.check_branch.outputs.ABORT_SYNC == 'false'
+        id: sync
+        uses: aormsby/Fork-Sync-With-Upstream-action@v3.4.1
+        with:
+          target_sync_branch: ${{ steps.check_branch.outputs.ALIVE_BRANCH }}
+          shallow_since: 6 months ago
+          target_repo_token: ${{ secrets.GH_PAT }}
+          upstream_sync_branch: ${{ env.UPSTREAM_BRANCH }}
+          upstream_sync_repo: ${{ env.UPSTREAM_REPO }}
+
+      # Display a sample message based on the sync output var 'has_new_commits'
+      - name: New commits found
+        if: |
+          needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
+          vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'true'
+        run: echo "New commits were found to sync."
+
+      - name: No new commits
+        if: |
+          needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && 
+          vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'false'
+        run: echo "There were no new commits."
+
+      - name: Show value of 'has_new_commits'
+        if: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && vars.SCHEDULED_SYNC != 'false' && steps.check_branch.outputs.ABORT_SYNC == 'false'
+        run: |
+          echo ${{ steps.sync.outputs.has_new_commits }}
+          echo "NEW_COMMITS=${{ steps.sync.outputs.has_new_commits }}" >> $GITHUB_OUTPUT
+
+      # Keep repository "alive": add empty commits to ALIVE_BRANCH after "time_elapsed" days of inactivity to avoid inactivation of scheduled workflows
+      - name: Keep alive
+        if: |
+          needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
+          (vars.SCHEDULED_BUILD != 'false' || vars.SCHEDULED_SYNC != 'false')
+        uses: gautamkrishnar/keepalive-workflow@v1 # using the workflow with default settings
+        with:
+          time_elapsed: 20 # Time elapsed from the previous commit to trigger a new automated commit (in days)
+
+      - name: Show scheduled build configuration message
+        if: needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION != 'true'
+        run: |
+          echo "### :calendar: Scheduled Sync and Build Disabled :mobile_phone_off:" >> $GITHUB_STEP_SUMMARY
+          echo "You have not yet configured the scheduled sync and build for Trio's browser build." >> $GITHUB_STEP_SUMMARY
+          echo "Synchronizing your fork of <code>Trio</code> with the upstream repository <code>nightscout/Trio</code> will be skipped." >> $GITHUB_STEP_SUMMARY
+          echo "If you want to enable automatic builds and updates for your Trio, please follow the instructions \
+              under the following path <code>Trio/fastlane/testflight.md</code>." >> $GITHUB_STEP_SUMMARY
+  
+  # Builds Trio
+  build:
+    name: Build
+    needs: [validate, check_alive_and_permissions, check_latest_from_upstream]
+    runs-on: macos-14
+    permissions:
+      contents: write
+    if:
+      | # runs if started manually, or if sync schedule is set and enabled and scheduled on the first Saturday each month, or if sync schedule is set and enabled and new commits were found
+      github.event_name == 'workflow_dispatch' ||
+      (needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
+        (vars.SCHEDULED_BUILD != 'false' && github.event.schedule == '0 6 1 * *') ||
+        (vars.SCHEDULED_SYNC != 'false' && needs.check_latest_from_upstream.outputs.NEW_COMMITS == 'true' )
+      )
+    steps:
+      - name: Select Xcode version
+        run: "sudo xcode-select --switch /Applications/Xcode_15.4.app/Contents/Developer"
+      
+      - name: Checkout Repo for syncing
+        if: |
+          needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
+          vars.SCHEDULED_SYNC != 'false'
+        uses: actions/checkout@v4
+        with:
+          token: ${{ secrets.GH_PAT }}
+          ref: ${{ env.TARGET_BRANCH }}
+
+      - name: Sync upstream changes
+        if: | # do not run the upstream sync action on the upstream repository
+          needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
+          vars.SCHEDULED_SYNC != 'false' && github.repository_owner != 'nightscout' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
+        id: sync
+        uses: aormsby/Fork-Sync-With-Upstream-action@v3.4.1
+        with:
+          target_sync_branch: ${{ env.TARGET_BRANCH }}
+          shallow_since: 6 months ago
+          target_repo_token: ${{ secrets.GH_PAT }}
+          upstream_sync_branch: ${{ env.UPSTREAM_BRANCH }}
+          upstream_sync_repo: ${{ env.UPSTREAM_REPO }}
+
+      # Display a sample message based on the sync output var 'has_new_commits'
+      - name: New commits found
+        if: |
+          needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' &&
+          vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'true' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
+        run: echo "New commits were found to sync."
+
+      - name: No new commits
+        if: |
+          needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true' && 
+          vars.SCHEDULED_SYNC != 'false' && steps.sync.outputs.has_new_commits == 'false' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
+        run: echo "There were no new commits."
+
+      - name: Show value of 'has_new_commits'
+        if: |
+          needs.check_alive_and_permissions.outputs.WORKFLOW_PERMISSION == 'true'
+          && vars.SCHEDULED_SYNC != 'false' && needs.check_latest_from_upstream.outputs.ABORT_SYNC == 'false'
+        run: |
+          echo ${{ steps.sync.outputs.has_new_commits }}
+          echo "NEW_COMMITS=${{ steps.sync.outputs.has_new_commits }}" >> $GITHUB_OUTPUT
+
+      - name: Checkout Repo for building
+        uses: actions/checkout@v4
+        with:
+          token: ${{ secrets.GH_PAT }}
+          submodules: recursive
+          ref: ${{ env.TARGET_BRANCH }}
+
+      # Patch Fastlane Match to not print tables
+      - name: Patch Match Tables
+        run: |
+          TABLE_PRINTER_PATH=$(ruby -e 'puts Gem::Specification.find_by_name("fastlane").gem_dir')/match/lib/match/table_printer.rb
+          if [ -f "$TABLE_PRINTER_PATH" ]; then
+            sed -i "" "/puts(Terminal::Table.new(params))/d" "$TABLE_PRINTER_PATH"
+          else
+            echo "table_printer.rb not found"
+            exit 1
+          fi
+
+      # Install project dependencies
+      - name: Install Project Dependencies
+        run: bundle install
+
+      # Sync the GitHub runner clock with the Windows time server (workaround as suggested in https://github.com/actions/runner/issues/2996)
+      - name: Sync clock
+        run: sudo sntp -sS time.windows.com
+
+      # Build signed Trio IPA file
+      - name: Fastlane Build & Archive
+        run: bundle exec fastlane build_trio
+        env:
+          TEAMID: ${{ secrets.TEAMID }}
+          GH_PAT: ${{ secrets.GH_PAT }}
+          FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }}
+          FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }}
+          FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }}
+          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
+
+      # Upload to TestFlight
+      - name: Fastlane upload to TestFlight
+        run: bundle exec fastlane release
+        env:
+          TEAMID: ${{ secrets.TEAMID }}
+          GH_PAT: ${{ secrets.GH_PAT }}
+          FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }}
+          FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }}
+          FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }}
+          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
+
+      # Upload Build artifacts
+      - name: Upload build log, IPA and Symbol artifacts
+        if: always()
+        uses: actions/upload-artifact@v4
+        with:
+          name: build-artifacts
+          path: |
+            artifacts
+            buildlog

+ 26 - 13
.github/workflows/create_certs.yml

@@ -1,36 +1,49 @@
 name: 3. Create Certificates
-run-name: Create Certificates
+run-name: Create Certificates (${{ github.ref_name }})
 on:
   workflow_dispatch:
 
 jobs:
-  secrets:
+  validate:
+    name: Validate
     uses: ./.github/workflows/validate_secrets.yml
     secrets: inherit
-
+  
   certificates:
-    needs: secrets
-    runs-on: macos-13
+    name: Create Certificates
+    needs: validate
+    runs-on: macos-14
     steps:
-      # Uncomment to manually select Xcode version if needed
-      #- name: Select Xcode version
-      #  run: "sudo xcode-select --switch /Applications/Xcode_14.1.app/Contents/Developer"
+      # Uncomment to manually select latest Xcode if needed
+      #- name: Select Latest Xcode
+      #  run: "sudo xcode-select --switch /Applications/Xcode_13.0.app/Contents/Developer"
       
       # Checks-out the repo
       - name: Checkout Repo
-        uses: actions/checkout@v3
-        
+        uses: actions/checkout@v4
+      
       # Patch Fastlane Match to not print tables
       - name: Patch Match Tables
-        run: find /usr/local/lib/ruby/gems -name table_printer.rb | xargs sed -i "" "/puts(Terminal::Table.new(params))/d"
+        run: |
+          TABLE_PRINTER_PATH=$(ruby -e 'puts Gem::Specification.find_by_name("fastlane").gem_dir')/match/lib/match/table_printer.rb
+          if [ -f "$TABLE_PRINTER_PATH" ]; then
+            sed -i "" "/puts(Terminal::Table.new(params))/d" "$TABLE_PRINTER_PATH"
+          else
+            echo "table_printer.rb not found"
+            exit 1
+          fi
+
+      # Install project dependencies
+      - name: Install Project Dependencies
+        run: bundle install
 
       # Sync the GitHub runner clock with the Windows time server (workaround as suggested in https://github.com/actions/runner/issues/2996)
       - name: Sync clock
         run: sudo sntp -sS time.windows.com
-
+      
       # Create or update certificates for app
       - name: Create Certificates
-        run: fastlane certs
+        run: bundle exec fastlane certs
         env:
           TEAMID: ${{ secrets.TEAMID }}
           GH_PAT: ${{ secrets.GH_PAT }}

+ 48 - 0
.github/workflows/stale_issues.yml

@@ -0,0 +1,48 @@
+name: 8. DONT RUN close inactive issues
+on:
+  schedule:
+    - cron: "30 1 * * *"
+
+jobs:
+  close-issues:
+    runs-on: ubuntu-latest
+    permissions:
+      issues: write
+      pull-requests: write
+    if: github.repository_owner == 'nightscout'
+    steps:
+      - uses: actions/stale@v9.0.0
+        with:
+          days-before-issue-stale: 30
+          days-before-issue-close: 14
+          stale-issue-label: "stale"
+          stale-issue-message: "hey 👋 - silence for 30 days 🤐 ... anybody? triage is required!"
+          close-issue-message: "closed 📴 because silencio 🤫 since an additional 14 days after staleness 📠"
+          close-issue-label: "not-planned"
+          exempt-issue-labels: "needs-triage, long-term, in-progress"
+          days-before-pr-stale: -1
+          days-before-pr-close: -1
+          repo-token: ${{ secrets.GITHUB_TOKEN }}
+          
+
+  close-issues-triage:
+    runs-on: ubuntu-latest
+    permissions:
+      issues: write
+      pull-requests: write
+    if: github.repository_owner == 'nightscout'
+    steps:
+      - uses: actions/stale@v9.0.0
+        with:
+          days-before-issue-stale: 30
+          days-before-issue-close: 30
+          stale-issue-label: "stale"
+          stale-issue-message: "hey 👋 - no triage is done for 30 days 🤐 ... anybody? triage is required!"
+          close-issue-message: "closed 📴 because silencio 🤫 since an additional 30 days after staleness 📠"
+          close-issue-label: "not-planned"
+          exempt-issue-labels: "long-term, in-progress"
+          any-of-labels: "needs-triage"
+          days-before-pr-stale: -1
+          days-before-pr-close: -1
+          repo-token: ${{ secrets.GITHUB_TOKEN }}
+

+ 159 - 36
.github/workflows/validate_secrets.yml

@@ -1,74 +1,197 @@
 name: 1. Validate Secrets
-run-name: Validate Secrets
+run-name: Validate Secrets (${{ github.ref_name }})
 on: [workflow_call, workflow_dispatch]
 
 jobs:
-  validate:
-    runs-on: macos-13
+  validate-access-token:
+    name: Access
+    runs-on: macos-14
+    env:
+      GH_PAT: ${{ secrets.GH_PAT }}
+      GH_TOKEN: ${{ secrets.GH_PAT }}
+    outputs:
+      HAS_WORKFLOW_PERMISSION: ${{ steps.access-token.outputs.has_workflow_permission }}
+    steps:
+      - name: Validate Access Token
+        id: access-token
+        run: |
+          # Validate Access Token
+
+          # Ensure that gh exit codes are handled when output is piped.
+          set -o pipefail
+
+          # Define patterns to validate the access token (GH_PAT) and distinguish between classic and fine-grained tokens.
+          GH_PAT_CLASSIC_PATTERN='^ghp_[a-zA-Z0-9]{36}$'
+          GH_PAT_FINE_GRAINED_PATTERN='^github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}$'
+
+          # Validate Access Token (GH_PAT)
+          if [ -z "$GH_PAT" ]; then
+            failed=true
+            echo "::error::The GH_PAT secret is unset or empty. Set it and try again."
+          else
+            if [[ $GH_PAT =~ $GH_PAT_CLASSIC_PATTERN ]]; then
+              provides_scopes=true
+              echo "The GH_PAT secret is a structurally valid classic token."
+            elif [[ $GH_PAT =~ $GH_PAT_FINE_GRAINED_PATTERN ]]; then
+              echo "The GH_PAT secret is a structurally valid fine-grained token."
+            else
+              unknown_format=true
+              echo "The GH_PAT secret does not have a known token format."
+            fi
+            
+            # Attempt to capture the x-oauth-scopes scopes of the token.
+            if ! scopes=$(curl -sS -f -I -H "Authorization: token $GH_PAT" https://api.github.com | { grep -i '^x-oauth-scopes:' || true; } | cut -d ' ' -f2- | tr -d '\r'); then
+              failed=true
+              if [ $unknown_format ]; then
+                echo "::error::Unable to connect to GitHub using the GH_PAT secret. Verify that it is set correctly (including the 'ghp_' or 'github_pat_' prefix) and try again."
+              else
+                echo "::error::Unable to connect to GitHub using the GH_PAT secret. Verify that the token exists and has not expired at https://github.com/settings/tokens. If necessary, regenerate or create a new token (and update the secret), then try again."
+              fi
+            elif [[ $scopes =~ workflow ]]; then
+              echo "The GH_PAT secret has repo and workflow permissions."
+              echo "has_workflow_permission=true" >> $GITHUB_OUTPUT
+            elif [[ $scopes =~ repo ]]; then
+              echo "The GH_PAT secret has repo (but not workflow) permissions."
+            elif [ $provides_scopes ]; then
+              failed=true
+              if [ -z "$scopes" ]; then
+                echo "The GH_PAT secret is valid and can be used to connect to GitHub, but it does not provide any permission scopes."
+              else
+                echo "The GH_PAT secret is valid and can be used to connect to GitHub, but it only provides the following permission scopes: $scopes"
+              fi
+              echo "::error::The GH_PAT secret is lacking at least the 'repo' permission scope required to access the Match-Secrets repository. Update the token permissions at https://github.com/settings/tokens (to include the 'repo' and 'workflow' scopes) and try again."
+            else
+              echo "The GH_PAT secret is valid and can be used to connect to GitHub, but it does not provide inspectable scopes. Assuming that the 'repo' and 'workflow' permission scopes required to access the Match-Secrets repository and perform automations are present."
+              echo "has_workflow_permission=true" >> $GITHUB_OUTPUT
+            fi
+          fi
+
+          # Exit unsuccessfully if secret validation failed.
+          if [ $failed ]; then
+            exit 2
+          fi
+
+  validate-match-secrets:
+    name: Match-Secrets
+    needs: validate-access-token
+    runs-on: macos-14
+    env:
+      GH_TOKEN: ${{ secrets.GH_PAT }}
+    steps:
+      - name: Validate Match-Secrets
+        run: |
+          # Validate Match-Secrets
+
+          # Ensure that gh exit codes are handled when output is piped.
+          set -o pipefail
+
+          # If a Match-Secrets repository does not exist, attempt to create one.
+          if ! visibility=$(gh repo view ${{ github.repository_owner }}/Match-Secrets --json visibility | jq --raw-output '.visibility | ascii_downcase'); then
+            echo "A '${{ github.repository_owner }}/Match-Secrets' repository could not be found using the GH_PAT secret. Attempting to create one..."
+            
+            # Create a private Match-Secrets repository and verify that it exists and that it is private.
+            if gh repo create ${{ github.repository_owner }}/Match-Secrets --private >/dev/null && [ "$(gh repo view ${{ github.repository_owner }}/Match-Secrets --json visibility | jq --raw-output '.visibility | ascii_downcase')" == "private" ]; then
+              echo "Created a private '${{ github.repository_owner }}/Match-Secrets' repository."
+            else
+              failed=true
+              echo "::error::Unable to create a private '${{ github.repository_owner }}/Match-Secrets' repository. Create a private 'Match-Secrets' repository manually and try again. If a private 'Match-Secrets' repository already exists, verify that the token permissions of the GH_PAT are set correctly (or update them) at https://github.com/settings/tokens and try again."
+            fi
+          # Otherwise, if a Match-Secrets repository exists, but it is public, cause validation to fail.
+          elif [[ "$visibility" == "public" ]]; then
+            failed=true
+            echo "::error::A '${{ github.repository_owner }}/Match-Secrets' repository was found, but it is public. Change the repository visibility to private (or delete it) and try again. If necessary, a private repository will be created for you."
+          else
+            echo "Found a private '${{ github.repository_owner }}/Match-Secrets' repository to use."
+          fi
+
+          # Exit unsuccessfully if secret validation failed.
+          if [ $failed ]; then
+            exit 2
+          fi
+
+  validate-fastlane-secrets:
+    name: Fastlane
+    needs: [validate-access-token, validate-match-secrets]
+    runs-on: macos-14
+    env:
+      GH_PAT: ${{ secrets.GH_PAT }}
+      GH_TOKEN: ${{ secrets.GH_PAT }}
+      FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }}
+      FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }}
+      FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }}
+      MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
+      TEAMID: ${{ secrets.TEAMID }}
     steps:
-      # Checks-out the repo
       - name: Checkout Repo
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
+
+      - name: Install Project Dependencies
+        run: bundle install
 
       # Sync the GitHub runner clock with the Windows time server (workaround as suggested in https://github.com/actions/runner/issues/2996)
       - name: Sync clock
         run: sudo sntp -sS time.windows.com
 
-      # Validates the repo secrets
-      - name: Validate Secrets
+      - name: Validate Fastlane Secrets
         run: |
-          # Validate Secrets
-          echo Validating Repository Secrets...
+          # Validate Fastlane Secrets
 
           # Validate TEAMID
           if [ -z "$TEAMID" ]; then
             failed=true
-            echo "::error::TEAMID secret is unset or empty. Set it and try again."
+            echo "::error::The TEAMID secret is unset or empty. Set it and try again."
           elif [ ${#TEAMID} -ne 10 ]; then
             failed=true
-            echo "::error::TEAMID secret is set but has wrong length. Verify that it is set correctly and try again."
+            echo "::error::The TEAMID secret is set but has wrong length. Verify that it is set correctly and try again."
+          elif ! [[ $TEAMID =~ ^[A-Z0-9]+$ ]]; then
+            failed=true
+            echo "::error::The TEAMID secret is set but invalid. Verify that it is set correctly (only uppercase letters and numbers) and try again."
           fi
 
-          # Validate GH_PAT
-          if [ -z "$GH_PAT" ]; then
-            failed=true
-            echo "::error::GH_PAT secret is unset or empty. Set it and try again."
-          elif [ "$(gh api -H "Accept: application/vnd.github+json" /repos/${{ github.repository_owner }}/Match-Secrets | jq --raw-output '.permissions.push')" != "true" ]; then
+          # Validate MATCH_PASSWORD
+          if [ -z "$MATCH_PASSWORD" ]; then
             failed=true
-            echo "::error::GH_PAT secret is set but invalid or lacking appropriate privileges on the ${{ github.repository_owner }}/Match-Secrets repository. Verify that it is set correctly and try again."
+            echo "::error::The MATCH_PASSWORD secret is unset or empty. Set it and try again."
           fi
 
+          # Ensure that fastlane exit codes are handled when output is piped.
+          set -o pipefail
+
           # Validate FASTLANE_ISSUER_ID, FASTLANE_KEY_ID, and FASTLANE_KEY
+          FASTLANE_KEY_ID_PATTERN='^[A-Z0-9]+$'
+          FASTLANE_ISSUER_ID_PATTERN='^\{?[A-F0-9a-f]{8}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{12}\}?$'
+
           if [ -z "$FASTLANE_ISSUER_ID" ] || [ -z "$FASTLANE_KEY_ID" ] || [ -z "$FASTLANE_KEY" ]; then
             failed=true
             [ -z "$FASTLANE_ISSUER_ID" ] && echo "::error::The FASTLANE_ISSUER_ID secret is unset or empty. Set it and try again."
             [ -z "$FASTLANE_KEY_ID"    ] && echo "::error::The FASTLANE_KEY_ID secret is unset or empty. Set it and try again."
             [ -z "$FASTLANE_KEY"       ] && echo "::error::The FASTLANE_KEY secret is unset or empty. Set it and try again."
-          elif ! echo "$FASTLANE_KEY" | openssl pkcs8 -nocrypt >/dev/null; then
+          elif [ ${#FASTLANE_KEY_ID} -ne 10 ]; then
             failed=true
-            echo "::error::The FASTLANE_KEY secret is set but invalid. Verify that it is set correctly and try again."
-          elif ! fastlane validate_secrets; then
+            echo "::error::The FASTLANE_KEY_ID secret is set but has wrong length. Verify that you copied it correctly from the 'Keys' tab at https://appstoreconnect.apple.com/access/integrations/api and try again."
+          elif ! [[ $FASTLANE_KEY_ID =~ $FASTLANE_KEY_ID_PATTERN ]]; then
             failed=true
-            echo "::error::Unable to create a valid authorization token for the App Store Connect API.\
-            Verify that the FASTLANE_ISSUER_ID, FASTLANE_KEY_ID, and FASTLANE_KEY secrets are set correctly and try again."
-          fi
-
-          # Validate MATCH_PASSWORD
-          if [ -z "$MATCH_PASSWORD" ]; then
+            echo "::error::The FASTLANE_KEY_ID secret is set but invalid. Verify that you copied it correctly from the 'Keys' tab at https://appstoreconnect.apple.com/access/integrations/api and try again."
+          elif ! [[ $FASTLANE_ISSUER_ID =~ $FASTLANE_ISSUER_ID_PATTERN ]]; then
             failed=true
-            echo "::error::The MATCH_PASSWORD secret is unset or empty. Set it and try again."
+            echo "::error::The FASTLANE_ISSUER_ID secret is set but invalid. Verify that you copied it correctly from the 'Keys' tab at https://appstoreconnect.apple.com/access/integrations/api and try again."
+          elif ! echo "$FASTLANE_KEY" | openssl pkcs8 -nocrypt >/dev/null; then
+            failed=true
+            echo "::error::The FASTLANE_KEY secret is set but invalid. Verify that you copied it correctly from the API Key file (*.p8) you downloaded and try again."
+          elif ! bundle exec fastlane validate_secrets 2>&1 | tee fastlane.log; then
+            if grep -q "bad decrypt" fastlane.log; then
+              failed=true
+              echo "::error::Unable to decrypt the Match-Secrets repository using the MATCH_PASSWORD secret. Verify that it is set correctly and try again."
+            elif grep -q -e "required agreement" -e "license agreement" fastlane.log; then
+              failed=true
+              echo "::error::Unable to create a valid authorization token for the App Store Connect API. Verify that the latest developer program license agreement has been accepted at https://developer.apple.com/account (review and accept any updated agreement), then wait a few minutes for changes to propagate and try again."
+            elif ! grep -q -e "No code signing identity found" -e "Could not install WWDR certificate" fastlane.log; then
+              failed=true
+              echo "::error::Unable to create a valid authorization token for the App Store Connect API. Verify that the FASTLANE_ISSUER_ID, FASTLANE_KEY_ID, and FASTLANE_KEY secrets are set correctly and try again."
+            fi
           fi
 
           # Exit unsuccessfully if secret validation failed.
           if [ $failed ]; then
             exit 2
           fi
-        shell: bash
-        env:
-          TEAMID: ${{ secrets.TEAMID }}
-          GH_PAT: ${{ secrets.GH_PAT }}
-          FASTLANE_ISSUER_ID: ${{ secrets.FASTLANE_ISSUER_ID }}
-          FASTLANE_KEY_ID: ${{ secrets.FASTLANE_KEY_ID }}
-          FASTLANE_KEY: ${{ secrets.FASTLANE_KEY }}
-          MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
-          GH_TOKEN: ${{ secrets.GH_PAT }}

+ 0 - 2
.gitignore

@@ -80,5 +80,3 @@ fastlane/test_output
 fastlane/FastlaneRunner
 
 ConfigOverride.xcconfig
-
-branch.txt

+ 40 - 0
.gitmodules

@@ -0,0 +1,40 @@
+[submodule "LoopKit"]
+	path = LoopKit
+	url = https://github.com/loopandlearn/LoopKit.git
+	branch = trio
+[submodule "CGMBLEKit"]
+	path = CGMBLEKit
+	url = https://github.com/loopandlearn/CGMBLEKit.git
+	branch = trio
+[submodule "dexcom-share-client-swift"]
+	path = dexcom-share-client-swift
+	url = https://github.com/loopandlearn/dexcom-share-client-swift.git
+	branch = trio
+[submodule "RileyLinkKit"]
+	path = RileyLinkKit
+	url = https://github.com/loopandlearn/RileyLinkKit
+	branch = trio
+[submodule "OmniBLE"]
+	path = OmniBLE
+	url = https://github.com/loopandlearn/OmniBLE.git
+	branch = trio
+[submodule "G7SensorKit"]
+	path = G7SensorKit
+	url = https://github.com/loopandlearn/G7SensorKit.git
+	branch = trio
+[submodule "OmniKit"]
+	path = OmniKit
+	url = https://github.com/loopandlearn/OmniKit.git
+	branch = trio
+[submodule "MinimedKit"]
+	path = MinimedKit
+	url = https://github.com/loopandlearn/MinimedKit.git
+	branch = trio
+[submodule "LibreTransmitter"]
+	path = LibreTransmitter
+	url = https://github.com/loopandlearn/LibreTransmitter.git
+	branch = trio
+[submodule "TidepoolService"]
+	path = TidepoolService
+	url = https://github.com/loopandlearn/TidepoolService.git
+	branch = trio

+ 8 - 0
BuildDetails.plist

@@ -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>TidepoolServiceClientId</key>
+	<string>diy-loop</string>
+</dict>
+</plist>

+ 1 - 0
CGMBLEKit

@@ -0,0 +1 @@
+Subproject commit 15af9cf319bff2ac49c361da254ad667461d4687

+ 3 - 3
CODE_OF_CONDUCT.md

@@ -59,9 +59,9 @@ representative at an online or offline event.
 ## Enforcement
 
 Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported to the community leaders responsible for enforcement at
-jon.m@live.se.
-All complaints will be reviewed and investigated promptly and fairly.
+reported to the Discord server admins. Please join our [Discord server](https://discord.gg/dbe5Twav8D) to contact
+them directly for any enforcement issues. All complaints will be reviewed and
+investigated promptly and fairly.
 
 All community leaders are obligated to respect the privacy and security of the
 reporter of any incident.

+ 6 - 7
Config.xcconfig

@@ -1,12 +1,11 @@
-APP_DISPLAY_NAME = iAPS
-APP_VERSION = 2.3.3
+APP_DISPLAY_NAME = Trio
+APP_VERSION = 0.2.0
 APP_BUILD_NUMBER = 1
 COPYRIGHT_NOTICE =
 DEVELOPER_TEAM = ##TEAM_ID##
-BUNDLE_IDENTIFIER = ru.artpancreas.$(DEVELOPMENT_TEAM).FreeAPS
-APP_GROUP_ID = group.com.$(DEVELOPMENT_TEAM).loopkit.LoopGroup
-APP_ICON = pod_colorful
-APP_URL_SCHEME = freeaps-x
+BUNDLE_IDENTIFIER = org.nightscout.$(DEVELOPMENT_TEAM).trio
+APP_ICON = trioBlack
+APP_URL_SCHEME = Trio
 
+#include? "../../ConfigOverride.xcconfig"
 #include? "ConfigOverride.xcconfig"
-//#include? "../../ConfigOverride.xcconfig"

+ 4 - 3
Core_Data.xcdatamodeld/Core_Data.xcdatamodel/contents

@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21754" systemVersion="22F82" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
+<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22757" systemVersion="23E224" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
     <entity name="BGaverages" representedClassName="BGaverages" syncable="YES" codeGenerationType="class">
         <attribute name="average" optional="YES" attributeType="Decimal" defaultValueString="0.0"/>
         <attribute name="average_1" optional="YES" attributeType="Decimal" defaultValueString="0.0"/>
@@ -66,8 +66,8 @@
         <attribute name="isfAndCr" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
         <attribute name="isPreset" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
         <attribute name="percentage" optional="YES" attributeType="Double" defaultValueString="100" usesScalarValueType="YES"/>
-        <attribute name="smbIsAlwaysOff" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
         <attribute name="smbIsOff" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
+        <attribute name="smbIsScheduledOff" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
         <attribute name="smbMinutes" optional="YES" attributeType="Decimal" defaultValueString="30"/>
         <attribute name="start" optional="YES" attributeType="Decimal" defaultValueString="0.0"/>
         <attribute name="target" optional="YES" attributeType="Decimal" defaultValueString="100"/>
@@ -85,8 +85,8 @@
         <attribute name="isfAndCr" optional="YES" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
         <attribute name="name" optional="YES" attributeType="String"/>
         <attribute name="percentage" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="YES"/>
-        <attribute name="smbIsAlwaysOff" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
         <attribute name="smbIsOff" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
+        <attribute name="smbIsScheduledOff" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
         <attribute name="smbMinutes" optional="YES" attributeType="Decimal" defaultValueString="30"/>
         <attribute name="start" optional="YES" attributeType="Decimal" defaultValueString="0.0"/>
         <attribute name="target" optional="YES" attributeType="Decimal" defaultValueString="0.0"/>
@@ -105,6 +105,7 @@
     </entity>
     <entity name="Readings" representedClassName="Readings" syncable="YES" codeGenerationType="class">
         <attribute name="date" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
+        <attribute name="direction" optional="YES" attributeType="String"/>
         <attribute name="glucose" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
         <attribute name="id" optional="YES" attributeType="String"/>
     </entity>

+ 0 - 36
Dependencies/CGMBLEKit/.gitignore

@@ -1,36 +0,0 @@
-# OS X
-.DS_Store
-
-# Xcode
-build/
-*.pbxuser
-!default.pbxuser
-*.mode1v3
-!default.mode1v3
-*.mode2v3
-!default.mode2v3
-*.perspectivev3
-!default.perspectivev3
-xcuserdata
-*.xccheckout
-profile
-*.moved-aside
-DerivedData
-*.hmap
-*.ipa
-
-# Bundler
-.bundle
-
-Carthage
-# We recommend against adding the Pods directory to your .gitignore. However
-# you should judge for yourself, the pros and cons are mentioned at:
-# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
-#
-# Note: if you ignore the Pods directory, make sure to uncomment
-# `pod install` in .travis.yml
-#
-
-Pods/
-Carthage/
-.gitmodules

+ 0 - 13
Dependencies/CGMBLEKit/.travis.yml

@@ -1,13 +0,0 @@
-language: objective-c
-osx_image: xcode12.2
-
-before_script:
-    - ./Scripts/carthage.sh bootstrap
-
-script:
-    # Build frameworks and run tests
-    - travis_wait 25 xcodebuild -project CGMBLEKit.xcodeproj -scheme Shared build -destination name="iPhone 8" test | xcpretty
-    # Build apps
-    - xcodebuild -project CGMBLEKit.xcodeproj -scheme "CGMBLEKit Example" build -destination name="iPhone 8" | xcpretty
-    - xcodebuild -project CGMBLEKit.xcodeproj -scheme ResetTransmitter build -destination name="iPhone 8"
-

+ 0 - 140
Dependencies/CGMBLEKit/CGMBLEKit Example/AppDelegate.swift

@@ -1,140 +0,0 @@
-//
-//  AppDelegate.swift
-//  xDrip5
-//
-//  Created by Nathan Racklyeft on 10/1/15.
-//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
-//
-
-import UIKit
-import CGMBLEKit
-import CoreBluetooth
-
-@UIApplicationMain
-class AppDelegate: UIResponder, UIApplicationDelegate, TransmitterDelegate, TransmitterCommandSource {
-    
-    var window: UIWindow?
-
-    static var sharedDelegate: AppDelegate {
-        return UIApplication.shared.delegate as! AppDelegate
-    }
-
-    var transmitterID: String? {
-        didSet {
-            if let id = transmitterID {
-                transmitter = Transmitter(
-                    id: id,
-                    passiveModeEnabled: UserDefaults.standard.passiveModeEnabled
-                )
-                transmitter?.stayConnected = UserDefaults.standard.stayConnected
-                transmitter?.delegate = self
-                transmitter?.commandSource = self
-
-                UserDefaults.standard.transmitterID = id
-            }
-            glucose = nil
-        }
-    }
-
-    var transmitter: Transmitter?
-
-    let commandQueue = CommandQueue()
-
-    var glucose: Glucose?
-
-    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
-
-        transmitterID = UserDefaults.standard.transmitterID
-
-        return true
-    }
-
-    func applicationWillResignActive(_ application: UIApplication) {
-        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
-        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
-    }
-
-    func applicationDidEnterBackground(_ application: UIApplication) {
-        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
-        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
-
-        if let transmitter = transmitter, !transmitter.stayConnected {
-            transmitter.stopScanning()
-        }
-    }
-
-    func applicationWillEnterForeground(_ application: UIApplication) {
-        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
-    }
-
-    func applicationDidBecomeActive(_ application: UIApplication) {
-        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
-
-        transmitter?.resumeScanning()
-    }
-
-    func applicationWillTerminate(_ application: UIApplication) {
-        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
-    }
-
-    // MARK: - TransmitterDelegate
-
-    private let dateFormatter: DateFormatter = {
-        let dateFormatter = DateFormatter()
-
-        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
-        dateFormatter.locale = Locale(identifier: "en_US_POSIX")
-
-        return dateFormatter
-    }()
-
-    func dequeuePendingCommand(for transmitter: Transmitter) -> Command? {
-        return commandQueue.dequeue()
-    }
-
-    func transmitter(_ transmitter: Transmitter, didFail command: Command, with error: Error) {
-        // TODO: implement
-    }
-
-    func transmitter(_ transmitter: Transmitter, didComplete command: Command) {
-        // TODO: implement
-    }
-
-    func transmitter(_ transmitter: Transmitter, didError error: Error) {
-        DispatchQueue.main.async {
-            if let vc = self.window?.rootViewController as? TransmitterDelegate {
-                vc.transmitter(transmitter, didError: error)
-            }
-        }
-    }
-
-    func transmitter(_ transmitter: Transmitter, didRead glucose: Glucose) {
-        self.glucose = glucose
-        DispatchQueue.main.async {
-            if let vc = self.window?.rootViewController as? TransmitterDelegate {
-                vc.transmitter(transmitter, didRead: glucose)
-            }
-        }
-    }
-
-    func transmitter(_ transmitter: Transmitter, didReadUnknownData data: Data) {
-        DispatchQueue.main.async {
-            if let vc = self.window?.rootViewController as? TransmitterDelegate {
-                vc.transmitter(transmitter, didReadUnknownData: data)
-            }
-        }
-    }
-    
-    func transmitter(_ transmitter: Transmitter, didReadBackfill glucose: [Glucose]) {
-        DispatchQueue.main.async {
-            if let vc = self.window?.rootViewController as? TransmitterDelegate {
-                vc.transmitter(transmitter, didReadBackfill: glucose)
-            }
-        }
-    }
-    
-    func transmitterDidConnect(_ transmitter: Transmitter) {
-        // Ignore
-    }
-
-}

+ 0 - 98
Dependencies/CGMBLEKit/CGMBLEKit Example/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -1,98 +0,0 @@
-{
-  "images" : [
-    {
-      "idiom" : "iphone",
-      "size" : "20x20",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "20x20",
-      "scale" : "3x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "29x29",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "29x29",
-      "scale" : "3x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "40x40",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "40x40",
-      "scale" : "3x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "60x60",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "60x60",
-      "scale" : "3x"
-    },
-    {
-      "idiom" : "ipad",
-      "size" : "20x20",
-      "scale" : "1x"
-    },
-    {
-      "idiom" : "ipad",
-      "size" : "20x20",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "ipad",
-      "size" : "29x29",
-      "scale" : "1x"
-    },
-    {
-      "idiom" : "ipad",
-      "size" : "29x29",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "ipad",
-      "size" : "40x40",
-      "scale" : "1x"
-    },
-    {
-      "idiom" : "ipad",
-      "size" : "40x40",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "ipad",
-      "size" : "76x76",
-      "scale" : "1x"
-    },
-    {
-      "idiom" : "ipad",
-      "size" : "76x76",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "ipad",
-      "size" : "83.5x83.5",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "ios-marketing",
-      "size" : "1024x1024",
-      "scale" : "1x"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
-}

+ 0 - 25
Dependencies/CGMBLEKit/CGMBLEKit Example/Base.lproj/LaunchScreen.storyboard

@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" systemVersion="17A277" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
-    <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
-        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <scenes>
-        <!--View Controller-->
-        <scene sceneID="EHf-IW-A2E">
-            <objects>
-                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
-                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
-                    </view>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="53" y="375"/>
-        </scene>
-    </scenes>
-</document>

+ 0 - 172
Dependencies/CGMBLEKit/CGMBLEKit Example/Base.lproj/Main.storyboard

@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
-    <device id="retina5_5" orientation="portrait">
-        <adaptation id="fullscreen"/>
-    </device>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
-        <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <scenes>
-        <!--View Controller-->
-        <scene sceneID="tne-QT-ifu">
-            <objects>
-                <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="CGMBLEKit_Example" customModuleProvider="target" sceneMemberID="viewController">
-                    <layoutGuides>
-                        <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
-                        <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
-                    </layoutGuides>
-                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
-                        <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <subviews>
-                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="mqJ-p6-sSU">
-                                <rect key="frame" x="20" y="40" width="374" height="676"/>
-                                <subviews>
-                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="K5I-e5-MvQ">
-                                        <rect key="frame" x="15.666666666666657" y="0.0" width="343" height="52"/>
-                                        <subviews>
-                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Transmitter ID" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5y6-vU-qC3">
-                                                <rect key="frame" x="8" y="14.333333333333334" width="249" height="20.333333333333329"/>
-                                                <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
-                                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                                <nil key="highlightedColor"/>
-                                            </label>
-                                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oUg-jb-mCK">
-                                                <rect key="frame" x="265" y="42" width="70" height="1"/>
-                                                <color key="backgroundColor" red="0.33333333333333331" green="0.33333333333333331" blue="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                                <constraints>
-                                                    <constraint firstAttribute="height" constant="1" id="Rjq-qn-DaB"/>
-                                                </constraints>
-                                            </view>
-                                            <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="500000" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="e0T-ru-tWD">
-                                                <rect key="frame" x="265" y="8" width="70" height="34"/>
-                                                <constraints>
-                                                    <constraint firstAttribute="width" constant="70" id="1v1-n5-aT4"/>
-                                                    <constraint firstAttribute="height" constant="34" id="CVt-L0-Ts1"/>
-                                                </constraints>
-                                                <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
-                                                <textInputTraits key="textInputTraits" autocapitalizationType="allCharacters" autocorrectionType="no" spellCheckingType="no" keyboardType="alphabet" returnKeyType="done"/>
-                                                <connections>
-                                                    <outlet property="delegate" destination="BYZ-38-t0r" id="XHs-Ei-i6K"/>
-                                                </connections>
-                                            </textField>
-                                        </subviews>
-                                        <constraints>
-                                            <constraint firstItem="e0T-ru-tWD" firstAttribute="leading" secondItem="5y6-vU-qC3" secondAttribute="trailing" constant="8" id="1Y6-Tc-fCe"/>
-                                            <constraint firstItem="5y6-vU-qC3" firstAttribute="leading" secondItem="K5I-e5-MvQ" secondAttribute="leadingMargin" id="2up-6R-sUw"/>
-                                            <constraint firstItem="e0T-ru-tWD" firstAttribute="top" secondItem="K5I-e5-MvQ" secondAttribute="topMargin" id="9sj-7n-OeZ"/>
-                                            <constraint firstAttribute="trailingMargin" secondItem="e0T-ru-tWD" secondAttribute="trailing" id="BGc-6v-F21"/>
-                                            <constraint firstItem="5y6-vU-qC3" firstAttribute="baseline" secondItem="e0T-ru-tWD" secondAttribute="baseline" id="Ieq-vZ-reG"/>
-                                            <constraint firstItem="e0T-ru-tWD" firstAttribute="leading" secondItem="oUg-jb-mCK" secondAttribute="leading" id="PU1-pi-afh"/>
-                                            <constraint firstAttribute="bottomMargin" secondItem="e0T-ru-tWD" secondAttribute="bottom" constant="2" id="S63-7X-au0"/>
-                                            <constraint firstItem="oUg-jb-mCK" firstAttribute="width" secondItem="e0T-ru-tWD" secondAttribute="width" id="bYX-uk-kK1"/>
-                                            <constraint firstItem="oUg-jb-mCK" firstAttribute="top" secondItem="e0T-ru-tWD" secondAttribute="bottom" id="xJ6-dd-9PN"/>
-                                        </constraints>
-                                    </view>
-                                    <stackView opaque="NO" contentMode="scaleToFill" spacing="8" baselineRelativeArrangement="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4lp-eb-b4C">
-                                        <rect key="frame" x="74.333333333333329" y="129" width="225.33333333333337" height="31"/>
-                                        <subviews>
-                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Stay connected" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NSs-9e-3Sl">
-                                                <rect key="frame" x="0.0" y="0.0" width="168.33333333333334" height="31"/>
-                                                <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
-                                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                                <nil key="highlightedColor"/>
-                                            </label>
-                                            <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="DR7-3h-biq">
-                                                <rect key="frame" x="176.33333333333337" y="0.0" width="51" height="31"/>
-                                                <connections>
-                                                    <action selector="toggleStayConnected:" destination="BYZ-38-t0r" eventType="valueChanged" id="Wci-5s-BJm"/>
-                                                </connections>
-                                            </switch>
-                                        </subviews>
-                                    </stackView>
-                                    <stackView opaque="NO" contentMode="scaleToFill" spacing="8" baselineRelativeArrangement="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lPZ-HJ-Wji">
-                                        <rect key="frame" x="74.333333333333329" y="237.33333333333331" width="225.33333333333337" height="31"/>
-                                        <subviews>
-                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Run alongside G5 app" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3i8-2m-QFG">
-                                                <rect key="frame" x="0.0" y="0.0" width="168.33333333333334" height="31"/>
-                                                <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
-                                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                                <nil key="highlightedColor"/>
-                                            </label>
-                                            <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="mjL-My-zyc">
-                                                <rect key="frame" x="176.33333333333337" y="0.0" width="51" height="31"/>
-                                                <connections>
-                                                    <action selector="togglePassiveMode:" destination="BYZ-38-t0r" eventType="valueChanged" id="vGB-RZ-H3T"/>
-                                                </connections>
-                                            </switch>
-                                        </subviews>
-                                    </stackView>
-                                    <activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" animating="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="v7k-HB-Hm0">
-                                        <rect key="frame" x="177" y="345.33333333333331" width="20" height="20"/>
-                                    </activityIndicatorView>
-                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="––" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zAF-A7-1Oc">
-                                        <rect key="frame" x="173.66666666666666" y="442.33333333333331" width="27" height="31.333333333333314"/>
-                                        <fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
-                                        <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                        <nil key="highlightedColor"/>
-                                    </label>
-                                    <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" alignment="center" spacing="20" baselineRelativeArrangement="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VKn-a6-Gbj">
-                                        <rect key="frame" x="74" y="551" width="226" height="30"/>
-                                        <subviews>
-                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HEQ-Bp-kx7" userLabel="Start">
-                                                <rect key="frame" x="0.0" y="0.0" width="62" height="30"/>
-                                                <state key="normal" title="Start"/>
-                                                <connections>
-                                                    <action selector="start:" destination="BYZ-38-t0r" eventType="touchUpInside" id="CoA-cH-SFe"/>
-                                                </connections>
-                                            </button>
-                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HYW-Ex-7LC">
-                                                <rect key="frame" x="82" y="0.0" width="62" height="30"/>
-                                                <state key="normal" title="Calibrate"/>
-                                                <connections>
-                                                    <action selector="calibrate:" destination="BYZ-38-t0r" eventType="touchUpInside" id="5Ft-BY-tyB"/>
-                                                </connections>
-                                            </button>
-                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JAM-9K-KeE" userLabel="Stop">
-                                                <rect key="frame" x="164" y="0.0" width="62" height="30"/>
-                                                <state key="normal" title="Stop"/>
-                                                <connections>
-                                                    <action selector="stop:" destination="BYZ-38-t0r" eventType="touchUpInside" id="hWH-qi-m3s"/>
-                                                </connections>
-                                            </button>
-                                        </subviews>
-                                    </stackView>
-                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Waiting for first reading" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9p7-LX-EMK">
-                                        <rect key="frame" x="-20" y="658" width="0.0" height="18"/>
-                                        <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
-                                        <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                        <nil key="highlightedColor"/>
-                                    </label>
-                                </subviews>
-                                <constraints>
-                                    <constraint firstItem="NSs-9e-3Sl" firstAttribute="width" secondItem="3i8-2m-QFG" secondAttribute="width" id="drg-Lk-TNg"/>
-                                </constraints>
-                            </stackView>
-                        </subviews>
-                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                        <constraints>
-                            <constraint firstItem="mqJ-p6-sSU" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="20" id="9eQ-5E-KMl"/>
-                            <constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="mqJ-p6-sSU" secondAttribute="bottom" constant="20" id="A1x-Bz-xwd"/>
-                            <constraint firstAttribute="trailingMargin" secondItem="mqJ-p6-sSU" secondAttribute="trailing" id="DSk-No-ziO"/>
-                            <constraint firstItem="mqJ-p6-sSU" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leadingMargin" id="m2Y-0g-gsl"/>
-                        </constraints>
-                    </view>
-                    <connections>
-                        <outlet property="passiveModeEnabledSwitch" destination="mjL-My-zyc" id="GAn-9j-EwV"/>
-                        <outlet property="scanningIndicatorView" destination="v7k-HB-Hm0" id="HgS-lj-R6v"/>
-                        <outlet property="stayConnectedSwitch" destination="DR7-3h-biq" id="cN5-a1-x8J"/>
-                        <outlet property="subtitleLabel" destination="9p7-LX-EMK" id="jTI-sZ-dNb"/>
-                        <outlet property="titleLabel" destination="zAF-A7-1Oc" id="W9K-V8-bIj"/>
-                        <outlet property="transmitterIDField" destination="e0T-ru-tWD" id="MTX-44-H7O"/>
-                    </connections>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="231" y="399"/>
-        </scene>
-    </scenes>
-</document>

+ 0 - 34
Dependencies/CGMBLEKit/CGMBLEKit Example/CommandQueue.swift

@@ -1,34 +0,0 @@
-//
-//  CommandQueue.swift
-//  CGMBLEKit Example
-//
-//  Created by Paul Dickens on 25/03/2018.
-//  Copyright © 2018 LoopKit Authors. All rights reserved.
-//
-
-import Foundation
-import CGMBLEKit
-
-
-class CommandQueue {
-    private var list = Array<Command>()
-    private var lock = os_unfair_lock()
-
-    func enqueue(_ element: Command) {
-        os_unfair_lock_lock(&lock)
-        list.append(element)
-        os_unfair_lock_unlock(&lock)
-    }
-
-    func dequeue() -> Command? {
-        os_unfair_lock_lock(&lock)
-        defer {
-            os_unfair_lock_unlock(&lock)
-        }
-        if !list.isEmpty {
-            return list.removeFirst()
-        } else {
-            return nil
-        }
-    }
-}

+ 0 - 49
Dependencies/CGMBLEKit/CGMBLEKit Example/Info.plist

@@ -1,49 +0,0 @@
-<?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>CFBundleDevelopmentRegion</key>
-	<string>$(DEVELOPMENT_LANGUAGE)</string>
-	<key>CFBundleExecutable</key>
-	<string>$(EXECUTABLE_NAME)</string>
-	<key>CFBundleIdentifier</key>
-	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
-	<key>CFBundleName</key>
-	<string>$(PRODUCT_NAME)</string>
-	<key>CFBundlePackageType</key>
-	<string>APPL</string>
-	<key>CFBundleShortVersionString</key>
-	<string>3.2</string>
-	<key>CFBundleVersion</key>
-	<string>1</string>
-	<key>LSRequiresIPhoneOS</key>
-	<true/>
-	<key>UIBackgroundModes</key>
-	<array>
-		<string>bluetooth-central</string>
-	</array>
-	<key>UILaunchStoryboardName</key>
-	<string>LaunchScreen</string>
-	<key>UIMainStoryboardFile</key>
-	<string>Main</string>
-	<key>UIRequiredDeviceCapabilities</key>
-	<array>
-		<string>armv7</string>
-	</array>
-	<key>UISupportedInterfaceOrientations</key>
-	<array>
-		<string>UIInterfaceOrientationPortrait</string>
-		<string>UIInterfaceOrientationLandscapeLeft</string>
-		<string>UIInterfaceOrientationLandscapeRight</string>
-	</array>
-	<key>UISupportedInterfaceOrientations~ipad</key>
-	<array>
-		<string>UIInterfaceOrientationPortrait</string>
-		<string>UIInterfaceOrientationPortraitUpsideDown</string>
-		<string>UIInterfaceOrientationLandscapeLeft</string>
-		<string>UIInterfaceOrientationLandscapeRight</string>
-	</array>
-</dict>
-</plist>

+ 0 - 39
Dependencies/CGMBLEKit/CGMBLEKit Example/NSUserDefaults.swift

@@ -1,39 +0,0 @@
-//
-//  NSUserDefaults.swift
-//  xDripG5
-//
-//  Created by Nathan Racklyeft on 11/24/15.
-//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
-//
-
-import Foundation
-
-
-extension UserDefaults {
-    var passiveModeEnabled: Bool {
-        get {
-            return bool(forKey: "passiveModeEnabled")
-        }
-        set {
-            set(newValue, forKey: "passiveModeEnabled")
-        }
-    }
-
-    var stayConnected: Bool {
-        get {
-            return object(forKey: "stayConnected") != nil ? bool(forKey: "stayConnected") : true
-        }
-        set {
-            set(newValue, forKey: "stayConnected")
-        }
-    }
-
-    var transmitterID: String {
-        get {
-            return string(forKey: "transmitterID") ?? "500000"
-        }
-        set {
-            set(newValue, forKey: "transmitterID")
-        }
-    }
-}

+ 0 - 200
Dependencies/CGMBLEKit/CGMBLEKit Example/ViewController.swift

@@ -1,200 +0,0 @@
-//
-//  ViewController.swift
-//  xDrip5
-//
-//  Created by Nathan Racklyeft on 10/1/15.
-//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
-//
-
-import UIKit
-import HealthKit
-import CGMBLEKit
-
-class ViewController: UIViewController, TransmitterDelegate, UITextFieldDelegate {
-
-    @IBOutlet weak var titleLabel: UILabel!
-
-    @IBOutlet weak var subtitleLabel: UILabel!
-
-    @IBOutlet weak var passiveModeEnabledSwitch: UISwitch!
-
-    @IBOutlet weak var stayConnectedSwitch: UISwitch!
-
-    @IBOutlet weak var transmitterIDField: UITextField!
-
-    @IBOutlet weak var scanningIndicatorView: UIActivityIndicatorView!
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-
-        passiveModeEnabledSwitch.isOn = AppDelegate.sharedDelegate.transmitter?.passiveModeEnabled ?? false
-
-        stayConnectedSwitch.isOn = AppDelegate.sharedDelegate.transmitter?.stayConnected ?? false
-
-        transmitterIDField.text = AppDelegate.sharedDelegate.transmitter?.ID
-    }
-
-    override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-
-        updateIndicatorViewDisplay()
-    }
-
-    // MARK: - Actions
-
-    func updateIndicatorViewDisplay() {
-        if let transmitter = AppDelegate.sharedDelegate.transmitter, transmitter.isScanning {
-            scanningIndicatorView.startAnimating()
-        } else {
-            scanningIndicatorView.stopAnimating()
-        }
-    }
-
-    @IBAction func toggleStayConnected(_ sender: UISwitch) {
-        AppDelegate.sharedDelegate.transmitter?.stayConnected = sender.isOn
-        UserDefaults.standard.stayConnected = sender.isOn
-
-        updateIndicatorViewDisplay()
-    }
-
-    @IBAction func togglePassiveMode(_ sender: UISwitch) {
-        AppDelegate.sharedDelegate.transmitter?.passiveModeEnabled = sender.isOn
-        UserDefaults.standard.passiveModeEnabled = sender.isOn
-    }
-
-    @IBAction func start(_ sender: UIButton) {
-        let dialog = UIAlertController(title: "Confirm", message: "Start sensor session.", preferredStyle: .alert)
-
-        dialog.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action: UIAlertAction!) in
-            AppDelegate.sharedDelegate.commandQueue.enqueue(.startSensor(at: Date()))
-        }))
-
-        dialog.addAction(UIAlertAction(title: "Cancel", style: .cancel))
-
-        present(dialog, animated: true, completion: nil)
-    }
-
-    @IBAction func calibrate(_ sender: UIButton) {
-        let dialog = UIAlertController(title: "Enter BG", message: "Calibrate sensor.", preferredStyle: .alert)
-
-        let unit = HKUnit.milligramsPerDeciliter
-
-        dialog.addTextField { (textField : UITextField!) in
-            textField.placeholder = unit.unitString
-            textField.keyboardType = .numberPad
-        }
-
-        dialog.addAction(UIAlertAction(title: "Calibrate", style: .default, handler: { (action: UIAlertAction!) in
-            let textField = dialog.textFields![0] as UITextField
-            let minGlucose = HKQuantity(unit: HKUnit.milligramsPerDeciliter, doubleValue: 40)
-            let maxGlucose = HKQuantity(unit: HKUnit.milligramsPerDeciliter, doubleValue: 400)
-
-            if let text = textField.text, let entry = Double(text) {
-                guard entry >= minGlucose.doubleValue(for: unit) && entry <= maxGlucose.doubleValue(for: unit) else {
-                    // TODO: notify the user if the glucose is not in range
-                    return
-                }
-                let glucose = HKQuantity(unit: unit, doubleValue: Double(entry))
-                AppDelegate.sharedDelegate.commandQueue.enqueue(.calibrateSensor(to: glucose, at: Date()))
-            }
-        }))
-
-        dialog.addAction(UIAlertAction(title: "Cancel", style: .cancel))
-
-        present(dialog, animated: true, completion: nil)
-    }
-
-    @IBAction func stop(_ sender: UIButton) {
-        let dialog = UIAlertController(title: "Confirm", message: "Stop sensor session.", preferredStyle: .alert)
-
-        dialog.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action: UIAlertAction!) in
-            AppDelegate.sharedDelegate.commandQueue.enqueue(.stopSensor(at: Date()))
-        }))
-
-        dialog.addAction(UIAlertAction(title: "Cancel", style: .cancel))
-
-        present(dialog, animated: true, completion: nil)
-    }
-
-    // MARK: - UITextFieldDelegate
-
-    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
-        if let text = textField.text {
-            let newString = text.replacingCharacters(in: range.rangeOfString(text), with: string)
-
-            if newString.count > 6 {
-                return false
-            } else if newString.count == 6 {
-                AppDelegate.sharedDelegate.transmitterID = newString
-                textField.text = newString
-
-                textField.resignFirstResponder()
-
-                return false
-            }
-        }
-
-        return true
-    }
-
-    func textFieldDidEndEditing(_ textField: UITextField) {
-        if textField.text?.count != 6 {
-            textField.text = UserDefaults.standard.transmitterID
-        }
-    }
-
-    func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
-        return true
-    }
-
-    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
-        return true
-    }
-
-    // MARK: - TransmitterDelegate
-
-    func transmitter(_ transmitter: Transmitter, didError error: Error) {
-        print("Transmitter Error: \(error)")
-        titleLabel.text = NSLocalizedString("Error", comment: "Title displayed during error response")
-
-        subtitleLabel.text = "\(error)"
-    }
-
-    func transmitter(_ transmitter: Transmitter, didRead glucose: Glucose) {
-        let unit = HKUnit.milligramsPerDeciliter
-        if let value = glucose.glucose?.doubleValue(for: unit) {
-            titleLabel.text = "\(value) \(unit.unitString)"
-        } else {
-            titleLabel.text = String(describing: glucose.state)
-        }
-
-
-        let date = glucose.readDate
-        subtitleLabel.text = DateFormatter.localizedString(from: date, dateStyle: .none, timeStyle: .long)
-    }
-
-    func transmitter(_ transmitter: Transmitter, didReadUnknownData data: Data) {
-        titleLabel.text = NSLocalizedString("Unknown Data", comment: "Title displayed during unknown data response")
-        subtitleLabel.text = data.hexadecimalString
-    }
-    
-    func transmitter(_ transmitter: Transmitter, didReadBackfill glucose: [Glucose]) {
-        titleLabel.text = NSLocalizedString("Backfill", comment: "Title displayed during backfill response")
-        subtitleLabel.text = String(describing: glucose.map { $0.glucose })
-    }
-    
-    func transmitterDidConnect(_ transmitter: Transmitter) {
-        // Ignore
-    }
-
-}
-
-
-private extension NSRange {
-    func rangeOfString(_ string: String) -> Range<String.Index> {
-        let startIndex = string.index(string.startIndex, offsetBy: location)
-        let endIndex = string.index(startIndex, offsetBy: length)
-        return startIndex..<endIndex
-    }
-}
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/da.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "Eksempel på CGMBLEKit";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/da.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Backfill";
-
-/* Title displayed during error response */
-"Error" = "Fejl";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Ukendte data";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/da.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Kør sammen med G5-appen";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "Sender ID";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Venter på første aflæsning";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Start";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Kalibrer";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Stop";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Forbliv forbundet";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/de.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "CGMBLEKit Beispiel";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/de.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Auffüllen";
-
-/* Title displayed during error response */
-"Error" = "Fehler";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Unbekannte Daten";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/de.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Neben G5-App ausführen";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "Transmitter-ID";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Warte auf den ersten Wert";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Start";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Kalibrieren";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Stop";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Verbunden bleiben";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 8
Dependencies/CGMBLEKit/CGMBLEKit Example/en.lproj/Localizable.strings

@@ -1,8 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Backfill";
-
-/* Title displayed during error response */
-"Error" = "Error";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Unknown Data";

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/en.lproj/Main.strings

@@ -1,27 +0,0 @@
-
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Run alongside G5 app";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "Transmitter ID";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Waiting for first reading";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Start";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Calibrate";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Stop";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Stay connected";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/es.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "Ejemplo de CGMBLEKit";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/es.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Rellenar";
-
-/* Title displayed during error response */
-"Error" = "Error";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Datos desconocidos";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/es.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Ejecutar junto con la aplicación del G5";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "Identificación del transmisor";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Esperando el primero dato";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Comenzar";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Calibrar";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Parar";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Mantenerse conectado";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/fi.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "CGMBLEKit esimerkki";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/fi.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Täyttö";
-
-/* Title displayed during error response */
-"Error" = "Virhe";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Tuntematon tieto";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/fi.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Käytä G5-sovelluksen rinnalla";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "Lähettimen tunniste";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Odotetaan ensimmäistä lukemaa";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Aloita";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Kalibroi";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Pysäytä";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Pidä yhdistettynä";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/fr.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "Exemple CGMBLEKit";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/fr.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Récupération des données antérieures";
-
-/* Title displayed during error response */
-"Error" = "Erreur";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Donnée inconnue";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/fr.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Exécuter en même temps que l'application G5";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "ID du transmetteur";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "En attente de la première mesure";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Commencer";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Étalonner";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Arrêter";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Rester connecté";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 1
Dependencies/CGMBLEKit/CGMBLEKit Example/he.lproj/LaunchScreen.strings

@@ -1 +0,0 @@
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/he.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Backfill";
-
-/* Title displayed during error response */
-"Error" = "Error";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Unknown Data";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/he.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Run alongside G5 app";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "Transmitter ID";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Waiting for first reading";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Start";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Calibrate";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Stop";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Stay connected";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/it.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "esempio CGMBLE kit";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/it.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Riempimento";
-
-/* Title displayed during error response */
-"Error" = "Errore";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Unknown Data";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/it.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Esegui insieme all’app G5";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "ID trasmettitore";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "In attesa della prima lettura";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Avvia";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Calibra";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Interrompi";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Rimani connesso";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/ja.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "埋め戻し";
-
-/* Title displayed during error response */
-"Error" = "エラー";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "不明なデータ";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/ja.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "G5アプリのそばで使用してください";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "トランスミッタ ID";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "最初の読み取りを待っています";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "開始";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "較正";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "停止";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "接続を維持";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/nb.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "CGMBLEKit Eksempel";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/nb.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Hent historikk";
-
-/* Title displayed during error response */
-"Error" = "Feil";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Ukjent data";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/nb.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Kjør parallelt med G5 app";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "Sender ID";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Venter på første måling";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Start";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Kalibrer";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Stop";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Vær tilkoblet";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/nl.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "CGMBLEKit Voorbeeld";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/nl.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Aanvullen";
-
-/* Title displayed during error response */
-"Error" = "Fout";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Onbekende Gegevens";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/nl.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Gebruik tegelijk met G5 app";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "Zenderserienummer";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Wachten op eerste meting";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Start";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Kalibreren";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Stop";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Blijf verbonden";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/pl.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "CGMBLEKit Example";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/pl.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Backfill";
-
-/* Title displayed during error response */
-"Error" = "Błąd";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Unknown Data";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/pl.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Uruchom aplikację G5";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "ID nadajnika";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Czekam na pierwszy odczyt";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Start";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Kalibruj";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Stop";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Nie rozłączaj się";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/pt-BR.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Preenchimento";
-
-/* Title displayed during error response */
-"Error" = "Erro";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Dados Desconhecidos";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/pt-BR.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Executa em paralelo com o aplicativo G5";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "ID do Transmissor";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Esperando a primeira leitura";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Iniciar";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Calibrar";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Parar";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Permanecer conectado";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/ro.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "Exemplu CGMBLEKit";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/ro.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Completare retroactivă";
-
-/* Title displayed during error response */
-"Error" = "Eroare";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Date necunoscute";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/ro.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Rulează împreună cu aplicația G5";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "ID transmițător";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Se așteaptă prima citire";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Pornește";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Calibrează";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Stop";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Păstrează conexiunea";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/ru.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "Пример CGMBLEKit";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/ru.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Заполнение данными";
-
-/* Title displayed during error response */
-"Error" = "Ошибка";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Неизвестные данные";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/ru.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Запустить совместно с приложением G5";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "ID трансмиттера";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Ожидание первого показания";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Начать";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Калибровка";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Стоп";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Оставайтесь подключенными";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/sk.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "Príklad CGMBLEKit";
-

+ 0 - 6
Dependencies/CGMBLEKit/CGMBLEKit Example/sk.lproj/Localizable.strings

@@ -1,6 +0,0 @@
-/* Title displayed during error response */
-"Error" = "Chyba";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Neznáme dáta";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/sk.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Beží spolu s aplikáciou G5";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "ID vysielača";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Čaká sa na prvé načítanie";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Štart";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Kalibrovať";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Stop";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Zostať pripojený";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/sv.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "CGMBLEKit Example";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/sv.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Fyller i historisk data";
-
-/* Title displayed during error response */
-"Error" = "Fel";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Okänd data";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/sv.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Kör samtidigt som G5-appen";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "Sändari-ID";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Väntar på första värdet";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Starta";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Kalibrera";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Stoppa";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Fortsätt att vara ansluten";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 3
Dependencies/CGMBLEKit/CGMBLEKit Example/tr.lproj/InfoPlist.strings

@@ -1,3 +0,0 @@
-/* Bundle name */
-"CFBundleName" = "CGMBLEKit Örneği";
-

+ 0 - 1
Dependencies/CGMBLEKit/CGMBLEKit Example/tr.lproj/LaunchScreen.strings

@@ -1 +0,0 @@
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/tr.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Dolgu";
-
-/* Title displayed during error response */
-"Error" = "Hata";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Bilinmeyen Veri";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/tr.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "G5 uygulamasıyla birlikte çalıştırın";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "Verici Kimliği";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "İlk okuma bekleniyor..";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Başlat";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Kalibrasyon";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Durdur";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Bağlı kalın";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/vi.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "Lấp đầy";
-
-/* Title displayed during error response */
-"Error" = "Lỗi";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "Không nhận biết dữ liệu";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/vi.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "Chạy song song cùng ứng dụng G5";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "Số ID của Transmitter";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "Đang đợi đọc kết quả đầu tiên";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "Bắt đầu";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "Hiệu chỉnh";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "Dừng lại";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "Giữ kết  nối";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

+ 0 - 9
Dependencies/CGMBLEKit/CGMBLEKit Example/zh-Hans.lproj/Localizable.strings

@@ -1,9 +0,0 @@
-/* Title displayed during backfill response */
-"Backfill" = "数据回填";
-
-/* Title displayed during error response */
-"Error" = "错误";
-
-/* Title displayed during unknown data response */
-"Unknown Data" = "未知数据";
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit Example/zh-Hans.lproj/Main.strings

@@ -1,27 +0,0 @@
-/* Class = "UILabel"; text = "Run alongside G5 app"; ObjectID = "3i8-2m-QFG"; */
-"3i8-2m-QFG.text" = "与G5 App同时使用";
-
-/* Class = "UILabel"; text = "Transmitter ID"; ObjectID = "5y6-vU-qC3"; */
-"5y6-vU-qC3.text" = "发射器编号";
-
-/* Class = "UILabel"; text = "Waiting for first reading"; ObjectID = "9p7-LX-EMK"; */
-"9p7-LX-EMK.text" = "输入第一个校准值";
-
-/* Class = "UITextField"; text = "500000"; ObjectID = "e0T-ru-tWD"; */
-"e0T-ru-tWD.text" = "500000";
-
-/* Class = "UIButton"; normalTitle = "Start"; ObjectID = "HEQ-Bp-kx7"; */
-"HEQ-Bp-kx7.normalTitle" = "启动";
-
-/* Class = "UIButton"; normalTitle = "Calibrate"; ObjectID = "HYW-Ex-7LC"; */
-"HYW-Ex-7LC.normalTitle" = "校准";
-
-/* Class = "UIButton"; normalTitle = "Stop"; ObjectID = "JAM-9K-KeE"; */
-"JAM-9K-KeE.normalTitle" = "停止";
-
-/* Class = "UILabel"; text = "Stay connected"; ObjectID = "NSs-9e-3Sl"; */
-"NSs-9e-3Sl.text" = "保持连接";
-
-/* Class = "UILabel"; text = "––"; ObjectID = "zAF-A7-1Oc"; */
-"zAF-A7-1Oc.text" = "––";
-

File diff ditekan karena terlalu besar
+ 0 - 2493
Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.pbxproj


+ 0 - 7
Dependencies/CGMBLEKit/CGMBLEKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Workspace
-   version = "1.0">
-   <FileRef
-      location = "self:">
-   </FileRef>
-</Workspace>

+ 0 - 19
Dependencies/CGMBLEKit/CGMBLEKit/AESCrypt.h

@@ -1,19 +0,0 @@
-//
-//  AESCrypt.h
-//  xDripG5
-//
-//  Created by Nate Racklyeft on 6/17/16.
-//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-@interface AESCrypt : NSObject
-
-NS_ASSUME_NONNULL_BEGIN
-
-+ (nullable NSData *)encryptData:(NSData *)data usingKey:(NSData *)key error:(NSError **)error;
-
-NS_ASSUME_NONNULL_END
-
-@end

+ 0 - 33
Dependencies/CGMBLEKit/CGMBLEKit/AESCrypt.m

@@ -1,33 +0,0 @@
-//
-//  AESCrypt.m
-//  xDripG5
-//
-//  Created by Nate Racklyeft on 6/17/16.
-//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
-//
-
-#import "AESCrypt.h"
-#import <CommonCrypto/CommonCryptor.h>
-
-@implementation AESCrypt
-
-+ (NSData *)encryptData:(NSData *)data usingKey:(NSData *)key error:(NSError * _Nullable __autoreleasing *)error
-{
-    NSMutableData *dataOut = [NSMutableData dataWithLength: data.length + kCCBlockSizeAES128];
-
-    CCCryptorStatus status = CCCrypt(kCCEncrypt,
-                                     kCCAlgorithmAES,
-                                     kCCOptionECBMode,
-                                     key.bytes,
-                                     key.length,
-                                     NULL,
-                                     data.bytes,
-                                     data.length,
-                                     dataOut.mutableBytes,
-                                     dataOut.length,
-                                     NULL);
-
-    return status == kCCSuccess ? dataOut : nil;
-}
-
-@end

+ 0 - 41
Dependencies/CGMBLEKit/CGMBLEKit/Base.lproj/Localizable.strings

@@ -1,41 +0,0 @@
-/* CGM display title */
-"Dexcom G5" = "Dexcom G5";
-
-/* CGM display title */
-"Dexcom G6" = "Dexcom G6";
-
-/* Error description for unreliable state */
-"Glucose data is unavailable" = "Glucose data is unavailable";
-
-/* Describes a low battery */
-"Low Battery" = "Low Battery";
-
-/* Describes a functioning transmitter */
-"OK" = "OK";
-
-/* invlid config error description */
-"Peripheral command was invalid" = "Peripheral command was invalid";
-
-/* Timeout error description */
-"Peripheral did not respond in time" = "Peripheral did not respond in time";
-
-/* Not ready error description */
-"Peripheral isnʼt connected" = "Peripheral isnʼt connected";
-
-/* The description of sensor calibration state when sensor calibration is ok. */
-"Sensor calibration is OK" = "Sensor calibration is OK";
-
-/* The description of sensor calibration state when raw value is unknown. (1: missing data details) */
-"Sensor is in unknown state %1$d" = "Sensor is in unknown state %1$d";
-
-/* The description of sensor calibration state when sensor sensor is stopped. */
-"Sensor is stopped" = "Sensor is stopped";
-
-/* The description of sensor calibration state when sensor sensor is warming up. */
-"Sensor is warming up" = "Sensor is warming up";
-
-/* The description of sensor calibration state when sensor needs calibration. */
-"Sensor needs calibration" = "Sensor needs calibration";
-
-/* Error description */
-"Unknown characteristic" = "Unknown characteristic";

+ 0 - 350
Dependencies/CGMBLEKit/CGMBLEKit/BluetoothManager.swift

@@ -1,350 +0,0 @@
-//
-//  BluetoothManager.swift
-//  xDripG5
-//
-//  Created by Nathan Racklyeft on 10/1/15.
-//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
-//
-
-import CoreBluetooth
-import Foundation
-import os.log
-
-
-protocol BluetoothManagerDelegate: AnyObject {
-
-    /**
-     Tells the delegate that the bluetooth manager has finished connecting to and discovering all required services of its peripheral, or that it failed to do so
-
-     - parameter manager: The bluetooth manager
-     - parameter peripheralManager: The peripheral manager
-     - parameter error:   An error describing why bluetooth setup failed
-     */
-    func bluetoothManager(_ manager: BluetoothManager, peripheralManager: PeripheralManager, isReadyWithError error: Error?)
-
-    /**
-     Asks the delegate whether the discovered or restored peripheral should be connected
-
-     - parameter manager:    The bluetooth manager
-     - parameter peripheral: The found peripheral
-
-     - returns: True if the peripheral should connect
-     */
-    func bluetoothManager(_ manager: BluetoothManager, shouldConnectPeripheral peripheral: CBPeripheral) -> Bool
-
-    /// Informs the delegate that the bluetooth manager received new data in the control characteristic
-    ///
-    /// - Parameters:
-    ///   - manager: The bluetooth manager
-    ///   - peripheralManager: The peripheral manager
-    ///   - response: The data received on the control characteristic
-    func bluetoothManager(_ manager: BluetoothManager, peripheralManager: PeripheralManager, didReceiveControlResponse response: Data)
-
-    /// Informs the delegate that the bluetooth manager received new data in the backfill characteristic
-    ///
-    /// - Parameters:
-    ///   - manager: The bluetooth manager
-    ///   - response: The data received on the backfill characteristic
-    func bluetoothManager(_ manager: BluetoothManager, didReceiveBackfillResponse response: Data)
-
-    /// Informs the delegate that the bluetooth manager received new data in the authentication characteristic
-    ///
-    /// - Parameters:
-    ///   - manager: The bluetooth manager
-    ///   - peripheralManager: The peripheral manager
-    ///   - response: The data received on the authentication characteristic
-    func bluetoothManager(_ manager: BluetoothManager, peripheralManager: PeripheralManager, didReceiveAuthenticationResponse response: Data)
-}
-
-
-class BluetoothManager: NSObject {
-
-    var stayConnected: Bool {
-        get {
-            return lockedStayConnected.value
-        }
-        set {
-            lockedStayConnected.value = newValue
-        }
-    }
-    private let lockedStayConnected: Locked<Bool> = Locked(true)
-
-    weak var delegate: BluetoothManagerDelegate?
-
-    private let log = OSLog(category: "BluetoothManager")
-
-    /// Isolated to `managerQueue`
-    private var manager: CBCentralManager! = nil
-
-    /// Isolated to `managerQueue`
-    private var peripheral: CBPeripheral? {
-        get {
-            return peripheralManager?.peripheral
-        }
-        set {
-            guard let peripheral = newValue else {
-                peripheralManager = nil
-                return
-            }
-
-            if let peripheralManager = peripheralManager {
-                peripheralManager.peripheral = peripheral
-            } else {
-                peripheralManager = PeripheralManager(
-                    peripheral: peripheral,
-                    configuration: .dexcomG5,
-                    centralManager: manager
-                )
-            }
-        }
-    }
-
-    var peripheralIdentifier: UUID? {
-        get {
-            return lockedPeripheralIdentifier.value
-        }
-        set {
-            lockedPeripheralIdentifier.value = newValue
-        }
-    }
-    private let lockedPeripheralIdentifier: Locked<UUID?> = Locked(nil)
-
-    /// Isolated to `managerQueue`
-    private var peripheralManager: PeripheralManager? {
-        didSet {
-            oldValue?.delegate = nil
-            peripheralManager?.delegate = self
-
-            peripheralIdentifier = peripheralManager?.peripheral.identifier
-        }
-    }
-
-    // MARK: - Synchronization
-
-    private let managerQueue = DispatchQueue(label: "com.loudnate.CGMBLEKit.bluetoothManagerQueue", qos: .unspecified)
-
-    override init() {
-        super.init()
-
-        managerQueue.sync {
-            self.manager = CBCentralManager(delegate: self, queue: managerQueue, options: [CBCentralManagerOptionRestoreIdentifierKey: "com.loudnate.CGMBLEKit"])
-        }
-    }
-
-    // MARK: - Actions
-
-    func scanForPeripheral() {
-        dispatchPrecondition(condition: .notOnQueue(managerQueue))
-
-        managerQueue.sync {
-            self.managerQueue_scanForPeripheral()
-        }
-    }
-
-    func disconnect() {
-        dispatchPrecondition(condition: .notOnQueue(managerQueue))
-
-        managerQueue.sync {
-            if manager.isScanning {
-                manager.stopScan()
-            }
-
-            if let peripheral = peripheral {
-                manager.cancelPeripheralConnection(peripheral)
-            }
-        }
-    }
-
-    private func managerQueue_scanForPeripheral() {
-        dispatchPrecondition(condition: .onQueue(managerQueue))
-
-        guard manager.state == .poweredOn else {
-            return
-        }
-
-        let currentState = peripheral?.state ?? .disconnected
-        guard currentState != .connected else {
-            return
-        }
-
-        if let peripheralID = peripheralIdentifier, let peripheral = manager.retrievePeripherals(withIdentifiers: [peripheralID]).first {
-            log.debug("Re-connecting to known peripheral %{public}@", peripheral.identifier.uuidString)
-            self.peripheral = peripheral
-            self.manager.connect(peripheral)
-        } else if let peripheral = manager.retrieveConnectedPeripherals(withServices: [
-                TransmitterServiceUUID.advertisement.cbUUID,
-                TransmitterServiceUUID.cgmService.cbUUID
-            ]).first,
-            delegate == nil || delegate!.bluetoothManager(self, shouldConnectPeripheral: peripheral)
-        {
-            log.debug("Found system-connected peripheral: %{public}@", peripheral.identifier.uuidString)
-            self.peripheral = peripheral
-            self.manager.connect(peripheral)
-        } else {
-            log.debug("Scanning for peripherals")
-            manager.scanForPeripherals(withServices: [
-                    TransmitterServiceUUID.advertisement.cbUUID
-                ],
-                options: nil
-            )
-        }
-    }
-
-    /**
-    
-     Persistent connections don't seem to work with the transmitter shutoff: The OS won't re-wake the
-     app unless it's scanning.
-     
-     The sleep gives the transmitter time to shut down, but keeps the app running.
-
-     */
-    fileprivate func scanAfterDelay() {
-        DispatchQueue.global(qos: .utility).async {
-            Thread.sleep(forTimeInterval: 2)
-
-            self.scanForPeripheral()
-        }
-    }
-
-    // MARK: - Accessors
-
-    var isScanning: Bool {
-        dispatchPrecondition(condition: .notOnQueue(managerQueue))
-
-        var isScanning = false
-        managerQueue.sync {
-            isScanning = manager.isScanning
-        }
-        return isScanning
-    }
-
-    override var debugDescription: String {
-        return [
-            "## BluetoothManager",
-            peripheralManager.map(String.init(reflecting:)) ?? "No peripheral",
-        ].joined(separator: "\n")
-    }
-}
-
-
-extension BluetoothManager: CBCentralManagerDelegate {
-    func centralManagerDidUpdateState(_ central: CBCentralManager) {
-        dispatchPrecondition(condition: .onQueue(managerQueue))
-
-        peripheralManager?.centralManagerDidUpdateState(central)
-        log.default("%{public}@: %{public}@", #function, String(describing: central.state.rawValue))
-
-        switch central.state {
-        case .poweredOn:
-            managerQueue_scanForPeripheral()
-        case .resetting, .poweredOff, .unauthorized, .unknown, .unsupported:
-            fallthrough
-        @unknown default:
-            if central.isScanning {
-                central.stopScan()
-            }
-        }
-    }
-
-    func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {
-        dispatchPrecondition(condition: .onQueue(managerQueue))
-
-        if let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral] {
-            for peripheral in peripherals {
-                if delegate == nil || delegate!.bluetoothManager(self, shouldConnectPeripheral: peripheral) {
-                    log.default("Restoring peripheral from state: %{public}@", peripheral.identifier.uuidString)
-                    self.peripheral = peripheral
-                }
-            }
-        }
-    }
-
-    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
-        dispatchPrecondition(condition: .onQueue(managerQueue))
-
-        log.info("%{public}@: %{public}@", #function, peripheral)
-        if delegate == nil || delegate!.bluetoothManager(self, shouldConnectPeripheral: peripheral) {
-            self.peripheral = peripheral
-
-            central.connect(peripheral, options: nil)
-
-            central.stopScan()
-        }
-    }
-
-    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
-        dispatchPrecondition(condition: .onQueue(managerQueue))
-
-        log.default("%{public}@: %{public}@", #function, peripheral)
-        if central.isScanning {
-            central.stopScan()
-        }
-
-        peripheralManager?.centralManager(central, didConnect: peripheral)
-
-        if case .poweredOn = manager.state, case .connected = peripheral.state, let peripheralManager = peripheralManager {
-            self.delegate?.bluetoothManager(self, peripheralManager: peripheralManager, isReadyWithError: nil)
-        }
-    }
-
-    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
-        dispatchPrecondition(condition: .onQueue(managerQueue))
-        log.default("%{public}@: %{public}@", #function, peripheral)
-        // Ignore errors indicating the peripheral disconnected remotely, as that's expected behavior
-        if let error = error as NSError?, CBError(_nsError: error).code != .peripheralDisconnected {
-            log.error("%{public}@: %{public}@", #function, error)
-            if let peripheralManager = peripheralManager {
-                self.delegate?.bluetoothManager(self, peripheralManager: peripheralManager, isReadyWithError: error)
-            }
-        }
-
-        if stayConnected {
-            scanAfterDelay()
-        }
-    }
-
-    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
-        dispatchPrecondition(condition: .onQueue(managerQueue))
-
-        log.error("%{public}@: %{public}@", #function, String(describing: error))
-        if let error = error, let peripheralManager = peripheralManager {
-            self.delegate?.bluetoothManager(self, peripheralManager: peripheralManager, isReadyWithError: error)
-        }
-
-        if stayConnected {
-            scanAfterDelay()
-        }
-    }
-}
-
-
-extension BluetoothManager: PeripheralManagerDelegate {
-    func peripheralManager(_ manager: PeripheralManager, didReadRSSI RSSI: NSNumber, error: Error?) {
-        
-    }
-
-    func peripheralManagerDidUpdateName(_ manager: PeripheralManager) {
-
-    }
-
-    func completeConfiguration(for manager: PeripheralManager) throws {
-
-    }
-
-    func peripheralManager(_ manager: PeripheralManager, didUpdateValueFor characteristic: CBCharacteristic) {
-        guard let value = characteristic.value else {
-            return
-        }
-
-        switch CGMServiceCharacteristicUUID(rawValue: characteristic.uuid.uuidString.uppercased()) {
-        case .none, .communication?:
-            return
-        case .control?:
-            self.delegate?.bluetoothManager(self, peripheralManager: manager, didReceiveControlResponse: value)
-        case .backfill?:
-            self.delegate?.bluetoothManager(self, didReceiveBackfillResponse: value)
-        case .authentication?:
-            self.delegate?.bluetoothManager(self, peripheralManager: manager, didReceiveAuthenticationResponse: value)
-        }
-    }
-}

+ 0 - 87
Dependencies/CGMBLEKit/CGMBLEKit/BluetoothServices.swift

@@ -1,87 +0,0 @@
-//
-//  BluetoothServices.swift
-//  xDripG5
-//
-//  Created by Nathan Racklyeft on 10/16/15.
-//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
-//
-
-import CoreBluetooth
-
-/*
-G5 BLE attributes, retrieved using LightBlue on 2015-10-01
-
-These are the G4 details, for reference:
-https://github.com/StephenBlackWasAlreadyTaken/xDrip/blob/af20e32652d19aa40becc1a39f6276cad187fdce/app/src/main/java/com/eveningoutpost/dexdrip/UtilityModels/DexShareAttributes.java
-*/
-
-protocol CBUUIDRawValue: RawRepresentable {}
-extension CBUUIDRawValue where RawValue == String {
-    var cbUUID: CBUUID {
-        return CBUUID(string: rawValue)
-    }
-}
-
-
-enum TransmitterServiceUUID: String, CBUUIDRawValue {
-    case deviceInfo = "180A"
-    case advertisement = "FEBC"
-    case cgmService = "F8083532-849E-531C-C594-30F1F86A4EA5"
-
-    case serviceB = "F8084532-849E-531C-C594-30F1F86A4EA5"
-}
-
-
-enum DeviceInfoCharacteristicUUID: String, CBUUIDRawValue {
-    // Read
-    // "DexcomUN"
-    case manufacturerNameString = "2A29"
-}
-
-
-enum CGMServiceCharacteristicUUID: String, CBUUIDRawValue {
-
-    // Read/Notify
-    case communication = "F8083533-849E-531C-C594-30F1F86A4EA5"
-
-    // Write/Indicate
-    case control = "F8083534-849E-531C-C594-30F1F86A4EA5"
-
-    // Write/Indicate
-    case authentication = "F8083535-849E-531C-C594-30F1F86A4EA5"
-
-    // Read/Write/Notify
-    case backfill = "F8083536-849E-531C-C594-30F1F86A4EA5"
-
-//    // Unknown attribute present on older G6 transmitters
-//    case unknown1 = "F8083537-849E-531C-C594-30F1F86A4EA5"
-//
-//    // Updated G6 characteristic (read/notify)
-//    case unknown2 = "F8083538-849E-531C-C594-30F1F86A4EA5"
-}
-
-
-enum ServiceBCharacteristicUUID: String, CBUUIDRawValue {
-    // Write/Indicate
-    case characteristicE = "F8084533-849E-531C-C594-30F1F86A4EA5"
-    // Read/Write/Notify
-    case characteristicF = "F8084534-849E-531C-C594-30F1F86A4EA5"
-}
-
-
-extension PeripheralManager.Configuration {
-    static var dexcomG5: PeripheralManager.Configuration {
-        return PeripheralManager.Configuration(
-            serviceCharacteristics: [
-                TransmitterServiceUUID.cgmService.cbUUID: [
-                    CGMServiceCharacteristicUUID.communication.cbUUID,
-                    CGMServiceCharacteristicUUID.authentication.cbUUID,
-                    CGMServiceCharacteristicUUID.control.cbUUID,
-                    CGMServiceCharacteristicUUID.backfill.cbUUID,
-                ]
-            ],
-            notifyingCharacteristics: [:],
-            valueUpdateMacros: [:]
-        )
-    }
-}

+ 0 - 45
Dependencies/CGMBLEKit/CGMBLEKit/CBPeripheral.swift

@@ -1,45 +0,0 @@
-//
-//  CBPeripheral.swift
-//  xDripG5
-//
-//  Copyright © 2017 LoopKit Authors. All rights reserved.
-//
-
-import CoreBluetooth
-
-
-// MARK: - Discovery helpers.
-extension CBPeripheral {
-    func servicesToDiscover(from serviceUUIDs: [CBUUID]) -> [CBUUID] {
-        let knownServiceUUIDs = services?.compactMap({ $0.uuid }) ?? []
-        return serviceUUIDs.filter({ !knownServiceUUIDs.contains($0) })
-    }
-
-    func characteristicsToDiscover(from characteristicUUIDs: [CBUUID], for service: CBService) -> [CBUUID] {
-        let knownCharacteristicUUIDs = service.characteristics?.compactMap({ $0.uuid }) ?? []
-        return characteristicUUIDs.filter({ !knownCharacteristicUUIDs.contains($0) })
-    }
-}
-
-
-extension Collection where Element: CBAttribute {
-    func itemWithUUID(_ uuid: CBUUID) -> Element? {
-        for attribute in self {
-            if attribute.uuid == uuid {
-                return attribute
-            }
-        }
-
-        return nil
-    }
-
-    func itemWithUUIDString(_ uuidString: String) -> Element? {
-        for attribute in self {
-            if attribute.uuid.uuidString == uuidString {
-                return attribute
-            }
-        }
-
-        return nil
-    }
-}

+ 0 - 17
Dependencies/CGMBLEKit/CGMBLEKit/CGMBLEKit.h

@@ -1,17 +0,0 @@
-//
-//  CGMBLEKit.h
-//  xDripG5
-//
-//  Created by Nathan Racklyeft on 12/30/15.
-//  Copyright © 2015 Nathan Racklyeft. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-#import <CGMBLEKit/AESCrypt.h>
-
-//! Project version number for CGMBLEKIt.
-FOUNDATION_EXPORT double CGMBLEKitVersionNumber;
-
-//! Project version string for CGMBLEKit.
-FOUNDATION_EXPORT const unsigned char CGMBLEKitVersionString[];
-

+ 0 - 27
Dependencies/CGMBLEKit/CGMBLEKit/Calibration.swift

@@ -1,27 +0,0 @@
-//
-//  Calibration.swift
-//  xDripG5
-//
-//  Created by Paul Dickens on 17/03/2018.
-//  Copyright © 2018 LoopKit Authors. All rights reserved.
-//
-
-import Foundation
-import HealthKit
-
-
-public struct Calibration {
-    init?(calibrationMessage: CalibrationDataRxMessage, activationDate: Date) {
-        guard calibrationMessage.glucose > 0 else {
-            return nil
-        }
-
-        let unit = HKUnit.milligramsPerDeciliter
-
-        glucose = HKQuantity(unit: unit, doubleValue: Double(calibrationMessage.glucose))
-        date = activationDate.addingTimeInterval(TimeInterval(calibrationMessage.timestamp))
-    }
-
-    public let glucose: HKQuantity
-    public let date: Date
-}

+ 0 - 106
Dependencies/CGMBLEKit/CGMBLEKit/CalibrationState.swift

@@ -1,106 +0,0 @@
-//
-//  CalibrationState.swift
-//  xDripG5
-//
-//  Created by Nate Racklyeft on 8/6/16.
-//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
-//
-
-import Foundation
-
-
-public enum CalibrationState: RawRepresentable {
-    public typealias RawValue = UInt8
-
-    public enum State: RawValue {
-        case stopped = 1
-        case warmup = 2
-
-        case needFirstInitialCalibration = 4
-        case needSecondInitialCalibration = 5
-        case ok = 6
-        case needCalibration7 = 7
-        case calibrationError8 = 8
-        case calibrationError9 = 9
-        case calibrationError10 = 10
-        case sensorFailure11 = 11
-        case sensorFailure12 = 12
-        case calibrationError13 = 13
-        case needCalibration14 = 14
-        case sessionFailure15 = 15
-        case sessionFailure16 = 16
-        case sessionFailure17 = 17
-        case questionMarks = 18
-    }
-
-    case known(State)
-    case unknown(RawValue)
-
-    public init(rawValue: RawValue) {
-        guard let state = State(rawValue: rawValue) else {
-            self = .unknown(rawValue)
-            return
-        }
-
-        self = .known(state)
-    }
-
-    public var rawValue: RawValue {
-        switch self {
-        case .known(let state):
-            return state.rawValue
-        case .unknown(let rawValue):
-            return rawValue
-        }
-    }
-
-    public var hasReliableGlucose: Bool {
-        guard case .known(let state) = self else {
-            return false
-        }
-
-        switch state {
-        case .stopped,
-             .warmup,
-             .needFirstInitialCalibration,
-             .needSecondInitialCalibration,
-             .calibrationError8,
-             .calibrationError9,
-             .calibrationError10,
-             .sensorFailure11,
-             .sensorFailure12,
-             .calibrationError13,
-             .sessionFailure15,
-             .sessionFailure16,
-             .sessionFailure17,
-             .questionMarks:
-            return false
-        case .ok, .needCalibration7, .needCalibration14:
-            return true
-        }
-    }
-}
-
-extension CalibrationState: Equatable {
-    public static func ==(lhs: CalibrationState, rhs: CalibrationState) -> Bool {
-        switch (lhs, rhs) {
-        case (.known(let lhs), .known(let rhs)):
-            return lhs == rhs
-        case (.unknown(let lhs), .unknown(let rhs)):
-            return lhs == rhs
-        default:
-            return false
-        }
-    }
-}
-
-extension CalibrationState: CustomStringConvertible {
-    public var description: String {
-        switch self {
-        case .known(let state):
-            return String(describing: state)
-        case .unknown(let value):
-            return ".unknown(\(value))"
-        }
-    }
-}

+ 0 - 79
Dependencies/CGMBLEKit/CGMBLEKit/Command.swift

@@ -1,79 +0,0 @@
-//
-//  Command.swift
-//  xDripG5
-//
-//  Created by Paul Dickens on 22/03/2018.
-//  Copyright © 2018 LoopKit Authors. All rights reserved.
-//
-
-import Foundation
-import HealthKit
-
-
-public enum Command: RawRepresentable {
-    public typealias RawValue = [String: Any]
-
-    case startSensor(at: Date)
-    case stopSensor(at: Date)
-    case calibrateSensor(to: HKQuantity, at: Date)
-    case resetTransmitter
-
-    public init?(rawValue: RawValue) {
-        guard let action = rawValue["action"] as? Action.RawValue else {
-            return nil
-        }
-
-        let date = rawValue["date"] as? Date
-
-        switch Action(rawValue: action) {
-        case .startSensor?:
-            guard let date = date else {
-                return nil
-            }
-            self = .startSensor(at: date)
-        case .stopSensor?:
-            guard let date = date else {
-                return nil
-            }
-            self = .stopSensor(at: date)
-        case .calibrateSensor?:
-            guard let date = date, let glucose = rawValue["glucose"] as? HKQuantity else {
-                return nil
-            }
-            self = .calibrateSensor(to: glucose, at: date)
-        case .resetTransmitter?:
-            self = .resetTransmitter
-        case .none:
-            return nil
-        }
-    }
-
-    private enum Action: Int {
-        case startSensor, stopSensor, calibrateSensor, resetTransmitter
-    }
-
-    public var rawValue: RawValue {
-        switch self {
-        case .startSensor(let date):
-            return [
-                "action": Action.startSensor.rawValue,
-                "date": date
-            ]
-        case .stopSensor(let date):
-            return [
-                "action": Action.stopSensor.rawValue,
-                "date": date
-            ]
-        case .calibrateSensor(let glucose, let date):
-            return [
-                "action": Action.calibrateSensor.rawValue,
-                "date": date,
-                "glucose": glucose
-            ]
-        case .resetTransmitter:
-            return [
-                "action": Action.resetTransmitter.rawValue
-            ]
-        }
-    }
-}

+ 0 - 85
Dependencies/CGMBLEKit/CGMBLEKit/Glucose+SensorDisplayable.swift

@@ -1,85 +0,0 @@
-//
-//  GlucoseRxMessage.swift
-//  Loop
-//
-//  Created by Nathan Racklyeft on 5/30/16.
-//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
-//
-
-import Foundation
-import LoopKit
-
-
-extension Glucose: GlucoseDisplayable {
-    public var isStateValid: Bool {
-        return state == .known(.ok) && status == .ok
-    }
-
-    public var stateDescription: String {
-        var messages = [String]()
-
-        switch state {
-        case .known(.ok):
-            break  // Suppress the "OK" message
-        default:
-            messages.append(state.localizedDescription)
-        }
-
-        switch self.status {
-        case .ok:
-            if messages.isEmpty {
-                messages.append(status.localizedDescription)
-            } else {
-                break  // Suppress the "OK" message
-            }
-        case .lowBattery, .unknown:
-            messages.append(status.localizedDescription)
-        }
-
-        return messages.joined(separator: ". ")
-    }
-
-    public var trendType: GlucoseTrend? {
-        guard trend < Int(Int8.max) else {
-            return nil
-        }
-
-        switch trend {
-        case let x where x <= -30:
-            return .downDownDown
-        case let x where x <= -20:
-            return .downDown
-        case let x where x <= -10:
-            return .down
-        case let x where x < 10:
-            return .flat
-        case let x where x < 20:
-            return .up
-        case let x where x < 30:
-            return .upUp
-        default:
-            return .upUpUp
-        }
-    }
-
-    public var isLocal: Bool {
-        return true
-    }
-    
-    // TODO Placeholders. This functionality will come with LOOP-1311
-    public var glucoseRangeCategory: GlucoseRangeCategory? {
-        return nil
-    }
-}
-
-extension Glucose {
-    public var condition: GlucoseCondition? {
-        if glucoseMessage.glucose < GlucoseLimits.minimum {
-            return .belowRange
-        } else if glucoseMessage.glucose > GlucoseLimits.maximum {
-            return .aboveRange
-        } else {
-            return nil
-        }
-    }
-}

+ 0 - 111
Dependencies/CGMBLEKit/CGMBLEKit/Glucose.swift

@@ -1,111 +0,0 @@
-//
-//  Glucose.swift
-//  xDripG5
-//
-//  Created by Nate Racklyeft on 8/6/16.
-//  Copyright © 2016 Nathan Racklyeft. All rights reserved.
-//
-
-import Foundation
-import HealthKit
-
-enum GlucoseLimits {
-    static var minimum: UInt16 = 40
-    static var maximum: UInt16 = 400
-}
-
-public struct Glucose {
-    let glucoseMessage: GlucoseSubMessage
-    let timeMessage: TransmitterTimeRxMessage
-
-    init(
-        transmitterID: String,
-        glucoseMessage: GlucoseRxMessage,
-        timeMessage: TransmitterTimeRxMessage,
-        calibrationMessage: CalibrationDataRxMessage? = nil,
-        activationDate: Date
-    ) {
-        self.init(
-            transmitterID: transmitterID,
-            status: glucoseMessage.status,
-            glucoseMessage: glucoseMessage.glucose,
-            timeMessage: timeMessage,
-            calibrationMessage: calibrationMessage,
-            activationDate: activationDate
-        )
-    }
-
-    init(
-        transmitterID: String,
-        status: UInt8,
-        glucoseMessage: GlucoseSubMessage,
-        timeMessage: TransmitterTimeRxMessage,
-        calibrationMessage: CalibrationDataRxMessage? = nil,
-        activationDate: Date
-    ) {
-        self.transmitterID = transmitterID
-        self.glucoseMessage = glucoseMessage
-        self.timeMessage = timeMessage
-        self.status = TransmitterStatus(rawValue: status)
-        self.activationDate = activationDate
-
-        sessionStartDate = activationDate.addingTimeInterval(TimeInterval(timeMessage.sessionStartTime))
-        sessionExpDate = activationDate.addingTimeInterval(TimeInterval(timeMessage.sessionStartTime) + (10*24*60*60))
-        readDate = activationDate.addingTimeInterval(TimeInterval(glucoseMessage.timestamp))
-        lastCalibration = calibrationMessage != nil ? Calibration(calibrationMessage: calibrationMessage!, activationDate: activationDate) : nil
-    }
-
-    // MARK: - Transmitter Info
-    public let transmitterID: String
-    public let status: TransmitterStatus
-    public let activationDate: Date
-    public let sessionStartDate: Date
-    public let sessionExpDate: Date
-
-    // MARK: - Glucose Info
-    public let lastCalibration: Calibration?
-    public let readDate: Date
-
-    public var isDisplayOnly: Bool {
-        return glucoseMessage.glucoseIsDisplayOnly
-    }
-
-    public var glucose: HKQuantity? {
-        guard state.hasReliableGlucose && glucoseMessage.glucose >= 39 else { 
-            return nil
-        }
-
-        let unit = HKUnit.milligramsPerDeciliter
-
-        return HKQuantity(unit: unit, doubleValue: Double(min(max(glucoseMessage.glucose, GlucoseLimits.minimum), GlucoseLimits.maximum)))
-    }
-
-    public var state: CalibrationState {
-        return CalibrationState(rawValue: glucoseMessage.state)
-    }
-
-    public var trend: Int {
-        return Int(glucoseMessage.trend)
-    }
-
-    public var trendRate: HKQuantity? {
-        guard glucoseMessage.trend < Int8.max && glucoseMessage.trend > Int8.min else {
-            return nil
-        }
-
-        let unit = HKUnit.milligramsPerDeciliterPerMinute
-        return HKQuantity(unit: unit, doubleValue: Double(glucoseMessage.trend) / 10)
-    }
-
-    // An identifier for this reading thatʼs consistent between backfill/live data
-    public var syncIdentifier: String {
-        return "\(transmitterID) \(glucoseMessage.timestamp)"
-    }
-}
-
-
-extension Glucose: Equatable {
-    public static func ==(lhs: Glucose, rhs: Glucose) -> Bool {
-        return lhs.glucoseMessage == rhs.glucoseMessage && lhs.syncIdentifier == rhs.syncIdentifier
-    }
-}

+ 0 - 0
Dependencies/CGMBLEKit/CGMBLEKit/Info.plist


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini