1#ifndef BLUETOE_ATTRIBUTE_HANDLE_HPP
2#define BLUETOE_ATTRIBUTE_HANDLE_HPP
4#include <bluetoe/meta_types.hpp>
15 struct attribute_handle_meta_type {};
16 struct attribute_handles_meta_type {};
32 template < std::u
int16_t AttributeHandleValue >
36 static constexpr std::uint16_t attribute_handle_value = AttributeHandleValue;
39 details::attribute_handle_meta_type,
40 details::valid_service_option_meta_type,
41 details::valid_characteristic_option_meta_type {};
56 template < std::u
int16_t Declaration, std::u
int16_t Value, std::u
int16_t CCCD = 0x0000 >
60 static constexpr std::uint16_t declaration_handle = Declaration;
61 static constexpr std::uint16_t value_handle = Value;
62 static constexpr std::uint16_t cccd_handle = CCCD;
64 static_assert( value_handle > declaration_handle,
"value handle has to be larger than declaration handle" );
65 static_assert( cccd_handle > declaration_handle || cccd_handle == 0,
"CCCD handle has to be larger than declaration handle" );
66 static_assert( cccd_handle > value_handle || cccd_handle == 0,
"CCCD handle has to be larger than value handle" );
69 details::attribute_handles_meta_type,
70 details::valid_characteristic_option_meta_type {};
74 template <
typename ... Options >
77 template <
typename ... Options >
80 template <
typename ... Options >
85 static constexpr std::uint16_t invalid_attribute_handle = 0;
86 static constexpr std::size_t invalid_attribute_index = ~0;
91 template < std::u
int16_t Default,
class,
class >
92 struct select_attribute_handles
94 static constexpr std::uint16_t declaration_handle = Default;
95 static constexpr std::uint16_t value_handle = Default + 1;
96 static constexpr std::uint16_t cccd_handle = Default + 2;
99 template < std::u
int16_t Default, std::u
int16_t AttributeHandleValue,
typename T >
100 struct select_attribute_handles< Default, attribute_handle< AttributeHandleValue >, T >
102 static constexpr std::uint16_t declaration_handle = AttributeHandleValue;
103 static constexpr std::uint16_t value_handle = AttributeHandleValue + 1;
104 static constexpr std::uint16_t cccd_handle = AttributeHandleValue + 2;
107 template < std::u
int16_t Default,
typename T, std::u
int16_t Declaration, std::u
int16_t Value, std::u
int16_t CCCD >
108 struct select_attribute_handles< Default, T, attribute_handles< Declaration, Value, CCCD > >
110 static constexpr std::uint16_t declaration_handle = Declaration;
111 static constexpr std::uint16_t value_handle = Value;
112 static constexpr std::uint16_t cccd_handle = CCCD == 0 ? Value + 1 : CCCD;
115 template < std::u
int16_t Default, std::u
int16_t AttributeHandleValue, std::u
int16_t Declaration, std::u
int16_t Value, std::u
int16_t CCCD >
116 struct select_attribute_handles< Default, attribute_handle< AttributeHandleValue >, attribute_handles< Declaration, Value, CCCD > >
118 static_assert( Declaration == Value,
"either attribute_handle<> or attribute_handles<> can be used as characteristic<> option, not both." );
121 template < std::uint16_t StartHandle, std::uint16_t StartIndex,
typename ... Options >
122 struct characteristic_index_mapping
126 using attribute_handles_t = select_attribute_handles< StartHandle,
127 typename find_by_meta_type< attribute_handle_meta_type, Options... >::type,
128 typename find_by_meta_type< attribute_handles_meta_type, Options... >::type
131 static_assert( attribute_handles_t::declaration_handle >= StartHandle,
"attribute_handle<> can only be used to create increasing attribute handles." );
133 static constexpr std::uint16_t end_handle = characteristic_t::number_of_attributes == 2
134 ? attribute_handles_t::value_handle + 1
135 : attribute_handles_t::cccd_handle + ( characteristic_t::number_of_attributes - 2 );
136 static constexpr std::uint16_t end_index = StartIndex + characteristic_t::number_of_attributes;
138 static constexpr std::size_t declaration_position = 0;
139 static constexpr std::size_t value_position = 1;
140 static constexpr std::size_t cccd_position = 2;
142 static std::uint16_t characteristic_attribute_handle_by_index( std::size_t index )
144 const std::size_t relative_index = index - StartIndex;
146 assert( relative_index < characteristic_t::number_of_attributes );
148 switch ( relative_index )
150 case declaration_position:
151 return attribute_handles_t::declaration_handle;
155 return attribute_handles_t::value_handle;
159 return attribute_handles_t::cccd_handle;
163 return relative_index - cccd_position + attribute_handles_t::cccd_handle;
166 static std::size_t characteristic_attribute_index_by_handle( std::uint16_t handle )
168 if ( handle <= attribute_handles_t::declaration_handle )
169 return StartIndex + declaration_position;
171 if ( handle <= attribute_handles_t::value_handle )
172 return StartIndex + value_position;
174 if ( handle <= attribute_handles_t::cccd_handle )
175 return StartIndex + cccd_position;
177 return StartIndex + cccd_position + handle - attribute_handles_t::cccd_handle;
181 template < std::u
int16_t StartHandle, std::u
int16_t StartIndex,
typename CharacteristicList >
182 struct interate_characteristic_index_mappings;
184 template < std::u
int16_t StartHandle, std::u
int16_t StartIndex >
185 struct interate_characteristic_index_mappings< StartHandle, StartIndex, std::tuple<> >
187 static std::uint16_t attribute_handle_by_index( std::size_t )
189 return invalid_attribute_handle;
192 static std::size_t attribute_index_by_handle( std::uint16_t )
194 return invalid_attribute_index;
197 static constexpr std::uint16_t last_characteristic_end_handle = StartHandle;
200 template < std::uint16_t StartHandle, std::uint16_t StartIndex,
typename Characteristics,
typename ... Options >
201 using next_characteristic_mapping = interate_characteristic_index_mappings<
202 characteristic_index_mapping< StartHandle, StartIndex, Options... >::end_handle,
203 characteristic_index_mapping< StartHandle, StartIndex, Options... >::end_index,
207 template < std::uint16_t StartHandle, std::uint16_t StartIndex,
typename ...Options,
typename ... Chars >
208 struct interate_characteristic_index_mappings< StartHandle, StartIndex, std::tuple< ::bluetoe::characteristic< Options... >, Chars... > >
209 : characteristic_index_mapping< StartHandle, StartIndex, Options... >
210 , next_characteristic_mapping< StartHandle, StartIndex, std::tuple< Chars... >, Options... >
212 static constexpr std::uint16_t last_characteristic_end_handle =
213 next_characteristic_mapping< StartHandle, StartIndex, std::tuple< Chars... >, Options... >::last_characteristic_end_handle;
215 using next = characteristic_index_mapping< StartHandle, StartIndex, Options... >;
217 static std::uint16_t attribute_handle_by_index( std::size_t index )
219 if ( index < next::end_index )
220 return next::characteristic_attribute_handle_by_index( index );
222 return next_characteristic_mapping< StartHandle, StartIndex, std::tuple< Chars... >, Options... >::attribute_handle_by_index( index );
225 static std::size_t attribute_index_by_handle( std::uint16_t handle )
227 if ( handle < next::end_handle )
228 return next::characteristic_attribute_index_by_handle( handle );
230 return next_characteristic_mapping< StartHandle, StartIndex, std::tuple< Chars... >, Options... >::attribute_index_by_handle( handle );
234 template < std::uint16_t StartHandle, std::uint16_t StartIndex,
typename ... Options >
235 struct service_start_handle
237 using start_handle_t =
typename find_by_meta_type< attribute_handle_meta_type, Options..., attribute_handle< StartHandle > >::type;
239 static constexpr std::uint16_t value = start_handle_t::attribute_handle_value;
242 template < std::uint16_t StartHandle, std::uint16_t StartIndex,
typename ... Options >
243 using next_char_mapping = interate_characteristic_index_mappings<
244 service_start_handle< StartHandle, StartIndex, Options... >::value + 1, StartIndex + 1,
245 typename find_all_by_meta_type< characteristic_meta_type, Options... >::type >;
250 template < std::uint16_t StartHandle, std::uint16_t StartIndex,
typename ... Options >
251 struct service_index_mapping
252 : next_char_mapping< StartHandle, StartIndex, Options... >
256 static constexpr std::uint16_t service_handle = service_start_handle< StartHandle, StartIndex, Options... >::value;
258 static_assert( service_handle >= StartHandle,
"attribute_handle<> can only be used to create increasing attribute handles." );
260 static constexpr std::uint16_t end_handle = next_char_mapping< StartHandle, StartIndex, Options... >::last_characteristic_end_handle;
261 static constexpr std::uint16_t end_index = StartIndex + service_t::number_of_attributes;
263 static std::uint16_t characteristic_handle_by_index( std::size_t index )
265 if ( index == StartIndex )
266 return service_handle;
268 return next_char_mapping< StartHandle, StartIndex, Options... >::attribute_handle_by_index( index );
271 static std::size_t characteristic_first_index_by_handle( std::uint16_t handle )
273 if ( handle <= service_handle )
276 return next_char_mapping< StartHandle, StartIndex, Options... >::attribute_index_by_handle( handle );
283 template < std::u
int16_t StartHandle, std::u
int16_t StartIndex,
typename OptionTuple >
284 struct interate_service_index_mappings;
286 template < std::u
int16_t StartHandle, std::u
int16_t StartIndex >
287 struct interate_service_index_mappings< StartHandle, StartIndex, std::tuple<> >
289 static std::uint16_t service_handle_by_index( std::size_t )
291 return invalid_attribute_handle;
294 static std::size_t service_first_index_by_handle( std::uint16_t )
296 return invalid_attribute_index;
300 template < std::uint16_t StartHandle, std::uint16_t StartIndex,
typename Services,
typename ... Options >
301 using next_service_mapping = interate_service_index_mappings<
302 service_index_mapping< StartHandle, StartIndex, Options... >::end_handle,
303 service_index_mapping< StartHandle, StartIndex, Options... >::end_index,
307 template < std::uint16_t StartHandle, std::uint16_t StartIndex,
typename ... Options,
typename ... Services >
308 struct interate_service_index_mappings< StartHandle, StartIndex, std::tuple< ::bluetoe::service< Options... >, Services... > >
309 : service_index_mapping< StartHandle, StartIndex, Options... >
310 , next_service_mapping< StartHandle, StartIndex, std::tuple< Services... >, Options... >
312 static std::uint16_t service_handle_by_index( std::size_t index )
314 if ( index < service_index_mapping< StartHandle, StartIndex, Options... >::end_index )
315 return service_index_mapping< StartHandle, StartIndex, Options... >::characteristic_handle_by_index( index );
317 return next_service_mapping< StartHandle, StartIndex, std::tuple< Services... >, Options... >::service_handle_by_index( index );
320 static std::size_t service_first_index_by_handle( std::uint16_t handle )
322 if ( handle < service_index_mapping< StartHandle, StartIndex, Options... >::end_handle )
323 return service_index_mapping< StartHandle, StartIndex, Options... >::characteristic_first_index_by_handle( handle );
325 return next_service_mapping< StartHandle, StartIndex, std::tuple< Services... >, Options... >::service_first_index_by_handle( handle );
336 template <
typename Server >
337 struct handle_index_mapping;
339 template <
typename ... Options >
341 :
private interate_service_index_mappings< 1u, 0u, typename ::bluetoe::server< Options... >::services >
343 static constexpr std::size_t invalid_attribute_index = ::bluetoe::details::invalid_attribute_index;
344 static constexpr std::uint16_t invalid_attribute_handle = ::bluetoe::details::invalid_attribute_handle;
346 using iterator = interate_service_index_mappings< 1u, 0u, typename ::bluetoe::server< Options... >::services >;
348 static std::uint16_t handle_by_index( std::size_t index )
350 return iterator::service_handle_by_index( index );
359 static std::size_t first_index_by_handle( std::uint16_t handle )
361 return iterator::service_first_index_by_handle( handle );
364 static std::size_t index_by_handle( std::uint16_t handle )
366 std::size_t result = first_index_by_handle( handle );
367 if ( result != invalid_attribute_index && handle_by_index( result ) != handle )
368 result = invalid_attribute_index;
A characteristic is a typed value that is accessable by a GATT client hosted by a GATT server.
Definition: characteristic.hpp:160
Root of the declaration of a GATT server.
Definition: server.hpp:85
a service with zero or more characteristics
Definition: service.hpp:150
define the first attribute handle used by a characteristic or service
Definition: attribute_handle.hpp:34
define the attributes handles for the characteristic declaration, characteristic value and optional,...
Definition: attribute_handle.hpp:58