Hello World لتلقي البيانات من جهاز Bluetooth (BLE) عبر C #

مساء الخير

قبل أسبوعين ، واجهت مشكلة أنه لا توجد ببساطة مقالة عادية وحديثة حول تلقي البيانات لأول مرة باستخدام Bluetooth . وكان علي أن العبث بها لفهم من أين أبدأ وكيف أفعل ذلك على الإطلاق. ولكي لا يكرر الناس أخطائي ، إليك مقالة قصيرة حول كيفية القيام بذلك.



لكن أولاً ، بضع كلمات رثاء ، وهذا ضروري بشكل عام. ينغمس العالم الحديث بشكل متزايد في أيديولوجية إنترنت الأشياء. الآن كل شيء يتفاعل مع بعضها البعض ، ثلاجة مع موقد ، مكواة مع مكنسة كهربائية ، إلخ. تم رفع الكثير من الضوضاء بسبب تخطيط كهربية القلب في Apple Watch ، ولكن أجهزة قياس ضغط الدم الحديثة ، وأجهزة مراقبة معدل ضربات القلب ، وموازين الحرارة كانت قادرة منذ فترة طويلة على نقل البيانات عبر البلوتوث. وكل هذا يحتاج بطريقة أو بأخرى إلى أن يكون متصلاً بشبكة واحدة. والعنصر الرئيسي في هذه الشبكة هو ، مهما كان ما يقوله المرء ، جهاز كمبيوتر. في هذا الصدد ، نشأت المهمة لتلقي البيانات من جهاز معين عبر Bluetooth.

بادئ ذي بدء ، ما كان لدينا بالفعل وما فاقم البحث عن حل. وكان لدينا طلب مكتوب بلغة .Net Core . ما هو جوهر التطبيق غير مهم ، من أجل البساطة سنفترض أن لدينا فقط وحدة تحكم على .Net Core . حسنًا ، سيتم استدعاء الجهاز بالحرف N.

ستؤدي المحاولات الأولى للعثور على شيء يعمل مع Bluetooth عبر C # إلى مكتبة 32 قدمًا .

في حزم NuGet ، يبدو أن 32feet.NET .

وبالمناسبة ، عثرت في أحدث إصدار من منتجها على أجهزة Bluetooth ، ولكن لم تجد معيار BLE [كما اتضح فيما بعد]. على سبيل المثال ، تم البحث عن نفس OnePlus 5T بشكل ثابت ، ولكن الجهاز الضروري N ليس كذلك. بالتوازي مع ذلك ، تم العثور على الجواب الرسمي للمؤلف أن مكتبته لا تتفاعل مع BLE من حيث المبدأ ، ولا فائدة من المحاولة. على الرغم من وجود إصدار أولي من InTheHand.Devices.Bluetooth على Github والذي يجب أن يدعم BLE ، فقد تم تغيير كل شيء كثيرًا ولا توجد وثائق على الإطلاق لم تعمل حتى على تجميع المشروع بأفكار مأخوذة من 32feet.NET .

قادني بحث جديد إلى المزيد من الحلول القياسية ، وهي منصة Windows العالمية ( UWP ). في تطوير هذا النظام الأساسي ، قامت شركة Microsoft ، التي تبنتها فكرة التنوع والتطبيق الواحد للكمبيوتر والهاتف ، بتجربة والتفاعل مع Bluetooth. وهنا كل شيء يعمل بشكل جيد ، ولكن ... لدينا مشروع على .Net Core ... ولا يوجد شيء يمكن القيام به حيال ذلك.

يجب أن أقول على الفور أننا لم نتمكن من إيجاد حلول لتفاعل مكتبات UWP مع .Net Core والمشروع يجب أن يتحول إلى 4.7.1. ، الفائدة ليست صعبة. على الرغم من وجود أفكار حول كيفية ترك المشروع على .Net Core وعلى سبيل المثال إنشاء خدمة Windows منفصلة مع نقل البيانات من خلال الأنابيب المسماة (توجيه الإخراج) أو رفع خدمة WCF وإنشاء تفاعل معها ، ولكن في حالتنا لم يكن ذلك منطقيًا.



