- < 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: объект не получен"
Так что же я пропустил? Службы и характеристики 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
Сервер Bluetooth LE GATT, работающий на Raspberry Pi с .NET 8 ⇐ C#
Сервер Bluetooth LE GATT, работающий на Raspberry Pi с .NET 8
Я собрал это приложение .NET 8, которое должно работать на Raspberry Pi (ОС Raspberry Pi, 64-разрядная версия Linux), и делаю следующее:
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Может ли устройство Android одновременно действовать как GATT-сервер и GATT-клиент?
Anonymous » » в форуме Android - 0 Ответы
- 17 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Создайте Bluetooth-сервер BLE GATT с низким энергопотреблением с помощью .NET C#
Anonymous » » в форуме C# - 0 Ответы
- 17 Просмотры
-
Последнее сообщение Anonymous
-