1 /**
2 ****************************************************************************************
3 *
4 * @file gls_db.c
5 *
6 * @brief Glucose Service Database implementation.
7 *
8 ****************************************************************************************
9 * @attention
10 #####Copyright (c) 2019 GOODIX
11 All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions are met:
15 * Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
17 * Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20 * Neither the name of GOODIX nor the names of its contributors may be used
21 to endorse or promote products derived from this software without
22 specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
35 *****************************************************************************************
36 */
37
38 /*
39 * INCLUDE FILES
40 ****************************************************************************************
41 */
42 #include "gls_db.h"
43
44 /*
45 * STRUCTURES
46 *****************************************************************************************
47 */
48 /**@brief Glucose Service record structure. */
49 struct gls_db_single_rec_t {
50 bool is_recorded;
51 gls_rec_t record;
52 };
53
54 /**@brief Glucose Service Database environment variable. */
55 struct gls_db_env_t {
56 struct gls_db_single_rec_t database[GLS_DB_RECORDS_MAX]; /**< Glucose Service measurement values \
57 records database. */
58 uint8_t rec_index[GLS_DB_RECORDS_MAX]; /**< Glucose Service measurement values record indexs. */
59 uint16_t num_records; /**< Number of measurement values records in database. */
60 };
61
62 /*
63 * LOCAL VARIABLE DEFINITIONS
64 ****************************************************************************************
65 */
66 static struct gls_db_env_t s_gls_db_env;
67
68 /*
69 * LOCAL FUNCTION DEFINITIONS
70 ****************************************************************************************
71 */
72 /**
73 *****************************************************************************************
74 * @brief Get number of records which are less or equal to setting value.
75 *
76 * @param[in] p_filter: Pointer to filter parameters.
77 *
78 * @return Number of records.
79 *****************************************************************************************
80 */
gls_db_le_or_eq_record_num_get(gls_racp_filter_t * p_filter)81 uint16_t gls_db_le_or_eq_record_num_get(gls_racp_filter_t *p_filter)
82 {
83 gls_rec_t gls_res;
84 uint16_t num_get = 0;
85
86 for (uint8_t i = 0; i < s_gls_db_env.num_records; i++) {
87 if (!gls_db_record_get(i, &gls_res)) {
88 return num_get;
89 }
90 if (GLS_RACP_FILTER_SEQ_NUMBER == p_filter->racp_filter_type) {
91 if (p_filter->val.seq_num.max >= gls_res.meas_val.sequence_number) {
92 num_get++;
93 }
94 } else if (GLS_RACP_FILTER_USER_FACING_TIME == p_filter->racp_filter_type) {
95 if (-1 != gls_racp_user_time_compare(&p_filter->val.time.max,
96 &gls_res.meas_val.base_time)) {
97 num_get++;
98 }
99 }
100 }
101
102 return num_get;
103 }
104
105 /**
106 *****************************************************************************************
107 * @brief Get number of records which are greater or equal to setting value.
108 *
109 * @param[in] p_filter: Pointer to filter parameters.
110 *
111 * @return Number of records.
112 *****************************************************************************************
113 */
gls_db_gt_or_eq_record_num_get(gls_racp_filter_t * p_filter)114 uint16_t gls_db_gt_or_eq_record_num_get(gls_racp_filter_t *p_filter)
115 {
116 gls_rec_t gls_res;
117 uint16_t num_get = 0;
118
119 for (uint8_t i = 0; i < s_gls_db_env.num_records; i++) {
120 if (gls_db_record_get(i, &gls_res)) {
121 return num_get;
122 }
123 if (GLS_RACP_FILTER_SEQ_NUMBER == p_filter->racp_filter_type) {
124 if (p_filter->val.seq_num.min <= gls_res.meas_val.sequence_number) {
125 num_get++;
126 }
127 } else if (GLS_RACP_FILTER_USER_FACING_TIME == p_filter->racp_filter_type) {
128 if (-1 != gls_racp_user_time_compare(&gls_res.meas_val.base_time,
129 &p_filter->val.time.min)) {
130 num_get++;
131 }
132 }
133 }
134 }
135
136 /**
137 *****************************************************************************************
138 * @brief Get number of records which are within range of setting value.
139 *
140 * @param[in] p_filter: Pointer to filter parameters.
141 *
142 * @return Number of records.
143 *****************************************************************************************
144 */
gls_db_within_range_record_num_get(gls_racp_filter_t * p_filter)145 uint16_t gls_db_within_range_record_num_get(gls_racp_filter_t *p_filter)
146 {
147 gls_rec_t gls_res;
148 uint16_t num_get = 0;
149
150 for (uint8_t i = 0; i < s_gls_db_env.num_records; i++) {
151 if (gls_db_record_get(i, &gls_res)) {
152 return num_get;
153 }
154 if (GLS_RACP_FILTER_SEQ_NUMBER == p_filter->racp_filter_type) {
155 if ((gls_res.meas_val.sequence_number >= p_filter->val.seq_num.min) && \
156 (gls_res.meas_val.sequence_number <= p_filter->val.seq_num.max)) {
157 num_get++;
158 }
159 } else if (GLS_RACP_FILTER_USER_FACING_TIME == p_filter->racp_filter_type) {
160 if ((-1 != gls_racp_user_time_compare(&gls_res.meas_val.base_time, &p_filter->val.time.min)) && \
161 (-1 != gls_racp_user_time_compare(&p_filter->val.time.max, &gls_res.meas_val.base_time))) {
162 num_get++;
163 }
164 }
165 }
166
167 return num_get;
168 }
169
170 /*
171 * GLOBAL FUNCTION DEFINITIONS
172 ****************************************************************************************
173 */
gls_db_init(void)174 void gls_db_init(void)
175 {
176 for (uint8_t i = 0; i < GLS_DB_RECORDS_MAX; i++) {
177 s_gls_db_env.database[i].is_recorded = false;
178 s_gls_db_env.rec_index[i] = 0xFF;
179 }
180
181 s_gls_db_env.num_records = 0;
182 }
183
gls_db_record_add(gls_rec_t * p_rec)184 bool gls_db_record_add(gls_rec_t *p_rec)
185 {
186 uint8_t i = 0;
187
188 if (GLS_DB_RECORDS_MAX <= s_gls_db_env.num_records) {
189 return false;
190 }
191
192 for (i = 0; i < GLS_DB_RECORDS_MAX; i++) {
193 if (!s_gls_db_env.database[i].is_recorded) {
194 s_gls_db_env.database[i].is_recorded = true;
195 s_gls_db_env.database[i].record = *p_rec;
196 s_gls_db_env.rec_index[s_gls_db_env.num_records] = i;
197 s_gls_db_env.num_records++;
198 return true;
199 }
200 }
201
202 return false;
203 }
204
gls_db_record_delete(uint8_t rec_idx)205 bool gls_db_record_delete(uint8_t rec_idx)
206 {
207 if (rec_idx >= s_gls_db_env.num_records) {
208 return false;
209 }
210
211 s_gls_db_env.database[s_gls_db_env.rec_index[rec_idx]].is_recorded = false;
212
213 s_gls_db_env.num_records--;
214
215 for (uint8_t i = rec_idx; i < s_gls_db_env.num_records; i++) {
216 s_gls_db_env.rec_index[i] = s_gls_db_env.rec_index[i + 1];
217 }
218
219 return true;
220 }
221
gls_db_records_num_get(void)222 uint16_t gls_db_records_num_get(void)
223 {
224 return s_gls_db_env.num_records;
225 }
226
gls_db_filter_records_num_get(gls_racp_filter_t * p_filter)227 uint16_t gls_db_filter_records_num_get(gls_racp_filter_t *p_filter)
228 {
229 uint16_t num_get = 0;
230
231 switch (p_filter->racp_operator) {
232 case GLS_RACP_OPERATOR_ALL_RECS:
233 num_get = s_gls_db_env.num_records;
234 break;
235
236 case GLS_RACP_OPERATOR_LE_OR_EQ:
237 num_get = gls_db_le_or_eq_record_num_get(p_filter);
238 break;
239
240 case GLS_RACP_OPERATOR_GT_OR_EQ:
241 num_get = gls_db_gt_or_eq_record_num_get(p_filter);
242 break;
243
244 case GLS_RACP_OPERATOR_WITHIN_RANGE_OF:
245 num_get = gls_db_within_range_record_num_get(p_filter);
246 break;
247
248 case GLS_RACP_OPERATOR_FIRST_REC:
249 case GLS_RACP_OPERATOR_LAST_REC:
250 if (s_gls_db_env.num_records != 0) {
251 num_get = 1;
252 }
253 break;
254
255 default:
256 break;
257 }
258
259 return num_get;
260 }
261
gls_db_record_get(uint8_t rec_idx,gls_rec_t * p_rec)262 bool gls_db_record_get(uint8_t rec_idx, gls_rec_t *p_rec)
263 {
264 if (rec_idx >= s_gls_db_env.num_records) {
265 return false;
266 }
267
268 *p_rec = s_gls_db_env.database[s_gls_db_env.rec_index[rec_idx]].record;
269
270 return true;
271 }
272
gls_db_record_clear(void)273 void gls_db_record_clear(void)
274 {
275 for (uint8_t i = 0; i < GLS_DB_RECORDS_MAX; i++) {
276 s_gls_db_env.database[i].is_recorded = false;
277 s_gls_db_env.rec_index[i] = 0xFF;
278 }
279
280 s_gls_db_env.num_records = 0;
281 }
282
283