simplersble 1.1.1-dev29

The all-in-one Bluetooth library that makes it easy to add wireless connectivity to your projects.
Documentation
#pragma once

#include <atomic>
#include <functional>
#include <memory>
#include <mutex>
#include <set>

#include <kvn_safe_callback.hpp>

#include "../common/LocalCharacteristicBase.h"
#include "winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h"
#include "winrt/Windows.Foundation.Collections.h"

namespace SimpleBLE::Local {

class CharacteristicWindows : public CharacteristicBase, public std::enable_shared_from_this<CharacteristicWindows> {
  public:
    using GattSession = winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattSession;
    using SessionObserver = std::function<void(const GattSession&)>;

    CharacteristicWindows(BluetoothUUID uuid, std::set<CharacteristicCapability> capabilities);
    ~CharacteristicWindows() override;

    void create_native(const winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattLocalService& service,
                       SessionObserver session_observer, std::shared_ptr<std::atomic_bool> active);
    void destroy_native() noexcept;

    BluetoothUUID uuid() override;
    std::set<CharacteristicCapability> capabilities() override;

    ByteArray value() override;
    void set_value(ByteArray value) override;

    void set_callback_on_read(std::function<ByteArray()> on_read) override;
    void set_callback_on_write(std::function<void(ByteArray value)> on_write) override;

    void set_callback_on_subscribed(std::function<void()> on_subscribed) override;
    void set_callback_on_unsubscribed(std::function<void()> on_unsubscribed) override;

  private:
    using GattLocalCharacteristic =
        winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattLocalCharacteristic;
    using GattReadRequestedEventArgs =
        winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattReadRequestedEventArgs;
    using GattWriteRequestedEventArgs =
        winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattWriteRequestedEventArgs;

    struct NativeState {
        GattLocalCharacteristic characteristic{nullptr};
        SessionObserver session_observer;
        std::shared_ptr<std::atomic_bool> active;
        std::atomic_bool subscribed{false};
        winrt::event_token read_requested_token{};
        winrt::event_token write_requested_token{};
        winrt::event_token subscribed_clients_changed_token{};

        bool is_active() const { return active && active->load(); }
    };

    BluetoothUUID _uuid;
    std::set<CharacteristicCapability> _capabilities;

    ByteArray _value;
    std::mutex _value_mutex;
    std::shared_ptr<NativeState> _native;
    std::mutex _native_mutex;

    kvn::safe_callback<ByteArray()> _callback_on_read;
    kvn::safe_callback<void(ByteArray)> _callback_on_write;
    kvn::safe_callback<void()> _callback_on_subscribed;
    kvn::safe_callback<void()> _callback_on_unsubscribed;

    std::shared_ptr<NativeState> _native_state();
    static void _revoke_handlers(const std::shared_ptr<NativeState>& native) noexcept;
    void _on_read_requested(const std::shared_ptr<NativeState>& native, const GattReadRequestedEventArgs& args);
    void _on_write_requested(const std::shared_ptr<NativeState>& native, const GattWriteRequestedEventArgs& args);
    void _on_subscribed_clients_changed(const std::shared_ptr<NativeState>& native);
};

}  // namespace SimpleBLE::Local