Сервер Bluetooth LE GATT, работающий на Raspberry Pi с .NET 8C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Сервер Bluetooth LE GATT, работающий на Raspberry Pi с .NET 8

Сообщение Anonymous »

Я собрал это приложение .NET 8, которое должно работать на Raspberry Pi (ОС Raspberry Pi, 64-разрядная версия Linux), и делаю следующее:
  • < li>Публикуйте рекламные объявления Bluetooth LE с конкретными данными производителя, чтобы клиенты могли идентифицировать устройство.
  • Предлагайте определенные услуги GATT с характеристиками, чтобы клиенты могли запрашивать данные из Raspi.
    Это содержит множество интерфейсов D-Bus, которые в основном были созданы ChatGPT, и я частично исправил их в соответствии со спецификацией BlueZ. Я новичок в BlueZ и D-Bus, поэтому могу лишь приблизительно представить, что все это делает. Кроме того, ИИ оказался не так уж полезен, потому что мне приходилось снова и снова исследовать, гадать и запрашивать конкретные API, которые оказались необходимыми, но раньше не учитывались (например, GattManager и GattApplication).
    Однако в коде есть несколько проблем, которые мне пока не удалось решить:
    • При отправке рекламных объявлений (проверено с помощью приложения nRF Connect) для Android), они не содержат никаких данных. Нет локального имени, нет мощности передачи, нет данных производителя.
    • Когда используется код сервера GATT (как указано здесь), он выдает исключение Tmds.DBus.DBusException: " org.bluez.Error.Failed: объект не получен"
    До сих пор я мог определить ошибки из спецификации, но теперь я потерялся и часть GattApplication больше не описывается. Это вообще правильно?
    Так что же я пропустил? Службы и характеристики GATT связаны только через строковое значение ObjectPath с общими префиксами или мне нужно явно установить это соединение где-то в коде? И что означает это сообщение об исключении?
    Любая помощь приветствуется, поскольку мне не удалось найти никаких ресурсов по этому поводу в Интернете. Я не уверен, делал ли кто-нибудь это раньше.
    Вот код (Program.cs):
    using Tmds.DBus;

    namespace RadarSender;

    public class Program
    {
    public static async Task Main()
    {
    // Create a DBus connection with manual connection management
    var connection = new Connection(Address.System);
    await connection.ConnectAsync();

    // Access the LEAdvertisingManager1 interface
    const string adapterPath = "/org/bluez/hci0";
    var advertisingManager = connection.CreateProxy("org.bluez", adapterPath);

    // Advertisement setup
    const string advertisementPath = "/com/example/Advertisement";
    Dictionary manufacturerData = [];
    manufacturerData["0x8001"] = new byte[] { 0x12, 0x34, 0x56 };
    var advertisement = new LEAdvertisement(advertisementPath, manufacturerData);
    await connection.RegisterObjectAsync(advertisement);

    await advertisingManager.RegisterAdvertisementAsync(advertisement.ObjectPath, new Dictionary());
    Console.WriteLine("BLE Advertisement started.");

    // Create GATT objects
    var application = new GattApplication("/com/example/gattapp");
    var service = new GattService("/com/example/gattapp/service0", "12345678-1234-5678-1234-56789abcdef0");
    var characteristic = new GattCharacteristic("/com/example/gattapp/service0/char0", "12345678-1234-5678-1234-56789abcdef1");

    // Register objects with DBus
    await connection.RegisterObjectAsync(application);
    await connection.RegisterObjectAsync(service);
    await connection.RegisterObjectAsync(characteristic);

    // Register application with BlueZ
    var gattManager = connection.CreateProxy("org.bluez", "/org/bluez/hci0");
    await gattManager.RegisterApplicationAsync(application.ObjectPath, new Dictionary());
    Console.WriteLine("GATT server started.");

    Console.WriteLine("Press Enter to exit...");
    Console.ReadLine();

    // Cleanup
    await advertisingManager.UnregisterAdvertisementAsync(advertisement.ObjectPath);
    connection.UnregisterObject(advertisement.ObjectPath);
    await gattManager.UnregisterApplicationAsync(application.ObjectPath);
    connection.UnregisterObject(service.ObjectPath);
    connection.UnregisterObject(characteristic.ObjectPath);
    connection.Dispose();
    }
    }

    [DBusInterface("org.bluez.LEAdvertisingManager1")]
    public interface ILEAdvertisingManager1 : IDBusObject
    {
    Task RegisterAdvertisementAsync(ObjectPath advertisement, IDictionary options);
    Task UnregisterAdvertisementAsync(ObjectPath advertisement);
    }

    [DBusInterface("org.bluez.LEAdvertisement1")]
    public interface ILEAdvertisement1 : IDBusObject
    {
    Task GetIncludesAsync();
    Task GetTypeAsync();
    Task GetServiceUUIDsAsync();
    Task GetLocalNameAsync();
    Task GetAppearanceAsync();
    Task GetTxPowerAsync();
    Task GetManufacturerDataAsync();
    Task GetServiceDataAsync();
    Task ReleaseAsync();
    }

    public class LEAdvertisement : ILEAdvertisement1
    {
    private readonly IDictionary manufacturerData;

    public LEAdvertisement(string path, IDictionary manufacturerData)
    {
    ObjectPath = new ObjectPath(path);
    this.manufacturerData = manufacturerData;
    }

    public ObjectPath ObjectPath { get; }

    public Task GetIncludesAsync() => Task.FromResult(["local-name", "tx-power"]);

    public Task GetTypeAsync() => Task.FromResult("peripheral");

    public Task GetServiceUUIDsAsync() => Task.FromResult(["12345678-1234-5678-1234-56789abcdef0"]);

    public Task GetLocalNameAsync() => Task.FromResult("RaspberryPiBLE");

    public Task GetAppearanceAsync() => Task.FromResult(0);

    public Task GetTxPowerAsync() => Task.FromResult(10);

    public Task GetManufacturerDataAsync() => Task.FromResult(manufacturerData);

    public Task GetServiceDataAsync() => Task.FromResult(new Dictionary());

    public Task ReleaseAsync()
    {
    Console.WriteLine("Advertisement released.");
    return Task.CompletedTask;
    }
    }

    [DBusInterface("org.bluez.GattManager1")]
    public interface IGattManager1 : IDBusObject
    {
    Task RegisterApplicationAsync(ObjectPath application, IDictionary options);
    Task UnregisterApplicationAsync(ObjectPath application);
    }

    public class GattApplication : IDBusObject
    {
    public GattApplication(string path)
    {
    ObjectPath = new ObjectPath(path);
    }

    public ObjectPath ObjectPath { get; }
    }

    [DBusInterface("org.bluez.GattService1")]
    public interface IGattService1 : IDBusObject
    {
    Task GetUUIDAsync();
    Task GetPrimaryAsync();
    Task GetIncludesAsync();
    Task GetCharacteristicsAsync();
    }

    public class GattService : IGattService1
    {
    private readonly string uuid;

    public GattService(string path, string uuid)
    {
    ObjectPath = new ObjectPath(path);
    this.uuid = uuid;
    }

    public ObjectPath ObjectPath { get; }

    public Task GetUUIDAsync() => Task.FromResult(uuid);

    public Task GetPrimaryAsync() => Task.FromResult(true);

    public Task GetIncludesAsync() => Task.FromResult([]);

    public Task GetCharacteristicsAsync()
    {
    // TODO: Add future characteristics here
    var characteristicPath = new ObjectPath($"{ObjectPath}/char0");
    return Task.FromResult(new[] { characteristicPath });
    }
    }

    [DBusInterface("org.bluez.GattCharacteristic1")]
    public interface IGattCharacteristic1 : IDBusObject
    {
    Task ReadValueAsync(IDictionary options);
    Task WriteValueAsync(byte[] value, IDictionary options);
    Task StartNotifyAsync();
    Task StopNotifyAsync();
    Task GetUUIDAsync();
    Task GetFlagsAsync();
    Task GetServiceAsync();
    Task GetNotifyingAsync();
    Task GetValueAsync();
    }

    public class GattCharacteristic : IGattCharacteristic1
    {
    private readonly string uuid;

    public GattCharacteristic(string path, string uuid)
    {
    ObjectPath = new ObjectPath(path);
    this.uuid = uuid;
    }

    public ObjectPath ObjectPath { get; }

    public Task GetFlagsAsync() => Task.FromResult(["read", "write", "notify"]);

    public Task ReadValueAsync(IDictionary options)
    {
    Console.WriteLine("Characteristic read requested.");
    return Task.FromResult(new byte[] { 0x01, 0x02, 0x03 });
    }

    public Task WriteValueAsync(byte[] value, IDictionary options)
    {
    Console.WriteLine($"Characteristic write requested: {BitConverter.ToString(value)}");
    return Task.CompletedTask;
    }

    public Task StartNotifyAsync()
    {
    Console.WriteLine("Notifications started.");
    return Task.CompletedTask;
    }

    public Task StopNotifyAsync()
    {
    Console.WriteLine("Notifications stopped.");
    return Task.CompletedTask;
    }

    public Task GetUUIDAsync() => Task.FromResult(uuid);

    // TODO: Make configurable
    public Task GetServiceAsync() => Task.FromResult(new ObjectPath("/com/example/gattapp/service0"));

    public Task GetNotifyingAsync() => Task.FromResult(false);

    public Task GetValueAsync() => Task.FromResult(new byte[] { 0x11, 0x22, 0x33, 0x44 });
    }

    И соответствующий файл проекта (.csproj):



    Exe
    net8.0
    enable
    enable









    Подробнее здесь: https://stackoverflow.com/questions/792 ... with-net-8
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Сервер Bluetooth LE GATT, работающий на Raspberry Pi с .NET 8
    Anonymous » » в форуме C#
    0 Ответы
    13 Просмотры
    Последнее сообщение Anonymous
  • Может ли устройство Android одновременно действовать как GATT-сервер и GATT-клиент?
    Anonymous » » в форуме Android
    0 Ответы
    17 Просмотры
    Последнее сообщение Anonymous
  • Создайте Bluetooth-сервер BLE GATT с низким энергопотреблением с помощью .NET C#
    Anonymous » » в форуме C#
    0 Ответы
    17 Просмотры
    Последнее сообщение Anonymous
  • Виртуальный принтер сервер GATT физическое устройство Android
    Anonymous » » в форуме Android
    0 Ответы
    32 Просмотры
    Последнее сообщение Anonymous
  • Реализуйте CTS-подобный сервер GATT на iOS
    Anonymous » » в форуме IOS
    0 Ответы
    11 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»