示例#1
0
        /// <summary>
        /// Set alarm clock for Band.
        /// </summary>
        /// <param name="status"></param>
        /// <param name="alarmSlot"></param>
        /// <param name="alarmDays"></param>
        /// <param name="hour"></param>
        /// <param name="minute"></param>
        /// <returns></returns>
        public async Task <bool> SetAlarmClock(AlarmStatus status, int alarmSlot, List <AlarmDays> alarmDays, int hour, int minute)
        {
            GattCharacteristic notificationCharacteristic = await Gatt.GetCharacteristicByServiceUuid(MIBAND3_SERVICE, CONFIGURATION_CHARACTERISTIC);

            int maxAlarmSlots = 5;
            int days          = 0;

            if (alarmSlot >= maxAlarmSlots)
            {
                Debug.WriteLine("Only 5 slots for alarms available. Saving to 0 slot.");
                alarmSlot = 0;
            }

            if (alarmDays.Count == 0)
            {
                Debug.WriteLine("alarmDays is empty. Setting alarm once.");
                days = 128;
            }
            else
            {
                foreach (var day in alarmDays)
                {
                    days += (int)day;
                }
            }

            Debug.WriteLine($"Setting alarm clock at {hour}:{minute} to slot {alarmSlot}");
            byte[] setAlarmCmd = new byte[] { 0x2, (byte)(status + alarmSlot), (byte)hour, (byte)minute, (byte)days };

            return(await notificationCharacteristic.WriteValueAsync(setAlarmCmd.AsBuffer()) == GattCommunicationStatus.Success);
        }
        private Guid USER_SETTINGS_CHARACTERISTIC = new Guid("00000008-0000-3512-2118-0009af100700"); // Xiaomi User Info Characteristic on Mi Band 3

        /// <summary>
        /// Get steps and activity info.
        /// </summary>
        /// <returns>StepInfo object as Activity data.</returns>
        public async Task <StepInfo> GetStepInfoAsync()
        {
            var characteristic = await Gatt.GetCharacteristicByServiceUuid(MI_BAND_SERVICE, STEP_INFO_CHARACTERISTIC);

            var gattReadResult = await characteristic.ReadValueAsync(BluetoothCacheMode.Uncached);

            StepInfo stepInfo = new StepInfo();

            if (gattReadResult.Status == GattCommunicationStatus.ProtocolError)
            {
                Debug.WriteLine("Protocol error. Trying to take values from cache");
                gattReadResult = await characteristic.ReadValueAsync(BluetoothCacheMode.Cached);
            }

            var data       = gattReadResult.Value.ToArray();
            int totalSteps = ((data[1] & 255) | ((data[2] & 255) << 8));
            int distance   = ((((data[5] & 255) | ((data[6] & 255) << 8)) | (data[7] & 16711680)) | ((data[8] & 255) << 24));
            int calories   = ((((data[9] & 255) | ((data[10] & 255) << 8)) | (data[11] & 16711680)) | ((data[12] & 255) << 24));

            stepInfo.Steps    = totalSteps;
            stepInfo.Distance = distance;
            stepInfo.Calories = calories;

            return(stepInfo);
        }
示例#3
0
        public async Task <bool> SetUserInfo(DateTime dateOfBirth, Gender gender, int height, int weight)
        {
            int userId         = (new Random()).Next(000000, 999999);
            var characteristic = await Gatt.GetCharacteristicByServiceUuid(MI_BAND_SERVICE, USERSETTINGS_CHARACTERISTIC);

            List <byte> data           = new List <byte>();
            byte        setUserInfoCmd = 79;

            data.Add(setUserInfoCmd);
            data.Add(0);
            data.Add(0);
            data.Add((byte)(dateOfBirth.Year & 255));
            data.Add((byte)((dateOfBirth.Year >> 8) & 255));
            data.Add((byte)dateOfBirth.Month);
            data.Add((byte)dateOfBirth.Day);
            data.Add((byte)gender);
            data.Add((byte)(height & 255));
            data.Add((byte)((height >> 8) & 255));
            data.Add((byte)((weight * 200) & 255));
            data.Add((byte)((weight * 200 >> 8) & 255));
            data.Add((byte)(userId & 255));
            data.Add((byte)((userId >> 8) & 255));
            data.Add((byte)((userId >> 16) & 255));
            data.Add((byte)((userId >> 24) & 255));

            Debug.WriteLine("Writing user info to Band");

            return(await characteristic.WriteValueAsync(data.ToArray().AsBuffer()) == GattCommunicationStatus.Success);
        }
