/// <summary>
        /// Listen for any changed in device access permission. The user can block access to the device while the device is in use.
        /// If the user blocks access to the device while the device is opened, the device's handle will be closed automatically by
        /// the system; it is still a good idea to close the device explicitly so that resources are cleaned up.
        ///
        /// Note that by the time the AccessChanged event is raised, the device handle may already be closed by the system.
        /// </summary>
        private void RegisterForDeviceAccessStatusChange()
        {
            deviceAccessInformation = DeviceAccessInformation.CreateFromId(deviceInformation.Id);

            deviceAccessEventHandler = new TypedEventHandler <DeviceAccessInformation, DeviceAccessChangedEventArgs>(this.OnDeviceAccessChanged);
            deviceAccessInformation.AccessChanged += deviceAccessEventHandler;
        }
        private async Task Connect(DeviceInformation deviceInformation)
        {
            // Perform device access checks before trying to get the device.
            // First, we check if consent has been explicitly denied by the user.
            var accessStatus = DeviceAccessInformation.CreateFromId(deviceInformation.Id).CurrentStatus;

            if (accessStatus == DeviceAccessStatus.DeniedByUser)
            {
                throw new UnauthorizedAccessException("This app does not have access to connect to the remote device (please grant access in Settings > Privacy > Other Devices");
            }
            var bluetoothDevice = await BluetoothDevice.FromIdAsync(deviceInformation.Id);

            // This should return a list of uncached Bluetooth services (so if the server was not active when paired, it will still be detected by this call)
            var rfcommServices = await bluetoothDevice.GetRfcommServicesAsync();

            RfcommDeviceService bluetoothService = null;

            foreach (var service in rfcommServices.Services)
            {
                System.Diagnostics.Debug.WriteLine("Service {0}: {1}", service.ConnectionHostName, service.ConnectionServiceName);
                if (service.ServiceId.Uuid == RfcommServiceId.SerialPort.Uuid)
                {
                    bluetoothService = service;
                    break;
                }
            }
            if (bluetoothService != null)
            {
                bluetoothDevice.ConnectionStatusChanged += BluetoothDevice_ConnectionStatusChanged;
                var device = new UwpRfcommDevice(deviceInformation, bluetoothService);
                connectedDevices.Add(device.deviceInfo.Id, device);
                DeviceConnected?.Invoke(device);
            }
        }
Example #3
0
        /// <summary>
        /// This method opens the device using the WinRT USB API. After the device is opened, save the device
        /// so that it can be used across scenarios.
        ///
        /// It is important that the FromIdAsync call is made on the UI thread because the consent prompt can only be displayed
        /// on the UI thread.
        ///
        /// This method is used to reopen the device after the device reconnects to the computer and when the app resumes.
        /// </summary>
        /// <param name="deviceInfo">Device information of the device to be opened</param>
        /// <param name="deviceSelector">The AQS used to find this device</param>
        /// <returns>True if the device was successfully opened, false if the device could not be opened for well known reasons.
        /// An exception may be thrown if the device could not be opened for extraordinary reasons.</returns>
        public async Task <bool> OpenDeviceAsync(DeviceInformation deviceInfo, String deviceSelector)
        {
            Device = await UsbDevice.FromIdAsync(deviceInfo.Id);

            Boolean successfullyOpenedDevice = false;

            MainPage.NotifyType notificationStatus;
            String notificationMessage = null;

            // Device could have been blocked by user or the device has already been opened by another app.
            if (Device != null)
            {
                successfullyOpenedDevice = true;

                DeviceInformation   = deviceInfo;
                this.DeviceSelector = deviceSelector;

                notificationStatus  = MainPage.NotifyType.StatusMessage;
                notificationMessage = "Device Opened";

                // Notify registered callback handle that the device has been opened
                if (OnDeviceConnected != null)
                {
                    OnDeviceConnected(this, DeviceInformation);
                }
            }
            else
            {
                successfullyOpenedDevice = false;

                notificationStatus = MainPage.NotifyType.ErrorMessage;

                DeviceAccessInformation dai = DeviceAccessInformation.CreateFromId(deviceInfo.Id);

                var deviceAccessStatus = dai.CurrentStatus;

                if (deviceAccessStatus == DeviceAccessStatus.DeniedByUser)
                {
                    notificationMessage = "Access to the device was blocked by the user.";
                }
                else if (deviceAccessStatus == DeviceAccessStatus.DeniedBySystem)
                {
                    // This status is most likely caused by app permissions (did not declare the device in the app's package.appxmanifest)
                    // This status does not cover the case where the device is already opened by another app.
                    notificationMessage = "Access to the device was blocked by the system.";
                }
                else
                {
                    // The only time I made it to this error I forgot to add Fadecandy to package.appxmanifest
                    // Most likely the device is opened by another app, but cannot be sure
                    notificationMessage = "Unknown error, possibly opened by another app.";
                }
            }

            MainPage.Current.NotifyUser(notificationMessage, deviceInfo.Id, notificationStatus);

            return(successfullyOpenedDevice);
        }
        private void RegisterForDeviceAccessStatusChange()
        {
            if (_deviceAccessInformation == null)
            {
                _deviceAccessInformation = DeviceAccessInformation.CreateFromId(DeviceInformation.Id);
            }

            _deviceAccessInformation.AccessChanged += OnAccessInformation_AccessChanged;
        }
Example #5
0
        /// <summary>
        /// Listen for any changed in device access permission. The user can block access to the device while the device is in use.
        /// If the user blocks access to the device while the device is opened, the device's handle will be closed automatically by
        /// the system; it is still a good idea to close the device explicitly so that resources are cleaned up.
        ///
        /// Note that by the time the AccessChanged event is raised, the device handle may already be closed by the system.
        /// </summary>
        private void RegisterForDeviceAccessStatusChange()
        {
            // Enable the following registration ONLY if the Serial device under test is non-internal.
            //

            deviceAccessInformation  = DeviceAccessInformation.CreateFromId(deviceInformation.Id);
            deviceAccessEventHandler = this.OnDeviceAccessChanged;
            deviceAccessInformation.AccessChanged += deviceAccessEventHandler;
        }
Example #6
0
        private async Task XboxJoystickInit(DeviceInformationCollection deviceInformationCollection)
        {
            //string deviceSelector = HidDevice.GetDeviceSelector(0x01, 0x05);
            //DeviceInformationCollection deviceInformationCollection = await DeviceInformation.FindAllAsync(deviceSelector);

            DeviceId = null;
            int deviceCount = deviceInformationCollection.Count;

            if (deviceCount == 0)
            {
                Debug.WriteLine("Error: No Xbox360 controller found!");
                JoystickIsWorking = false;
            }
            else
            {
                foreach (DeviceInformation d in deviceInformationCollection)
                {
                    Debug.WriteLine("OK: Found: Xbox 360 Joystick Device ID: " + d.Id);

                    HidDevice hidDevice = await HidDevice.FromIdAsync(d.Id, Windows.Storage.FileAccessMode.Read);

                    if (hidDevice == null)
                    {
                        JoystickIsWorking = false;
                        try
                        {
                            var deviceAccessStatus = DeviceAccessInformation.CreateFromId(d.Id).CurrentStatus;

                            if (!deviceAccessStatus.Equals(DeviceAccessStatus.Allowed))
                            {
                                Debug.WriteLine("IP: DeviceAccess: " + deviceAccessStatus.ToString());
                            }
                        }
                        catch (Exception e)
                        {
                            Debug.WriteLine("Error: Xbox init - " + e.Message);
                        }

                        Debug.WriteLine("Error: Failed to connect to Xbox 360 Joystick controller!");
                    }
                    else
                    {
                        controller = new XboxHidController(hidDevice);
                        controller.JoystickDataChanged += Controller_JoystickDataChanged;
                        JoystickIsWorking = true;
                        DeviceId          = d.Id;
                    }
                }
            }
            lastControllerCount = deviceCount;
        }
Example #7
0
        private async Task <SerialDevice> GetSerialDeviceAsync(string serialPortName)
        {
            Assure.CheckFlowState(!string.IsNullOrEmpty(serialPortName), $"Empty '{nameof(serialPortName)}'.");

            // ReSharper disable AssignNullToNotNullAttribute
            var aqsFilter = SerialDevice.GetDeviceSelector(serialPortName);
            // ReSharper restore AssignNullToNotNullAttribute
            var deviceInformation = (await DeviceInformation.FindAllAsync(aqsFilter)).FirstOrDefault();

            if (deviceInformation == null)
            {
                throw new DeviceIoPortInitializationException($"Serial device on '{serialPortName}' port was not found.");
            }

            var portOpenningTry = 0;

GetSerialDeviceTry:
            portOpenningTry++;

            var serialDevice = await SerialDevice.FromIdAsync(deviceInformation.Id);

            if (serialDevice != null)
            {
                return(serialDevice);
            }

            var deviceAccessStatus = DeviceAccessInformation.CreateFromId(deviceInformation.Id).CurrentStatus;

            switch (deviceAccessStatus)
            {
            case DeviceAccessStatus.DeniedByUser:
                throw new DeviceIoPortInitializationException($"Access to device on '{serialPortName}' port was blocked by the user.");

            case DeviceAccessStatus.DeniedBySystem:
                // This status is most likely caused by app permissions (did not declare the device in the app's package.appxmanifest)
                // This status does not cover the case where the device is already opened by another app.
                throw new DeviceIoPortInitializationException($"Access to device on '{serialPortName}' was blocked by the system.");

            default:
                // Sometimes serial port is not freed fast after previous Dispose. Retry.
                var message = $"Access to device on '{serialPortName}' was blocked with unknown error (try {portOpenningTry}). Possibly opened by another app.";
                if (portOpenningTry < MaxPortOpenningTries)
                {
                    Log.Error(LogContextEnum.Device, message);
                    await Task.Delay(PortOpenningTryDelay);

                    goto GetSerialDeviceTry;
                }
                throw new DeviceIoPortInitializationException(message);
            }
        }
