ब्लूटूथ ले के साथ iOS और Android के बीच संचार




core-bluetooth bluetooth-lowenergy (4)

मैं एंड्रॉइड सेंट्रल और iOS परिधीय के साथ कुछ ऐसा ही कर रहा हूं। मैंने पाया कि वे परिधीय सेवाओं में से किसी को भी सब्सक्राइब नहीं करेंगे तो वे डिस्कनेक्ट हो जाएंगे।

जब यह वास्तव में कुछ भी नहीं करता है (यानी iOS पक्ष पर प्रतिनिधि विधि को कॉल करें) तो सब्स्क्राइबर को अपडेट करने के लिए मत भूलना।

public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
        Log.v(TAG, "BluetoothAdapter not initialized");
        return;
    }

    UUID uuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");    // UUID for client config desc
    BluetoothGattDescriptor descriptor = characteristic.getDescriptor(uuid);
    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
    mBluetoothGatt.writeDescriptor(descriptor);

    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
}

यह भी ध्यान दिया जा सकता है कि मैं iOS डिवाइस को एंड्रॉइड डिवाइस (startLeScan) पर सामान्य BLE स्कैन कर भी नहीं सकता था, लेकिन एक ब्रॉडकास्ट रिसीवर के साथ BT क्लासिक स्कैन शुरू करने से समस्या (startDiscovery) हल हो गई।

मुझे iPad (केंद्रीय) और iPhone (परिधीय) के बीच संवाद करने के लिए CoreBlu ब्लूटूथ का उपयोग करके एक काम करने वाला ऐप मिला है। मेरी एक सेवा है जिसमें दो विशेषताएं हैं। मेरे पास एक नेक्सस 7 है जो नवीनतम एंड्रॉइड 4.3 को बीटीएलई समर्थन के साथ चला रहा है। Android को BTLE बैंडवागन पर कूदने में थोड़ी देर हो गई है, लेकिन ऐसा प्रतीत होता है कि वे इसे उसी तरह से देख रहे हैं जैसे iOS ने किया, जहां शुरुआत में वे केवल बाद के संस्करण में आने वाले परिधीय मोड के साथ केंद्रीय के रूप में अभिनय का समर्थन करते हैं। मैं नमूना Android BTLE एप्लिकेशन लोड कर सकता हूं और पास के बाह्य उपकरणों के लिए ब्राउज़ कर सकता हूं। एक परिधीय के रूप में मेरे iPhone विज्ञापन के साथ मैं CBAdvertisementDataLocalNameKey से मान को एंड्रॉइड पर पास के बाह्य उपकरणों की सूची में देख सकता हूं। मैं iPhone से कनेक्ट कर सकता हूं और ब्लूटूथ प्रतीक हल्के ग्रे से काले रंग में बदल जाता है जब कनेक्शन बनाया जाता है। कनेक्शन हमेशा 10 सेकंड तक रहता है और फिर डिस्कनेक्ट हो जाता है। एंड्रॉइड ओर मैं उपलब्ध सेवाओं की एक सूची देखने वाला हूं और कनेक्शन पर तुरंत दिखाई देने वाली विशेषताएं। मैंने साबित किया है कि एंड्रॉइड कोड सही तरीके से सेटअप है क्योंकि मैं इसे TI CC2541DK-SENSOR हार्डवेयर से कनेक्ट कर सकता हूं जो मेरे पास हैं और सभी सेवाओं और विशेषताओं को इसे कनेक्ट करने पर सूचीबद्ध किया गया है।

