public void NewContact(HourlyTracerKey key, DateHour time) { Case matchingCase = null; // Adds the new case to the database. db.RunInTransaction(() => { var exists = db.Find <Contact>(c => c.Key == key.Value && c.Year == time.Year && c.Month == time.Month && c.Day == time.Day && c.Hour == time.Hour ) != null; if (!exists) { Logger.Info( $"New contact: {key.ToHumanReadableString()} at {time}." ); db.Insert(new Contact { Key = key.Value, Year = time.Year, Month = time.Month, Day = time.Day, Hour = time.Hour }); // Gets any matching know case matchingCase = db.Find <Case>(ca => ca.Key == key.Value && ca.Year == time.Year && ca.Month == time.Month && ca.Day == time.Day ); } }); // Classifies the newly added case if (matchingCase != null) { lock (Matches) { if (matchingCase.Type == "positive") { Matches.Positives.Add(time); } else { Matches.Symptomatics.Add(time); } } MatchesChange?.Invoke(this, Matches); CurrentInfectionStatusChange?.Invoke( this, CurrentInfectionStatus); } }
/** Returns the current tracer key that should be sent over BLE. */ protected byte[] HandleReadCharacteristic() { var now = DateHour.Now; // TODO key generation could be cached instead of being recomputed // at every characteristic read. HourlyTracerKey currentKey = Key .DerivateDailyKey(now.AsDate()) .DerivateHourlyKey(now); Logger.Info($"BLE characteristic read request."); return(currentKey.Value); }
/** Record a new device contact that happens at the moment. */ public void NewContact(HourlyTracerKey key) { NewContact(key, DateHour.Now); }
/** Processes a discovery response of a Bluetooth device. * * Adds the device to the persistent data-store when required. * * Returns `false` if the discovery failed with a Bluetooth exception. */ protected async Task <bool> DiscoverDevice( IAdapter adapter, IDevice device) { var deviceIdStr = FormatDeviceId(device.Id); Logger.Info( $"Discovering BLE device: " + $"{deviceIdStr}/{device.Name} ({device.Rssi} dBm)" ); // Cancellation token that will abort the discovery process after // DEVICE_CONNECT_TIMEOUT. var tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(DEVICE_CONNECT_TIMEOUT); var token = tokenSource.Token; try { // Retrives the CovidTracerID from the BLE characteristic. if (device.State != DeviceState.Connected) { var connectParams = new ConnectParameters( /* autoConnect = */ false, /* forceBleTransport = */ true); await adapter.ConnectToDeviceAsync( device, connectParams, token); } if (device.State != DeviceState.Connected) { Logger.Error($"Failed to connect to {deviceIdStr}"); return(false); } var service = await device.GetServiceAsync(SERVICE_NAME, token); if (service == null) { Logger.Info( $"Device {deviceIdStr} does not have CovidTracer " + "service"); return(true); } var characteristic = await service.GetCharacteristicAsync(CHARACTERISTIC_NAME); if (characteristic == null) { Logger.Error( $"Device {deviceIdStr} does not support CovidTracer " + "characteristic."); return(false); } var keyBytes = await characteristic.ReadAsync(token); if (keyBytes == null) { Logger.Error( $"Device {deviceIdStr} characteristic can not be read." ); return(false); } var key = new HourlyTracerKey(keyBytes); // Logs the successful encounter Contacts.NewContact(key); return(true); } catch (Exception e) { Logger.Error($"Bluetooth exception: '{e.Message}'."); return(false); } finally { tokenSource.Dispose(); device.Dispose(); }; }