1#ifndef BLUETOE_CHARACTERISTIC_VALUE_HPP
2#define BLUETOE_CHARACTERISTIC_VALUE_HPP
5#include <bluetoe/attribute.hpp>
6#include <bluetoe/codes.hpp>
7#include <bluetoe/meta_types.hpp>
16 struct characteristic_value_meta_type {};
18 struct characteristic_parameter_meta_type {};
20 struct characteristic_value_read_handler_meta_type {};
22 struct characteristic_value_write_handler_meta_type {};
24 struct characteristic_value_declaration_parameter {};
25 struct client_characteristic_configuration_parameter {};
26 struct characteristic_subscription_call_back_meta_type {};
49 using meta_type = details::valid_characteristic_option_meta_type;
71 using meta_type = details::valid_characteristic_option_meta_type;
92 details::client_characteristic_configuration_parameter,
93 details::characteristic_parameter_meta_type,
94 details::valid_characteristic_option_meta_type {};
113 details::client_characteristic_configuration_parameter,
114 details::characteristic_parameter_meta_type,
115 details::valid_characteristic_option_meta_type {};
129 template <
typename UUID,
typename Server >
130 static void on_subscription( std::uint16_t flags, Server& srv )
132 if ( flags & details::client_characteristic_configuration_notification_enabled )
137 details::characteristic_subscription_call_back_meta_type,
138 details::characteristic_parameter_meta_type,
139 details::valid_characteristic_option_meta_type {};
153 template <
typename UUID,
typename Server >
154 static void on_subscription( std::uint16_t flags, Server& srv )
156 if ( flags & details::client_characteristic_configuration_indication_enabled )
161 details::characteristic_subscription_call_back_meta_type,
162 details::characteristic_parameter_meta_type,
163 details::valid_characteristic_option_meta_type {};
168 struct default_on_characteristic_subscription {
169 template <
typename UUID,
typename Server >
170 static void on_subscription( std::uint16_t, Server& ) {}
173 details::characteristic_subscription_call_back_meta_type,
174 details::characteristic_parameter_meta_type,
175 details::valid_characteristic_option_meta_type {};
193 details::characteristic_parameter_meta_type,
194 details::valid_characteristic_option_meta_type {};
210 details::characteristic_parameter_meta_type,
211 details::valid_characteristic_option_meta_type {};
216 template <
bool RequiresEncryption >
217 struct encryption_requirements;
220 struct encryption_requirements< false > {
222 return attribute_access_result::success;
227 struct encryption_requirements< true > {
228 static attribute_access_result check(
const connection_security_attributes& attr )
230 if ( attr.is_encrypted )
231 return attribute_access_result::success;
233 return attr.pairing_status == device_pairing_status::no_key
234 ? attribute_access_result::insufficient_authentication
235 : attribute_access_result::insufficient_encryption;
242 template <
typename ... Options >
243 struct value_impl_base
245 static constexpr bool has_only_write_without_response = details::has_option< only_write_without_response, Options... >::value;
252 template <
typename T, T* Ptr >
260 template <
typename ... Options >
261 class value_impl :
public details::value_impl_base< Options... >
264 static constexpr bool has_read_access = !details::has_option<
no_read_access, Options... >::value;
265 static constexpr bool has_write_access = !std::is_const< T >::value && !details::has_option<
no_write_access, Options... >::value;
266 static constexpr bool has_write_without_response = details::has_option<
write_without_response, Options... >::value;
267 static constexpr bool has_notification = details::has_option<
notify, Options... >::value;
268 static constexpr bool has_indication = details::has_option<
indicate, Options... >::value;
270 template <
class Server, std::
size_t ClientCharacteristicIndex,
bool RequiresEncryption >
271 static details::attribute_access_result characteristic_value_access( details::attribute_access_arguments& args, std::size_t )
273 const auto security_result = details::encryption_requirements< RequiresEncryption >::check( args.connection_security );
275 if ( security_result != details::attribute_access_result::success )
276 return security_result;
278 if ( args.type == details::attribute_access_type::read )
280 return characteristic_value_read_access( args, std::integral_constant< bool, has_read_access >() );
282 else if ( args.type == details::attribute_access_type::write )
284 return characteristic_value_write_access( args, std::integral_constant< bool, has_write_access >() );
287 return details::attribute_access_result::write_not_permitted;
293 static constexpr bool is_this(
const void* value )
299 static constexpr details::attribute_access_result characteristic_value_read_access( details::attribute_access_arguments& args,
const std::true_type& )
301 return details::attribute_value_read_access( args,
static_cast< const std::uint8_t*
>(
static_cast< const void*
>( Ptr ) ),
sizeof( T ) );
304 static constexpr details::attribute_access_result characteristic_value_read_access( details::attribute_access_arguments&,
const std::false_type& )
306 return details::attribute_access_result::read_not_permitted;
309 static details::attribute_access_result characteristic_value_write_access( details::attribute_access_arguments& args,
const std::true_type& )
311 if ( args.buffer_offset >
sizeof( T ) )
312 return details::attribute_access_result::invalid_offset;
314 if ( args.buffer_size + args.buffer_offset >
sizeof( T ) )
315 return details::attribute_access_result::invalid_attribute_value_length;
317 args.buffer_size = std::min< std::size_t >( args.buffer_size,
sizeof( T ) - args.buffer_offset );
319 std::uint8_t*
const ptr =
static_cast< std::uint8_t*
>(
static_cast< void*
>( Ptr ) );
320 std::copy( args.buffer, args.buffer + args.buffer_size, ptr + args.buffer_offset );
322 return details::attribute_access_result::success;
325 static constexpr details::attribute_access_result characteristic_value_write_access( details::attribute_access_arguments&,
const std::false_type& )
327 return details::attribute_access_result::write_not_permitted;
333 details::characteristic_value_meta_type,
334 details::characteristic_value_declaration_parameter,
335 details::valid_characteristic_option_meta_type {};
344 template <
class T, T Value >
349 template <
typename ... Options >
350 class value_impl :
public details::value_impl_base< Options... >
353 static constexpr bool has_read_access = !details::has_option<
no_read_access, Options... >::value;
354 static constexpr bool has_write_access =
false;
355 static constexpr bool has_write_without_response =
false;
356 static constexpr bool has_notification = details::has_option<
notify, Options... >::value;
357 static constexpr bool has_indication = details::has_option<
indicate, Options... >::value;
359 template <
class Server, std::
size_t ClientCharacteristicIndex,
bool RequiresEncryption >
360 static details::attribute_access_result characteristic_value_access( details::attribute_access_arguments& args, std::size_t )
362 const auto security_result = details::encryption_requirements< RequiresEncryption >::check( args.connection_security );
364 if ( security_result != details::attribute_access_result::success )
365 return security_result;
367 if ( !has_read_access )
368 return details::attribute_access_result::read_not_permitted;
370 if ( args.type != details::attribute_access_type::read )
371 return details::attribute_access_result::write_not_permitted;
373 if ( args.buffer_offset >
sizeof( T ) )
374 return details::attribute_access_result::invalid_offset;
376 args.buffer_size = std::min< std::size_t >( args.buffer_size,
sizeof( T ) - args.buffer_offset );
379 std::uint8_t* output = args.buffer;
380 for (
auto i = args.buffer_offset; i != args.buffer_offset + args.buffer_size; ++i, ++output )
381 *output = ( Value >> ( 8 * i ) ) & 0xff;
383 return details::attribute_access_result::success;
386 static constexpr bool is_this(
const void* )
393 details::characteristic_value_meta_type,
394 details::characteristic_value_declaration_parameter,
395 details::valid_characteristic_option_meta_type {};
403 template < std::u
int8_t Value >
410 template < std::u
int16_t Value >
418 template < std::u
int32_t Value >
427 template <
class Text >
433 template <
typename ... Options >
434 class value_impl :
public details::value_impl_base< Options... >
437 static constexpr bool has_read_access =
true;
438 static constexpr bool has_write_access =
false;
439 static constexpr bool has_write_without_response =
false;
440 static constexpr bool has_notification =
false;
441 static constexpr bool has_indication =
false;
443 template <
class Server, std::
size_t ClientCharacteristicIndex,
bool RequiresEncryption >
444 static details::attribute_access_result characteristic_value_access( details::attribute_access_arguments& args, std::size_t )
446 const auto security_result = details::encryption_requirements< RequiresEncryption >::check( args.connection_security );
448 if ( security_result != details::attribute_access_result::success )
449 return security_result;
451 if ( args.type != details::attribute_access_type::read )
452 return details::attribute_access_result::write_not_permitted;
454 const char* value =
static_cast< const char*
>(
static_cast< const void*
>( Text::value() ) );
455 std::size_t length = Text::size();
457 if ( args.buffer_offset > length )
458 return details::attribute_access_result::invalid_offset;
460 args.buffer_size = std::min< std::size_t >( args.buffer_size, length - args.buffer_offset );
463 std::copy( value + args.buffer_offset, value + args.buffer_offset + args.buffer_size, args.buffer );
465 return details::attribute_access_result::success;
468 static constexpr bool is_this(
const void* )
476 details::characteristic_value_meta_type,
477 details::characteristic_value_declaration_parameter,
478 details::valid_characteristic_option_meta_type {};
485 template < const
char* const Name >
489 static constexpr char const * name = Name;
491 static constexpr char const * value()
496 static constexpr std::size_t size()
498 return std::strlen( name );
509 template < const std::u
int8_t* const Value, std::
size_t Size >
513 static constexpr std::uint8_t
const * value()
518 static constexpr std::size_t size()
527 struct invoke_read_handler {
528 template <
class Server >
529 static constexpr std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void*
server )
531 return T::template call_read_handler< Server >( offset, read_size, out_buffer, out_size,
server );
536 struct invoke_read_handler< no_such_type > {
537 template <
class Server >
538 static constexpr std::uint8_t call_read_handler( std::size_t, std::size_t, std::uint8_t*, std::size_t&,
void* )
545 struct invoke_write_handler {
546 template <
class Server, std::
size_t ClientCharacteristicIndex >
547 static constexpr std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& config,
void* server )
549 return T::template call_write_handler< Server, ClientCharacteristicIndex >( offset, write_size, value, config, server );
554 struct invoke_write_handler< no_such_type > {
555 template <
class Server, std::
size_t ClientCharacteristicIndex >
556 static constexpr std::uint8_t call_write_handler( std::size_t, std::size_t,
const std::uint8_t*,
const details::client_characteristic_configuration&,
void* )
562 struct value_handler_base {
564 template <
typename ... Options >
565 class value_impl :
public details::value_impl_base< Options... >
568 using read_handler_type =
typename find_by_meta_type< characteristic_value_read_handler_meta_type, Options... >::type;
569 using write_handler_type =
typename find_by_meta_type< characteristic_value_write_handler_meta_type, Options... >::type;
570 static constexpr bool no_read = has_option< no_read_access, Options... >::value;
571 static constexpr bool no_write = has_option< no_write_access, Options... >::value;
573 static constexpr bool has_read_handler = !std::is_same< read_handler_type, no_such_type >::value;
574 static constexpr bool has_read_access = has_read_handler && !no_read;
575 static constexpr bool has_write_access = !std::is_same< write_handler_type, no_such_type >::value;
576 static constexpr bool has_write_without_response = details::has_option< write_without_response, Options... >::value;
577 static constexpr bool has_notification = has_option< notify, Options... >::value;
578 static constexpr bool has_indication = has_option< indicate, Options... >::value;
580 static_assert( !( no_write && ( has_write_access || has_write_without_response ) ),
"There is no point in providing a write_handler and disabling write by using no_write_access" );
582 static_assert( !has_notification || ( has_notification && has_read_handler ),
"When enabling notification, the characteristic needs to have a read_handler" );
583 static_assert( !has_indication || ( has_indication && has_read_handler ),
"When enabling indications, the characteristic needs to have a read_handler" );
585 static_assert( has_read_access || has_write_access || has_notification || has_indication,
"Ups!");
587 template <
class Server, std::
size_t ClientCharacteristicIndex,
bool RequiresEncryption >
588 static attribute_access_result characteristic_value_access( attribute_access_arguments& args, std::size_t )
590 const auto security_result = details::encryption_requirements< RequiresEncryption >::check( args.connection_security );
592 if ( security_result != details::attribute_access_result::success )
593 return security_result;
595 if ( args.type == attribute_access_type::read )
597 return static_cast< attribute_access_result
>(
598 invoke_read_handler< read_handler_type >::template call_read_handler< Server >( args.buffer_offset, args.buffer_size, args.buffer, args.buffer_size, args.server ) );
600 else if ( args.type == attribute_access_type::write )
602 return static_cast< attribute_access_result
>(
603 invoke_write_handler< write_handler_type >::template call_write_handler< Server, ClientCharacteristicIndex >( args.buffer_offset, args.buffer_size, args.buffer, args.client_config, args.server ) );
607 return attribute_access_result::request_not_supported;
611 static constexpr bool is_this(
const void* )
618 characteristic_value_meta_type,
619 characteristic_value_declaration_parameter,
620 details::valid_characteristic_option_meta_type {};
623 template <
typename T >
624 inline std::pair< std::uint8_t, T > deserialize( std::size_t write_size,
const std::uint8_t* value )
626 static_assert( CHAR_BIT == 8,
"needs porting!" );
628 if ( write_size !=
sizeof( T ) )
633 for (
const std::uint8_t* v = value +
sizeof( T ); v != value; --v )
635 result = ( result << 8 ) | *( v - 1 );
642 inline std::pair< std::uint8_t, bool > deserialize( std::size_t write_size,
const std::uint8_t* value )
644 if ( write_size != 1 )
651 else if ( *value == 1 )
690 template < std::u
int8_t (*F)( std::
size_t offset, std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) >
694 template <
class Server >
695 static constexpr std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void* )
697 return F( offset, read_size, out_buffer, out_size );
700 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
733 template < std::u
int8_t (*F)( std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) >
737 template <
class Server >
738 static constexpr std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void* )
741 ? F( read_size, out_buffer, out_size )
745 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
776 template < std::u
int8_t (*F)( std::
size_t offset, std::
size_t write_size, const std::u
int8_t* value ) >
780 template <
class Server, std::
size_t ClientCharacteristicIndex >
781 static constexpr std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void* )
783 return F( offset, write_size, value );
786 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
813 template < std::u
int8_t (*F)( std::
size_t write_size, const std::u
int8_t* value ) >
817 template <
class Server, std::
size_t ClientCharacteristicIndex >
818 static constexpr std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void* )
821 ? F( write_size, value )
825 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
829 template <
class Obj, Obj& O, std::u
int8_t (Obj::*F)( std::
size_t offset, std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) >
833 template <
class Server >
834 static constexpr std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void* )
836 return (O.*F)( offset, read_size, out_buffer, out_size );
839 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
843 template <
class Obj, const Obj& O, std::u
int8_t (Obj::*F)( std::
size_t offset, std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) const >
847 template <
class Server >
848 static constexpr std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void* )
850 return (O.*F)( offset, read_size, out_buffer, out_size );
853 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
857 template <
class Obj, volatile Obj& O, std::u
int8_t (Obj::*F)( std::
size_t offset, std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) volatile >
861 template <
class Server >
862 static constexpr std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void* )
864 return (O.*F)( offset, read_size, out_buffer, out_size );
867 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
871 template <
class Obj, const volatile Obj& O, std::u
int8_t (Obj::*F)( std::
size_t offset, std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) const volatile >
875 template <
class Server >
876 static constexpr std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void* )
878 return (O.*F)( offset, read_size, out_buffer, out_size );
881 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
885 template <
class Obj, Obj& O, std::u
int8_t (Obj::*F)( std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) >
889 template <
class Server >
890 static constexpr std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void* )
893 ? (O.*F)( read_size, out_buffer, out_size )
897 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
901 template <
class Obj, const Obj& O, std::u
int8_t (Obj::*F)( std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) const >
905 template <
class Server >
906 static constexpr std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void* )
909 ? (O.*F)( read_size, out_buffer, out_size )
913 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
917 template <
class Obj, volatile Obj& O, std::u
int8_t (Obj::*F)( std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) volatile >
921 template <
class Server >
922 static constexpr std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void* )
925 ? (O.*F)( read_size, out_buffer, out_size )
929 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
933 template <
class Obj, const volatile Obj& O, std::u
int8_t (Obj::*F)( std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) const volatile >
937 template <
class Server >
938 static constexpr std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void* )
941 ? (O.*F)( read_size, out_buffer, out_size )
945 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
949 template <
class Obj, Obj& O, std::u
int8_t (Obj::*F)( std::
size_t offset, std::
size_t write_size, const std::u
int8_t* value ) >
953 template <
class Server, std::
size_t ClientCharacteristicIndex >
954 static constexpr std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void* )
956 return (O.*F)( offset, write_size, value );
959 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
963 template <
class Obj, const Obj& O, std::u
int8_t (Obj::*F)( std::
size_t offset, std::
size_t write_size, const std::u
int8_t* value ) const >
967 template <
class Server, std::
size_t ClientCharacteristicIndex >
968 static constexpr std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void* )
970 return (O.*F)( offset, write_size, value );
973 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
977 template <
class Obj, volatile Obj& O, std::u
int8_t (Obj::*F)( std::
size_t offset, std::
size_t write_size, const std::u
int8_t* value ) volatile >
981 template <
class Server, std::
size_t ClientCharacteristicIndex >
982 static constexpr std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void* )
984 return (O.*F)( offset, write_size, value );
987 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
991 template <
class Obj, const volatile Obj& O, std::u
int8_t (Obj::*F)( std::
size_t offset, std::
size_t write_size, const std::u
int8_t* value ) const volatile >
995 template <
class Server, std::
size_t ClientCharacteristicIndex >
996 static constexpr std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void* )
998 return (O.*F)( offset, write_size, value );
1001 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
1005 template <
class Obj, Obj& O, std::u
int8_t (Obj::*F)( std::
size_t write_size, const std::u
int8_t* value ) >
1009 template <
class Server, std::
size_t ClientCharacteristicIndex >
1010 static constexpr std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void* )
1013 ? (O.*F)( write_size, value )
1017 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
1021 template <
class Obj, const Obj& O, std::u
int8_t (Obj::*F)( std::
size_t write_size, const std::u
int8_t* value ) const >
1025 template <
class Server, std::
size_t ClientCharacteristicIndex >
1026 static constexpr std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void* )
1029 ? (O.*F)( write_size, value )
1033 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
1037 template <
class Obj, volatile Obj& O, std::u
int8_t (Obj::*F)( std::
size_t write_size, const std::u
int8_t* value ) volatile >
1041 template <
class Server, std::
size_t ClientCharacteristicIndex >
1042 static std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void* )
1045 ? (O.*F)( write_size, value )
1049 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
1053 template <
class Obj, const volatile Obj& O, std::u
int8_t (Obj::*F)( std::
size_t write_size, const std::u
int8_t* value ) const volatile >
1057 template <
class Server, std::
size_t ClientCharacteristicIndex >
1058 static constexpr std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void* )
1061 ? (O.*F)( write_size, value )
1065 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
1069 template <
class Mixin, std::u
int8_t (Mixin::*F)( std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) >
1073 template <
class Server >
1074 static std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void*
server )
1077 static_assert( std::is_convertible< Server*, Mixin* >::value,
"Use bluetoe::mixin<> to mixin an instance of the mixin_read_handler into the server." );
1079 Mixin&
mixin =
static_cast< Mixin&
>( *
static_cast< Server*
>(
server ) );
1082 ? (
mixin.*F)( read_size, out_buffer, out_size )
1087 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
1091 template <
class Mixin, std::u
int8_t (Mixin::*F)( std::
size_t write_size, const std::u
int8_t* value ) >
1095 template <
class Server, std::
size_t ClientCharacteristicIndex >
1096 static std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void*
server )
1099 static_assert( std::is_convertible< Server*, Mixin* >::value,
"Use bluetoe::mixin<> to mixin an instance of the mixin_write_handler into the server." );
1101 Mixin&
mixin =
static_cast< Mixin&
>( *
static_cast< Server*
>(
server ) );
1104 ? (
mixin.*F)( write_size, value )
1108 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
1112 template <
class Mixin, std::u
int8_t (Mixin::*F)( std::
size_t offset, std::
size_t read_size, std::u
int8_t* out_buffer, std::
size_t& out_size ) >
1116 template <
class Server >
1117 static std::uint8_t call_read_handler( std::size_t offset, std::size_t read_size, std::uint8_t* out_buffer, std::size_t& out_size,
void*
server )
1120 static_assert( std::is_convertible< Server*, Mixin* >::value,
"Use bluetoe::mixin<> to mixin an instance of the mixin_read_blob_handler into the server." );
1122 Mixin&
mixin =
static_cast< Mixin&
>( *
static_cast< Server*
>(
server ) );
1123 return (
mixin.*F)( offset, read_size, out_buffer, out_size );
1126 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_read_handler_meta_type {};
1130 template <
class Mixin, std::u
int8_t (Mixin::*F)( std::
size_t offset, std::
size_t write_size, const std::u
int8_t* value ) >
1134 template <
class Server, std::
size_t ClientCharacteristicIndex >
1135 static std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void*
server )
1138 static_assert( std::is_convertible< Server*, Mixin* >::value,
"Use bluetoe::mixin<> to mixin an instance of the mixin_write_blob_handler into the server." );
1140 Mixin&
mixin =
static_cast< Mixin&
>( *
static_cast< Server*
>(
server ) );
1141 return (
mixin.*F)( offset, write_size, value );
1144 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
1157 template < class Mixin, std::pair< std::uint8_t, bool > (Mixin::*F)( std::size_t write_size,
const std::uint8_t* value ),
typename IndicationUUID >
1161 template <
class Server, std::
size_t >
1162 static std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& config,
void* server_ptr )
1164 assert( server_ptr );
1165 static_assert( std::is_convertible< Server*, Mixin* >::value,
"Use bluetoe::mixin<> to mixin an instance of the mixin_write_handler into the server." );
1171 Server&
server = *
static_cast< Server*
>( server_ptr );
1175 if ( !
server.template configured_for_indications< IndicationUUID >( config ) )
1178 const std::pair< std::uint8_t, bool > result = (
mixin.*F)( write_size, value );
1180 if ( result.second )
1183 return static_cast< std::uint8_t
>( result.first );
1186 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
1196 template < class Mixin, std::pair< std::uint8_t, bool > (Mixin::*F)( std::size_t write_size,
const std::uint8_t* value ),
typename NotificationUUID >
1200 template <
class Server, std::
size_t >
1201 static std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& config,
void* server_ptr )
1203 assert( server_ptr );
1204 static_assert( std::is_convertible< Server*, Mixin* >::value,
"Use bluetoe::mixin<> to mixin an instance of the mixin_write_handler into the server." );
1210 Server&
server = *
static_cast< Server*
>( server_ptr );
1214 if ( !
server.template configured_for_notifications< NotificationUUID >( config ) )
1217 const std::pair< std::uint8_t, bool > result = (
mixin.*F)( write_size, value );
1219 if ( result.second )
1222 return static_cast< std::uint8_t
>( result.first );
1225 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
1251 template <
typename T, std::u
int8_t (*F)( T ) >
1255 template <
class Server, std::
size_t ClientCharacteristicIndex >
1256 static std::uint8_t call_write_handler( std::size_t offset, std::size_t write_size,
const std::uint8_t* value,
const details::client_characteristic_configuration& ,
void* )
1261 const std::pair< std::uint8_t, T > deserialized_value = details::deserialize< T >( write_size, value );
1264 return deserialized_value.first;
1266 return (*F)( deserialized_value.second );
1269 struct meta_type : details::value_handler_base::meta_type, details::characteristic_value_write_handler_meta_type {};
a very simple device to bind a characteristic to a global variable to provide access to the character...
Definition: characteristic_value.hpp:254
Root of the declaration of a GATT server.
Definition: server.hpp:85
@ out_of_range
Definition: codes.hpp:256
@ success
Definition: codes.hpp:154
@ write_not_permitted
Definition: codes.hpp:169
@ attribute_not_long
Definition: codes.hpp:209
@ invalid_attribute_value_length
Definition: codes.hpp:219
@ cccd_improperly_configured
Definition: codes.hpp:269
@ read_not_permitted
Definition: codes.hpp:164
the basic security attributes of a connection
Definition: pairing_status.hpp:24
a constant string characteristic with the value Name
Definition: characteristic_value.hpp:487
a constant string characteristic value
Definition: characteristic_value.hpp:429
A fixed length and fixed value, read-only characteristic value.
Definition: characteristic_value.hpp:511
provides a characteristic with a fixed, read-only value
Definition: characteristic_value.hpp:345
binds a free function as a write handler for the given characteristic
Definition: characteristic_value.hpp:815
binds a free function as a read handler for the given characteristic
Definition: characteristic_value.hpp:692
binds a free function as a read handler for the given characteristic
Definition: characteristic_value.hpp:735
binds a free function as a write handler for the given characteristic
Definition: characteristic_value.hpp:778
binds a free function as a write handler for the given characteristic
Definition: characteristic_value.hpp:1253
queues a indication of a characteristic as soon, as it was configured for indication.
Definition: characteristic_value.hpp:151
adds the ability to indicate this characteristic.
Definition: characteristic_value.hpp:110
Definition: characteristic_value.hpp:1114
Definition: characteristic_value.hpp:1071
Definition: characteristic_value.hpp:1132
Definition: characteristic_value.hpp:1093
characteristic value binding for a control point
Definition: characteristic_value.hpp:1159
characteristic value binding for a control point
Definition: characteristic_value.hpp:1198
class to be mixed into the server instance
Definition: mixin.hpp:78
if added as option to a characteristic, read access is removed from the characteristic
Definition: characteristic_value.hpp:47
if added as option to a characteristic, write access is removed from the characteristic
Definition: characteristic_value.hpp:69
queues a notification of a characteristic as soon, as it was configured for notification.
Definition: characteristic_value.hpp:127
adds the ability to notify this characteristic.
Definition: characteristic_value.hpp:89
set only the Write Without Response Characteristic Property bit.
Definition: characteristic_value.hpp:207
Definition: characteristic_value.hpp:845
Definition: characteristic_value.hpp:873
Definition: characteristic_value.hpp:859
Definition: characteristic_value.hpp:831
Definition: characteristic_value.hpp:903
Definition: characteristic_value.hpp:935
Definition: characteristic_value.hpp:919
Definition: characteristic_value.hpp:887
Definition: characteristic_value.hpp:965
Definition: characteristic_value.hpp:993
Definition: characteristic_value.hpp:979
Definition: characteristic_value.hpp:951
Definition: characteristic_value.hpp:1023
Definition: characteristic_value.hpp:1055
Definition: characteristic_value.hpp:1039
Definition: characteristic_value.hpp:1007
sets the Write Without Response Characteristic Property bit.
Definition: characteristic_value.hpp:190