public async void Connect()
        {
            // Repair the device if needed
            if (!devInfo.Pairing.IsPaired)
            {
                Debug.WriteLine("Pairing...");

                DeviceInformationCustomPairing customPairing = devInfo.Pairing.Custom;
                customPairing.PairingRequested += PairingRequested;
                DevicePairingResult result = await customPairing.PairAsync(DevicePairingKinds.ProvidePin, DevicePairingProtectionLevel.None);

                customPairing.PairingRequested -= PairingRequested;

                Debug.WriteLine("Pair status: " + result.Status);
            }
            else
            {
                Debug.WriteLine("Already Paired");
            }

            // Get the actual device
            try {
                device = await BluetoothDevice.FromIdAsync(devInfo.Id);

                device.ConnectionStatusChanged += ConnectionStatusChanged;
            } catch (Exception ex) {
                Debug.WriteLine("Bluetooth Not Available");
                return;
            }

            //try {
            var services = await device.GetRfcommServicesAsync();

            if (services.Services.Count > 0)
            {
                var service = services.Services[0];
                stream = new StreamSocket();
                //try {
                await stream.ConnectAsync(service.ConnectionHostName, service.ConnectionServiceName);

                //} catch (Exception ex) {
                //Debug.WriteLine("Could not connect to device");
                //}
                Debug.WriteLine("Stream Connected");
                rx = new DataReader(stream.InputStream);
                rx.InputStreamOptions = InputStreamOptions.Partial;
                tx = new DataWriter(stream.OutputStream);

                OnConnected();
            }

            /*} catch (Exception ex) {
             *  Debug.WriteLine("Failed to get services");
             *  return;
             * }*/
        }
示例#2
0
        private async void Button_Click_GetRfcommServices(object sender, RoutedEventArgs e)
        {
            BluetoothDevice bt = await BluetoothDevice.FromIdAsync(ViewModel.SelectedDevice.Id);

            RfcommDeviceServicesResult result = await bt.GetRfcommServicesAsync();

            foreach (var b in bt.SdpRecords)
            {
                Debug.WriteLine(Encoding.UTF8.GetString(b.ToArray()));
            }
            foreach (var service in result.Services)
            {
                Debug.WriteLine(service.ServiceId.AsString() + "    " + service.ConnectionHostName + "    " + service.ConnectionServiceName);
            }
        }