示例#4
0
        /// <summary>
        /// Set display date mode (datetime or time, 12 hour or 24 hour)
        /// </summary>
        /// <param name="mode"></param>
        /// <returns></returns>
        public async Task <bool> SetDisplayDate(DateMode mode)
        {
            byte[] date = null;

            switch (mode)
            {
            case DateMode.DATEFORMAT_TIME:
                date = new byte[] { 6, 10, 0, 0 };
                break;

            case DateMode.DATEFORMAT_DATETIME:
                date = new byte[] { 6, 10, 0, 3 };
                break;

            case DateMode.DATEFORMAT_12_HOURS:
                date = new byte[] { 6, 2, 0, 0 };
                break;

            case DateMode.DATEFORMAT_24_HOURS:
                date = new byte[] { 6, 2, 0, 1 };
                break;
            }

            Debug.WriteLine("Set display time");

            var characteristic = await Gatt.GetCharacteristicByServiceUuid(MI_BAND_SERVICE, DISPLAY_DATE_CHARACTERISTIC);

            var gattWriteResult = await characteristic.WriteValueAsync(date.AsBuffer());

            return(gattWriteResult == GattCommunicationStatus.Success);
        }
示例#5
0
        public async Task <string> GetDeviceName()
        {
            var deviceNameCharacteristic = await Gatt.GetCharacteristicByServiceUuid(DEVICE_NAME_SERVICE, DEVICE_NAME_CHARACTERISTIC);

            GattReadResult deviceNameReadResult = await deviceNameCharacteristic.ReadValueAsync(BluetoothCacheMode.Uncached);

            return(Encoding.UTF8.GetString(deviceNameReadResult.Value.ToArray()));
        }
        public async Task <bool> ActivateDisplayByRotateWrist(WristMode mode)
        {
            GattCharacteristic wearLocationCharacteristic = await Gatt.GetCharacteristicByServiceUuid(MIBAND3_SERVICE, CONFIGURATION_CHARACTERISTIC);

            byte[] activateByRotateCmd = new byte[] { 6, 5, 0, (byte)mode };

            return(await wearLocationCharacteristic.WriteValueAsync(activateByRotateCmd.AsBuffer()) == GattCommunicationStatus.Success);
        }
        public async Task <bool> SetWearLocation(Enums.WearLocation location)
        {
            GattCharacteristic wearLocationCharacteristic = await Gatt.GetCharacteristicByServiceUuid(MIBAND3_SERVICE, USER_SETTINGS_CHARACTERISTIC);

            byte[] setWearLocationCmd = new byte[] { 32, 0, 0, (byte)location };

            return(await wearLocationCharacteristic.WriteValueAsync(setWearLocationCmd.AsBuffer()) == GattCommunicationStatus.Success);
        }
示例#8
0
        /// <summary>
        /// Set fithess goal notification on the Band
        /// </summary>
        /// <param name="notification"></param>
        /// <returns></returns>
        public async Task <bool> SetFitnessGoalNotification(FitnessGoalNotification notification)
        {
            GattCharacteristic notificationCharacteristic = await Gatt.GetCharacteristicByServiceUuid(MIBAND3_SERVICE, CONFIGURATION_CHARACTERISTIC);

            byte[] setNotificationCmd = new byte[] { 6, 0, (byte)notification };

            return(await notificationCharacteristic.WriteValueAsync(setNotificationCmd.AsBuffer()) == GattCommunicationStatus.Success);
        }
