Skip to content

Commit

Permalink
Merge pull request #220 from DP-3T/feature/en-2
Browse files Browse the repository at this point in the history
Migrate to ENAPIVersion 2
  • Loading branch information
stmitt committed Oct 22, 2020
2 parents dcb592a + 22b8b31 commit f0f4939
Show file tree
Hide file tree
Showing 58 changed files with 1,491 additions and 1,625 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
##
- 'Bearer' is not added as a prefix to auth key if using HTTPAuthorizationHeader auth method.
- HTTPAuthorizationBearer auth method is deprecated
- updates to Exposure Notification Framework version 2
- ENAPIVersion has to be set to 2 in the Info.plist for this update to work
- increases the deployment target to 13.7
- outdated SDK methods have been removed
- the SDK now exposes all exposure dates not only the most recent one

## Version 1.3.0 (29.09.2020)
- Improve last day TEK export handling for iOS > 13.7 (must not disable EN until the following day)
Expand Down
48 changes: 33 additions & 15 deletions EXPOSURE_NOTIFICATION_API_USAGE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ExposureNotification API usage
This document outlines the interaction of the SDK with the [Exposure Notification](https://developer.apple.com/documentation/exposurenotification) Framework by Apple.
This document outlines the interaction of the SDK with the [Exposure Notification](https://developer.apple.com/documentation/exposurenotification) Framework version 2 by Apple.

## Enabling Exposure Notifications

Expand All @@ -13,31 +13,49 @@ To disable Exposure Notifications for our app we need to call [ENManager.setExpo

To retrieve the Temporary Exposure Keys (TEKs) we need to call [ENManager.getDiagnosisKeys(completionHandler:)](https://developer.apple.com/documentation/exposurenotification/enmanager/3583725-getdiagnosiskeys). This will trigger a system popup asking the user whether he wants to share the TEKs of the last 14 days with the app. If the user agrees to share the keys with the app the completion handler will get called with a maximum of 14 TEKs.

The TEK of the current day is currently not returned by [getDiagnosisKeys(completionHandler:)](https://developer.apple.com/documentation/exposurenotification/enmanager/3583725-getdiagnosiskeys), but only the keys of the previous 13 days. After the user agreed to share the keys we call [getDiagnosisKeys(completionHandler:)](https://developer.apple.com/documentation/exposurenotification/enmanager/3583725-getdiagnosiskeys) again on the following day and will then receive the TEK of last day. For this to work, the user has to open the app, after which we will temporarily enable EN, then call [getDiagnosisKeys(completionHandler:)](https://developer.apple.com/documentation/exposurenotification/enmanager/3583725-getdiagnosiskeys) (which triggers a system popup once once) and disable EN again.

## Detecting Exposure

For a contact to be counted as a possible exposure it must be longer than a certain number of minutes on a certain day. The current implementation of the EN-framework does not expose this information. Our way to overcome this limitation is to pass the published keys to the framework grouped by day.

To check for exposure on a given day (we check the past 10 days) we need to call [ENManager.detectExposures(configuration:diagnosisKeyURLs:completionHandler:)](https://developer.apple.com/documentation/exposurenotification/enmanager/3586331-detectexposures). This method has three parameters:
To check for exposure on a given day we need to call [ENManager.detectExposures(configuration:diagnosisKeyURLs:completionHandler:)](https://developer.apple.com/documentation/exposurenotification/enmanager/3586331-detectexposures). This method has three parameters:

#### Exposure Configuration

The [ENExposureConfiguration](https://developer.apple.com/documentation/exposurenotification/enexposureconfiguration) defines the configuration for the Apple scoring of exposures. In our case we ignore most of the scoring methods and only provide [attenuationDurationThresholds](https://developer.apple.com/documentation/exposurenotification/enexposureconfiguration/3601128-attenuationdurationthresholds), the thresholds for the duration at attenuation buckets. The thresholds for the attenuation buckets are loaded from our [config server](https://github.com/DP-3T/dp3t-config-backend-ch/blob/master/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/GAENSDKConfig.java). This allows us to group the duration of a contact with another device into three buckets regarding the measured attenuation values that we then use to detect if the contact was long and close enough.
To detect an exposure the following formula is used to compute the exposure duration:
```
durationAttenuationLow * factorLow + durationAtttenuationMedium * factorMedium
```
If this duration is at least as much as defined in the triggerThreshold a notification is triggered for that day.
The [ENExposureConfiguration](https://developer.apple.com/documentation/exposurenotification/enexposureconfiguration) defines the configuration for the Apple scoring of exposures. In our case we ignore most of the scoring methods and only provide:

- [reportTypeNoneMap](https://developer.apple.com/documentation/exposurenotification/enexposureconfiguration/3644397-reporttypenonemap): this defines what report type a key should bet set if no value is provided by the backend. This is set to `.confirmedTest`.
- [infectiousnessForDaysSinceOnsetOfSymptoms](https://developer.apple.com/documentation/exposurenotification/enexposureconfiguration/3644389-infectiousnessfordayssinceonseto): This value is obligatory and has to map between the days since onset of symptoms to the degree of infectiousness. Since we score each day equally we set all values to `ENInfectiousness.high`

#### Diagnosis key URLs

We need to unzip the file which we got from our backend, store the key file (.bin) and signature file (.sig) locally and pass the local urls to the EN API. Unlike Android, on iOS we can't just pass the difference from last detection but we have to pass the every key of a day everytime we do a detection.
We need to unzip the file which we got from our backend, store the key file (.bin) and signature file (.sig) locally and pass the local urls to the EN API.

#### Completion Handler

The completionHandler is called with a [ENExposureDetectionSummary](https://developer.apple.com/documentation/exposurenotification/enexposuredetectionsummary). That allows us to check if the exposure limit for a notification was reached by checking the minutes of exposure per attenuation bucket. The duration per bucket has a maximum of 30min, longer exposures are also returned as 30min of exposure.
The completion handler is called with a [ENExposureDetectionSummary](https://developer.apple.com/documentation/exposurenotification/enexposuredetectionsummary).

Given a [ENExposureDetectionSummary](https://developer.apple.com/documentation/exposurenotification/enexposuredetectionsummary) we get ENExposureWindows by calling [ENManager.getExposureWindows(summary:completionHandler:)](https://developer.apple.com/documentation/exposurenotification/enmanager/3644438-getexposurewindows). This method has two parameters:

#### Summary

Here we pass the previously obtained [ENExposureDetectionSummary](https://developer.apple.com/documentation/exposurenotification/enexposuredetectionsummary).

#### Completion Handler

The completion handler is called with [[ENExposureWindow]](https://developer.apple.com/documentation/exposurenotification/enexposurewindow).

A [ENExposureWindow](https://developer.apple.com/documentation/exposurenotification/enexposurewindow) is a set of Bluetooth scan events from observed beacons within a timespan. A window contains multiple [ENScanInstance](https://developer.apple.com/documentation/exposurenotification/enscaninstance) which are aggregations of attenuation of beacons during a scan.

By grouping the ENExposureWindows by day and then adding up all seconds which lie between our defined attenuation thresholds we can compose the buckets.

The thresholds for the attenuation buckets are loaded from our [config server](https://github.com/DP-3T/dp3t-config-backend-ch/blob/master/dpppt-config-backend/src/main/java/org/dpppt/switzerland/backend/sdk/config/ws/model/GAENSDKConfig.java).

To detect an exposure the following formula is used to compute the exposure duration:

```
durationAttenuationLow * factorLow + durationAtttenuationMedium * factorMedium
```

If this duration is at least as much as defined in the triggerThreshold a notification is triggered for that day.

#### Rate limit

We are only allowed to call [detectExposures()](https://developer.apple.com/documentation/exposurenotification/enmanager/3586331-detectexposures) 20 times within 24h. Because we check for every of the past 10 days individually, this allows us to check for exposure twice per day. These checks happen after 6am and 6pm (swiss time) when the BackgroundTask is scheduled the next time or the app is opened. All 10 days are checked individually and if one fails it is retried on the next run. No checks are made between midnight UTC and 6am (swiss time) to prevent exceeding the rate limit per 24h.
We are only allowed to call [detectExposures()](https://developer.apple.com/documentation/exposurenotification/enmanager/3586331-detectexposures) 6 times within 24h.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import PackageDescription
let package = Package(
name: "DP3TSDK",
platforms: [
.iOS("13.5"),
.iOS("13.7"),
],
products: [
.library(
Expand Down
28 changes: 19 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ DP-3T is a free-standing effort started at EPFL and ETHZ that produced this prot


## Introduction
This is the implementation of the DP-3T protocol using the [Exposure Notification](https://developer.apple.com/documentation/exposurenotification) Framework of Apple/Google. Only approved government public health authorities can access the APIs. Therefore, using this SDK will result in an API error unless you were granted the `com.apple.developer.exposure-notification` entitlement by Apple. The ExposureNotification.framework is available starting with iOS 13.5.
This is the implementation of the DP-3T protocol using the [Exposure Notification](https://developer.apple.com/documentation/exposurenotification) Framework of Apple/Google. Only approved government public health authorities can access the APIs. Therefore, using this SDK will result in an API error unless you were granted the `com.apple.developer.exposure-notification` entitlement by Apple. We are using [Exposure Notification](https://developer.apple.com/documentation/exposurenotification) Framework version 2, and the deployment target is therefore set to 13.7.

Our prestandard solution that is not using the Apple/Google framework can be found under the [tag prestandard](https://github.com/DP-3T/dp3t-sdk-ios/tree/prestandard).

Expand All @@ -24,6 +24,12 @@ Our prestandard solution that is not using the Apple/Google framework can be fou
## Further Documentation
The full set of documents for DP3T is at https://github.com/DP-3T/documents. Please refer to the technical documents and whitepapers for a description of the implementation.

## DP3T Exposure Score Calculation

The in-depth technical specification of the methodology used for the score calculation can be found [here](https://github.com/admin-ch/PT-System-Documents/blob/master/SwissCovid-ExposureScore.pdf).

A description of the usage of the Apple Exposure Notification API can be found [here](https://github.com/DP-3T/dp3t-sdk-ios/blob/master/EXPOSURE_NOTIFICATION_API_USAGE.md).

## Calibration App
Included in this repository is a Calibration App that can run, debug and test the SDK directly without implementing it in a new app first. Various parameters of the SDK are exposed and can be changed at runtime. Additionally it provides an overview of how to use the SDK.

Expand All @@ -44,12 +50,12 @@ init | Initializes the SDK and configures it | `initialize(applicationDescriptor
### Methods
Name | Description | Function Name
---- | ----------- | -------------
startTracing | Starts EN tracing | `func startTracing(completionHandler: )throws`
startTracing | Starts EN tracing | `func startTracing(completionHandler:)`
stopTracing | Stops EN tracing | `func stopTracing(completionHandler:)`
sync | Pro-actively triggers sync with backend to refresh exposed list | `func sync(callback:)`
status | Returns a TracingState-Object describing the current state. This contains:<br/>- `numberOfHandshakes` : `Int` <br /> - `trackingState` : `TrackingState` <br /> - `lastSync` : `Date` <br /> - `infectionStatus`:`InfectionStatus`<br /> - `backgroundRefreshState`:`UIBackgroundRefreshStatus ` | `func status(callback:)`
iWasExposed | This method must be called upon positive test. | `func iWasExposed(onset:authentication:isFakeRequest:callback:)`
reset | Removes all SDK related data | `func reset() throws`
reset | Removes all SDK related data | `func reset()`


## Installation
Expand Down Expand Up @@ -85,17 +91,21 @@ This version points to the HEAD of the `develop` branch and will always fetch th
In order to use the SDK with iOS 14 you need to specify the region for which the app works and the version of the [Exposure Notification](https://developer.apple.com/documentation/exposurenotification) Framework which should be used.

This is done by adding [`ENDeveloperRegion`](https://developer.apple.com/documentation/bundleresources/information_property_list/endeveloperregion) as an `Info.plist` property with the according ISO 3166-1 country code as its value.
The SDK currently works with EN Framework version 1 and therefore we need to specify [`ENAPIVersion`](https://developer.apple.com/documentation/bundleresources/information_property_list/enapiversion) with a value of 1 in the `Info.plist`.
The SDK works with EN Framework version 2 and therefore we need to specify [`ENAPIVersion`](https://developer.apple.com/documentation/bundleresources/information_property_list/enapiversion) with a value of 2 in the `Info.plist`.

### Backend

Starting with DP3T SDK version 2.0 the required [backend](https://github.com/DP-3T/dp3t-sdk-backend) version is 2.0.

### Initialization

In your AppDelegate in the `didFinishLaunchingWithOptions` function you have to initialize the SDK.

```swift
let url = URL(string: "https://example.com/your/api/")!
try! DP3TTracing.initialize(with: .init(appId: "com.example.your.app",
bucketBaseUrl: url,
reportBaseUrl: url))
DP3TTracing.initialize(with: .init(appId: "com.example.your.app",
bucketBaseUrl: url,
reportBaseUrl: url))
```

#####
Expand All @@ -107,13 +117,13 @@ The SDK accepts a `URLSession` as an optional argument to the initializer. This
### Start / Stop tracing
To start and stop tracing use
```swift
try DP3TTracing.startTracing()
DP3TTracing.startTracing()
DP3TTracing.stopTracing()
```

### Checking the current tracing status
```swift
DP3TTracing.status(callback: (Result<TracingState, DP3TTracingErrors>) -> Void)
let status = DP3TTracing.status
```
The `TracingState` object contains all information regarding the current tracing status.

Expand Down
Loading

0 comments on commit f0f4939

Please sign in to comment.