Example #8
0
        private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation dev)
        {
            SerialDevice serialDevice = await SerialDevice.FromIdAsync(dev.Id);

            var deviceAccessStatus = DeviceAccessInformation.CreateFromId(dev.Id).CurrentStatus;

            if (serialDevice != null)
            {
                SerialDeviceInfo devinfo;
                devinfo.devInfo      = dev;
                devinfo.serialDevice = serialDevice;
                DeviceList.Add(serialDevice.PortName, devinfo);
                NotifySerialDeviceStatus?.Invoke("Serial Device added.");
            }
        }
        /// <summary>
        /// Invoked when the device watcher detects that the activity sensor was added.
        /// </summary>
        /// <param name="sender">The device watcher.</param>
        /// <param name="device">The device that was added.</param>
        private async void OnActivitySensorAddedAsync(DeviceWatcher sender, DeviceInformation device)
        {
            if (this.activitySensor == null)
            {
                var addedSensor = await ActivitySensor.FromIdAsync(device.Id);

                if (addedSensor != null)
                {
                    this.activitySensor = addedSensor;

                    this.deviceAccessInformation = DeviceAccessInformation.CreateFromId(this.activitySensor.DeviceId);
                    this.deviceAccessInformation.AccessChanged += DeviceAccessInfo_AccessChangedAsync;
                }
            }
        }
Example #10
0
        private async void XboxJoystickInit()
        {
            string deviceSelector = HidDevice.GetDeviceSelector(0x01, 0x05);
            DeviceInformationCollection deviceInformationCollection = await DeviceInformation.FindAllAsync(deviceSelector);

            if (deviceInformationCollection.Count == 0)
            {
                Debug.WriteLine("No Xbox360 controller found!");
            }
            lastControllerCount = deviceInformationCollection.Count;

            foreach (DeviceInformation d in deviceInformationCollection)
            {
                Debug.WriteLine("Device ID: " + d.Id);

                HidDevice hidDevice = await HidDevice.FromIdAsync(d.Id, Windows.Storage.FileAccessMode.Read);

                if (hidDevice == null)
                {
                    try
                    {
                        var deviceAccessStatus = DeviceAccessInformation.CreateFromId(d.Id).CurrentStatus;

                        if (!deviceAccessStatus.Equals(DeviceAccessStatus.Allowed))
                        {
                            Debug.WriteLine("DeviceAccess: " + deviceAccessStatus.ToString());
                            FoundLocalControlsWorking = true;
                        }
                    }
                    catch (Exception e)
                    {
                        Debug.WriteLine("Xbox init - " + e.Message);
                    }

                    Debug.WriteLine("Failed to connect to the controller!");
                }

                // controller = new XboxHidController(hidDevice);
                // controller.DirectionChanged += Controller_DirectionChanged;
                this.deviceHandle = hidDevice;
                this.deviceHandle.InputReportReceived += DeviceHandle_InputReportReceived1;
            }
        }
 /// <summary>
 /// 可以使用当前设备
 /// </summary>
 private static ErrorMessageType IsCanUseCurrentDevice()
 {
     try
     {
         var deviceInfo = DeviceAccessInformation.CreateFromId(CurrentCamDevice.Id);
         if (deviceInfo.CurrentStatus == DeviceAccessStatus.DeniedByUser)
         {
             return(ErrorMessageType.Camera_Start_UserDenied);
         }
         else if (deviceInfo.CurrentStatus == DeviceAccessStatus.DeniedBySystem)
         {
             return(ErrorMessageType.Camera_Start_SystemDenied);
         }
     }
     catch (Exception ex)
     {
     }
     return(ErrorMessageType.None);
 }
Example #12
0
        private async Task <bool> InitializeRfcommClient(IRemoteDevice remoteServer)
        {
            var accessStatus = DeviceAccessInformation.CreateFromId(remoteServer.DeviceId).CurrentStatus;

            if (accessStatus == DeviceAccessStatus.DeniedByUser)
            {
                Debug.Write("This app does not have access to connect to the remote device (please grant access in Settings > Privacy > Other Devices");
                return(false);
            }

            var success = await remoteServer.TryAndConnectToDevice();

            var bluetoothDevice = (RemoteBluetoothDevice)remoteServer;

            m_socket = await bluetoothDevice.EstablishSocketEndPoint();

            m_messageOutstream = new DataWriter(m_socket.OutputStream);
            m_messageInStream  = new DataReader(m_socket.InputStream);
            return(success);
        }
Example #13
0
        public override async void Connect()
        {
            var accessStatus = DeviceAccessInformation.CreateFromId(Id).CurrentStatus;

            if (accessStatus == DeviceAccessStatus.DeniedByUser)
            {
                _logger.NotifyUserError("BT Channel", "This app does not have access to connect to the remote device (please grant access in Settings > Privacy > Other Devices");
                return;
            }

            try
            {
                var bluetoothDevice = await BluetoothDevice.FromIdAsync(Id);

                if (bluetoothDevice == null)
                {
                    _logger.NotifyUserError("BT Channel", "Bluetooth Device returned null. Access Status = " + accessStatus.ToString());
                    return;
                }

                var services = await bluetoothDevice.GetRfcommServicesAsync();

                if (!services.Services.Any())
                {
                    _logger.NotifyUserError("BT Channel", "Could not discover any remote devices.");
                    return;
                }

                _deviceService = services.Services.FirstOrDefault();

                if (await ConnectAsync())
                {
                    InvokeConnected();
                }
            }
            catch (Exception ex)
            {
                _logger.NotifyUserError("BT Channel", ex.Message);
                return;
            }
        }
Example #14
0
        // Find HID devices.
        public static async void Enumerate()
        {
            // Microsoft Input Configuration Device.
            ushort vendorId  = 0x0483;
            ushort productId = 0xA2CA;
            ushort usagePage = 0xf1d0;
            ushort usageId   = 0x0001; // 20 input report, 21, output report

            // Create the selector.
            string selector =
                HidDevice.GetDeviceSelector(usagePage, usageId, vendorId, productId);

            // Enumerate devices using the selector.
            //var devices = await DeviceInformation.FindAllAsync(selector);
            var devicesInfo = await DeviceInformation.FindAllAsync(selector);

            foreach (var deviceInfo in devicesInfo)
            {
                Console.WriteLine($"Device: {deviceInfo.Id}, name:{deviceInfo.Name}, enabled:{deviceInfo.IsEnabled}, kind: {deviceInfo.Kind}");

                var das = DeviceAccessInformation.CreateFromId(deviceInfo.Id);
                Console.WriteLine($"DeviceAccessInforamtion.currentStatus=={das?.CurrentStatus}");

                // Do your stuff here
                HidDevice device = await HidDevice.FromIdAsync(deviceInfo.Id, FileAccessMode.ReadWrite);

                if (device == null)
                {
                    Console.WriteLine($"HidDevice.FromIdAsync({deviceInfo.Id}, {FileAccessMode.ReadWrite})=={device}");
                }
                else
                {
                    Console.WriteLine($"Device connected {device?.ProductId}");
                }
            }
            Console.WriteLine("Done");
        }
        public async Task <bool> InternalOpenDeviceAsync(DeviceInformation deviceInformation)
        {
            if (_device != null)
            {
                throw new Exception();
            }

            _device = await HidDevice.FromIdAsync(deviceInformation.Id, FileAccessMode.ReadWrite);

            if (_device != null)
            {
                DeviceInformation            = deviceInformation;
                _device.InputReportReceived += OnDevice_InputReportReceived;
            }
            else
            {
                var deviceAccessStatus = DeviceAccessInformation.CreateFromId(deviceInformation.Id).CurrentStatus;

                if (deviceAccessStatus == DeviceAccessStatus.DeniedByUser)
                {
                }
                else if (deviceAccessStatus == DeviceAccessStatus.DeniedBySystem)
                {
                    // This status is most likely caused by app permissions (did not declare the device in the app's package.appxmanifest)
                    // This status does not cover the case where the device is already opened by another app.
                }
                else
                {
                    // Most likely the device is opened by another app, but cannot be sure
                }
            }

            OnConnected(_device != null);

            return(_device != null);
        }
