Example #1
0
        /// <summary>
        /// Connect to an unconnected IMBLE device.
        /// </summary>
        /// <param name="device">An UnconnectedImbleDevice instance corresponding to the IMBLE device to connect to.</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<ImbleDevice> ConnectAsync(UnconnectedImbleDevice device, CancellationToken cancellationToken)
        {
            var imble = new ImbleDevice();

            // I tried to use DeviceInformation.FindAllAsync combined with BluetoothLEDevice.GetDeviceSelectorFromBluetoothAddress
            // to obtain a device information corresponding to a Bluetooth address.
            // But this implementation is not feasible because DeviceInformation.FindAllAsync takes 10 to 20 seconds.
            // Thus, I've decided to use BluetoothLEDevice.FromBluetoothAddressAsync instead of DeviceInformation.FindAllAsync.
            var bleDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(device.Address);
            var deviceInformation = bleDevice.DeviceInformation;
            bleDevice.Dispose();    // Do not forget to dispose BLE related objects.

            await imble.Initialize(deviceInformation, device.Address, cancellationToken);
            return imble;
        }
        public UnconnectedDeviceViewModel(UnconnectedImbleDevice device)
        {
            this.Device = device;

            this.Name = this.Device.Advertisement.LocalName;

            var addressBytes = BitConverter.GetBytes(this.Device.Address);
            if (!BitConverter.IsLittleEndian)
            {
                Array.Reverse(addressBytes);
            }
            this.Address = string.Join(":", addressBytes.Select(@byte => @byte.ToString("X02")));
            this.Rssi = this.Device.Rssi;

            this.ConnectCommand = new ReactiveCommand();
            this.ConnectCommand
                .Select(_ => Observable.FromAsync(token => this.Device.Connect(token)))
                .Switch()
                .OnErrorRetry()
                .Subscribe()
                .AddTo(this.disposables);

        }
