protected async override void OnNavigatedTo(NavigationEventArgs args)
        {
            DI = args.Parameter as DeviceInformationWrapper;
            ParentStatusHandler?.SetStatusActive(true);
            uiTerminalControl.ParentTerminal = this;
            uiTerminalControl.DoSendData     = this;
            uiTerminalControl.DI             = DI;
            uiTerminalControl.UpdateShortcutButtons();

            TerminalAdapter = new BluetoothCommTerminalAdapter(this, DI);
            await TerminalAdapter.InitAsync();

            ParentStatusHandler?.SetStatusActive(false);
        }
예제 #2
0
        protected override void OnNavigatedTo(NavigationEventArgs args)
        {
            di = args.Parameter as DeviceInformationWrapper;
            // When will this be null? When we've created a page generically instead of for a particular device.
            // This happens when you do a beacon search.
            if (di.BleAdvert != null)
            {
                di.BleAdvert.UpdatedBleAdvertisement += BleAdvert_UpdatedBleAdvertisement;
            }
            BleAdvertisementWrapper.UpdatedUniversalBleAdvertisement += BleAdvert_UpdatedUniversalBleAdvertisement;

            if (di.BleAdvert == null)
            {
                // Don't let the user switch off the track all.
                uiTrackAll.Visibility = Visibility.Collapsed;
                uiTrackAll.IsChecked  = true; // belt and suspenders
            }
        }
예제 #3
0
        public static (string name, string id, string description) GetBleName(DeviceInformationWrapper wrapper, BluetoothLEAdvertisementReceivedEventArgs bleAdvert)
        {
            string name        = "???";
            string id          = "??-??";
            string description = "??--??";

            if (bleAdvert == null || (wrapper != null && wrapper.BleAdvert == null))
            {
                return(name, id, description);
            }
            name = bleAdvert.Advertisement.LocalName;
            id   = BluetoothAddress.AsString(bleAdvert.BluetoothAddress);
            if (EmptyOrAllNull(name))
            {
                // BAD: There's a device where the LocalName is 13 NUL chars!
                name = id;
            }
            name        = CustomizeWrapperFromAdvertisement(wrapper, bleAdvert, name);
            description = AsDescription(bleAdvert);

            return(name, id, description);
        }
예제 #4
0
        /// <summary>
        /// Warning: in addition to its normal function, this function ALSO triggers events. Yes, it's gross, and yes, I'm sorry. This only happens when wrapper is non-null
        /// </summary>
        /// <param name="wrapper"></param>
        /// <param name="ble"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        private static string CustomizeWrapperFromAdvertisement(DeviceInformationWrapper wrapper, BluetoothLEAdvertisementReceivedEventArgs ble, string name)
        {
            // Lets's see if it's an Eddystone beacon...
            // https://github.com/google/eddystone
            // https://github.com/google/eddystone/blob/master/protocol-specification.md

            foreach (var section in ble.Advertisement.DataSections)
            {
                switch (section.DataType)
                {
                case 0x16:     // 22=service data
                    var dr = DataReader.FromBuffer(section.Data);
                    dr.ByteOrder = ByteOrder.LittleEndian;
                    var Service = dr.ReadUInt16();
                    // https://github.com/google/eddystone
                    if (Service == 0xFEAA)     // An Eddystone type
                    {
                        //EddystoneFrameType = (byte)(0x0F & (dr.ReadByte() >> 4));
                        var       EddystoneFrameType = dr.ReadByte();
                        const int TypeUID            = 0x00;
                        const int TypeURL            = 0x10;
                        const int TypeTLM            = 0x20;
                        const int TypeEID            = 0x40;
                        switch (EddystoneFrameType)
                        {
                        case TypeUID:
                            wrapper?.BleAdvert.Event("UID: <data>");
                            break;

                        case TypeTLM:
                            wrapper?.BleAdvert.Event("TLM: <data>");
                            break;

                        case TypeEID:
                            wrapper?.BleAdvert.Event("EID: <data>");
                            break;

                        case TypeURL:         // 0x10: An Eddystone-URL
                            // https://github.com/google/eddystone/tree/master/eddystone-url
                            var result = BluetoothDeviceController.Beacons.Eddystone.ParseEddystoneUrlArgs(section.Data);
                            name = result.Success ? result.Url : "Invalid eddystone!";
                            if (wrapper != null)
                            {
                                wrapper.BleAdvert.EddystoneUrl = name;
                            }
                            if (result.Success && result.Url.StartsWith("https://ruu.vi/#"))
                            {
                                //foundValues.Add(AdvertisementType.RuuviTag);
                                var ruuvi = BluetoothDeviceController.Beacons.RuuviTag.ParseRuuviTag(result.Url);
                                ruuvi.Data.EventTime = DateTime.Now;
                                if (ruuvi.Success)
                                {
                                    name = ruuvi.ToString();         // Make a new user-friendly string
                                }
                                if (wrapper != null)
                                {
                                    wrapper.BleAdvert.AdvertisementType = BleAdvertisementWrapper.BleAdvertisementType.RuuviTag;
                                }
                                // TODO: this is actually weird; it should be done somewhere else.
                                // This function is all about setting up the wrapper, not actually
                                // triggering events!
                                wrapper?.BleAdvert.Event(ruuvi.Data);
                            }
                            else
                            {
                                if (wrapper != null)
                                {
                                    wrapper.BleAdvert.AdvertisementType = BleAdvertisementWrapper.BleAdvertisementType.Eddystone;
                                }
                                name = $"Eddystone {result.Url}";
                                // TODO: this is actually weird; it should be done somewhere else.
                                // This function is all about setting up the wrapper, not actually
                                // triggering events!
                                wrapper?.BleAdvert.Event(result.Url);
                            }
                            break;
                        }
                    }
                    break;
                }
            }
            return(name);
        }