示例#9
0
        /// <summary>
        /// Setting display caller information while ringing.
        /// </summary>
        /// <param name="callerInfo"></param>
        /// <returns></returns>
        public async Task <bool> SetDisplayCallerInfo(DisplayCallerInfo callerInfo)
        {
            GattCharacteristic notificationCharacteristic = await Gatt.GetCharacteristicByServiceUuid(MIBAND3_SERVICE, CONFIGURATION_CHARACTERISTIC);

            byte[] setDisplayCallerInfoCmd = new byte[] { 6, 16, 0, (byte)callerInfo };

            return(await notificationCharacteristic.WriteValueAsync(setDisplayCallerInfoCmd.AsBuffer()) == GattCommunicationStatus.Success);
        }
示例#10
0
        /// <summary>
        /// Send default notification to the Band
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public async Task <bool> SendDefaultNotification(NotificationType type)
        {
            GattCharacteristic notificationCharacteristic = await Gatt.GetCharacteristicByServiceUuid(ALERT_LEVEL_SERVICE, ALERT_LEVEL_CHARACTERISTIC);

            byte[] sendNotificationCmd = new byte[] { (byte)type };

            return(await notificationCharacteristic.WriteValueAsync(sendNotificationCmd.AsBuffer()) == GattCommunicationStatus.Success);
        }
示例#11
0
        /// <summary>
        /// Set metric system (default - metric)
        /// </summary>
        /// <param name="metricSystem"></param>
        /// <returns></returns>
        public async Task <bool> SetMetricSystem(MetricSystem metricSystem)
        {
            var characteristic = await Gatt.GetCharacteristicByServiceUuid(MI_BAND_SERVICE, CONFIGURATION_CHARACTERISTIC);

            byte[] setMetricSystemCmd = new byte[] { 6, 3, 0, (byte)metricSystem };

            return(await characteristic.WriteValueAsync(setMetricSystemCmd.ToArray().AsBuffer()) == GattCommunicationStatus.Success);
        }
示例#12
0
        public async Task <string> GetSoftwareRevision()
        {
            var softwareRevisionCharacteristic = await Gatt.GetCharacteristicByServiceUuid(DEVICE_INFO_SERVICE, SOFTWARE_REVISION_CHARACTERISTIC);

            GattReadResult softwareRevisionReadResult = await softwareRevisionCharacteristic.ReadValueAsync(BluetoothCacheMode.Uncached);

            return(Encoding.UTF8.GetString(softwareRevisionReadResult.Value.ToArray()));
        }
示例#13
0
        public async Task <string> GetSerialNumber()
        {
            var serialNumberCharacteristic = await Gatt.GetCharacteristicByServiceUuid(DEVICE_INFO_SERVICE, SERIAL_NUMBER_CHARACTERISTIC);

            GattReadResult serialNumberReadResult = await serialNumberCharacteristic.ReadValueAsync(BluetoothCacheMode.Uncached);

            return(Encoding.UTF8.GetString(serialNumberReadResult.Value.ToArray()));
        }
示例#14
0
        /// <summary>
        /// Read service characteristic with result.
        /// </summary>
        /// <returns></returns>
        private async Task <GattReadResult> ReadCurrentCharacteristic()
        {
            var batteryStateCharacteristic = await Gatt.GetCharacteristicByServiceUuid(MI_BAND_SERVICE, BATTERY_INFO_CHARACTERISTIC);

            GattReadResult gattReadResult = (batteryStateCharacteristic != null)
                ? await batteryStateCharacteristic.ReadValueAsync(BluetoothCacheMode.Uncached)
                : null;

            return(gattReadResult);
        }
        /// <summary>
        /// Subscribe to HeartRate notifications from band.
        /// </summary>
        /// <param name="eventHandler">Handler for interact with heartRate values</param>
        /// <returns></returns>
        public async Task SubscribeToHeartRateNotificationsAsync(TypedEventHandler <GattCharacteristic, GattValueChangedEventArgs> eventHandler)
        {
            _heartRateMeasurementCharacteristic = await Gatt.GetCharacteristicByServiceUuid(HEART_RATE_SERVICE, HEART_RATE_MEASUREMENT_CHARACTERISTIC);

            Debug.WriteLine("Subscribe to HeartRate notifications from band...");
            if (await _heartRateMeasurementCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify) == GattCommunicationStatus.Success)
            {
                _heartRateMeasurementCharacteristic.ValueChanged += eventHandler;
            }
        }