Example #16
0
        private async Task <HidDevice> connectAsync(string id)
        {
            try
            {
                var device = await HidDevice.FromIdAsync(id, Windows.Storage.FileAccessMode.Read);

                if (device == null)
                {
                    var    deviceAccessStatus = DeviceAccessInformation.CreateFromId(id).CurrentStatus;
                    var    caption            = this.resources.GetString("errorCaption");
                    string msg = string.Empty;
                    switch (deviceAccessStatus)
                    {
                    case DeviceAccessStatus.DeniedBySystem:
                        msg = this.resources.GetString("hidDeniedBySystem");
                        break;

                    case DeviceAccessStatus.DeniedByUser:
                        msg = this.resources.GetString("hidDeniedByUser");
                        break;
                    }
                    if (this.services != null && msg != string.Empty)
                    {
                        await this.services.MessageService.ShowMessage(msg, caption);
                    }
                    return(null);
                }
                return(device);
            }catch (Exception e)
            {
#if DEBUG
                System.Diagnostics.Debug.WriteLine(e.Message);
#endif
                return(null);
            }
        }
        /// <summary>
        /// Invoked once the user has selected the device to connect to.
        /// Once the user has selected the device,
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void ConnectButton_Click(object sender, RoutedEventArgs e)
        {
            // Make sure user has selected a device first
            if (resultsListView.SelectedItem != null)
            {
                rootPage.NotifyUser("Connecting to remote device. Please wait...", NotifyType.StatusMessage);
            }
            else
            {
                rootPage.NotifyUser("Please select an item to connect to", NotifyType.ErrorMessage);
                return;
            }

            RfcommChatDeviceDisplay deviceInfoDisp = resultsListView.SelectedItem as RfcommChatDeviceDisplay;

            // Perform device access checks before trying to get the device.
            // First, we check if consent has been explicitly denied by the user.
            DeviceAccessStatus accessStatus = DeviceAccessInformation.CreateFromId(deviceInfoDisp.Id).CurrentStatus;

            if (accessStatus == DeviceAccessStatus.DeniedByUser)
            {
                rootPage.NotifyUser("This app does not have access to connect to the remote device (please grant access in Settings > Privacy > Other Devices", NotifyType.ErrorMessage);
                return;
            }

            // If not, try to get the Bluetooth device
            try
            {
                bluetoothDevice = await BluetoothDevice.FromIdAsync(deviceInfoDisp.Id);
            }
            catch (Exception ex)
            {
                rootPage.NotifyUser(ex.Message, NotifyType.ErrorMessage);
                return;
            }

            // If we were unable to get a valid Bluetooth device object,
            // it's most likely because the user has specified that all unpaired devices
            // should not be interacted with.
            if (bluetoothDevice == null)
            {
                rootPage.NotifyUser("Bluetooth Device returned null. Access Status = " + accessStatus.ToString(), NotifyType.ErrorMessage);
            }

            // This should return a list of uncached Bluetooth services (so if the server was not active when paired, it will still be detected by this call
            var rfcommServices = await bluetoothDevice.GetRfcommServicesForIdAsync(
                RfcommServiceId.FromUuid(Constants.RfcommChatServiceUuid), BluetoothCacheMode.Uncached);

            if (rfcommServices.Services.Count > 0)
            {
                chatService = rfcommServices.Services[0];
            }
            else
            {
                rootPage.NotifyUser(
                    "Could not discover the chat service on the remote device",
                    NotifyType.StatusMessage);
                return;
            }

            // Do various checks of the SDP record to make sure you are talking to a device that actually supports the Bluetooth Rfcomm Chat Service
            var attributes = await chatService.GetSdpRawAttributesAsync();

            if (!attributes.ContainsKey(Constants.SdpServiceNameAttributeId))
            {
                rootPage.NotifyUser(
                    "The Chat service is not advertising the Service Name attribute (attribute id=0x100). " +
                    "Please verify that you are running the BluetoothRfcommChat server.",
                    NotifyType.ErrorMessage);
                RunButton.IsEnabled = true;
                return;
            }

            var attributeReader = DataReader.FromBuffer(attributes[Constants.SdpServiceNameAttributeId]);
            var attributeType   = attributeReader.ReadByte();

            if (attributeType != Constants.SdpServiceNameAttributeType)
            {
                rootPage.NotifyUser(
                    "The Chat service is using an unexpected format for the Service Name attribute. " +
                    "Please verify that you are running the BluetoothRfcommChat server.",
                    NotifyType.ErrorMessage);
                RunButton.IsEnabled = true;
                return;
            }

            var serviceNameLength = attributeReader.ReadByte();

            // The Service Name attribute requires UTF-8 encoding.
            attributeReader.UnicodeEncoding = UnicodeEncoding.Utf8;

            deviceWatcher.Stop();

            lock (this)
            {
                chatSocket = new StreamSocket();
            }
            try
            {
                await chatSocket.ConnectAsync(chatService.ConnectionHostName, chatService.ConnectionServiceName);

                SetChatUI(attributeReader.ReadString(serviceNameLength), bluetoothDevice.Name);
                chatWriter = new DataWriter(chatSocket.OutputStream);

                DataReader chatReader = new DataReader(chatSocket.InputStream);
                ReceiveStringLoop(chatReader);
            }
            catch (Exception ex)
            {
                switch ((uint)ex.HResult)
                {
                case (0x80070490):     // ERROR_ELEMENT_NOT_FOUND
                    rootPage.NotifyUser("Please verify that you are running the BluetoothRfcommChat server.", NotifyType.ErrorMessage);
                    RunButton.IsEnabled = true;
                    break;

                default:
                    throw;
                }
            }
        }
Example #18
0
        /// <summary>
        /// This method opens the device using the WinRT Usb API. After the device is opened, save the device
        /// so that it can be used across scenarios.
        ///
        /// It is important that the FromIdAsync call is made on the UI thread because the consent prompt can only be displayed
        /// on the UI thread.
        ///
        /// This method is used to reopen the device after the device reconnects to the computer and when the app resumes.
        /// </summary>
        /// <param name="deviceInfo">Device information of the device to be opened</param>
        /// <param name="deviceSelector">The AQS used to find this device</param>
        /// <returns>True if the device was successfully opened, false if the device could not be opened for well known reasons.
        /// An exception may be thrown if the device could not be opened for extraordinary reasons.</returns>
        public async Task <bool> OpenDeviceAsync(DeviceInformation deviceInfo, String deviceSelector)
        {
            device = await Windows.Devices.Usb.UsbDevice.FromIdAsync(deviceInfo.Id);

            bool successfullyOpenedDevice = false;

            try
            {
                // Device could have been blocked by user or the device has already been opened by another app.
                if (device != null)
                {
                    successfullyOpenedDevice = true;

                    deviceInformation   = deviceInfo;
                    this.deviceSelector = deviceSelector;

                    Debug.WriteLine($"Device {deviceInformation.Id} opened");

                    // Notify registered callback handle that the device has been opened
                    deviceConnectedCallback?.Invoke(this, deviceInformation);

                    // Background tasks are not part of the app, so app events will not have an affect on the device
                    if (!isBackgroundTask && (appSuspendEventHandler == null || appResumeEventHandler == null))
                    {
                        RegisterForAppEvents();
                    }

                    // User can block the device after it has been opened in the Settings charm. We can detect this by registering for the
                    // DeviceAccessInformation.AccessChanged event
                    if (deviceAccessEventHandler == null)
                    {
                        RegisterForDeviceAccessStatusChange();
                    }

                    // Create and register device watcher events for the device to be opened unless we're reopening the device
                    if (deviceWatcher == null)
                    {
                        deviceWatcher = DeviceInformation.CreateWatcher(deviceSelector);

                        RegisterForDeviceWatcherEvents();
                    }

                    if (!watcherStarted)
                    {
                        // Start the device watcher after we made sure that the device is opened.
                        StartDeviceWatcher();
                    }
                }
                else
                {
                    successfullyOpenedDevice = false;

                    //notificationStatus = NotifyType.ErrorMessage;

                    var deviceAccessStatus = DeviceAccessInformation.CreateFromId(deviceInfo.Id).CurrentStatus;

                    switch (deviceAccessStatus)
                    {
                    case DeviceAccessStatus.DeniedByUser:
                        Debug.WriteLine($"Access to the device was blocked by the user : {deviceInfo.Id}");
                        break;

                    case DeviceAccessStatus.DeniedBySystem:
                        // This status is most likely caused by app permissions (did not declare the device in the app's package.appxmanifest)
                        // This status does not cover the case where the device is already opened by another app.
                        Debug.WriteLine($"Access to the device was blocked by the system : {deviceInfo.Id}");
                        break;

                    default:
                        // Most likely the device is opened by another app, but cannot be sure
                        Debug.WriteLine($"Unknown error, possibly opened by another app : {deviceInfo.Id}");
                        break;
                    }
                }
            }
            // catch all because the device open might fail for a number of reasons
            catch { }

            return(successfullyOpenedDevice);
        }
        /// <summary>
        /// This method opens the device using the WinRT Usb API. After the device is opened, save the device
        /// so that it can be used across scenarios.
        ///
        /// It is important that the FromIdAsync call is made on the UI thread because the consent prompt can only be displayed
        /// on the UI thread.
        ///
        /// This method is used to reopen the device after the device reconnects to the computer and when the app resumes.
        /// </summary>
        /// <param name="deviceInfo">Device information of the device to be opened</param>
        /// <param name="deviceSelector">The AQS used to find this device</param>
        /// <returns>True if the device was successfully opened, false if the device could not be opened for well known reasons.
        /// An exception may be thrown if the device could not be opened for extraordinary reasons.</returns>
        public async Task <Boolean> OpenDeviceAsync(DeviceInformation deviceInfo, String deviceSelector)
        {
            device = await UsbDevice.FromIdAsync(deviceInfo.Id);

            Boolean    successfullyOpenedDevice = false;
            NotifyType notificationStatus;
            String     notificationMessage = null;

            // Device could have been blocked by user or the device has already been opened by another app.
            if (device != null)
            {
                successfullyOpenedDevice = true;

                deviceInformation   = deviceInfo;
                this.deviceSelector = deviceSelector;

                notificationStatus  = NotifyType.StatusMessage;
                notificationMessage = "Device " + deviceInformation.Id + " opened";

                // Notify registered callback handle that the device has been opened
                if (deviceConnectedCallback != null)
                {
                    deviceConnectedCallback(this, deviceInformation);
                }

                // Background tasks are not part of the app, so app events will not have an affect on the device
                if (!isBackgroundTask && (appSuspendEventHandler == null || appResumeEventHandler == null))
                {
                    RegisterForAppEvents();
                }

                // User can block the device after it has been opened in the Settings charm. We can detect this by registering for the
                // DeviceAccessInformation.AccessChanged event
                if (deviceAccessEventHandler == null)
                {
                    RegisterForDeviceAccessStatusChange();
                }

                // Create and register device watcher events for the device to be opened unless we're reopening the device
                if (deviceWatcher == null)
                {
                    deviceWatcher = DeviceInformation.CreateWatcher(deviceSelector);

                    RegisterForDeviceWatcherEvents();
                }

                if (!watcherStarted)
                {
                    // Start the device watcher after we made sure that the device is opened.
                    StartDeviceWatcher();
                }
            }
            else
            {
                successfullyOpenedDevice = false;

                notificationStatus = NotifyType.ErrorMessage;

                var deviceAccessStatus = DeviceAccessInformation.CreateFromId(deviceInfo.Id).CurrentStatus;

                switch (deviceAccessStatus)
                {
                case DeviceAccessStatus.DeniedByUser:
                    notificationMessage = "Access to the device was blocked by the user : "******"Access to the device was blocked by the system : " + deviceInfo.Id;
                    break;

                default:
                    // Most likely the device is opened by another app, but cannot be sure
                    notificationMessage = "Unknown error, possibly opened by another app : " + deviceInfo.Id;
                    break;
                }
            }

            MainPage.Current.NotifyUser(notificationMessage, notificationStatus);

            return(successfullyOpenedDevice);
        }