لذا في النهاية لدينا قبل البداية:

  • المشروع على 4.7.1.
  • تم تحديث Win10 إلى الإصدار 10.0.17134 Build 17134.

تحتاج أولاً إلى ربط مكتبتين بأقلام ، وهما

  • "Windows من النظام الأساسي العالمي لـ Windows"
    ملفات C: \ Program (x86) \ Windows Kits \ 10 \ UnionMetadata \ 10.0.17134.0 \ Windows.winmd
  • "System.Runtime.WindowsRuntime"
    ملفات C: \ Program (x86) \ Reference Assemblies \ Microsoft \ Framework \ .NETCore \ v4.5 \ System.Runtime.WindowsRuntime.dll

وفي الواقع كل شيء ، ثم يذهب العمل مع الجهاز نفسه من خلال الوثائق دون مشاكل.
تفاعل مع BLE عبر فئة BluetoothLEAdvertisementWatcher
ولكن يجب ألا ننسى أنه بدون واجهة برمجة التطبيقات الخاصة بالجهاز نفسه ، لن يعمل شيء معقول.

إليك عينة من التعليمات البرمجية حول كيفية الحصول على البيانات من جهاز.

تم تصميم هذا الرمز لضمان إضافة الجهاز بالفعل (متصل).

public class BluetoothObserver { BluetoothLEAdvertisementWatcher Watcher { get; set; } public void Start() { Watcher = new BluetoothLEAdvertisementWatcher() { ScanningMode = BluetoothLEScanningMode.Active }; Watcher.Received += Watcher_Received; Watcher.Stopped += Watcher_Stopped; Watcher.Start(); } private bool isFindDevice { get; set; } = false; private async void Watcher_Received(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args) { if (isFindDevice) return; if (args.Advertisement.LocalName.Contains("deviceName")) { isFindDevice = true; BluetoothLEDevice bluetoothLeDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress); GattDeviceServicesResult result = await bluetoothLeDevice.GetGattServicesAsync(); if (result.Status == GattCommunicationStatus.Success) { var services = result.Services; foreach (var service in services) { if (!service.Uuid.ToString().StartsWith("serviceName")) { continue; } GattCharacteristicsResult characteristicsResult = await service.GetCharacteristicsAsync(); if (characteristicsResult.Status == GattCommunicationStatus.Success) { var characteristics = characteristicsResult.Characteristics; foreach (var characteristic in characteristics) { if (!characteristic.Uuid.ToString().StartsWith("characteristicName")) { continue; } GattCharacteristicProperties properties = characteristic.CharacteristicProperties; if (properties.HasFlag(GattCharacteristicProperties.Indicate)) { characteristic.ValueChanged += Characteristic_ValueChanged; GattWriteResult status = await characteristic.WriteClientCharacteristicConfigurationDescriptorWithResultAsync(GattClientCharacteristicConfigurationDescriptorValue.Indicate); return; } if (properties.HasFlag(GattCharacteristicProperties.Read)) { GattReadResult gattResult = await characteristic.ReadValueAsync(); if (gattResult.Status == GattCommunicationStatus.Success) { var reader = DataReader.FromBuffer(gattResult.Value); byte[] input = new byte[reader.UnconsumedBufferLength]; reader.ReadBytes(input); // input } } } } } } } } private void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args) { var reader = DataReader.FromBuffer(args.CharacteristicValue); byte[] input = new byte[reader.UnconsumedBufferLength]; reader.ReadBytes(input); // input } private void Watcher_Stopped(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementWatcherStoppedEventArgs args) { ; } } 

شكرا لكم على اهتمامكم.

Source: https://habr.com/ru/post/ar423893/


All Articles