मैंने पिछले कुछ दिनों को बिना किसी सफलता के समस्या के निवारण में बिताया है। समस्या यह है कि मैं यह निर्धारित नहीं कर सकता कि कौन सा डिवाइस एक त्रुटि का सामना कर रहा है और इस प्रकार वियोग का कारण बन रहा है। कनेक्शन चरण या सेवा खोज चरण के दौरान CBPeripheralManagerDelegate से कोई कॉलबैक नहीं हैं, इसलिए मुझे इस बात का कोई पता नहीं है कि त्रुटि क्या होती है (यदि आईओएस पक्ष में त्रुटि है)। एंड्रॉइड की ओर से एक विधि को सेवा खोज शुरू करने के लिए कहा जाता है, हालांकि उनका कॉलबैक "ऑनसर्विसडिकेटेड" कभी नहीं कहा जाता है जो कि हैरान करने वाला है। क्या कोई तरीका है जिससे मैं iOS पर BTLE संचार की हिम्मत खोद सकता हूं, यह देखने के लिए कि क्या हो रहा है और यह निर्धारित करें कि क्या त्रुटि हो रही है?


मैं क्रॉस प्लेटफॉर्म के बीच BLE विषय पर हमारे RnD के एक भाग के रूप में इस थ्रेड में कुछ जानकारी जोड़ना चाहूंगा।

पेरिफेरल मोड शीओमी एमआई ए 1 (ओएस संस्करण ओरेओ, एंड्रॉइड 8.0) के साथ किसी भी मुद्दे के बिना काम कर रहा है।

यहाँ थ्रूपुट पर कुछ अवलोकन दिए गए हैं जो हमें अपने आरएनडी के दौरान आईफोन 8 और श्याओमी एमआई ए 1 पर देखने को मिले थे, लेकिन अभी भी इसे नवीनतम सैमसंग एस 8 में उपयोग किए गए अन्य एंड्रॉइड ओएस के साथ परिपक्व होना है। नीचे दिया गया डेटा write_with_response पर आधारित है।

  1. iPhone 8 (BLE 5.0) सेंट्रल और लिनक्स डेस्कटॉप के रूप में (Ubuntu 16.04 के साथ BLE डोंगल 4.0): MTU = 2048: थ्रूपुट - 2.5 किलोबाइट्स प्रति सेकंड।

  2. iPhone 8 (BLE 5.0) सेंट्रल और एंड्रॉइड ओएस के रूप में BLE संस्करण 4.2 के साथ पेरिफेरल (शियोमी Mi A1): MTU = 180: थ्रूपुट - 2.5 किलोबाइट प्रति सेकंड।

  3. iPhone 8 (BLE 5.0) सेंट्रल और iPhone 7 प्लस (BLE 4.2) को पेरिफेरल के रूप में: MTU = 512: थ्रूपुट - 7.1 किलोहाइट्स प्रति सेकंड।

  4. iPhone 8 (BLE 5.0) सेंट्रल और सैमसंग S8 के रूप में (BLE 5.0) परिधीय के रूप में: सैमसंग S8 परिधीय के रूप में काम करने में विफल रहा

  5. iPhone 8 (BLE 5.0) सेंट्रल और iPhone 8 प्लस (BLE 5.0) पेरिफेरल के रूप में: MTU = 512: थ्रूपुट - 15.5 प्रति सेकंड KiloBytes।


मैं बस अपना ज्ञान उस पर साझा करना चाहता था क्योंकि मैंने कुछ समय पहले इससे निपटा था और मैंने इसे छोड़ दिया क्योंकि Google द्वारा कोई समर्थन नहीं है। उपरोक्त कोड, जो मैं बहुत धन्यवाद करता हूं, वह काम नहीं करता है। आप उचित समय में एक iOS से iOS या एंड्रॉइड ब्लूटूथ ले एप्लीकेशन में iOS के लिए कोड कर सकते हैं लेकिन समस्या तब आती है जब आप iOS और एंड्रॉइड के बीच संवाद करने का प्रयास करते हैं। एक अच्छी तरह से प्रलेखित Google समस्या है ( code.google.com/p/android/issues/… ) मैंने सहयोग किया लेकिन google ने बिल्कुल भी उच्चारण नहीं किया और ऐसा लगता है कि उन्होंने इस मुद्दे को बंद कर दिया है और एंड्रॉइड M में कुछ भी नहीं बदला है क्योंकि Ive कोड में देख रहा है और आगे कोई अंतर नहीं देख सकता है। समस्या तब आती है जब एंड्रॉइड कनेक्ट करने की कोशिश करता है और विशेष रूप से "यदि और" वाक्य में; यह कोड मूल रूप से ट्रांसमिशन को अस्वीकार कर देता है और संचार में कटौती करता है इसलिए यह काम नहीं करता है। फिलहाल, इसका कोई समाधान नहीं है। आप वाईफाई डायरेक्ट सॉल्यूशन कर सकते हैं, लेकिन यह सीमित है और ऐसा करने में और भी समस्याएं हैं। यदि आप BLE को बाहरी हार्डवेयर (रास्पबेरी, सेंसर, आदि) के साथ लागू करना चाहते हैं, तो समस्या मौजूद नहीं है, लेकिन यह iOS और Android के बीच काम नहीं करता है। दोनों प्लेटफार्मों में तकनीक काफी समान है, लेकिन यह अच्छी तरह से एंड्रॉइड में लागू नहीं होता है या दोनों प्लेटफार्मों के बीच संवाद करने के लिए दर्शक को खोलने के लिए नहीं करने के लिए Google द्वारा उद्देश्य डाला जाता है।