示例#16
0
        /// MODIFIED BY ARCHER
        ///
        /// <summary>
        /// Unsubscribe from HeartRate notifications from band
        /// </summary>
        /// <returns></returns>
        public async Task UnsubscribeFromHeartRateNotificationsAsync()
        {
            _heartRateMeasurementCharacteristic = await Gatt.GetCharacteristicByServiceUuid(HEART_RATE_SERVICE, HEART_RATE_MEASUREMENT_CHARACTERISTIC);

            Debug.WriteLine("Unsubscribe from HeartRate notifications from band...");
            if (await _heartRateMeasurementCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.None) == GattCommunicationStatus.Success)
            {
                _heartRateMeasurementCharacteristic.ValueChanged -= HeartRateMeasurementCharacteristicValueChanged;
            }
        }
示例#17
0
        /// <summary>
        /// Send notification when user is so lazy
        /// </summary>
        /// <param name="warningMode"></param>
        /// <param name="startHours"></param>
        /// <param name="startMinutes"></param>
        /// <param name="endHours"></param>
        /// <param name="endMinutes"></param>
        /// <returns></returns>
        public async Task <bool> SetInactivityWarnings(InactivityWarningMode warningMode,
                                                       byte startHours, byte startMinutes,
                                                       byte endHours, byte endMinutes)
        {
            var characteristic = await Gatt.GetCharacteristicByServiceUuid(MIBAND3_SERVICE, CONFIGURATION_CHARACTERISTIC);

            byte[] data = new byte[] { 8, (byte)warningMode, 60, 0, startHours, startMinutes, endHours, endMinutes, startHours, startMinutes, endHours, endMinutes };

            return(await characteristic.WriteValueAsync(data.AsBuffer()) == GattCommunicationStatus.Success);
        }
示例#18
0
        /// <summary>
        /// Subscribe to device events (touch to band)
        /// </summary>
        /// <param name="eventHandler"></param>
        /// <returns></returns>
        public async Task SubscribeToDeviceEventNotificationsAsync(TypedEventHandler <GattCharacteristic, GattValueChangedEventArgs> eventHandler)
        {
            var deviceCharacteristic = await Gatt.GetCharacteristicByServiceUuid(MIBAND2_SERVICE, DEVICE_EVENT_CHARACTERISTIC);

            var deviceNotify = await deviceCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);

            Debug.WriteLine("Subscribe to device event notifications");
            if (deviceNotify == GattCommunicationStatus.Success)
            {
                deviceCharacteristic.ValueChanged += eventHandler;
            }
        }
示例#19
0
        /// <summary>
        /// Send more customizable notification to the Band.
        /// </summary>
        /// <param name="vibration">Strength and length of notification</param>
        /// <param name="pause"></param>
        /// <param name="times"></param>
        /// <returns></returns>
        public async Task <bool> SendCustomNotification(short vibration, short pause, short times)
        {
            GattCharacteristic notificationCharacteristic = await Gatt.GetCharacteristicByServiceUuid(ALERT_LEVEL_SERVICE, ALERT_LEVEL_CHARACTERISTIC);

            if (notificationCharacteristic != null)
            {
                byte   repeat = (byte)(times * (2 / 2));
                byte[] sendNotificationCmd = new byte[] { unchecked ((byte)-1), (byte)(vibration & 255), (byte)((vibration >> 8) & 255), (byte)(pause & 255), (byte)((pause >> 8) & 255), repeat };

                System.Diagnostics.Debug.WriteLine($"Starting vibrate {repeat} times");
                return(await notificationCharacteristic.WriteValueAsync(sendNotificationCmd.AsBuffer()) == GattCommunicationStatus.Success);
            }

            return(false);
        }