Example #20
0
        /// <summary>
        /// This method opens the device using the WinRT Hid API. After the device is opened, save the device
        /// so that it can be used across scenarios.
        ///
        /// It is important that the FromIdAsync call is made on the UI thread because the consent prompt can only be displayed
        /// on the UI thread.
        ///
        /// This method is used to reopen the device after the device reconnects to the computer and when the app resumes.
        /// </summary>
        /// <param name="deviceInfo">Device information of the device to be opened</param>
        /// <param name="deviceSelector">The AQS used to find this device</param>
        /// <returns>True if the device was successfully opened, false if the device could not be opened for well known reasons.
        /// An exception may be thrown if the device could not be opened for extraordinary reasons.</returns>
        public async Task <Boolean> OpenDeviceAsync(DeviceInformation deviceInfo, String deviceSelector)
        {
            // This sample uses FileAccessMode.ReadWrite to open the device because we do not want other apps opening our device and
            // changing the state of our device. FileAccessMode.Read can be used instead.
            device = await HidDevice.FromIdAsync(deviceInfo.Id, FileAccessMode.ReadWrite);

            Boolean    successfullyOpenedDevice = false;
            NotifyType notificationStatus;
            String     notificationMessage = null;

            // Device could have been blocked by user or the device has already been opened by another app.
            if (device != null)
            {
                successfullyOpenedDevice = true;

                deviceInformation   = deviceInfo;
                this.deviceSelector = deviceSelector;

                notificationStatus  = NotifyType.StatusMessage;
                notificationMessage = "Device " + deviceInformation.Id + " opened";

                if (appSuspendEventHandler == null || appResumeEventHandler == null)
                {
                    RegisterForAppEvents();
                }

                // User can block the device after it has been opened in the Settings charm. We can detect this by registering for the
                // DeviceAccessInformation.AccessChanged event
                if (deviceAccessEventHandler == null)
                {
                    RegisterForDeviceAccessStatusChange();
                }

                // Create and register device watcher events for the device to be opened unless we're reopening the device
                if (deviceWatcher == null)
                {
                    deviceWatcher = DeviceInformation.CreateWatcher(deviceSelector);

                    RegisterForDeviceWatcherEvents();
                }

                if (!watcherStarted)
                {
                    // Start the device watcher after we made sure that the device is opened.
                    StartDeviceWatcher();
                }
            }
            else
            {
                successfullyOpenedDevice = false;

                notificationStatus = NotifyType.ErrorMessage;

                var deviceAccessStatus = DeviceAccessInformation.CreateFromId(deviceInfo.Id).CurrentStatus;

                if (deviceAccessStatus == DeviceAccessStatus.DeniedByUser)
                {
                    notificationMessage = "Access to the device was blocked by the user : "******"Access to the device was blocked by the system : " + deviceInfo.Id;
                }
                else
                {
                    // Most likely the device is opened by another app, but cannot be sure
                    notificationMessage = "Unknown error, possibly opened by another app : " + deviceInfo.Id;
                }
            }

            MainPage.Current.NotifyUser(notificationMessage, notificationStatus);

            // Notify registered callback handle that the device has been opened
            if (deviceConnectedCallback != null)
            {
                var deviceConnectedEventArgs = new OnDeviceConnectedEventArgs(successfullyOpenedDevice, deviceInfo);

                deviceConnectedCallback(this, deviceConnectedEventArgs);
            }

            return(successfullyOpenedDevice);
        }
Example #21
0
        /// <summary>
        /// Invoked once the user has selected the device to connect to.
        /// Once the user has selected the device,
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public async Task <bool> ConnectAsync(RomeRemoteSystem system)
        {
            // Make sure user has selected a device first
            if (system != null)
            {
                Debug.WriteLine("Connecting to remote device. Please wait...");
            }
            else
            {
                Debug.WriteLine("Please select an item to connect to");
                return(false);
            }

            // Perform device access checks before trying to get the device.
            // First, we check if consent has been explicitly denied by the user.
            DeviceAccessStatus accessStatus = DeviceAccessInformation.CreateFromId(system.Id).CurrentStatus;

            if (accessStatus == DeviceAccessStatus.DeniedByUser)
            {
                Debug.WriteLine("This app does not have access to connect to the remote device (please grant access in Settings > Privacy > Other Devices");
                return(false);
            }

            // If not, try to get the Bluetooth device
            try
            {
                _bluetoothDevice = await BluetoothDevice.FromIdAsync(system.Id);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                StopWatcher();
                return(false);
            }

            // If we were unable to get a valid Bluetooth device object,
            // it's most likely because the user has specified that all unpaired devices
            // should not be interacted with.
            if (_bluetoothDevice == null)
            {
                Debug.WriteLine("Bluetooth Device returned null. Access Status = " + accessStatus.ToString());
            }

            if (_bluetoothDevice == null)
            {
                return(false);
            }

            // This should return a list of uncached Bluetooth services (so if the server was not active when paired, it will still be detected by this call
            var rfcommServices = await _bluetoothDevice?.GetRfcommServicesForIdAsync(
                RfcommServiceId.FromUuid(Constants.SERVICE_UUID), BluetoothCacheMode.Uncached);

            if (rfcommServices?.Services.Count > 0)
            {
                _chatService = rfcommServices.Services[0];
            }
            else
            {
                Debug.WriteLine("Could not discover the chat service on the remote device");
                StopWatcher();
                return(false);
            }

            // Do various checks of the SDP record to make sure you are talking to a device that actually supports the Bluetooth Rfcomm Chat Service
            var attributes = await _chatService.GetSdpRawAttributesAsync();

            if (!attributes.ContainsKey(Constants.SERVICE_ATTRIBUTE_ID))
            {
                Debug.WriteLine(
                    "The Chat service is not advertising the Service Name attribute (attribute id=0x100). " +
                    "Please verify that you are running the BluetoothRfcommChat server.");
                StopWatcher();
                return(false);
            }
            var attributeReader = DataReader.FromBuffer(attributes[Constants.SERVICE_ATTRIBUTE_ID]);
            var attributeType   = attributeReader.ReadByte();

            if (attributeType != Constants.SERVICE_ATTRIBUTE_TYPE)
            {
                Debug.WriteLine(
                    "The Chat service is using an unexpected format for the Service Name attribute. " +
                    "Please verify that you are running the BluetoothRfcommChat server.");
                StopWatcher();
                return(false);
            }

            var serviceNameLength = attributeReader.ReadByte();

            // The Service Name attribute requires UTF-8 encoding.
            attributeReader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;

            StopWatcher();

            lock (this)
            {
                _chatSocket = new StreamSocket();
            }
            try
            {
                await _chatSocket.ConnectAsync(_chatService.ConnectionHostName, _chatService.ConnectionServiceName);

                Debug.WriteLine("Connected to : " + attributeReader.ReadString(serviceNameLength) + _bluetoothDevice.Name);
                _chatWriter = new DataWriter(_chatSocket.OutputStream);

                DataReader chatReader = new DataReader(_chatSocket.InputStream);
                ReceiveStringLoop(chatReader);

                return(true);
            }
            catch (Exception ex) when((uint)ex.HResult == 0x80070490)  // ERROR_ELEMENT_NOT_FOUND
            {
                Debug.WriteLine("Please verify that you are running the BluetoothRfcommChat server.");
                StopWatcher();
            }
            catch (Exception ex) when((uint)ex.HResult == 0x80072740)  // WSAEADDRINUSE
            {
                Debug.WriteLine("Please verify that there is no other RFCOMM connection to the same device.");
                StopWatcher();
            }

            return(false);
        }