मैंने एक साधारण कामकाजी उदाहरण लिखा है, अच्छी तरह से अपेक्षाकृत सरल है, और इसे Github पर ओपन-सोर्स में शामिल किया है: https://github.com/GitGarage । अब तक यह केवल एक एंड्रॉइड नेक्सस 9 और एक आईफोन 5 एस के साथ परीक्षण किया गया है, लेकिन मुझे लगता है कि यह एक नेक्सस 6 और विभिन्न आईफोन प्रकारों के साथ भी काम करेगा। अब तक यह स्पष्ट रूप से एक Android और एक iPhone के बीच संवाद स्थापित करने के लिए स्थापित किया गया है, लेकिन मुझे लगता है कि यह और अधिक करने के लिए tweakable है।

यहां जानिए प्रमुख तरीके ...

ड्रॉप साइड - iOS पर भेजा जा रहा है:

private void sendMessage() {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            if (mBTAdapter == null) {
                return;
            }
            if (mBTAdvertiser == null) {
                mBTAdvertiser = mBTAdapter.getBluetoothLeAdvertiser();
            }
               // get the full message from the UI
            String textMessage = mEditText.getText().toString(); 
            if (textMessage.length() > 0)
            {
                   // add 'Android' as the user name
                String message = "Android: " + textMessage; 

                while (message.length() > 0) {
                    String subMessage;
                    if(message.length() > 8)
                    {    // add dash to unfinished messages
                        subMessage = message.substring(0,8) + "-"; 
                        message = message.substring(8);
                        for (int i = 0; i < 20; i++) // twenty times (better safe than sorry) send this part of the message. duplicate parts will be ignored
                        {
                            AdvertiseData ad = BleUtil.makeAdvertiseData(subMessage);
                            mBTAdvertiser.startAdvertising(BleUtil.createAdvSettings(true, 100), ad, mAdvCallback);
                            mBTAdvertiser.stopAdvertising(mAdvCallback);
                        }
                    }
                    else
                    {  // otherwise, send the last part
                        subMessage = message;
                        message = "";
                        for (int i = 0; i < 5; i++)
                        {
                            AdvertiseData ad = BleUtil.makeAdvertiseData(subMessage);
                            mBTAdvertiser.startAdvertising(
                                    BleUtil.createAdvSettings(true, 40), ad,
                                    mAdvCallback);
                            mBTAdvertiser.stopAdvertising(mAdvCallback);
                        }
                    }
                }
                threadHandler.post(updateRunnable);
            }
        }
    });
    thread.start();
}

DROID SIDE - iOS से प्राप्त:

