खोज…


परिचय

एक ब्लूटूथ कम ऊर्जा डिवाइस पर डेटा पढ़ने और लिखने के लिए गर्म।

टिप्पणियों

कुछ महत्वपूर्ण बिंदु

  • कोई क्षमताओं की जरूरत नहीं है।
  • लिटिल एंडियन प्रारूप में iPhone स्टोर बाइट्स, इसलिए जांचें कि क्या ब्लूटूथ एक्सेसरी लिटिल एंडियन का भी उपयोग करता है। उदाहरण:
    • इंटेल सीपीयू आमतौर पर छोटे एंडियन का उपयोग करते हैं।
    • एआरएम आर्किटेक्चर संस्करण 3 से पहले थोड़ा-एंडियन था जब यह बड़ा-एंडियन बन गया।
  • एकल या बैच ऑपरेशन के बाद कनेक्शन खो जाएगा, इसलिए आपको जारी रखने से पहले फिर से कनेक्ट करना होगा।

सेवा यूयूआईडी के लिए स्कैन करें

func SearchBLE(){
    cb_manager.scanForPeripherals(withServices:[service_uuid], options: nil)
    StopSearchBLE()
}

प्रलेखन के बिना सेवा यूयूआईडी की खोज कैसे करें

func centralManager(_ central: CBCentralManager, didConnect peripheral:             
CBPeripheral) {
        peripheral.delegate = self
        peripheral.discoverServices(nil)
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    for service in peripheral.services! {
        print("Service: \(service)\n error: \(error)")
    }
}
  • searchServices (nil) - NIL का मतलब है कि सभी सेवाएं वापस मिल जाएंगी, जो एक अच्छा विकल्प नहीं है। (READ Remarks 1)
  • यदि आपको सेवा UUID नहीं मिली है तो अपना कोड चलाएं और कंसोल में देखें यहाँ छवि विवरण दर्ज करें
  • मैंने पाया कि 3 सेवाएं हैं: बैटरी, डिवाइस जानकारी (फर्मवेयर) और FFF0
  • यह uuid सेवा मानक नहीं है, मानकों वाली एक सूची यहां मिल सकती है
  • FFF0 इस मामले में सेवा UUID है

UInt16 में डेटा कन्वर्ट करें और इसके विपरीत

इस एक्सटेंशन को अपनी कक्षा में जोड़ें

protocol DataConvertible {
    init?(data: Data)
    var data: Data { get }
}

extension DataConvertible {

    init?(data: Data) {
        guard data.count == MemoryLayout<Self>.size else { return nil }
        self = data.withUnsafeBytes { $0.pointee }
    }

    var data: Data {
        var value = self
        return Data(buffer: UnsafeBufferPointer(start: &value, count: 1))
    }
}
extension UInt16 : DataConvertible {
    init?(data: Data) {
        guard data.count == MemoryLayout<UInt16>.size else { return nil }
        self = data.withUnsafeBytes { $0.pointee }
    }
    var data: Data {
        var value = CFSwapInt16HostToBig(self)
        return Data(buffer: UnsafeBufferPointer(start: &value, count: 1))
    }
}

सभी ब्लूटूथ कम ऊर्जा (BLE) के नाम दिखा रहा है

  • इस उदाहरण के लिए मेरे पास एक एकल BLE डिवाइस सक्षम के साथ एक नियंत्रित कमरा है।
  • आपकी कक्षा को CBCentralManagerDelegate का विस्तार करना चाहिए।
  • विधि को लागू करें: centralManagerDidUpdateState (_ केंद्रीय: CBCentralManager)।
  • डिवाइस की खोज करते समय स्क्रीन को फ्रीज न करने के लिए वैश्विक कतार का उपयोग करें।
  • त्वरित CBCentralManager और callback centralManagerDidUpdateState प्रतिक्रिया की प्रतीक्षा करें।
class BLEController: CBCentralManagerDelegate{

var cb_manager: CBCentralManager!
var bles : [CBPeripheral] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        cb_manager = CBCentralManager(delegate: self, queue: DispatchQueue.global())
    }

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        print("UPDATE STATE - \(central)")
    }
}