Example #22
0
        /// <summary>
        /// This method opens the device using the WinRT Serial API. After the device is opened, save the device
        /// so that it can be used across scenarios.
        ///
        /// It is important that the FromIdAsync call is made on the UI thread because the consent prompt can only be displayed
        /// on the UI thread.
        ///
        /// This method is used to reopen the device after the device reconnects to the computer and when the app resumes.
        /// </summary>
        /// <param name="deviceInfo">Device information of the device to be opened</param>
        /// <param name="deviceSelector">The AQS used to find this device</param>
        /// <returns>True if the device was successfully opened, false if the device could not be opened for well known reasons.
        /// An exception may be thrown if the device could not be opened for extraordinary reasons.</returns>
        public async Task <Boolean> OpenDeviceAsync(DeviceInformation deviceInfo, String deviceSelector)
        {
            try
            {
                device = await SerialDevice.FromIdAsync(deviceInfo.Id);
            }
            catch (Exception)
            {
                throw;
            }

            Boolean    successfullyOpenedDevice = false;
            NotifyType notificationStatus;
            String     notificationMessage = null;

            // Device could have been blocked by user or the device has already been opened by another app.
            if (device != null)
            {
                successfullyOpenedDevice = true;

                deviceInformation   = deviceInfo;
                this.deviceSelector = deviceSelector;

                notificationStatus  = NotifyType.StatusMessage;
                notificationMessage = "Device " + deviceInformation.Id + " opened";

                // Notify registered callback handle that the device has been opened
                if (deviceConnectedCallback != null)
                {
                    deviceConnectedCallback(this, deviceInformation);
                }

                if (appSuspendEventHandler == null || appResumeEventHandler == null)
                {
                    RegisterForAppEvents();
                }

                // Register for DeviceAccessInformation.AccessChanged event and react to any changes to the
                // user access after the device handle was opened.
                if (deviceAccessEventHandler == null)
                {
                    RegisterForDeviceAccessStatusChange();
                }

                // Create and register device watcher events for the device to be opened unless we're reopening the device
                if (deviceWatcher == null)
                {
                    deviceWatcher = DeviceInformation.CreateWatcher(deviceSelector);

                    RegisterForDeviceWatcherEvents();
                }

                if (!watcherStarted)
                {
                    // Start the device watcher after we made sure that the device is opened.
                    StartDeviceWatcher();
                }
            }
            else
            {
                successfullyOpenedDevice = false;

                notificationStatus = NotifyType.ErrorMessage;

                var deviceAccessStatus = DeviceAccessInformation.CreateFromId(deviceInfo.Id).CurrentStatus;

                if (deviceAccessStatus == DeviceAccessStatus.DeniedByUser)
                {
                    notificationMessage = "Access to the device was blocked by the user : "******"Access to the device was blocked by the system : " + deviceInfo.Id;
                }
                else
                {
                    // Most likely the device is opened by another app, but cannot be sure
                    notificationMessage = "Unknown error, possibly opened by another app : " + deviceInfo.Id;
                }
            }

            SerialMain.NotifyUser(notificationMessage, notificationStatus);

            return(successfullyOpenedDevice);
        }