@Override
public void onLeScan(final BluetoothDevice newDevice, final int newRssi,
                     final byte[] newScanRecord) {

    int startByte = 0;
    String hex = asHex(newScanRecord).substring(0,29);
       // check five times, startByte was used for something else before
    while (startByte <= 5) {
       // check if this is a repeat message
        if (!Arrays.asList(used).contains(hex)) {
            used[ui] = hex;

            String message = new String(newScanRecord);
            String firstChar = message.substring(5, 6);
            Pattern pattern = Pattern.compile("[ [email protected]#$%^&*()_+{}|:\"<>?`\\-=;',\\./\\[\\]\\\\]", Pattern.DOTALL);
               // if the message is comprised of standard characters...
            Matcher matcher = pattern.matcher(firstChar);
            if (firstChar.equals("L"))
            {
                firstChar = message.substring(6, 7);
                pattern = Pattern.compile("[ [email protected]#$%^&*()_+{}|:\"<>?`\\-=;',\\./\\[\\]\\\\]", Pattern.DOTALL);
                matcher = pattern.matcher(firstChar);
            }

            if(matcher.matches())
            {
                TextView textViewToChange = (TextView) findViewById(R.id.textView);
                String oldText = textViewToChange.getText().toString();
                int len = 0;
                String subMessage = "";
                   // add this portion to our final message
                while (matcher.matches())  
                {
                    subMessage = message.substring(5, 6+len);
                    matcher = pattern.matcher(message.substring(5+len, 6+len));
                    len++;
                }
                subMessage = subMessage.substring(0,subMessage.length()-1);

                Log.e("Address",newDevice.getAddress());
                Log.e("Data",asHex(newScanRecord));
                boolean enter = subMessage.length() == 16;
                enter = enter && !subMessage.substring(15).equals("-");
                enter = enter || subMessage.length() < 16;
                textViewToChange.setText(oldText + subMessage.substring(0, subMessage.length() - 1) + (enter ? "\n" : ""));
                ui = ui == 2 ? -1 : ui;
                ui++;

                Log.e("String", subMessage);
            }
            break;
        }
        startByte++;
    }
}

iOS SIDE - Android पर भेजा जा रहा है:

func startAdvertisingToPeripheral() {
    var allTime:UInt64 = 0;
    if (dataToSend != nil)
    {
        datastring = NSString(data:dataToSend, encoding:NSUTF8StringEncoding) as String
        datastring = "iPhone: " + datastring
        if (datastring.length > 15)
        {
            for (var i:Double = 0; i < Double(datastring.length)/15.000; i++)
            {
                let delay = i/10.000 * Double(NSEC_PER_SEC)
                let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
                allTime = time
                dispatch_after(time, dispatch_get_main_queue(), { () -> Void in self.sendPart() });
            }
        }
        else
        {
            var messageUUID = StringToUUID(datastring)
            if !peripheralManager.isAdvertising {
                peripheralManager.startAdvertising([CBAdvertisementDataServiceUUIDsKey: [CBUUID(string: messageUUID)]])
            }
        }
    }
}

iOS SIDE - Android से प्राप्त करना:

func centralManager(central: CBCentralManager!, didDiscoverPeripheral peripheral: CBPeripheral!, advertisementData: [NSObject : AnyObject]!, RSSI: NSNumber!) {

    delegate?.didDiscoverPeripheral(peripheral)
    var splitUp = split("\(advertisementData)") {$0 == "\n"}
    if (splitUp.count > 1)
    {
        var chop = splitUp[1]
        chop = chop[0...chop.length-2]
        var chopSplit = split("\(chop)") {$0 == "\""}

        if !(chopSplit.count > 1 && chopSplit[1] == "Device Information")
        {
            var hexString = chop[4...7] + chop[12...19] + chop[21...26]
            var datas = hexString.dataFromHexadecimalString()
            var string = NSString(data: datas!, encoding: NSUTF8StringEncoding) as String
            if (!contains(usedList,string))
            {
                usedList.append(string)
                if (string.length == 9 && string[string.length-1...string.length-1] == "-")
                {
                    finalString = finalString + string[0...string.length-2]
                }
                else
                {
                    lastString = finalString + string + "\n"
                    println(lastString)
                    finalString = ""
                    usedList = newList
                    usedList.append(string)
                }
            }
        }
    }
}




android-bluetooth