示例#20
0
        /// <summary>
        /// Show notification on Band when steps per day value reached.
        /// </summary>
        /// <param name="stepsPerDay"></param>
        /// <returns></returns>
        public async Task <bool> SetFitnessGoalAsync(int stepsPerDay)
        {
            GattCharacteristic userSettingsCharacteristic = await Gatt.GetCharacteristicByServiceUuid(MI_BAND_SERVICE, USER_SETTINGS_CHARACTERISTIC);

            byte[] setFitnessGoalStartCmd = new byte[] { 0x10, 0x0, 0x0 };
            byte[] setFitnessGoalEndCmd   = new byte[] { 0, 0 };

            byte[]      data  = new byte[] { (byte)(stepsPerDay & 0xff), (byte)((stepsPerDay >> 8) & 0xff) };
            List <byte> bytes = new List <byte>();

            bytes = setFitnessGoalStartCmd.Concat(data).ToList();
            bytes = bytes.Concat(setFitnessGoalEndCmd).ToList();

            return(await userSettingsCharacteristic.WriteValueAsync(bytes.ToArray().AsBuffer()) == GattCommunicationStatus.Success);
        }
示例#21
0
        /// <summary>
        /// Set display items like calories, steps, distance etc.
        /// Display clock cannot be removed.
        /// </summary>
        /// <param name="items">Display items from Models.DisplayItems enumerable.</param>
        /// <returns></returns>
        public async Task <bool> SetDisplayItems(IEnumerable <byte> items)
        {
            GattCharacteristic displayItemsCharacteristic = await Gatt.GetCharacteristicByServiceUuid(MI_BAND_SERVICE, CONFIGURATION_CHARACTERISTIC);

            byte[] changeScreensCmd = new byte[] { 10, 1, 0, 0, 1, 2, 3, 4, 5 };
            byte   allItems         = 1;

            foreach (var item in items)
            {
                allItems += item;
            }

            changeScreensCmd[1] |= allItems;

            return(await displayItemsCharacteristic.WriteValueAsync(changeScreensCmd.ToArray().AsBuffer()) == GattCommunicationStatus.Success);
        }
示例#22
0
        /// <summary>
        /// Send custom notification to the Band
        /// </summary>
        /// <param name="profile"></param>
        /// <param name="times"></param>
        /// <returns></returns>
        public async Task <bool> SendCustomNotification(CustomVibrationProfile profile, short times)
        {
            GattCharacteristic notificationCharacteristic = await Gatt.GetCharacteristicByServiceUuid(ALERT_LEVEL_SERVICE, ALERT_LEVEL_CHARACTERISTIC);

            int[] onOffSequence = null;

            switch (profile)
            {
            case CustomVibrationProfile.INFINITE:
                onOffSequence = new int[] { 1, 1 };
                break;

            case CustomVibrationProfile.LONG:
                onOffSequence = new int[] { 500, 1000 };
                break;

            case CustomVibrationProfile.QUICK:
                onOffSequence = new int[] { 100, 100 };
                break;

            case CustomVibrationProfile.SHORT:
                onOffSequence = new int[] { 200, 200 };
                break;

            case CustomVibrationProfile.WATER_DROP:
                onOffSequence = new int[] { 100, 1500 };
                break;

            case CustomVibrationProfile.RING:
                onOffSequence = new int[] { 200, 300 };
                break;
            }

            if (notificationCharacteristic != null && onOffSequence != null)
            {
                short? vibration           = (short)onOffSequence[0];
                short? pause               = (short)onOffSequence[1];
                byte   repeat              = (byte)(times * (onOffSequence.Length / 2));
                byte[] sendNotificationCmd = new byte[] { unchecked ((byte)-1), (byte)(vibration & 255), (byte)((vibration >> 8) & 255), (byte)(pause & 255), (byte)((pause >> 8) & 255), repeat };

                System.Diagnostics.Debug.WriteLine($"Starting vibrate {repeat} times");
                return(await notificationCharacteristic.WriteValueAsync(sendNotificationCmd.AsBuffer()) == GattCommunicationStatus.Success);
            }

            return(false);
        }
        /// <summary>
        /// Set Heart Rate Measurements while sleep
        /// </summary>
        /// <param name="sleepMeasurement"></param>
        /// <returns></returns>
        public async Task <bool> SetHeartRateSleepMeasurement(SleepHeartRateMeasurement sleepMeasurement)
        {
            _heartRateControlPointCharacteristic = await Gatt.GetCharacteristicByServiceUuid(HEART_RATE_SERVICE, HEART_RATE_CONTROLPOINT_CHARACTERISTIC);

            byte[] command = null;

            switch (sleepMeasurement)
            {
            case SleepHeartRateMeasurement.ENABLE:
                command = new byte[] { 0x15, 0x00, 0x01 };
                break;

            case SleepHeartRateMeasurement.DISABLE:
                command = new byte[] { 0x15, 0x00, 0x00 };
                break;
            }

            return(await _heartRateControlPointCharacteristic.WriteValueAsync(command.AsBuffer()) == GattCommunicationStatus.Success);
        }