예제 #5
0
        private async Task DisplayBluetooth(NameDevice knownDevice, DeviceInformationWrapper di, BluetoothLEDevice ble)
        {
            var jsonFormat   = Newtonsoft.Json.Formatting.Indented;
            var jsonSettings = new Newtonsoft.Json.JsonSerializerSettings()
            {
                DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore,
                NullValueHandling    = Newtonsoft.Json.NullValueHandling.Ignore,
                ContractResolver     = IgnoreEmptyEnumerableResolver.Instance,
            };

            var wireAllDevices = new NameAllBleDevices();

            WireDevice          = new NameDevice();
            WireDevice.Name     = di.di.Name;
            WireDevice.Details += $"Id:{di.di.Id}\nCanPair:{di.di.Pairing.CanPair} IsPaired:{di.di.Pairing.IsPaired}";
            wireAllDevices.AllDevices.Add(WireDevice);

            WireDevice.ClassModifiers = knownDevice.ClassModifiers;
            WireDevice.ClassName      = knownDevice.ClassName;
            WireDevice.Description    = knownDevice.Description;


            uiRawData.Text = Newtonsoft.Json.JsonConvert.SerializeObject(WireDevice, jsonFormat);
            string raw = null;

            if (ble == null)
            {
                // Happens if another program is trying to use the device!
                raw = $"BLE: ERROR: Another app is using this device.\n";
            }
            else
            {
                // TODO: remove this code which is only here while I investigate the WESCALE scale
#if NEVER_EVER_DEFINED
                {
                    // WESCALE: no gatt services
                    var services     = ble.GattServices;
                    var count        = services.Count;
                    var devacc       = ble.DeviceAccessInformation;
                    var devaccstatus = devacc.CurrentStatus;

                    foreach (var service in services)
                    {
                        var chars = service.GetAllCharacteristics();
                    }
                    try
                    {
                        var guid    = Guid.Parse("0000fff0-0000-1000-8000-00805f9b34fb");
                        var request = await ble.RequestAccessAsync();

                        var allservice = await ble.GetGattServicesForUuidAsync(guid);

                        var servicefff0 = ble.GetGattService(guid);
                        var charsfff0   = servicefff0.GetAllCharacteristics();
                        var countfff0   = charsfff0.Count;
                        foreach (var ch in charsfff0)
                        {
                            ;
                        }
                    }
                    catch (Exception ex)
                    {
                        ;
                    }
                }
#endif

                var result = await ble.GetGattServicesAsync();

                if (result.Status != GattCommunicationStatus.Success)
                {
                    raw += GetStatusString(result.Status, result.ProtocolError);
                }
                else
                {
                    var header = new BleDeviceHeaderControl();
                    await header.InitAsync(ble);

                    int serviceCount = 0;

                    foreach (var service in result.Services)
                    {
                        await header.AddServiceAsync(ble, service);

                        var shouldDisplay = ServiceShouldBeEdited(service);

                        var defaultService = knownDevice.GetService(service.Uuid.ToString("D"));
                        var wireService    = new NameService(service, defaultService, serviceCount++);
                        WireDevice.Services.Add(wireService);

                        try
                        {
                            var cresult = await service.GetCharacteristicsAsync();

                            if (cresult.Status != GattCommunicationStatus.Success)
                            {
                                raw += GetStatusString(cresult.Status, cresult.ProtocolError);
                            }
                            else
                            {
                                var characteristicCount = 0;

                                foreach (var characteristic in cresult.Characteristics)
                                {
                                    //The descriptors don't seem to be actually interesting. it's how we read and write.
                                    var descriptorStatus = await characteristic.GetDescriptorsAsync();

                                    if (descriptorStatus.Status == GattCommunicationStatus.Success)
                                    {
                                        foreach (var descriptor in descriptorStatus.Descriptors)
                                        {
                                            ;
                                        }
                                    }

                                    var defaultCharacteristic = defaultService?.GetChacteristic(characteristic.Uuid.ToString("D"));
                                    var wireCharacteristic    = new NameCharacteristic(characteristic, defaultCharacteristic, characteristicCount++);
                                    wireService.Characteristics.Add(wireCharacteristic);

                                    if (wireCharacteristic.Suppress)
                                    {
                                        continue; // don't show a UI for a supressed characteristic.
                                    }
                                    //
                                    // Here are each of the editor children items
                                    //
                                    var edit = new BleCharacteristicControl(knownDevice, service, characteristic);
                                    uiEditor.Children.Add(edit);

                                    var dc = DeviceCharacteristic.Create(characteristic);

                                    //NOTE: does any device have a presentation format?
                                    foreach (var format in characteristic.PresentationFormats)
                                    {
                                        raw += $"    Fmt: Description:{format.Description} Namespace:{format.Namespace} Type:{format.FormatType} Unit: {format.Unit} Exp:{format.Exponent}\n";
                                    }


                                    try
                                    {
                                        if (wireCharacteristic.IsRead)
                                        {
                                            var vresult = await characteristic.ReadValueAsync();

                                            if (vresult.Status != GattCommunicationStatus.Success)
                                            {
                                                raw += GetStatusString(vresult.Status, vresult.ProtocolError);
                                            }
                                            else
                                            {
                                                var dt         = BluetoothLEStandardServices.GetDisplayInfo(service, characteristic);
                                                var hexResults = dt.AsString(vresult.Value);
                                                wireCharacteristic.ExampleData.Add(hexResults);

                                                // And add as a converted value
                                                var NC     = BleNames.Get(knownDevice, service, characteristic);
                                                var decode = NC?.Type;
                                                if (decode != null && !decode.StartsWith("BYTES|HEX"))
                                                {
                                                    var decoded = ValueParser.Parse(vresult.Value, decode);
                                                    wireCharacteristic.ExampleData.Add(decoded.UserString);
                                                }
                                            }
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        raw += $"    Exception reading value: {e.HResult} {e.Message}\n";
                                    }

                                    // Update the UI with the latest discovery
                                    // Later: or not. The raw data isn't super useful.
                                    //uiRawData.Text = Newtonsoft.Json.JsonConvert.SerializeObject(WireDevice, jsonFormat);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            raw += $"    Exception reading characteristic: {e.HResult} {e.Message}\n";
                        }
                    }
                }
            }
            JsonAsList   = Newtonsoft.Json.JsonConvert.SerializeObject(wireAllDevices, jsonFormat, jsonSettings);
            JsonAsSingle = Newtonsoft.Json.JsonConvert.SerializeObject(WireDevice, jsonFormat, jsonSettings);

            uiProgress.IsActive = false;
            uiRawData.Text     += raw;
            return;
        }
 public BluetoothCommTerminalAdapter(ITerminal terminal, DeviceInformationWrapper input_di)
 {
     Terminal = terminal;
     di       = input_di;
 }