Как добавить уведомление Bluetooth для обслуживания батареи на Xamarin Android? - PullRequest
0 голосов
/ 10 июля 2020

Пытаюсь понять, как можно включить уведомление для функции уровня заряда батареи. Я читал о дескрипторах, но пока не смог понять их использование. Я использую Android как клиент (xamarin) и Windows как сервер. Вот мой код:

Server (BatteryService)

using System;
using System.ComponentModel;
using System.Threading.Tasks;
using GattServicesLibrary.Helpers;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Power;

namespace GattServicesLibrary.Services
{
/// <summary>
/// Class for Battery Services
/// </summary>
public class BatteryService : GenericGattService
{
    /// <summary>
    /// Name of the service
    /// </summary>
    public override string Name
    {
        get
        {
            return "Battery Service";
        }
    }

    /// <summary>
    /// Battery level
    /// </summary>
    private GenericGattCharacteristic batteryLevel;

    /// <summary>
    /// Gets or sets the battery level 
    /// </summary>
    public GenericGattCharacteristic BatteryLevel
    {
        get
        {
            return batteryLevel;
        }

        set
        {
            if (batteryLevel != value)
            {
                batteryLevel = value;
                OnPropertyChanged(new PropertyChangedEventArgs("BatteryLevel"));
            }
        }
    }

    /// <summary>
    /// Asynchronous initialization
    /// </summary>
    /// <returns>Initialization Task</returns>
    public override async Task Init()
    {
        await CreateServiceProvider(GattServiceUuids.Battery);

        // Preparing the Battery Level characteristics
        GattLocalCharacteristicParameters batteryCharacteristicsParameters = PlainReadNotifyParameters;

        // Set the user descriptions
        batteryCharacteristicsParameters.UserDescription = "Battery Level percentage remaining";

        // Add presentation format - 16-bit integer, with exponent 0, the unit is percentage, defined per Bluetooth SIG with Microsoft as descriptor
        batteryCharacteristicsParameters.PresentationFormats.Add(
            GattPresentationFormat.FromParts(
                Convert.ToByte(PresentationFormats.FormatTypes.Unsigned8BitInteger),
                PresentationFormats.Exponent,
                Convert.ToUInt16(PresentationFormats.Units.Percentage),
                Convert.ToByte(PresentationFormats.NamespaceId.BluetoothSigAssignedNumber),
                PresentationFormats.Description));

        // Create the characteristic for the service
        GattLocalCharacteristicResult result = 
            await ServiceProvider.Service.CreateCharacteristicAsync(
                GattCharacteristicUuids.BatteryLevel, 
                batteryCharacteristicsParameters);

        // Grab the characterist object from the service set it to the BatteryLevel property which is of a specfic Characteristic type
        GattLocalCharacteristic baseBatteryLevel = null;
        GattServicesHelper.GetCharacteristicsFromResult(result, ref baseBatteryLevel);

        if (baseBatteryLevel != null)
        {
            BatteryLevel = new Characteristics.BatteryLevelCharacteristic(baseBatteryLevel, this);
        }
    }
}
}

Server Characteristi c (BatteryLevelCharacteristi c)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GattServicesLibrary.Helpers;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Power;
using Windows.Storage.Streams;

namespace GattServicesLibrary.Characteristics
{
/// <summary>
/// Implementation of the battery profile
/// </summary>
public class BatteryLevelCharacteristic : GenericGattCharacteristic
{
    /// <summary>
    /// Access to the battery of this system
    /// </summary>
    private Battery aggBattery = Battery.AggregateBattery;

    /// <summary>
    /// Initializes a new instance of the <see cref="BatteryLevelCharacteristic" /> class.
    /// </summary>
    /// <param name="characteristic">The characteristic that this wraps</param>
    public BatteryLevelCharacteristic(GattLocalCharacteristic characteristic, GenericGattService service) : base(characteristic, service)
    {
        aggBattery.ReportUpdated += AggBattery_ReportUpdated;
        UpdateBatteryValue();
    }

    /// <summary>
    /// Callback when the battery level changes
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    private void AggBattery_ReportUpdated(Battery sender, object args)
    {
        UpdateBatteryValue();
        NotifyValue();
    }

    /// <summary>
    /// Method that updates <see cref="GenericGattCharacteristic.Value"/> with the current battery level 
    /// </summary>
    private void UpdateBatteryValue()
    {
        // Get report
        BatteryReport report = aggBattery.GetReport();
        float fullCharge = Convert.ToSingle(report.FullChargeCapacityInMilliwattHours);
        float currentCharge = Convert.ToSingle(report.RemainingCapacityInMilliwattHours);

        float val = (fullCharge > 0) ? (currentCharge / fullCharge) * 100.0f : 0.0f;

        Value = GattHelper.Converters.GattConvert.ToIBuffer((byte)Math.Round(val, 0));
    }
}
}

Клиент (Xamarin.Droid)

На моем клиенте я хотел бы знать, как получать уведомления при изменении уровня заряда батареи. Я знаю, что это связано с дескрипторами, но я не знаю, как это сделать

using Android.App;
using Android.Bluetooth;

namespace MyProject.Bluetooth
{
public class GattCallback : BluetoothGattCallback
{
    private readonly BluetoothDevice _device;
    private readonly BluetoothScanner _scanner;

    internal GattCallback(BluetoothDevice device, BluetoothScanner scanner)
    {
        _device = device;
        _scanner = scanner;

        _device.ConnectGatt(Application.Context, true, this);
    }

    public override void OnConnectionStateChange(BluetoothGatt gatt, GattStatus status, ProfileState newState)
    {
        base.OnConnectionStateChange(gatt, status, newState);
        //this.Log("OnConnectionStateChange: " + newState);

        switch (newState)
        {
            case ProfileState.Connected:
                gatt.DiscoverServices();
                break;
            case ProfileState.Disconnected:
                _scanner.Disconnect(this, gatt);
                break;
        }
    }

    public override void OnServicesDiscovered(BluetoothGatt gatt, GattStatus status)
    {
        base.OnServicesDiscovered(gatt, status);
        //this.Log("OnServicesDiscovered: " + status);

        if (status == GattStatus.Success)
            _scanner.ConnectionSuccess(this, gatt);
        else
            _scanner.ConnectionFailed(this);
    }

    public override void OnCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, GattStatus status)
    {
        base.OnCharacteristicRead(gatt, characteristic, status);

     
        _scanner.OnCharacteristicUpdated(new DroidBtCharacteristic(characteristic));
    }
}
}
...