예제 #1
0
        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);
            }
        }
예제 #2
0
        /** 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);
        }
예제 #3
0
 /** Record a new device contact that happens at the moment. */
 public void NewContact(HourlyTracerKey key)
 {
     NewContact(key, DateHour.Now);
 }
예제 #4
0
        /** 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();
            };
        }