Hello everyone.

We have decided to phase out the Mixed Reality Forums over the next few months in favor of other ways to connect with us.

The first way we want to connect with you is our mixed reality developer program, which you can sign up for at https://aka.ms/IWantMR.

The plan between now and the beginning of May is to clean up old, unanswered questions that are no longer relevant. The forums will remain open and usable.

On May 1st we will be locking the forums to new posts and replies. They will remain available for another three months for the purposes of searching them, and then they will be closed altogether on August 1st.

So, where does that leave our awesome community to ask questions? Well, there are a few places we want to engage with you. For technical questions, please use Stack Overflow, and tag your questions using either hololens or windows-mixed-reality. If you want to join in discussions, please do so in the HoloDevelopers Slack, which you can join by going to https://aka.ms/holodevelopers. And always feel free to hit us up on Twitter @MxdRealityDev.

iBeacon, Beacons, Hololens

MattFedoCSGMattFedoCSG ✭✭ ✭✭

Ok so here is the breakdown.

1) Find and download the .NET 4 Windows.Devices.Bluetooth DLL
2) In Unity, create the Assets > Plugins > WSA folder and place that DLL in it. When you check the import settings of this DLL, it can be set to 'Any Platform' and it will say 'Native' as the Type, which is fine.
3) Next, add the DLL I attached to this comment to the Assets > Plugins folder. When you check the import settings of this DLL, you can check it just for WSAPlayer, SDK = UWP, Scripting = Dot Net, and you will see it Managed as a 4.x assembly.
4) So lets look at some code on the Unity side now. Everything you do to "reference" the DLL, you are going to need to wrap in #if !UNITY_EDITOR because you dont want it to compile.

#if !UNITY_EDITOR
using HoloBeaconScanner;
#endif

Next under Start() on your script we can place:

#if !UNITY_EDITOR
        Scanner beaconScanner = new Scanner();
        Scanner.ScannedBeaconEventHandler += BeaconFound;
        beaconScanner.StartScanning();
#endif

There is also a .StopScanning() function if you make your var global.

And once you are scanning you can just set the even handler to catch that Beacon info:

 public void BeaconFound(string str)
    {
        try
        {
            char[] delimiterChars = { '*' };
            string[] components = str.Split(delimiterChars, StringSplitOptions.RemoveEmptyEntries);
            if (components[1] != "0")
            {
                Debug.Log("[BEACON DETECTOR] : FOUND : " + str.ToString());
            }
        }
        catch(Exception ex)
        {
            //Log error or something else.
        }
    }

So the beacon data comes back as a delimited string. I will update it with a JSON package, but right now it is delimited by a *.

Components are as follows:
0 = UUID
1 = Major
2 = Minor
3 = TxPower
4 = Raw Signal Strength in DBm

If the Holo does not find a beacon or encounters an error, it will return:

0000000-0000-0000-0000-0000000000000000

So keep that in mind, and hence why I check for Component 1 to be 0 and ignore it.

I hope this helps someone out there and hope it keeps advancing the Hololens Experience! I will try to keep the DLL up to date! Thanks!