示例#24
0
        /// <summary>
        /// Set Do Not Disturb mode. (Unsubscribe to notifications from phone)
        /// </summary>
        /// <param name="dndMode"></param>
        /// <param name="startHours"></param>
        /// <param name="startMinutes"></param>
        /// <param name="endHours"></param>
        /// <param name="endMinutes"></param>
        /// <returns></returns>
        public async Task <bool> DoNotDisturb(DoNotDisturbMode dndMode,
                                              byte startHours = 0, byte startMinutes = 0,
                                              byte endHours   = 0, byte endMinutes   = 0)
        {
            var characteristic = await Gatt.GetCharacteristicByServiceUuid(MIBAND3_SERVICE, CONFIGURATION_CHARACTERISTIC);

            byte[] setDnd = null;

            if (dndMode != DoNotDisturbMode.SCHEDULED)
            {
                setDnd = new byte[] { 9, (byte)dndMode }
            }
            ;
            else
            {
                setDnd = new byte[] { 9, (byte)dndMode, startHours, startMinutes, endHours, endMinutes }
            };

            return(await characteristic.WriteValueAsync(setDnd.AsBuffer()) == GattCommunicationStatus.Success);
        }
        /// <summary>
        /// Starting heart rate measurement
        /// </summary>
        /// <returns></returns>
        private async Task <GattCommunicationStatus> StartHeartRateMeasurementAsync()
        {
            _heartRateMeasurementCharacteristic = await Gatt.GetCharacteristicByServiceUuid(HEART_RATE_SERVICE, HEART_RATE_MEASUREMENT_CHARACTERISTIC);

            _heartRateControlPointCharacteristic = await Gatt.GetCharacteristicByServiceUuid(HEART_RATE_SERVICE, HEART_RATE_CONTROLPOINT_CHARACTERISTIC);

            GattCommunicationStatus status = GattCommunicationStatus.ProtocolError;

            if (await _heartRateMeasurementCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify) == GattCommunicationStatus.Success)
            {
                Debug.WriteLine("Checking Heart Rate");

                if (await _heartRateControlPointCharacteristic.WriteValueAsync(HEART_RATE_START_COMMAND.AsBuffer()) == GattCommunicationStatus.Success)
                {
                    _heartRateMeasurementCharacteristic.ValueChanged += HeartRateMeasurementCharacteristicValueChanged;
                    status = GattCommunicationStatus.Success;
                    _WaitHandle.WaitOne();
                }
            }

            return(status);
        }
