BlueToe
an alternative GATT/BLE implementation
Loading...
Searching...
No Matches
find_notification_data.hpp
1#ifndef BLUETOE_FIND_NOTIFICATION_DATA_HPP
2#define BLUETOE_FIND_NOTIFICATION_DATA_HPP
3
5
6namespace bluetoe {
7namespace details {
8
9 namespace impl {
10 template < typename Characteristics, typename Pair >
11 struct filter_characteristics_with_cccd
12 {
13 using type = typename select_type<
14 Pair::characteristic_t::number_of_client_configs,
15 typename add_type< Characteristics, Pair >::type,
16 Characteristics
17 >::type;
18 };
19
20 template < typename Characteristic, std::size_t Offset, int Prio >
21 struct characteristic_with_service_attribute_offset
22 {
23 using characteristic_t = Characteristic;
24 static constexpr std::size_t service_offset = Offset;
25 static constexpr int priority = Prio;
26 };
27
28 struct preudo_first_char
29 {
30 static constexpr std::size_t number_of_attributes = 0;
31 };
32
33 template < typename Characteristic, std::size_t FirstAttributesIndex, int Prio >
34 struct characteristic_index_pair
35 {
36 using characteristic_t = Characteristic;
37 static constexpr std::size_t first_attribute_index = FirstAttributesIndex;
38 static constexpr int priority = Prio;
39 };
40
41 template < typename Characteristics, typename Characteristic >
42 struct add_index_to_characteristic
43 {
44 using last = typename last_type< Characteristics, impl::characteristic_index_pair< impl::preudo_first_char, 0, 0 > >::type;
45
46 static constexpr std::size_t attribute_handle = last::first_attribute_index + last::characteristic_t::number_of_attributes + Characteristic::service_offset;
47
48 using type = typename add_type<
49 Characteristics,
50 impl::characteristic_index_pair< typename Characteristic::characteristic_t, attribute_handle, Characteristic::priority >
51 >::type;
52 };
53
54 struct attribute_at
55 {
56 constexpr attribute_at( std::size_t& r, std::size_t i )
57 : result( r )
58 , index( i )
59 {}
60
61 template< typename O >
62 void each()
63 {
64 if ( index == 0 )
65 {
66 result = O::first_attribute_index;
67 }
68
69 --index;
70 }
71
72 std::size_t& result;
73 std::size_t index;
74 };
75
76 template < typename A, typename B >
77 struct order_by_prio
78 {
79 using type = std::integral_constant< bool, A::priority < B::priority >;
80 };
81
82 template < typename Characteristics, typename Characteristic >
83 struct add_cccd_position
84 {
85 template < std::size_t CCCD, typename HandlePair >
86 struct with_cccd_position : HandlePair
87 {
88 static constexpr std::size_t cccd_position = CCCD;
89 };
90
91 static constexpr std::size_t cccd_position = std::tuple_size< Characteristics >::value;
92
93 using type = typename add_type<
94 Characteristics,
95 with_cccd_position< cccd_position, Characteristic >
96 >::type;
97 };
98
99 template < typename Characteristics, typename Characteristic >
100 struct add_cccd_handle
101 {
102 template < std::size_t CCCD, typename HandlePair >
103 struct with_cccd_handle : HandlePair
104 {
105 static constexpr std::size_t cccd_handle = CCCD;
106 };
107
108 static constexpr std::size_t cccd_handle = std::tuple_size< Characteristics >::value;
109
110 using type = typename add_type<
111 Characteristics,
112 with_cccd_handle< cccd_handle, Characteristic >
113 >::type;
114 };
115
116 template < class Characteristic >
117 struct select_cccd_position {
118 using type = std::integral_constant< std::size_t, Characteristic::cccd_position >;
119 };
120
121 }
122
123 template <
124 typename Priorities,
125 typename Services
126 >
127 struct find_notification_data_in_list
128 {
129 template < typename Characteristics, typename Service >
130 struct characteristics_from_service
131 {
132 template < typename C >
133 struct add_service_offset
134 {
135 using type = std::tuple<>;
136 };
137
138 // Add just to the first characteritic of a service the numer of attributes that are used to
139 // model the service
140 template < typename C, typename ...Cs >
141 struct add_service_offset< std::tuple< C, Cs... > >
142 {
143 using type = std::tuple<
144 impl::characteristic_with_service_attribute_offset< C, Service::number_of_service_attributes, Priorities::template characteristic_priority< Services, Service, C >::value >,
145 impl::characteristic_with_service_attribute_offset< Cs, 0, Priorities::template characteristic_priority< Services, Service, Cs >::value >... >;
146 };
147
148 using type = typename add_type< Characteristics, typename add_service_offset< typename Service::characteristics >::type >::type;
149 };
150
151 using services = Services;
152 using all_characteristics = typename fold_left< services, characteristics_from_service >::type;
153 using characteristics_with_attribute_indizes = typename fold_left< all_characteristics, impl::add_index_to_characteristic >::type;
154 using characteristics_only_with_cccd = typename fold_left< characteristics_with_attribute_indizes, impl::filter_characteristics_with_cccd >::type;
155 using characteristics_with_cccd_position = typename fold_left< characteristics_only_with_cccd, impl::add_cccd_position >::type;
156 using characteristics_sorted_by_priority = typename stable_sort< impl::order_by_prio, characteristics_with_cccd_position >::type;
157 using characteristics_with_cccd_handle = typename fold_left< characteristics_sorted_by_priority, impl::add_cccd_handle >::type;
158
159 static notification_data find_notification_data_by_index( std::size_t notification_index )
160 {
161 std::size_t attribute_index = 0;
162 for_< characteristics_sorted_by_priority >::each( impl::attribute_at( attribute_index, notification_index ) );
163
164 return notification_data( attribute_index + 1, notification_index );
165 }
166
167 struct attribute_value
168 {
169 constexpr attribute_value( notification_data& r, const void* v )
170 : result( r )
171 , index( 0 )
172 , value( v )
173 {}
174
175 template< typename O >
176 void each()
177 {
178 if ( O::characteristic_t::value_type::is_this( value ) )
179 result = notification_data( O::first_attribute_index + 1, index );
180
181 ++index;
182 }
183
184 notification_data& result;
185 std::size_t index;
186 const void* value;
187 };
188
189 static notification_data find_notification_data( const void* value )
190 {
191 notification_data result;
192 for_< characteristics_only_with_cccd >::each( attribute_value( result, value ) );
193
194 return result;
195 }
196
197 using cccd_indices = typename transform_list< characteristics_with_cccd_handle, impl::select_cccd_position >::type;
198 };
199
200 template <
201 typename Priorities,
202 typename Services,
203 typename Characteristic
204 >
205 struct find_notification_by_uuid
206 {
207 using find = find_notification_data_in_list< Priorities, Services >;
208
209 template < typename Other >
210 struct equal_char
211 {
212 static constexpr bool value = std::is_same< typename Other::characteristic_t, Characteristic >::value;
213 };
214
215 using char_infos = typename find_if<
216 typename find::characteristics_with_cccd_handle,
217 equal_char >::type;
218
219 static notification_data data()
220 {
221 return notification_data( char_infos::first_attribute_index + 1, char_infos::cccd_handle );
222 }
223 };
224
225}
226}
227
228#endif
wrap< typename select_type_impl< Select >::template f< A, B > > select_type
Select A or B by Select. If Select == true, the result is A; B otherwise.
Definition: meta_tools.hpp:38