示例#3
0
        /// <summary>Get extra info for connection and other not gathered at discovery to save time</summary>
        /// <param name="deviceInfo">The device information data model to populate</param>
        /// <param name="forceRetrieve">Force re-reading of all extra information</param>
        /// <returns>An asynchronous task result</returns>
        private async Task GetExtraInfo(BTDeviceInfo deviceInfo, bool forceRetrieve)
        {
            this.log.InfoEntry("GetExtraInfo");

            // 0 length remote host name indicates that we require more information for connection
            if (deviceInfo.RemoteHostName.Length == 0 || forceRetrieve)
            {
                this.log.Info("GetExtraInfo", () => string.Format("Getting info to fill in host name for address:{0}", deviceInfo.Address));

                using (BluetoothDevice device = await BluetoothDevice.FromIdAsync(deviceInfo.Address)) {
                    // TODO - defer this to before connection or info request
                    // SDP records only after services
                    // Must use uncached
                    RfcommDeviceServicesResult serviceResult = await device.GetRfcommServicesAsync(BluetoothCacheMode.Uncached);

                    this.log.Info("GetExtraInfo", () => string.Format("Success. Number of services:{0}", serviceResult.Services.Count));

                    //WrapErr.ChkTrue(serviceResult.Services.Count > 0, 9999, () => string.Format("No services for BT:{0}", deviceInfo.Name));
                    if (serviceResult.Services.Count == 0)
                    {
                        throw new Exception(string.Format("No services for BT:{0}", deviceInfo.Name));
                    }


                    if (serviceResult.Error == BluetoothError.Success)
                    {
                        foreach (var service in serviceResult.Services)
                        {
                            BT_ServiceType serviceType = BT_ParseHelpers.GetServiceType(service.ConnectionServiceName);
                            this.log.Info("GetExtraInfo", () => string.Format("Device {0} Connection host name {1} Service name {2} Type {3}",
                                                                              deviceInfo.Name,
                                                                              service.ConnectionHostName,
                                                                              service.ConnectionServiceName,
                                                                              serviceType.ToString()));
                            if (serviceType == BT_ServiceType.SerialPort)
                            {
                                // TODO get extra info on attributes
                                //var sdpAttr = await service.GetSdpRawAttributesAsync(BluetoothCacheMode.Uncached);
                                //foreach (var attr in sdpAttr) {
                                //    this.log.Info("HarvestInfo", () => string.Format("             SDP Attribute:{0} Capacity:{1} Length:{2}", attr.Key, attr.Value.Capacity, attr.Value.Length));
                                //}
                                // Sample output. See: https://www.bluetooth.com/specifications/assigned-numbers/service-discovery/
                                //SDP Attribute id | Capacity | Length | Description(?)
                                //    256               7           7
                                //      0               5           5
                                //      6              11          11
                                //      4              14          14
                                //      1               5           5      (service class ID list
                                deviceInfo.ServiceType       = BT_ServiceType.SerialPort;
                                deviceInfo.RemoteHostName    = service.ConnectionHostName.ToString();
                                deviceInfo.RemoteServiceName = service.ConnectionServiceName;
                                // TODO info on access
                                //service.DeviceAccessInformation.CurrentStatus == DeviceAccessStatus.Allowed
                                this.log.Info("****", () => string.Format("Device:{0} Host Name:{1} Service:{2}",
                                                                          deviceInfo.Name, deviceInfo.RemoteHostName, deviceInfo.RemoteServiceName));
                            }
                            else
                            {
                                // Not used.
                            }
                        }
                    }
                    else
                    {
                        this.log.Error(9999, () => string.Format("Get Service result:{0}", serviceResult.Error.ToString()));
                    }
                }
            }
        }
        /// <summary>Get extra info for connection and other not gathered at discovery to save time</summary>
        /// <param name="deviceInfo">The device information data model to populate</param>
        /// <param name="forceRetrieve">Force re-reading of all extra information</param>
        /// <returns>An asynchronous task result</returns>
        private async Task GetExtraInfo(BTDeviceInfo deviceInfo, bool forceRetrieve, bool display)
        {
            try {
                this.log.InfoEntry("GetExtraInfo");

                // TODO Cannot call this after the services have already been retrieved. So do not force

                // 0 length remote host name indicates that we require more information for connection
                if (deviceInfo.RemoteHostName.Length == 0 || forceRetrieve)
                {
                    this.log.Info("GetExtraInfo", () => string.Format("Getting info to fill in host name for address:{0}", deviceInfo.Address));

                    using (BluetoothDevice device = await BluetoothDevice.FromIdAsync(deviceInfo.Address)) {
                        // TODO - defer this to before connection or info request
                        // SDP records only after services
                        // Must use uncached
                        RfcommDeviceServicesResult serviceResult = await device.GetRfcommServicesAsync(BluetoothCacheMode.Uncached);

                        this.log.Info("GetExtraInfo", () => string.Format("Success. Number of services:{0}", serviceResult.Services.Count));

                        //WrapErr.ChkTrue(serviceResult.Services.Count > 0, 9999, () => string.Format("No services for BT:{0}", deviceInfo.Name));
                        if (serviceResult.Services.Count == 0)
                        {
                            throw new Exception(string.Format("No services for BT:{0}", deviceInfo.Name));
                        }


                        if (serviceResult.Error == BluetoothError.Success)
                        {
                            foreach (var service in serviceResult.Services)
                            {
                                BT_ServiceType serviceType = BT_ParseHelpers.GetServiceType(service.ServiceId.AsShortId());
                                this.log.Info("GetExtraInfo", () => string.Format("Device {0} Connection host name {1} Service name {2} Type {3}",
                                                                                  deviceInfo.Name,
                                                                                  service.ConnectionHostName,
                                                                                  service.ConnectionServiceName,
                                                                                  serviceType.ToString()));
                                if (serviceType == BT_ServiceType.SerialPort)
                                {
                                    //await this.GetListSDPAttributes(service);
                                    deviceInfo.ServiceType       = serviceType;
                                    deviceInfo.RemoteHostName    = service.ConnectionHostName.ToString();
                                    deviceInfo.RemoteServiceName = service.ConnectionServiceName;
                                    deviceInfo.ServiceClassName  = serviceType.ToString().CamelCaseToSpaces();
                                    deviceInfo.ServiceClassInt   = (int)service.ServiceId.AsShortId();

                                    // TODO info on access
                                    //service.DeviceAccessInformation.CurrentStatus == DeviceAccessStatus.Allowed

                                    this.log.Info("****", () => string.Format("Device:{0} Host Name:{1} Service:{2}",
                                                                              deviceInfo.Name, deviceInfo.RemoteHostName, deviceInfo.RemoteServiceName));



                                    //deviceInfo.Strength = 0;
                                    this.ListDeviceInfoProperties(device);

                                    this.log.Info("****", () => string.Format("device.BluetoothAddress: {0}", device.BluetoothAddress));
                                    this.log.Info("****", () => string.Format("device.BluetoothDeviceId.id: {0}", device.BluetoothDeviceId.Id));
                                    this.log.Info("****", () => string.Format("device.DeviceId: {0}", device.DeviceId));
                                    this.log.Info("****", () => string.Format("device.DeviceInformation.Id: {0}", device.DeviceInformation.Id));
                                    this.log.Info("****", () => string.Format("device.ClassOfDevice: {0}", device.ClassOfDevice.RawValue));
                                    //this.log.Info("****", () => string.Format(":{0}", ));
                                    //this.log.Info("****", () => string.Format(":{0}", ));

                                    // Experimental. See the note on the method
                                    //await this.GetRadioInfo(device, deviceInfo, service.ConnectionServiceName);
                                    //await this.GetRadioInfo(device, deviceInfo, deviceInfo.RemoteHostName);

                                    // List of radios available on current device
                                    //await this.ListRadios();

                                    if (display)
                                    {
                                        this.BT_DeviceInfoGathered?.Invoke(this, deviceInfo);
                                    }
                                }
                                else
                                {
                                    //Not used.
                                }
                                service.Dispose();
                            }
                        }
                        else
                        {
                            this.log.Error(9999, () => string.Format("Get Service result:{0}", serviceResult.Error.ToString()));
                        }
                    }
                }
                else if (deviceInfo.RemoteHostName.Length > 0 && display)
                {
                    this.BT_DeviceInfoGathered?.Invoke(this, deviceInfo);
                }
            }
            catch (Exception e) {
                this.log.Exception(9999, "GetExtraInfo", "", e);
            }
        }
示例#5
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());
        }