Comments

  • DaZaDaZa

    Hi @MattFedoCSG
    Thank you for the documentation.
    I'm trying to get GPS information from android in my unity application on the Hololens.
    Can your plugins help me?
    And do you have some sample of the entirely bluetooth connection?

    Thank you!

  • MattFedoCSGMattFedoCSG ✭✭ ✭✭
    DaZa, this was merely implementing Bluetooth for low power devices. If you need to send your Hololens GPS info, I would consider creating a socket connection over a network and try that first. Then work on integrating dedicated Bluetooth data passing.
  • BillMcCraryBillMcCrary ✭✭ ✭✭

    @MattFedoCSG thanks for sharing this! Can you point me in the right direction to put your scanner into a continuous scanning mode? I'm probably doing something wrong, but I can only get exactly 1 successful 'read', then it seems to just stop working.

  • BillMcCraryBillMcCrary ✭✭ ✭✭

    @MattFedoCSG nevermind =) I managed to handroll some native WSA bits that are working for me.

    • HoloLens has native access to BLE broadcasting via Windows.Devices.Bluetooth.Advertisement
    • Leverage UnityEngine.WSA.Application.InvokeOnAppThread to handle the received data and pass to Unity to handle the data, otherwise you'll crash

    Here is some code I hope may help others. It's very imperfect and incomplete for fully handling the beacon data, but I'll tackle that next and update this post if I remember!:

    Usings:

    #if !UNITY_EDITOR
    using Windows.Devices.Bluetooth.Advertisement;
    using Windows.Storage.Streams;
    #endif
    

    Global scanner:

    #if !UNITY_EDITOR    
        BluetoothLEAdvertisementWatcher scanner;
    #endif
    

    Setup:

    #if !UNITY_EDITOR
    
            scanner = new BluetoothLEAdvertisementWatcher
                {
                    ScanningMode = BluetoothLEScanningMode.Passive
                };
    
            ////setup filter to only catch ibeacon for now
            var manufacturerData = new BluetoothLEManufacturerData()
            {
                CompanyId =  0x004C //Hexidecimal for 76 which is Apple, use Use 0x015D for 349 for the stickers
            };
    
            //boilerplate code to write the filter data
            var writer = new DataWriter();
            writer.WriteUInt16(0x0215);
            writer.WriteUInt64(0xB9407F30F5F8466E); //First half of your beacons' UUID, this is the Estimote out of the box UUID
            writer.WriteUInt64(0xAFF925556B57FE6D); //Second half of your beacons' UUID, this is the Estimote out of the box UUID
            manufacturerData.Data = writer.DetachBuffer();
            scanner.AdvertisementFilter.Advertisement.ManufacturerData.Clear();
            scanner.AdvertisementFilter.Advertisement.ManufacturerData.Add(manufacturerData);
    
            ////set some thresholds
            //scanner.SignalStrengthFilter.InRangeThresholdInDBm = -50;
            //scanner.SignalStrengthFilter.OutOfRangeThresholdInDBm = -100;
            scanner.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(2000);
    
            //setup callbacks
                scanner.Received += OnBeaconFound;
           // scanner.Stopped += OnScannerStopped;
    
            scanner.Start();
    
    #endif
    

    Receiving broadcasts:

        #if !UNITY_EDITOR
    
            private void OnBeaconFound(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
            {
    
                try
                {
                    UnityEngine.WSA.Application.InvokeOnAppThread (() =>
                    {
                        hitCount++;
                        InstructionText.text = "OnBeaconFound " + hitCount.ToString();
    
                        var foundBeacon = new FoundBeacon()
                        {
                            RSSI = args.RawSignalStrengthInDBm.ToString()
                        };
    
                        UUIDText.text = foundBeacon.RSSI;
    
                        foundBeacon.Major = args.AdvertisementType.ToString();
    
                        //check for manufacturer data section
                        var beaconDataString = string.Empty;
    
                        var beaconDataSections = args.Advertisement.ManufacturerData;
                        if (beaconDataSections.Count > 0)
                        {
                            //print first data section for now
                            var beaconData = beaconDataSections[0];
                            var beaconDataBytes = new byte[beaconData.Data.Length];
                            using (var reader = DataReader.FromBuffer(beaconData.Data))
                            {
                                reader.ReadBytes(beaconDataBytes);
                            }
    
                            beaconDataString = BitConverter.ToString(beaconDataBytes);
    
                            foundBeacon.TxPower = beaconDataString;
                        }
    
                   }, true );
                }
                catch (Exception ex)
                {
                    UUIDText.text = ex.Message;
                }
            }    
        #endif
    
  • Could I ask, what BLE device you are connecting too?

  • kartikkartik

    @MattFedoCSG can you please share the project as it is not working for me on hololens 1

Sign In or Register to comment.