Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit onderwerp wordt gedemonstreert hoe u de GATT-server-API's (Bluetooth Generic Attribute) gebruikt voor Windows-apps.
Important
U moet de mogelijkheid 'bluetooth' declareren in Package.appxmanifest.
<Capabilities> <DeviceCapability Name="bluetooth" /> </Capabilities>
- Belangrijke API's:Windows.Devices.Bluetooth, Windows.Devices.Bluetooth.GenericAttributeProfile
Overzicht
Windows werkt meestal in de clientrol. Niettemin ontstaan er veel scenario's waarvoor ook Windows moet fungeren als een Bluetooth LE GATT-server. Bijna alle scenario's voor IoT-apparaten, samen met de meeste platformoverschrijdende BLE-communicatie, moeten Windows een GATT-server zijn. Daarnaast is het verzenden van meldingen naar draagbare apparaten in de buurt een populair scenario geworden dat deze technologie ook vereist.
Serveractiviteiten zullen draaien rond de Service Provider en de GattLocalCharacteristic. Deze twee klassen bieden de functionaliteit die nodig is voor het declareren, implementeren en beschikbaar maken van een hiërarchie van gegevens op een extern apparaat.
De ondersteunde services definiëren
Uw app kan een of meer services declareren die worden gepubliceerd door Windows. Elke service wordt uniek geïdentificeerd door een UUID.
Kenmerken en UUID's
Elke service, kenmerk en descriptor wordt gedefinieerd door zijn eigen unieke 128-bits UUID.
Note
De Windows API's gebruiken allemaal de term GUID, maar de Bluetooth-standaard definieert deze als UUID's. Voor onze doeleinden zijn deze twee termen uitwisselbaar, zodat we de term UUID blijven gebruiken.
Als het kenmerk standaard is en door de Bluetooth SIG is gedefinieerd, heeft het ook een bijbehorende 16-bits korte id (bijvoorbeeld UUID op batterijniveau is 0000 2A19-0000-1000-8000-00805F9B34FB en de korte id is 0x2A19). Deze standaard UUID's zijn te zien in GattServiceUuids en GattCharacteristicUuids.
Als uw app een eigen aangepaste service implementeert, moet er een aangepaste UUID worden gegenereerd. Dit kan eenvoudig in Visual Studio via Tools > CreateGuid (gebruik optie 5 om het in de notatie "xxxxxxxx-xxxx-...xxxx" te krijgen). Deze uuid kan nu worden gebruikt om nieuwe lokale services, kenmerken of descriptors te declareren.
Beperkte services
De volgende services zijn gereserveerd door het systeem en kunnen op dit moment niet worden gepubliceerd:
- Apparaatinformatieservice (DIS)
- Algemene kenmerkprofielservice (GATT)
- Algemene toegangsprofielservice (GAP)
- Service voor scanparameters (SCP)
Caution
Als u een geblokkeerde service probeert te maken, wordt BluetoothError.DisabledByPolicy geretourneerd vanuit de aanroep naar CreateAsync.
Gegenereerde attributen
De volgende descriptors worden automatisch gegenereerd door het systeem, op basis van de GattLocalCharacteristicParameters die tijdens het maken van het kenmerk worden verstrekt:
- Configuratie van clientkenmerken (als het kenmerk is gemarkeerd als aan te geven of te markeren).
- Kenmerkende gebruikersbeschrijving (als de eigenschap UserDescription is ingesteld). Zie de eigenschap GattLocalCharacteristicParameters.UserDescription voor meer informatie.
- Kenmerkindeling (één descriptor voor elke opgegeven presentatieindeling). Zie de eigenschap GattLocalCharacteristicParameters.PresentationFormats voor meer informatie.
- Kenmerkaggregatiesindeling (als er meer dan één presentatie-indeling is opgegeven). Zie de eigenschap GattLocalCharacteristicParameters.See PresentationFormats voor meer informatie.
- Uitgebreide eigenschappen van de karakteristiek (als de karakteristiek is gemarkeerd met de bit voor uitgebreide eigenschappen).
Note
De waarde van de uitgebreide eigenschappendescriptor wordt bepaald via de ReliableWrites en WritableAuxiliaries karakteristieke eigenschappen.
Caution
Als u een gereserveerde descriptor probeert te maken, resulteert dit in een uitzondering.
Caution
Broadcast wordt momenteel niet ondersteund. Als u de Broadcast GattCharacteristicProperty opgeeft, resulteert dit in een uitzondering.
De hiërarchie van services en kenmerken opbouwen
De GattServiceProvider wordt gebruikt om de primaire basisservicedefinitie te maken en te adverteren. Voor elke service is een eigen ServiceProvider-object vereist dat een GUID inneemt:
GattServiceProviderResult result = await GattServiceProvider.CreateAsync(uuid);
if (result.Error == BluetoothError.Success)
{
serviceProvider = result.ServiceProvider;
//
}
Primaire diensten zijn het hoogste niveau van de GATT-structuur. Primaire services bevatten kenmerken en andere services (opgenomen of secundaire services genoemd).
Vul nu de service met de vereiste kenmerken en descriptors:
GattLocalCharacteristicResult characteristicResult = await serviceProvider.Service.CreateCharacteristicAsync(uuid1, ReadParameters);
if (characteristicResult.Error != BluetoothError.Success)
{
// An error occurred.
return;
}
_readCharacteristic = characteristicResult.Characteristic;
_readCharacteristic.ReadRequested += ReadCharacteristic_ReadRequested;
characteristicResult = await serviceProvider.Service.CreateCharacteristicAsync(uuid2, WriteParameters);
if (characteristicResult.Error != BluetoothError.Success)
{
// An error occurred.
return;
}
_writeCharacteristic = characteristicResult.Characteristic;
_writeCharacteristic.WriteRequested += WriteCharacteristic_WriteRequested;
characteristicResult = await serviceProvider.Service.CreateCharacteristicAsync(uuid3, NotifyParameters);
if (characteristicResult.Error != BluetoothError.Success)
{
// An error occurred.
return;
}
_notifyCharacteristic = characteristicResult.Characteristic;
_notifyCharacteristic.SubscribedClientsChanged += SubscribedClientsChanged;
Zoals hierboven wordt weergegeven, is dit ook een goede plek om gebeurtenis-handlers te declareren voor de bewerkingen die elk kenmerk ondersteunt. Als u correct wilt reageren op aanvragen, moet een app een gebeurtenis-handler definiëren en instellen voor elk aanvraagtype dat door het kenmerk wordt ondersteund. Als u geen handler registreert, wordt het verzoek door het systeem onmiddellijk voltooid met UnlikelyError.
Constante kenmerken
Soms zijn er kenmerkwaarden die niet veranderen tijdens de levensduur van de app. In dat geval is het raadzaam om een constante eigenschap te declareren om onnodige app-activering te voorkomen:
byte[] value = new byte[] {0x21};
var constantParameters = new GattLocalCharacteristicParameters
{
CharacteristicProperties = (GattCharacteristicProperties.Read),
StaticValue = value.AsBuffer(),
ReadProtectionLevel = GattProtectionLevel.Plain,
};
var characteristicResult = await serviceProvider.Service.CreateCharacteristicAsync(uuid4, constantParameters);
if (characteristicResult.Error != BluetoothError.Success)
{
// An error occurred.
return;
}
De service publiceren
Zodra de service volledig is gedefinieerd, is de volgende stap het publiceren van ondersteuning voor de service. Hiermee wordt het besturingssysteem geïnformeerd dat de service moet worden geretourneerd wanneer externe apparaten een servicedetectie uitvoeren. U moet twee eigenschappen instellen : IsDiscoverableIsConnectable
GattServiceProviderAdvertisingParameters advParameters = new GattServiceProviderAdvertisingParameters
{
IsDiscoverable = true,
IsConnectable = true
};
serviceProvider.StartAdvertising(advParameters);
-
IsDiscoverable: kondigt de beschrijvende naam aan externe apparaten in de advertentie aan, waardoor het apparaat detecteerbaar is. -
IsConnectable: Adverteert een verbindbare advertentie voor gebruik in de rol van randapparaat.
Wanneer een service zowel Discoverable als Connectable is, voegt het systeem de Service Uuid toe aan het advertentiepakket. Er zijn slechts 31 bytes in het advertentiepakket en een 128-bits UUID neemt er 16 van in beslag!
Wanneer een service op de voorgrond wordt gepubliceerd, moet een toepassing StopAdvertising aanroepen wanneer deze wordt geschorst.
Reageren op lees- en schrijfaanvragen
Zoals eerder gezien bij het declareren van de vereiste eigenschappen, hebben GattLocalCharacteristics drie typen gebeurtenissen: ReadRequested, WriteRequested en SubscribedClientsChanged.
Lezen
Wanneer een extern apparaat probeert een waarde van een kenmerk te lezen (en dit geen constante waarde is), wordt de ReadRequested gebeurtenis aangeroepen. De characteristiek waarop de leesactie is aangeroepen, evenals de argumenten (die informatie over het externe apparaat bevatten), worden doorgegeven aan de delegate:
characteristic.ReadRequested += Characteristic_ReadRequested;
// ...
async void ReadCharacteristic_ReadRequested(GattLocalCharacteristic sender, GattReadRequestedEventArgs args)
{
var deferral = args.GetDeferral();
// Our familiar friend - DataWriter.
var writer = new DataWriter();
// populate writer w/ some data.
// ...
var request = await args.GetRequestAsync();
request.RespondWithValue(writer.DetachBuffer());
deferral.Complete();
}
Write
Wanneer een extern apparaat probeert een waarde naar een kenmerk te schrijven, wordt de gebeurtenis WriteRequested aangeroepen met details over het externe apparaat, naar welk kenmerk moet worden geschreven en de waarde zelf:
characteristic.ReadRequested += Characteristic_ReadRequested;
// ...
async void WriteCharacteristic_WriteRequested(GattLocalCharacteristic sender, GattWriteRequestedEventArgs args)
{
var deferral = args.GetDeferral();
var request = await args.GetRequestAsync();
var reader = DataReader.FromBuffer(request.Value);
// Parse data as necessary.
if (request.Option == GattWriteOption.WriteWithResponse)
{
request.Respond();
}
deferral.Complete();
}
Er zijn twee typen schrijfbewerkingen: met en zonder reactie. Gebruik GattWriteOption (een eigenschap op het GattWriteRequest object) om te bepalen welk type schrijfbewerking het externe apparaat uitvoert.
Meldingen verzenden naar geabonneerde clients
De meest voorkomende bewerkingen van de GATT-server, meldingen voeren de kritieke functie uit van het pushen van gegevens naar de externe apparaten. Soms wilt u alle geabonneerde clients op de hoogte stellen, maar soms wilt u misschien kiezen naar welke apparaten de nieuwe waarde moet worden verzonden:
async void NotifyValue()
{
var writer = new DataWriter();
// Populate writer with data
// ...
await notifyCharacteristic.NotifyValueAsync(writer.DetachBuffer());
}
Wanneer een nieuw apparaat zich abonneert op meldingen, wordt de SubscribedClientsChanged gebeurtenis aangeroepen:
characteristic.SubscribedClientsChanged += SubscribedClientsChanged;
// ...
void _notifyCharacteristic_SubscribedClientsChanged(GattLocalCharacteristic sender, object args)
{
List<GattSubscribedClient> clients = sender.SubscribedClients;
// Diff the new list of clients from a previously saved one
// to get which device has subscribed for notifications.
// You can also just validate that the list of clients is expected for this app.
}
Note
Uw toepassing kan de maximale meldingsgrootte voor een bepaalde client met de MaxNotificationSize eigenschap ophalen. Gegevens die groter zijn dan de maximale grootte, worden door het systeem afgekapt.
Wanneer u de gattLocalCharacteristic.SubscribedClientsChanged-gebeurtenis verwerkt, kunt u het onderstaande proces gebruiken om volledige informatie te bepalen over de momenteel geabonneerde clientapparaten:
- De argumenten van de
SubscribedClientsChangedgebeurtenis zijn een GattLocalCharacteristic-object. - Toegang tot de eigenschap GattLocalCharacteristic.SubscribedClients van dat object, een verzameling GattSubscribedClient-objecten .
- Doorloop die verzameling. Ga als volgt te werk voor elk element:
- Gebruik de eigenschap GattSubscribedClient.Session, die een GattSession-object is.
- Gebruik de eigenschap GattSession.DeviceId, die een BluetoothDeviceId-object is.
- Open de eigenschap BluetoothDeviceId.Id , de apparaat-id-tekenreeks.
- Geef de tekenreeks van de apparaat-id door aan BluetoothLEDevice.FromIdAsync om een BluetoothLEDevice-object op te halen. U kunt volledige informatie krijgen over het apparaat van dat object.
Windows developer