CentralManagerDidUpdateState को कॉलबैक बताता है कि CoreBluaxy तैयार है, इसलिए आप अभी BLE खोज सकते हैं। अपडेट होने पर सभी BLE डिवाइस को खोजने के लिए CentralManagerDidUpdateState कोड अपडेट करें।

func centralManagerDidUpdateState(_ central: CBCentralManager) {
    print("UPDATE STATE - \(central)")
    SearchBLE()
}

func SearchBLE(){
    cb_manager.scanForPeripherals(withServices: nil, options: nil)
    StopSearchBLE()
}

func StopSearchBLE() {
    let when = DispatchTime.now() + 5 // change 5 to desired number of seconds
    DispatchQueue.main.asyncAfter(deadline: when) {
        self.cb_manager.stopScan()
    }
}
  • SearchBLE () BLE उपकरणों को खोजें और 5s के बाद खोजना बंद करें
  • cb_manager.scanForPeripherals (withServices: nil, options: nil) हर BLE को आपके साथ श्रेणी में देखता है।
  • StopSearchBLE () 5s के बाद खोज बंद कर देगा।
  • प्रत्येक बीएलई को कॉलबैक फंक सेंट्रल मैनजेंडर (_ सेंट्रल: CBCentralManager, didDiscover परिधीय: CBPeripheral, advertData: [स्ट्रिंग: कोई भी], rssi RSSI: NSNumber) कहेंगे
func centralManager(_ central: CBCentralManager, didDiscover peripheral:                                                             
    CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    guard let name = peripheral.name else {
        return
    }
    print(name)
    bles.append(peripheral)
}

कनेक्ट करें और प्रमुख मूल्य पढ़ें

  • मैं एक सिंगल मिन्यू बीकन के साथ एक नियंत्रित कमरे में हूं जो IBEACON प्रोटोकॉल का उपयोग करता है।
  • BLEController को CBPeripheralDelegate का विस्तार करने की आवश्यकता है
  • खोज बंद होने के बाद कनेक्ट करने के लिए मैं पहली BLE का उपयोग करूंगा।
  • विधि StopSearchBLE () संशोधित करें
class BLEController: CBCentralManagerDelegate, CBPeripheralDelegate{
//...
    func StopSearchMiniewBeacon() {
        let when = DispatchTime.now() + 5 // change 2 to desired number of seconds
        DispatchQueue.main.asyncAfter(deadline: when) {
            self.cb_manager.stopScan()
            self.cb_manager.connect(bles.first)
        }
    }
/...
}
  • अपने BLE डिवाइस के दस्तावेज़ में, आपको सेवा UUID और MAJOR UUID CHARACTERISTIC की तलाश करनी चाहिए
var service_uuid =  CBUUID(string: "0000fff0-0000-1000-8000-00805f9b34fb")
var major_uuid =  CBUUID(string: "0000fff2-0000-1000-8000-00805f9b34fb")
func centralManager(_ central: CBCentralManager, didConnect peripheral:             
CBPeripheral) {
    peripheral.delegate = self
    peripheral.discoverServices([service_uuid])
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    print("Service: \(service)\n error: \(error)")
    peripheral.discoverCharacteristics([major_uuid], for: (peripheral.services?[0])!)
}
  • ऊपर दिए गए कोड की तरह एक वैरिएबल 'service_uuid' और 'major_uuid' बनाएं। '-0000-1000-8000-00805f9b34fb' मानक का हिस्सा है। 'fff0' मेरी सेवा UUID है, 'fff2' मेरी प्रमुख UUID विशेषता है और 4 बाइट्स uuid 1º ब्लॉक को भरने के लिए '0000' आवश्यक हैं।
  • searchCharacteristics ([major_uuid], के लिए: (पेरिफेरल.सेर्विस [00])!) को मेरे डिवाइस gatt सर्वर से बड़ी विशेषता मिलेगी और इसमें अभी के लिए NIL मान होगा।
  • (Peripheral.services?[0])! - जब मैंने पेरिफेरल.डिस्कवर सर्विसेज़ ([service_uuid]) किया तो एक बार में एक एकल मूल्य वापस आ जाएगा
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    for characteristic in service.characteristics! {
        print("Characteristic: \(characteristic)\n error: \(error)")
        if(characteristic.uuid.uuidString == "FFF2"){
            peripheral.readValue(for: characteristic)
        }
    }
}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    print("Characteristic read: \(characteristic)\n error: \(error)")
    let major = UInt16.init(bigEndian: UInt16(data: characteristic.value!)!)
    print("major: \(major)")
}
  • विशेषता मान केवल परिधीय कॉल के बाद पठनीय होगा। VreadValue (के लिए: विशेषता)
  • readValue के परिणामस्वरूप फंक परिधीय (_ परिधीय: CBPeripheral, didUpdateValueFor विशेषता: CBCharacteristic, error: Error?) डेटा प्रकार में मूल्य के साथ होगा।