Example #23
0
        public async Task <bool> BtConnect(string deviceID)
        {
            try
            {
                //System.Diagnostics.Debug.Assert(Thread.CurrentThread.IsBackground, "SerialComm:BtConnect() cannot be called from the UI thread.");

                DeviceAccessStatus accessStatus = DeviceAccessInformation.CreateFromId(deviceID).CurrentStatus;
                if (accessStatus == DeviceAccessStatus.DeniedByUser)
                {
                    //await OBD2Xam.MainPage.Instance.DisplayAlert("Error",
                    //    "This app does not have access to connect to the remote device.  Please grant access in Settings > Privacy > Other Devices.",
                    //    "Cancel");
                    await Xamarin.Forms.Device.InvokeOnMainThreadAsync(
                        () => { OBD2Xam.MainPage.Instance.DisplayAlert("Error",
                                                                       "This app does not have access to connect to the remote device.  Please grant access in Settings > Privacy > Other Devices.",
                                                                       "Cancel"); }
                        );

                    return(false);
                }

                BluetoothDevice device = await BluetoothDevice.FromIdAsync(deviceID);

                if (device == null)
                {
                    //rootPage.NotifyUser("Bluetooth Device returned null. Access Status = " + accessStatus.ToString(), NotifyType.ErrorMessage);
                    System.Diagnostics.Debug.WriteLine("Bluetooth Device returned null. Access Status = " + accessStatus.ToString());
                    System.Diagnostics.Debugger.Break();
                    return(false);
                }
                //System.Diagnostics.Debug.WriteLine(device.ConnectionStatus);

                DeviceAccessStatus das;
                das = await device.RequestAccessAsync();  // might not always work...

                //System.Diagnostics.Debugger.Break();

                /*
                 * // RequestAccessAsync() needs to executed on the UI thread, which means the UI thread cannot be blocked
                 * // while waiting for all this other crap to run.  So this code needs to be executed in backround,
                 * // WITHOUT an await, because that would cause the UI thread to block.
                 * bool invokeComplete = false;
                 * Xamarin.Forms.Device.BeginInvokeOnMainThread( async () => {
                 *  das = await device.RequestAccessAsync();
                 *  invokeComplete = true;
                 * });
                 *
                 * // now we wait for the UI thread to finish it's task, without await
                 * // because BeginInvokeOnMainThread() isn't awaitable.
                 * while (!invokeComplete)
                 * {
                 *  System.Diagnostics.Debug.WriteLine("waiting...");
                 *  System.Threading.Thread.Sleep(100);
                 * }
                 */

                if (das == DeviceAccessStatus.Allowed)
                {
                    RfcommDeviceServicesResult rfResultList = await device.GetRfcommServicesAsync().AsTask().ConfigureAwait(false);

                    logRfTypes(rfResultList);

                    // https://blog.j2i.net/2018/07/29/connecting-to-bluetooth-rfcomm-with-uwp/
                    if (rfResultList.Services.Count > 0)
                    {
                        foreach (var service in rfResultList.Services)
                        {
                            if (service.ServiceId.AsString() == Constants.BT_SERIAL_PORT_INTERFACE)
                            {
                                streamSocket = new StreamSocket();
                                await streamSocket.ConnectAsync(service.ConnectionHostName, service.ConnectionServiceName);

                                dw = new DataWriter(streamSocket.OutputStream);
                                sr = new StreamReader(streamSocket.InputStream.AsStreamForRead(256));
                                break;
                            }
                        }
                        if (!IsOpen())
                        {
                            throw new Exception("Service not found)");
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                if (exc.Message == "Element not found. (Exception from HRESULT: 0x80070490)")
                {
                    //System.Diagnostics.Debug.WriteLine("Device not listening.");
                    await Xamarin.Forms.Device.InvokeOnMainThreadAsync(
                        () => { OBD2Xam.MainPage.Instance.DisplayAlert("Error", "Device not listening.", "Cancel"); }
                        );

                    this.Close();
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine(exc.Message);
                    System.Diagnostics.Debugger.Break();
                }
            }


            return(IsOpen());
        }
        private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
        {
            try
            {
                mre.WaitOne();

                // Find the Surface Buds
                if (args.Name != null && args.Name == SurfaceBudsName)
                {
                    // check the device isnt already in the list.
                    foreach (var device in deviceList)
                    {
                        if (device.DeviceId == args.Id)
                        {
                            // done - drop right out.
                            return;
                        }
                    }

                    // check it's what we are after
                    DeviceAccessStatus accessStatus = DeviceAccessInformation.CreateFromId(args.Id).CurrentStatus;
                    if (accessStatus != DeviceAccessStatus.DeniedByUser &&
                        accessStatus != DeviceAccessStatus.DeniedBySystem)
                    {
                        var bluetoothDevice = await BluetoothDevice.FromIdAsync(args.Id);

                        if (bluetoothDevice != null)
                        {
                            // add it to the list.
                            var result = await bluetoothDevice.GetRfcommServicesForIdAsync(RfcommServiceId.FromUuid(RfcommLaunchCommandUuid));

                            if (result.Services.Count > 0)
                            {
                                var newDevice = new BudsDeviceInfo();
                                newDevice.DeviceId        = args.Id;
                                newDevice.oneTouchService = result.Services[0];

                                // now check to see if the device is connected
                                foreach (var prop in args.Properties)
                                {
                                    if (prop.Key == "System.Devices.Aep.IsConnected" && prop.Value.GetType() == typeof(bool) && (bool)prop.Value == true)
                                    {
                                        newDevice.IsConnected = true;
                                    }
                                }
                                deviceList.Add(newDevice);

                                var countConnected = 0;
                                foreach (var device in deviceList)
                                {
                                    if (device.IsConnected)
                                    {
                                        countConnected++;
                                    }
                                }

                                UpdateStatusMessage(string.Format("Found {0} device(s). Connected: {1}", deviceList.Count, countConnected));
                            }
                        }
                    }
                }
            }
            catch
            {
                // any exception means its not our device, just ignore it
            }
            finally
            {
                mre.Release();
            }
        }
Example #25
0
        public async Task ConnectBTService()
        {
            BluetoothDevice btDevice;

            if (isSocketOpened)
            {
                Debug.WriteLine("すでにソケットが開かれています。");
                return;
            }

            // Perform device access checks before trying to get the device.
            // First, we check if consent has been explicitly denied by the user.
            DeviceAccessStatus accessStatus = DeviceAccessInformation.CreateFromId(BTDeviceInfo.Id).CurrentStatus;

            if (accessStatus == DeviceAccessStatus.DeniedByUser)
            {
                //rootPage.NotifyUser("This app does not have access to connect to the remote device (please grant access in Settings > Privacy > Other Devices", NotifyType.ErrorMessage);
                throw new UnauthorizedAccessException("ユーザーによってデバイスへのアクセスが拒否されました。");
            }
            // If not, try to get the Bluetooth device
            try
            {
                btDevice = await BluetoothDevice.FromIdAsync(BTDeviceInfo.Id);

                if (btDevice.ConnectionStatus == BluetoothConnectionStatus.Disconnected)
                {
                    //btDevice.RequestAccessAsync
                }
            }
            catch (Exception ex)
            {
                //rootPage.NotifyUser(ex.Message, NotifyType.ErrorMessage);
                //ResetMainUI();
                throw new Exception("Bluetooth Device の取得に失敗しました。", ex);
            }
            // If we were unable to get a valid Bluetooth device object,
            // it's most likely because the user has specified that all unpaired devices
            // should not be interacted with.
            if (btDevice == null)
            {
                throw new NullReferenceException("Bluetooth Device が空です。");
            }


            //Pairされているか確認する
            if (btDevice.DeviceInformation.Pairing.IsPaired == false)
            {
                var status = await btDevice.RequestAccessAsync();

                if (status == DeviceAccessStatus.Allowed)
                {
                    Debug.WriteLine("access granted");
                }
            }


            // This should return a list of uncached Bluetooth services (so if the server was not active when paired, it will still be detected by this call
            var rfcommServices = await btDevice.GetRfcommServicesForIdAsync(RfcommServiceId.FromUuid(Constants.RfcommChatServiceUuid), BluetoothCacheMode.Uncached);

            if (rfcommServices.Services.Count > 0)
            {
                BTDeviceService = rfcommServices.Services[0];
            }
            else
            {
                rfcommServices = await btDevice.GetRfcommServicesAsync();

                if (rfcommServices.Services.Count == 0)
                {
                    throw new NullReferenceException("対象のデバイスにBluetoothサービスが一つも見つかりません。正しい機器に接続していない可能性があります。");
                }
                else
                {
                    foreach (var service in rfcommServices.Services)
                    {
                        Debug.WriteLine(service.ConnectionServiceName + ":::" + service.Device.DeviceInformation.Kind.ToString());
                        if (service.ConnectionServiceName.Contains(Constants.RfcommChatServiceUuid.ToString()))
                        {
                            BTDeviceService = service;
                            break;
                        }
                    }
                    if (BTDeviceService == null)
                    {
                        throw new NullReferenceException("対象のデバイスにBluetoothサービスが一つも見つかりません。正しい機器に接続していない可能性があります。");
                    }
                }
            }

            // Do various checks of the SDP record to make sure you are talking to a device that actually supports the Bluetooth Rfcomm Chat Service
            var attributes = await BTDeviceService.GetSdpRawAttributesAsync();

            if (!attributes.ContainsKey(Constants.SdpServiceNameAttributeId))
            {
                throw new NullReferenceException("対象のデバイスにFantasmicサービスが見つかりません。正しい機器に接続していない可能性があります。");
            }
            var attributeReader = DataReader.FromBuffer(attributes[Constants.SdpServiceNameAttributeId]);
            var attributeType   = attributeReader.ReadByte();

            if (attributeType != Constants.SdpServiceNameAttributeType)
            {
                throw new NullReferenceException("対象のデバイスにFantasmicサービスが見つかりません。正しい機器に接続していない可能性があります。");
            }
            var serviceNameLength = attributeReader.ReadByte();

            // The Service Name attribute requires UTF-8 encoding.
            attributeReader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;

            lock (this)
            {
                BTStreamSocket = new StreamSocket();
            }
            try
            {
                await BTStreamSocket.ConnectAsync(BTDeviceService.ConnectionHostName, BTDeviceService.ConnectionServiceName);

                //SetChatUI(attributeReader.ReadString(serviceNameLength), bluetoothDevice.Name);
                BTWriter       = new DataWriter(BTStreamSocket.OutputStream);
                BTReader       = new DataReader(BTStreamSocket.InputStream);
                isSocketOpened = true;
            }
            catch (Exception ex) when((uint)ex.HResult == 0x80070490)  // ERROR_ELEMENT_NOT_FOUND
            {
                throw new NullReferenceException("ソケットのオープンに失敗しました。対象のデバイスでアプリケーションが起動されていることをご確認ください。(0x80070490: ERROR_ELEMENT_NOT_FOUND)", ex);
            }
            catch (Exception ex) when((uint)ex.HResult == 0x80072740)  // WSAEADDRINUSE
            {
                throw new InvalidOperationException("ソケットのオープンに失敗しました。対象のデバイスがすでに他のサーバーに接続されている可能性があります。(0x80072740: WSAEADDRINUSE)", ex);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("ソケットのオープンに失敗しました。", ex);
            }
        }
Example #26
0
        public virtual void openPort()
        {
            OneWireEventSource.Log.Debug("SerialService.openPort() called");
            OneWireEventSource.Log.Debug("SerialService.openPort: System.Enivronment.CurrentManagedThreadId()=" + Environment.CurrentManagedThreadId);

            // record this thread as an owner
            if (users.IndexOf(Environment.CurrentManagedThreadId) == -1)
            {
                users.Add(Environment.CurrentManagedThreadId);
            }

            if (PortOpen)
            {
                return;
            }

            try
            {
                var t = Task <SerialDevice> .Run(async() =>
                {
                    SerialDevice device;
                    DeviceInformation devInfo = null;

                    if (comPortName.Contains("\\"))
                    {
                        device = await SerialDevice.FromIdAsync(comPortName);

                        if (device == null)
                        {
                            throw new System.IO.IOException("Failed to open PortName: " + comPortName);
                        }
                    }
                    else
                    {
                        devInfo = await GetDeviceInformation(comPortName);

                        if (devInfo == null)
                        {
                            throw new System.IO.IOException("Failed to open PortName: " + comPortName);
                        }

                        device = await SerialDevice.FromIdAsync(devInfo.Id);
                    }

                    if (device == null)
                    {
                        var deviceAccessStatus = DeviceAccessInformation.CreateFromId(devInfo.Id).CurrentStatus;
                        if (deviceAccessStatus == DeviceAccessStatus.DeniedByUser)
                        {
                            OneWireEventSource.Log.Critical("Access to the device was blocked by the user : "******"Possible failure with Package.appamnifgest declaration");
                            OneWireEventSource.Log.Critical("Check your Package.appxmanifest Capabilities section:");
                            OneWireEventSource.Log.Critical("<DeviceCapability Name = \"serialcommunication\">");
                            OneWireEventSource.Log.Critical("  <Device Id = \"any\">");
                            OneWireEventSource.Log.Critical("    <Function Type = \"name:serialPort\"/>");
                            OneWireEventSource.Log.Critical("  </Device>");
                            OneWireEventSource.Log.Critical("</DeviceCapability>");
                        }
                        else
                        {
                            OneWireEventSource.Log.Critical("Unkown error, possibly open by another app : " + devInfo.Id);
                        }

                        throw new System.IO.IOException("Failed to open (" + comPortName + ") check log file!");
                    }

                    writer = new DataWriter(device.OutputStream);
                    reader = new DataReader(device.InputStream);
                    reader.InputStreamOptions = InputStreamOptions.Partial;

                    return(device);
                });

                t.Wait();
                if (t.Status != TaskStatus.RanToCompletion)
                {
                    throw new System.IO.IOException("Failed to open (" + comPortName + ")");
                }

                serialPort = t.Result;

                // flow i/o
                // This generates an exception on Keyspan USA-19HS
                //TODO                    serialPort.Handshake = SerialHandshake.None;

                // bug workaround
                write((byte)0);

                // settings
                serialPort.ReadTimeout  = new System.TimeSpan(0, 0, 0, 0, 100);
                serialPort.WriteTimeout = new System.TimeSpan(0, 0, 0, 0, 100);

                // set baud rate
                serialPort.BaudRate = 9600;
                serialPort.DataBits = 8;
                serialPort.StopBits = SerialStopBitCount.One;
                serialPort.Parity   = SerialParity.None;

                // power adapter
                serialPort.IsDataTerminalReadyEnabled = true;
                serialPort.IsRequestToSendEnabled     = true;

                OneWireEventSource.Log.Debug("SerialService.openPort: Port Openend (" + comPortName + ")");
            }
            catch (Exception e)
            {
                this.Close();
                throw new System.IO.IOException("Failed to open (" + comPortName + ") :" + e);
            }
        }
Example #27
0
        private async void Connect(DeviceInformation devInfo)
        {
            // Perform device access checks before trying to get the device.
            // First, we check if consent has been explicitly denied by the user.
            DeviceAccessStatus accessStatus = DeviceAccessInformation.CreateFromId(devInfo.Id).CurrentStatus;

            if (accessStatus != DeviceAccessStatus.Allowed)
            {
                System.Diagnostics.Debug.WriteLine("Access State: " + accessStatus);
                System.Diagnostics.Debug.WriteLine("This app does not have access to connect to the remote device (please grant access in Settings > Privacy > Other Devices");
                //return;
            }

            // TODO: Maybe automatic pairing?

            try {
                bluetoothDevice = await BluetoothDevice.FromIdAsync(devInfo.Id);
            } catch (Exception ex) {
                System.Diagnostics.Debug.WriteLine("Error: Couldn't get BluetoothDevice");
                return;
            }

            if (bluetoothDevice == null)
            {
                System.Diagnostics.Debug.WriteLine("Bluetooth Device returned null. Access Status = " + accessStatus.ToString());
            }

            // This should return a list of uncached Bluetooth services (so if the server was not active when paired, it will still be detected by this call
            var rfcommServices = await bluetoothDevice.GetRfcommServicesForIdAsync(
                RfcommServiceId.FromUuid(Constants.RfcommChatServiceUuid), BluetoothCacheMode.Uncached); // Maybe change to cached???

            if (rfcommServices.Services.Count > 0)
            {
                service = rfcommServices.Services[0];
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("Error: Could not discover the chat service on the remote device");
                System.Diagnostics.Debug.WriteLine("Paired: " + devInfo.Pairing.IsPaired);
                System.Diagnostics.Debug.WriteLine("Connection Status: " + bluetoothDevice.ConnectionStatus);
                return;
            }

            // Do various checks of the SDP record to make sure you are talking to a device that actually supports the Bluetooth Rfcomm Chat Service
            var attributes = await service.GetSdpRawAttributesAsync();

            if (!attributes.ContainsKey(Constants.SdpServiceNameAttributeId))
            {
                System.Diagnostics.Debug.WriteLine(
                    "The service is not advertising the Service Name attribute (attribute id=0x100).");
                return;
            }
            var attributeReader = DataReader.FromBuffer(attributes[Constants.SdpServiceNameAttributeId]);
            var attributeType   = attributeReader.ReadByte();

            if (attributeType != Constants.SdpServiceNameAttributeType)
            {
                System.Diagnostics.Debug.WriteLine(
                    "The Chat service is using an unexpected format for the Service Name attribute. ");
                return;
            }
            var serviceNameLength = attributeReader.ReadByte();

            // The Service Name attribute requires UTF-8 encoding.
            attributeReader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;

            StopWatcher();

            lock (this) {
                socket = new StreamSocket();
            }
            try {
                await socket.ConnectAsync(service.ConnectionHostName, service.ConnectionServiceName);

                writer = new DataWriter(socket.OutputStream);
                reader = new DataReader(socket.InputStream);

                System.Diagnostics.Debug.WriteLine("Connected to Server");
                isConnected = true;
                OnConnected();

                mainLoop();
            } catch (Exception ex) when((uint)ex.HResult == 0x80070490)   // ERROR_ELEMENT_NOT_FOUND
            {
                System.Diagnostics.Debug.WriteLine("Please verify that you are running the BluetoothRfcommChat server.");
            } catch (Exception ex) when((uint)ex.HResult == 0x80072740)    // WSAEADDRINUSE
            {
                System.Diagnostics.Debug.WriteLine("Please verify that there is no other RFCOMM connection to the same device.");
            }
        }
        /// <summary>
        /// This method opens the device using the WinRT Serial API. After the device is opened, save the device
        /// so that it can be used across scenarios.
        ///
        /// It is important that the FromIdAsync call is made on the UI thread because the consent prompt can only be displayed
        /// on the UI thread.
        ///
        /// This method is used to reopen the device after the device reconnects to the computer and when the app resumes.
        /// </summary>
        /// <returns>
        /// True if the device was successfully opened, false if the device could not be opened for well known reasons.
        /// An exception may be thrown if the device could not be opened for extraordinary reasons.
        /// </returns>
        public async Task <bool> OpenDeviceAsync(DeviceInformation deviceInfo, string deviceSelector)
        {
            bool       successfullyOpenedDevice = false;
            NotifyType notificationStatus;
            string     notificationMessage = null;

            Device = await SerialDevice.FromIdAsync(deviceInfo.Id);

            // Device could have been blocked by user or the device has already been opened by another app.
            if (Device != null)
            {
                successfullyOpenedDevice = true;
                DeviceInformation        = deviceInfo;
                DeviceSelector           = deviceSelector;

                // necessary for the MALT read/write to work
                try
                {
                    Device.BaudRate  = 9600;
                    Device.DataBits  = 8;
                    Device.Handshake = SerialHandshake.None;
                }
                catch { }

                // should be set by default
                try
                {
                    Device.StopBits = SerialStopBitCount.One;
                    Device.Parity   = SerialParity.None;
                }
                catch { }

                notificationStatus  = NotifyType.StatusMessage;
                notificationMessage = "Device " + DeviceInformation.Id + " opened";

                // Notify registered callback handle that the device has been opened
                OnDeviceConnected?.Invoke(this, DeviceInformation);

                if (appSuspendEventHandler == null || appResumeEventHandler == null)
                {
                    RegisterForAppEvents();
                }

                // Register for DeviceAccessInformation.AccessChanged event and react to any changes to the
                // user access after the device handle was opened.
                if (deviceAccessEventHandler == null)
                {
                    RegisterForDeviceAccessStatusChange();
                }

                // Create and register device watcher events for the device to be opened unless we're reopening the device
                if (deviceWatcher == null)
                {
                    deviceWatcher = DeviceInformation.CreateWatcher(deviceSelector);
                    RegisterForDeviceWatcherEvents();
                }

                if (!watcherStarted)
                {
                    // Start the device watcher after we made sure that the device is opened.
                    StartDeviceWatcher();
                }
            }
            else
            {
                successfullyOpenedDevice = false;
                notificationStatus       = NotifyType.ErrorMessage;

                var deviceAccessStatus = DeviceAccessInformation.CreateFromId(deviceInfo.Id).CurrentStatus;
                if (deviceAccessStatus == DeviceAccessStatus.DeniedByUser)
                {
                    notificationMessage = "Access to the device was blocked by the user : "******"Access to the device was blocked by the system : " + deviceInfo.Id;
                }
                else
                {
                    // Most likely the device is opened by another app, but cannot be sure
                    notificationMessage = "Unknown error, possibly opened by another app : " + deviceInfo.Id;
                }
            }

            MainPage.Current.NotifyUser(notificationMessage, notificationStatus);
            return(successfullyOpenedDevice);
        }
        public async Task ConnectAsync(string macAddress, string serviceUuid, bool noRetry = false)
        {
            if (IsConnecting)
            {
                Log.Debug($"WindowsRT.BluetoothService: Already connecting. Skipping request.");
                return;
            }
            if (IsStreamConnected)
            {
                Log.Debug($"WindowsRT.BluetoothService: Already connected. Skipping request.");
                return;
            }

            Connecting?.Invoke(this, EventArgs.Empty);

            try
            {
                var matches = _deviceCache.Where(x =>
                                                 string.Equals(x.Address, macAddress, StringComparison.CurrentCultureIgnoreCase)).ToList();
                if (matches.Count <= 0)
                {
                    Log.Error(
                        $"WindowsRT.BluetoothService: Registered device not available. Expected MAC: {macAddress}");
                    BluetoothErrorAsync?.Invoke(this, new BluetoothException(
                                                    BluetoothException.ErrorCodes.ConnectFailed,
                                                    "Device unavailable. Not device with registered MAC address not found nearby. If you are certain that your earbuds are connected to this computer, please unregister them and try again."));
                }
                else
                {
                    Log.Debug(
                        $"WindowsRT.BluetoothService: Selected '{matches[0].Name}' ({matches[0].Address}) from cache as target");
                }

                // Perform device access checks before trying to get the device.
                // First, we check if consent has been explicitly denied by the user.
                var accessStatus = DeviceAccessInformation.CreateFromId(matches[0].Id).CurrentStatus;
                if (accessStatus == DeviceAccessStatus.DeniedByUser)
                {
                    Log.Error($"WindowsRT.BluetoothService: Access to device explicitly denied by user");
                    BluetoothErrorAsync?.Invoke(this,
                                                new BluetoothException(BluetoothException.ErrorCodes.ConnectFailed,
                                                                       "This app does not have access to connect to the remote device (please grant access in Settings > Privacy > Other Devices"));
                    return;
                }

                if (accessStatus == DeviceAccessStatus.DeniedBySystem)
                {
                    Log.Error($"WindowsRT.BluetoothService: Access to device denied by system");
                    BluetoothErrorAsync?.Invoke(this,
                                                new BluetoothException(BluetoothException.ErrorCodes.ConnectFailed,
                                                                       "Access denied by system. This app does not have access to connect to the remote device"));
                    return;
                }

                // If not, try to get the Bluetooth device
                try
                {
                    _bluetoothDevice = await Windows.Devices.Bluetooth.BluetoothDevice.FromIdAsync(matches[0].Id);
                }
                catch (Exception ex)
                {
                    Log.Error(
                        $"WindowsRT.BluetoothService: Error while getting Bluetooth device from cached id: {ex.Message}");
                    BluetoothErrorAsync?.Invoke(this,
                                                new BluetoothException(BluetoothException.ErrorCodes.ConnectFailed,
                                                                       ex.Message));
                    return;
                }

                // If we were unable to get a valid Bluetooth device object,
                // it's most likely because the user has specified that all unpaired devices
                // should not be interacted with.
                if (_bluetoothDevice == null)
                {
                    Log.Error($"WindowsRT.BluetoothService: BluetoothDevice.FromIdAsync returned NULL");
                    BluetoothErrorAsync?.Invoke(this,
                                                new BluetoothException(BluetoothException.ErrorCodes.ConnectFailed,
                                                                       "Unable to retrieve device object. Try to re-pair your Bluetooth device."));
                    return;
                }

                // This should return a list of uncached Bluetooth services (so if the server was not active when paired, it will still be detected by this call
                var rfcommServices = await _bluetoothDevice.GetRfcommServicesForIdAsync(
                    RfcommServiceId.FromUuid(new Guid(serviceUuid)), BluetoothCacheMode.Uncached);

                if (rfcommServices.Services.Count > 0)
                {
                    _service = rfcommServices.Services[0];
                }
                else
                {
                    Log.Error($"WindowsRT.BluetoothService: SPP service not discovered");
                    BluetoothErrorAsync?.Invoke(this,
                                                new BluetoothException(BluetoothException.ErrorCodes.ConnectFailed,
                                                                       "Unable to discover SDP record for the RFCOMM protocol. Either your earbuds are out of range or ran out of battery."));
                    return;
                }

                lock (this)
                {
                    _socket = new StreamSocket();
                }

                try
                {
                    await _socket.ConnectAsync(_service.ConnectionHostName, _service.ConnectionServiceName);

                    Connected?.Invoke(this, EventArgs.Empty);
                    Log.Debug($"WindowsRT.BluetoothService: Connected");

                    _writer = new DataWriter(_socket.OutputStream);

                    Log.Debug("WindowsRT.BluetoothService: Launching BluetoothServiceLoop...");
                    RfcommConnected?.Invoke(this, EventArgs.Empty);

                    IsStreamConnected = true;

                    _loopCancellation = new CancellationTokenSource();
                    _loop             = Task.Run(BluetoothServiceLoop);
                }
                catch (Exception ex) when((uint)ex.HResult == 0x80070490)   // ERROR_ELEMENT_NOT_FOUND
                {
                    Log.Error(
                        "WindowsRT.BluetoothService: Error while connecting (HRESULT: ERROR_ELEMENT_NOT_FOUND): " +
                        ex.Message);
                    BluetoothErrorAsync?.Invoke(this,
                                                new BluetoothException(BluetoothException.ErrorCodes.ConnectFailed,
                                                                       "SPP server on remote device unavailable. Please reboot your earbuds by placing both into the case and closing it. (ERROR_ELEMENT_NOT_FOUND)"));
                }
                catch (Exception ex) when((uint)ex.HResult == 0x80072740)   // WSAEADDRINUSE
                {
                    Log.Error("WindowsRT.BluetoothService: Address already in use");
                    BluetoothErrorAsync?.Invoke(this,
                                                new BluetoothException(BluetoothException.ErrorCodes.ConnectFailed,
                                                                       "Target address already in use. Only one app can talk to the Galaxy Buds at a time. " +
                                                                       "Please make sure to close duplicate instances of this app and close all applications that are interacting with the proprietary RFCOMM protocol, such as Samsung's official firmware updater"));
                }
            }
            catch (Exception ex)
            {
                Log.Error("WindowsRT.BluetoothService: Unknown error while connecting: " + ex);
                BluetoothErrorAsync?.Invoke(this,
                                            new BluetoothException(BluetoothException.ErrorCodes.ConnectFailed,
                                                                   ex.Message));
            }
        }
Example #30
0
        public async void ConnectAsync(RfcommChatDeviceDisplay deviceInfoDisp)
        {
            // Perform device access checks before trying to get the device.
            // First, we check if consent has been explicitly denied by the user.
            DeviceAccessStatus accessStatus = DeviceAccessInformation.CreateFromId(deviceInfoDisp.Id).CurrentStatus;

            if (accessStatus == DeviceAccessStatus.DeniedByUser)
            {
                throw new UnauthorizedAccessException("This app does not have access to connect to the remote device (please grant access in Settings > Privacy > Other Devices");
            }
            // If not, try to get the Bluetooth device
            try
            {
                bluetoothDevice = await BluetoothDevice.FromIdAsync(deviceInfoDisp.Id);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            // If we were unable to get a valid Bluetooth device object,
            // it's most likely because the user has specified that all unpaired devices
            // should not be interacted with.
            if (bluetoothDevice == null)
            {
                throw new InvalidOperationException("Bluetooth Device returned null. Access Status = " + accessStatus.ToString());
            }

            // This should return a list of uncached Bluetooth services (so if the server was not active when paired, it will still be detected by this call
            var rfcommServices = await bluetoothDevice.GetRfcommServicesForIdAsync(
                RfcommServiceId.FromUuid(RfcommChatServiceUuid), BluetoothCacheMode.Uncached);

            if (rfcommServices.Services.Count > 0)
            {
                chatService = rfcommServices.Services[0];
            }
            else
            {
                throw new InvalidOperationException("Could not discover the chat service on the remote device");
            }

            // Do various checks of the SDP record to make sure you are talking to a device that actually supports the Bluetooth Rfcomm Chat Service
            var attributes = await chatService.GetSdpRawAttributesAsync();

            if (!attributes.ContainsKey(SdpServiceNameAttributeId))
            {
                throw new InvalidOperationException("The Chat service is not advertising the Service Name attribute (attribute id=0x100). " +
                                                    "Please verify that you are running the BluetoothRfcommChat server.");
            }
            var attributeReader = DataReader.FromBuffer(attributes[SdpServiceNameAttributeId]);
            var attributeType   = attributeReader.ReadByte();

            if (attributeType != SdpServiceNameAttributeType)
            {
                throw new InvalidOperationException(
                          "The Chat service is using an unexpected format for the Service Name attribute. " +
                          "Please verify that you are running the BluetoothRfcommChat server.");
            }
            var serviceNameLength = attributeReader.ReadByte();

            // The Service Name attribute requires UTF-8 encoding.
            attributeReader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;

            lock (this)
            {
                chatSocket = new StreamSocket();
            }
            try
            {
                await chatSocket.ConnectAsync(chatService.ConnectionHostName, chatService.ConnectionServiceName);

                // TODO: powiadomienie, że połączono
                //SetChatUI(attributeReader.ReadString(serviceNameLength), bluetoothDevice.Name);

                chatWriter = new DataWriter(chatSocket.OutputStream);
                DataReader chatReader = new DataReader(chatSocket.InputStream);

                ReceiveDataLoop(chatReader);
            }
            catch (Exception ex) when((uint)ex.HResult == 0x80070490)  // ERROR_ELEMENT_NOT_FOUND
            {
                throw new InvalidOperationException("Please verify that you are running the BluetoothRfcommChat server.");
            }
            catch (Exception ex) when((uint)ex.HResult == 0x80072740)  // WSAEADDRINUSE
            {
                throw new InvalidOperationException("Please verify that there is no other RFCOMM connection to the same device.");
            }
        }