Example #3
0
        public UnconnectedDeviceViewModel(UnconnectedImbleDevice device)
        {
            this.Device = device;

            this.Name = this.Device.Advertisement.LocalName;

            var addressBytes = BitConverter.GetBytes(this.Device.Address);

            if (!BitConverter.IsLittleEndian)
            {
                Array.Reverse(addressBytes);
            }
            this.Address = string.Join(":", addressBytes.Select(@byte => @byte.ToString("X02")));
            this.Rssi    = this.Device.Rssi;

            this.ConnectCommand = new ReactiveCommand();
            this.ConnectCommand
            .Select(_ => Observable.FromAsync(token => this.Device.Connect(token)))
            .Switch()
            .OnErrorRetry()
            .Subscribe()
            .AddTo(this.disposables);
        }
        public DevicePageViewModel(UnconnectedImbleDevice unconnectedDevice)
        {
            this.Device = Observable.FromAsync(token => unconnectedDevice.Connect(token))
                          .CatchIgnore((Exception e) => { })
                          .ToReadOnlyReactiveProperty()
                          .AddTo(this.disposables);

            this.IsConnected = this.Device.Select(device => device != null).ToReadOnlyReactiveProperty().AddTo(this.disposables);

            this.DeviceStatus = this.Device
                                .Where(device => device != null)
                                .Select(device => device.ObserveProperty(self => self.Status))
                                .Switch()
                                .Do(value => Debug.WriteLine(value))
                                .ObserveOnUIDispatcher()
                                .ToReadOnlyReactiveProperty()
                                .AddTo(this.disposables);

            this.ReceivedMessage = this.Device
                                   .Where(device => device != null)
                                   .Select(device => Observable.FromEventPattern <DataArrivedEventArgs>(handler => device.DataArrived += handler, handler => device.DataArrived -= handler))
                                   .Switch()
                                   .Select(args => new ReceivedMessageViewModel(args.EventArgs.Data, args.EventArgs.Timestamp))
                                   .OnErrorRetry()
                                   .ToReadOnlyReactiveProperty()
                                   .AddTo(this.disposables);

            var notBusyNotifier = new BooleanNotifier(false);

            this.Name = new ReactiveProperty <string>("Fuga")
                        .SetValidateNotifyError(value => value != null && Encoding.UTF8.GetByteCount(value) < 12 ? null : "Input short message")
                        .AddTo(this.disposables);

            this.CanSendCommand = Observable.CombineLatest(
                this.DeviceStatus.Select(status => status == ImbleDeviceStatus.Running),
                this.Name.ObserveHasErrors,
                notBusyNotifier.Do(value => Debug.WriteLine(value)),
                (isRunning, hasErrors, notBusy) => isRunning && !hasErrors && notBusy)
                                  .ToReadOnlyReactiveProperty().AddTo(this.disposables);
            notBusyNotifier.TurnOn();

            this.SendCommand = this.CanSendCommand.ToReactiveCommand().AddTo(this.disposables);
            this.SendCommand
            .Do(_ => notBusyNotifier.TurnOff())
            .Select(_ =>
            {
                var data = Encoding.UTF8.GetBytes(this.Name.Value);
                return(Observable.FromAsync(token =>
                {
                    using (var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
                        using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token, timeoutTokenSource.Token))
                        {
                            return this.Device.Value.SendAsync(data, 0, data.Length, linkedTokenSource.Token);
                        }
                })
                       .Finally(() => notBusyNotifier.TurnOn()));
            })
            .Switch()
            .OnErrorRetry((Exception e) => Debug.WriteLine(e))
            .Subscribe()
            .AddTo(this.disposables);
        }
        public DevicePageViewModel(UnconnectedImbleDevice unconnectedDevice)
        {
            this.Device = Observable.FromAsync(token => unconnectedDevice.Connect(token))
                .CatchIgnore((Exception e) => { })
                .ToReadOnlyReactiveProperty()
                .AddTo(this.disposables);

            this.IsConnected = this.Device.Select(device => device != null).ToReadOnlyReactiveProperty().AddTo(this.disposables);

            this.DeviceStatus = this.Device
                .Where(device => device != null)
                .Select(device => device.ObserveProperty(self => self.Status))
                .Switch()
                .Do(value => Debug.WriteLine(value))
                .ObserveOnUIDispatcher()
                .ToReadOnlyReactiveProperty()
                .AddTo(this.disposables);

            this.ReceivedMessage = this.Device
                .Where(device => device != null)
                .Select(device => Observable.FromEventPattern<DataArrivedEventArgs>(handler => device.DataArrived += handler, handler => device.DataArrived -= handler))
                .Switch()
                .Select(args => new ReceivedMessageViewModel(args.EventArgs.Data, args.EventArgs.Timestamp))
                .OnErrorRetry()
                .ToReadOnlyReactiveProperty()
                .AddTo(this.disposables);

            var notBusyNotifier = new BooleanNotifier(false);
            
            this.Name = new ReactiveProperty<string>("Fuga")
                .SetValidateNotifyError(value => value != null && Encoding.UTF8.GetByteCount(value) < 12 ? null : "Input short message")
                .AddTo(this.disposables);

            this.CanSendCommand = Observable.CombineLatest(
                this.DeviceStatus.Select(status => status == ImbleDeviceStatus.Running),
                this.Name.ObserveHasErrors,
                notBusyNotifier.Do(value => Debug.WriteLine(value)),
                (isRunning, hasErrors, notBusy) => isRunning && !hasErrors && notBusy)
                .ToReadOnlyReactiveProperty().AddTo(this.disposables);
            notBusyNotifier.TurnOn();

            this.SendCommand = this.CanSendCommand.ToReactiveCommand().AddTo(this.disposables);
            this.SendCommand
                .Do(_ => notBusyNotifier.TurnOff())
                .Select(_ =>
                {
                    var data = Encoding.UTF8.GetBytes(this.Name.Value);
                        return Observable.FromAsync(token =>
                        {
                            using (var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
                            using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token, timeoutTokenSource.Token))
                            {
                                return this.Device.Value.SendAsync(data, 0, data.Length, linkedTokenSource.Token);
                            }
                        })
                        .Finally(() => notBusyNotifier.TurnOn());
                })
                .Switch()
                .OnErrorRetry((Exception e) => Debug.WriteLine(e))
                .Subscribe()
                .AddTo(this.disposables);
        }