प्रमुख मूल्य लिखें

  • आपको सेवाओं और विशेषता की खोज करने की आवश्यकता है
  • इस पर लिखने से पहले आपको विशेषता से रीड वैल्यू की आवश्यकता नहीं है।
  • इस उदाहरण के लिए जारी रहेगा, पढ़ने के मूल्य के बाद। कवक परिधीय को संशोधित करें (_ परिधीय: CBPeripheral, didUpdateValueFor विशेषता: CBCharacteristic, error: त्रुटि?)
  • एक वैरिएबल new_major और reset_characteristic जोड़ें
var reset_characteristic : CBCharacteristic!
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    for characteristic in service.characteristics! {
        print("Characteristic: \(characteristic)\n error: \(error)")
        if(characteristic.uuid.uuidString == "FFF2"){
            peripheral.readValue(for: characteristic)
        }
        if(characteristic.uuid.uuidString == "FFFF"){
            reset_characteristic = characteristic
        }
    }
}
let new_major : UInt16 = 100
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    print("Characteristic read: \(characteristic)\n error: \(error)")
    let major = UInt16.init(bigEndian: UInt16(data: characteristic.value!)!)
    print("major: \(major)")
    peripheral.writeValue(new_major.data, for: characteristic, type: CBCharacteristicWriteType.withResponse)
}
  • आईफ़ोन बायफुल लिटिल एंडियन प्रारूप में बाइट्स भेजेगा और प्राप्त करेगा, लेकिन मेरे डिवाइस MINEW विच चिपसेट NRF51822 में ARM आर्कटेट है और बिग एंडियन प्रारूप में बाइट्स की आवश्यकता है, इसलिए मुझे इसे स्वैप करना होगा।
  • BLE डिवाइस प्रलेखन कहेगा कि किस प्रकार के इनपुट और आउटपुट प्रत्येक विशेषता के पास होंगे और यदि आप इसे ऊपर की तरह पढ़ सकते हैं (CBCharacteristicWriteType.withResponse)।
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
    print("Characteristic write: \(characteristic)\n error: \(error)")
    if(characteristic.uuid.uuidString == "FFF2"){
            print("Resetting")
            peripheral.writeValue("minew123".data(using: String.Encoding.utf8)!, for: reset_characteristic, type: CBCharacteristicWriteType.withResponse)
        }
    if(characteristic.uuid.uuidString == "FFFF"){
        print("Reboot finish")
        cb_manager.cancelPeripheralConnection(peripheral)
    }
}
  • एक गट सर्वर जानकारी को अपडेट करने के लिए आपको इसे प्रोग्रामेटिक रूप से रिबूट करना होगा या इसके लिए डेटा को सेव करना होगा और मैन्युअल रूप से बंद और चालू करना होगा।
  • एफएफएफएफ की विशेषता है कि यह इस उपकरण में करता है।
  • 'minew123' इस मामले में रिबूट ओ सेव जानकारी के लिए डिफ़ॉल्ट पासवर्ड है।
  • अपना ऐप चलाएं और किसी भी त्रुटि के लिए आपको सांत्वना दें, मुझे आशा है कि कोई भी नहीं, लेकिन आप अभी तक नया मूल्य नहीं देखेंगे।
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    print("Characteristic read: \(characteristic)\n error: \(error)")
    let major = UInt16.init(bigEndian: UInt16(data: characteristic.value!)!)
    print("major: \(major)")
    //peripheral.writeValue(new_major.data, for: characteristic, type: CBCharacteristicWriteType.withResponse)

}

  • अंतिम चरण विधि doUpdateValueFor और एप्लिकेशन को फिर से चलाने के लिए अंतिम पंक्ति में टिप्पणी करना है, अब आप नया मान लेंगे।


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow