1#ifndef BLUETOE_SERVICE_HPP 
    2#define BLUETOE_SERVICE_HPP 
    4#include <bluetoe/service_uuid.hpp> 
    5#include <bluetoe/attribute.hpp> 
    6#include <bluetoe/codes.hpp> 
    8#include <bluetoe/meta_types.hpp> 
    9#include <bluetoe/uuid.hpp> 
   10#include <bluetoe/characteristic.hpp> 
   11#include <bluetoe/bits.hpp> 
   12#include <bluetoe/find_notification_data.hpp> 
   13#include <bluetoe/outgoing_priority.hpp> 
   21    template < const 
char* const >
 
   24        using meta_type = details::valid_service_option_meta_type;
 
   29        struct is_secondary_service_meta_type {};
 
   30        struct include_service_meta_type {};
 
   31        struct service_defintion_tag {};
 
   33        template < 
typename ... Options >
 
   34        struct count_service_attributes;
 
   55            : 
public details::uuid< A, B, C, D, E >
 
   61            details::service_uuid_128_meta_type,
 
   62            details::valid_service_option_meta_type {};
 
   75    template < std::u
int64_t UUID >
 
   78            : 
public details::uuid16< UUID >
 
   84            details::service_uuid_16_meta_type,
 
   85            details::valid_service_option_meta_type {};
 
   94    template < std::u
int16_t Handle >
 
  100            details::valid_service_option_meta_type {};
 
  148    template < 
typename ... Options >
 
  153        typedef typename details::find_all_by_meta_type< details::characteristic_meta_type, Options... >::type  characteristics;
 
  155        typedef typename details::find_by_meta_type< details::service_uuid_meta_type, Options... >::type        uuid;
 
  157        static_assert( !std::is_same< uuid, details::no_such_type >::value, 
"Please provide a UUID to the service (service_uuid or service_uuid16 for example)." );
 
  159        static constexpr std::size_t number_of_service_attributes        = details::count_service_attributes< Options... >::number_of_attributes;
 
  160        static constexpr std::size_t number_of_characteristic_attributes = details::sum_by< characteristics, details::sum_by_attributes >::value;
 
  161        static constexpr std::size_t number_of_client_configs            = details::sum_by< characteristics, details::sum_by_client_configs >::value;
 
  163        using notification_priority = 
typename details::find_by_meta_type< details::outgoing_priority_meta_type, Options..., 
higher_outgoing_priority<> >::type;
 
  165        static_assert( std::tuple_size< 
typename details::find_all_by_meta_type< details::outgoing_priority_meta_type, Options... >::type >::value <= 1,
 
  166            "Only one of bluetoe::higher_outgoing_priority<> or bluetoe::lower_outgoing_priority<> per service allowed!" );
 
  171        static constexpr std::size_t number_of_attributes =
 
  172              number_of_service_attributes
 
  173            + number_of_characteristic_attributes;
 
  176            details::service_meta_type,
 
  177            details::valid_server_option_meta_type {};
 
  182        template < 
typename CCCDIndices, std::
size_t ClientCharacteristicIndex, 
typename ServiceList, 
typename Server >
 
  183        static details::attribute attribute_at( std::size_t index );
 
  188        template < 
typename CCCDIndices, std::
size_t ClientCharacteristicIndex, 
typename ServiceList, 
typename Server = 
void >
 
  189        static std::uint8_t* read_primary_service_response( std::uint8_t* output, std::uint8_t* end, std::size_t starting_index, 
bool is_128bit_filter, Server& 
server );
 
  191        static_assert( std::is_same<
 
  192                typename details::find_by_not_meta_type<
 
  193                    details::valid_service_option_meta_type,
 
  195                >::type, details::no_such_type
 
  196            >::value, 
"Parameter passed to a service that is not a valid service option!" );
 
  210            details::is_secondary_service_meta_type,
 
  211            details::valid_service_option_meta_type {};
 
  226    template < 
typename ... Options >
 
  240    template < 
typename UUID >
 
  253            details::include_service_meta_type,
 
  254            details::valid_service_option_meta_type {};
 
  258    template < std::u
int64_t UUID >
 
  263            details::include_service_meta_type,
 
  264            details::valid_service_option_meta_type {};
 
  277        template < 
typename ... Options >
 
  278        using attribute_generation_parameters = 
typename 
  280                    service_defintion_tag, 
 
  281                    typename find_all_by_meta_type<
 
  282                        include_service_meta_type,
 
  288    template < 
typename ... Options >
 
  289    template < 
typename CCCDIndices, std::
size_t ClientCharacteristicIndex, 
typename ServiceList, 
typename Server >
 
  290    details::attribute service< Options... >::attribute_at( std::size_t index )
 
  292        assert( index < number_of_attributes );
 
  294        using attribute_generator = details::generate_attribute_list< details::attribute_generation_parameters< Options... >, CCCDIndices, ClientCharacteristicIndex, service< Options... >, Server, std::tuple< Options..., ServiceList > >;
 
  296        if ( index < number_of_service_attributes )
 
  297            return attribute_generator::attribute_at( index );
 
  299        return details::attribute_at_list< characteristics, CCCDIndices, ClientCharacteristicIndex, service< Options... >, Server >::attribute_at( index - number_of_service_attributes );
 
  302    template < 
typename ... Options >
 
  303    template < 
typename CCCDIndices, std::
size_t ClientCharacteristicIndex, 
typename ServiceList, 
typename Server >
 
  304    std::uint8_t* service< Options... >::read_primary_service_response( std::uint8_t* output, std::uint8_t* end, std::size_t starting_index, 
bool is_128bit_filter, Server& server )
 
  306        const std::size_t attribute_data_size = is_128bit_filter ? 16 + 4 : 2 + 4;
 
  307        using mapping = 
typename Server::handle_mapping;
 
  309        if ( is_128bit_filter == uuid::is_128bit && 
static_cast< std::size_t 
>( end - output ) >= attribute_data_size )
 
  311            std::uint8_t* 
const old_output = output;
 
  313            output = details::write_handle( output, mapping::handle_by_index( starting_index ) );
 
  314            output = details::write_handle( output, mapping::handle_by_index( starting_index + number_of_attributes -1 ) );
 
  316            const details::attribute primary_service = attribute_at< CCCDIndices, ClientCharacteristicIndex, ServiceList, Server >( 0 );
 
  318            auto read = details::attribute_access_arguments::read( output, end, 0,
 
  319                            details::client_characteristic_configuration(),
 
  320                            connection_security_attributes(),
 
  323            if ( primary_service.access( read, 1 ) == details::attribute_access_result::success )
 
  325                output += read.buffer_size;
 
  338        template < 
typename ServiceList, 
typename UUID >
 
  339        struct find_service_by_uuid
 
  342            struct equal_uuid : std::is_same< typename T::uuid, UUID > {};
 
  344            typedef typename find_if< ServiceList, equal_uuid >::type type;
 
  347        template < 
typename ServiceList, 
typename Service, std::u
int16_t Handle = 1 >
 
  348        struct service_handles;
 
  350        template < 
typename Service, 
typename ... Ss, std::uint16_t Handle >
 
  351        struct service_handles< std::tuple< Service, Ss... >, Service, Handle >
 
  353            static constexpr std::uint16_t service_attribute_handle = Handle;
 
  354            static constexpr std::uint16_t end_service_handle       = Handle + Service::number_of_attributes - 1;
 
  357        template < 
typename Service, 
typename S, 
typename ... Ss, std::uint16_t Handle >
 
  358        struct service_handles< std::tuple< S, Ss... >, Service, Handle >
 
  360            typedef service_handles< std::tuple< Ss... >, Service, Handle + S::number_of_attributes > next;
 
  362            static constexpr std::uint16_t service_attribute_handle = next::service_attribute_handle;
 
  363            static constexpr std::uint16_t end_service_handle       = next::end_service_handle;
 
  369        template < 
typename CCCDIndices, std::size_t ClientCharacteristicIndex, 
typename ServiceUUID, 
typename Server, 
typename ... Options >
 
  370        struct generate_attribute< service_defintion_tag, CCCDIndices, ClientCharacteristicIndex, ServiceUUID, Server, Options... >
 
  372            static attribute_access_result access( attribute_access_arguments& args, std::size_t )
 
  374                typedef typename find_by_meta_type< service_uuid_meta_type, Options... >::type uuid;
 
  376                if ( args.type == attribute_access_type::read )
 
  378                    if ( args.buffer_offset > 
sizeof( uuid::bytes ) )
 
  379                        return attribute_access_result::invalid_offset;
 
  381                    args.buffer_size = std::min< std::size_t >( 
sizeof( uuid::bytes ) - args.buffer_offset, args.buffer_size );
 
  383                    std::copy( std::begin( uuid::bytes ) + args.buffer_offset , std::begin( uuid::bytes ) + args.buffer_offset + args.buffer_size, args.buffer );
 
  385                    return attribute_access_result::success;
 
  387                else if ( args.type == attribute_access_type::compare_value )
 
  389                    if ( 
sizeof( uuid::bytes ) == args.buffer_size
 
  390                      && std::equal( std::begin( uuid::bytes ), std::end( uuid::bytes ), &args.buffer[ 0 ] ) )
 
  392                        return attribute_access_result::value_equal;
 
  396                return attribute_access_result::write_not_permitted;
 
  399            static const attribute attr;
 
  402        template < 
typename CCCDIndices, std::size_t ClientCharacteristicIndex, 
typename ServiceUUID, 
typename Server, 
typename ... Options >
 
  403        constexpr attribute generate_attribute< service_defintion_tag, CCCDIndices, ClientCharacteristicIndex, ServiceUUID, Server, Options... >::attr {
 
  404            bits( has_option< is_secondary_service, Options... >::value
 
  405                ? gatt_uuids::secondary_service
 
  406                : gatt_uuids::primary_service ),
 
  407            &generate_attribute< service_defintion_tag, CCCDIndices, ClientCharacteristicIndex, ServiceUUID, Server, Options... >::access
 
  415            typename CCCDIndices,
 
  416            std::size_t ClientCharacteristicIndex,
 
  417            typename ServiceUUID,
 
  419            typename ... Options >
 
  420        struct generate_attribute< include_service< service_uuid16< UUID > >, CCCDIndices, ClientCharacteristicIndex, ServiceUUID, Server, Options... >
 
  422            typedef typename last_from_pack< Options... >::type service_list;
 
  423            typedef typename find_service_by_uuid< service_list, service_uuid16< UUID > >::type included_service;
 
  425            static_assert( !std::is_same< included_service, no_such_type >::value, 
"The included service is was not found by UUID, please add the referenced service." );
 
  427            typedef service_handles< service_list, included_service > handles;
 
  429            static details::attribute_access_result access( attribute_access_arguments& args, std::size_t )
 
  431                static constexpr std::uint8_t value[] = {
 
  432                    handles::service_attribute_handle & 0xff,
 
  433                    handles::service_attribute_handle >> 8,
 
  434                    handles::end_service_handle & 0xff,
 
  435                    handles::end_service_handle >> 8,
 
  440                return attribute_value_read_only_access( args, &value[ 0 ], 
sizeof( value ) );
 
  443            static const attribute attr;
 
  448            typename CCCDIndices,
 
  449            std::size_t ClientCharacteristicIndex,
 
  450            typename ServiceUUID,
 
  452            typename ... Options >
 
  453        constexpr attribute generate_attribute< include_service< service_uuid16< UUID > >, CCCDIndices, ClientCharacteristicIndex, ServiceUUID, Server, Options... >::attr =
 
  455            bits( details::gatt_uuids::include ),
 
  456            &generate_attribute< include_service< service_uuid16< UUID > >, CCCDIndices, ClientCharacteristicIndex, Options... >::access
 
  468            typename CCCDIndices,
 
  469            std::size_t ClientCharacteristicIndex,
 
  470            typename ServiceUUID,
 
  472            typename ... Options >
 
  473        struct generate_attribute< include_service< service_uuid< A, B, C, D, E > >, CCCDIndices, ClientCharacteristicIndex, ServiceUUID, Server, Options... >
 
  475            typedef typename last_from_pack< Options... >::type service_list;
 
  476            typedef typename find_service_by_uuid< service_list, service_uuid< A, B, C, D, E > >::type included_service;
 
  478            static_assert( !std::is_same< included_service, no_such_type >::value, 
"The included service is was not found by UUID, please add the references service." );
 
  480            typedef service_handles< service_list, included_service > handles;
 
  482            static details::attribute_access_result access( attribute_access_arguments& args, std::size_t )
 
  484                static constexpr std::uint8_t value[] = {
 
  485                    handles::service_attribute_handle & 0xff,
 
  486                    handles::service_attribute_handle >> 8,
 
  487                    handles::end_service_handle & 0xff,
 
  488                    handles::end_service_handle >> 8,
 
  491                return attribute_value_read_only_access( args, &value[ 0 ], 
sizeof( value ) );
 
  494            static const attribute attr;
 
  503            typename CCCDIndices,
 
  504            std::size_t ClientCharacteristicIndex,
 
  505            typename ServiceUUID,
 
  507            typename ... Options >
 
  508        constexpr attribute generate_attribute< include_service< service_uuid< A, B, C, D, E > >, CCCDIndices, ClientCharacteristicIndex, ServiceUUID, Server, Options... >::attr {
 
  509            bits( details::gatt_uuids::include ),
 
  510            &generate_attribute< include_service< service_uuid< A, B, C, D, E > >, CCCDIndices, ClientCharacteristicIndex, ServiceUUID, Server, Options... >::access
 
  513        template < 
typename ... Options >
 
  514        struct count_service_attributes{
 
  516                number_of_attributes = std::tuple_size< attribute_generation_parameters< Options... > >::value
 
Root of the declaration of a GATT server.
Definition: server.hpp:85
 
a 16-Bit UUID used to identify a service
Definition: service.hpp:80
 
a 128-Bit UUID used to identify a service.
Definition: service.hpp:57
 
a service with zero or more characteristics
Definition: service.hpp:150
 
value of the first attribute handle used in a service or characteristic
Definition: service.hpp:96
 
Defines priorities of notified or indicated characteristics.
Definition: outgoing_priority.hpp:160
 
includes an other service into the defined service
Definition: service.hpp:241
 
modifier that defines a service to be a secondary service.
Definition: service.hpp:207
 
definition of a secondary service
Definition: service.hpp:227
 
Definition: service.hpp:22