示例#26
0
        /// <summary>
        /// Authentication. If already authenticated, just send AuthNumber and EncryptedKey to band (auth levels 2 and 3)
        /// </summary>
        /// <returns></returns>
        public async Task <bool> AuthenticateAsync()
        {
            _AuthCharacteristic = await Gatt.GetCharacteristicByServiceUuid(AUTH_SERVICE, AUTH_CHARACTERISTIC);

            await _AuthCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);

            if (!IsAuthenticated())
            {
                Debug.WriteLine("Level 1 started");

                List <byte> sendKey = new List <byte>();
                sendKey.Add(0x01);
                sendKey.Add(0x08);
                sendKey.AddRange(AUTH_SECRET_KEY);

                if (await _AuthCharacteristic.WriteValueAsync(sendKey.ToArray().AsBuffer()) == GattCommunicationStatus.Success)
                {
                    Debug.WriteLine("Level 1 success");
                    _AuthCharacteristic.ValueChanged += AuthCharacteristic_ValueChanged;
                }
            }
            else
            {
                Debug.WriteLine("Already authorized (Level 1 successful)");
                Debug.WriteLine("Level 2 started");

                if (await SendAuthNumberAsync())
                {
                    Debug.WriteLine("Level 2 success");
                }

                _AuthCharacteristic.ValueChanged += AuthCharacteristic_ValueChanged;
            }

            _WaitHandle.WaitOne();
            return(IsAuthenticated());
        }
        /// <summary>
        /// Set Realtime (Continuous) Heart Rate Measurements
        /// </summary>
        /// <param name="measurements"></param>
        /// <returns></returns>
        public async Task <GattCommunicationStatus> SetRealtimeHeartRateMeasurement(RealtimeHeartRateMeasurements measurements)
        {
            _heartRateMeasurementCharacteristic = await Gatt.GetCharacteristicByServiceUuid(HEART_RATE_SERVICE, HEART_RATE_MEASUREMENT_CHARACTERISTIC);

            _heartRateControlPointCharacteristic = await Gatt.GetCharacteristicByServiceUuid(HEART_RATE_SERVICE, HEART_RATE_CONTROLPOINT_CHARACTERISTIC);

            GattCommunicationStatus status = GattCommunicationStatus.ProtocolError;

            if (await _heartRateMeasurementCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify) == GattCommunicationStatus.Success)
            {
                byte[] manualCmd     = null;
                byte[] continuousCmd = null;

                switch (measurements)
                {
                case RealtimeHeartRateMeasurements.ENABLE:
                    manualCmd     = new byte[] { 0x15, 0x02, 0 };
                    continuousCmd = new byte[] { 0x15, 0x01, 1 };
                    break;

                case RealtimeHeartRateMeasurements.DISABLE:
                    manualCmd     = new byte[] { 0x15, 0x02, 1 };
                    continuousCmd = new byte[] { 0x15, 0x01, 0 };
                    break;
                }

                if (await _heartRateControlPointCharacteristic.WriteValueAsync(manualCmd.AsBuffer()) == GattCommunicationStatus.Success &&
                    await _heartRateControlPointCharacteristic.WriteValueAsync(continuousCmd.AsBuffer()) == GattCommunicationStatus.Success)
                {
                    status = GattCommunicationStatus.Success;
                    _heartRateMeasurementCharacteristic.ValueChanged += HeartRateMeasurementCharacteristicValueChanged;
                }
            }

            return(status);
        }
        /// <summary>
        /// Sets Heart Rate Measurement interval in minutes (0 is off)
        /// </summary>
        /// <param name="minutes"></param>
        /// <returns></returns>
        public async Task <bool> SetHeartRateMeasurementInterval(int minutes)
        {
            _heartRateControlPointCharacteristic = await Gatt.GetCharacteristicByServiceUuid(HEART_RATE_SERVICE, HEART_RATE_CONTROLPOINT_CHARACTERISTIC);

            return(await _heartRateControlPointCharacteristic.WriteValueAsync(new byte[] { 0x14, (byte)minutes }.AsBuffer()) == GattCommunicationStatus.Success);
        }