ruuvi.drivers.c ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
Loading...
Searching...
No Matches
ruuvi_interface_communication_ble_gatt_test.c
Go to the documentation of this file.
2#if RUUVI_RUN_TESTS
4#include "ruuvi_driver_test.h"
11#include "ruuvi_interface_rtc.h"
14#include <stdbool.h>
15#include <string.h>
16#include <stdio.h>
17
30#define GATT_TX_TEST_TIMEOUT_MS (10000U)
31
32static ri_comm_channel_t m_channel;
33static ri_comm_channel_t m_adv;
34static volatile bool m_has_connected;
35static volatile bool m_has_disconnected;
36static volatile bool m_has_sent;
37static volatile bool m_has_received;
38static ri_comm_message_t rx_data;
39
40static rd_status_t ble_isr (ri_comm_evt_t evt,
41 void * p_data, size_t data_len)
42{
43 switch (evt)
44 {
45 // Note: This gets called only after the NFC notifications have been registered.
47 m_has_connected = true;
48 break;
49
51 m_has_disconnected = true;
52 break;
53
54 case RI_COMM_SENT:
55 m_has_sent = true;
56 break;
57
59 m_has_received = true;
61 m_channel.read (&rx_data);
62 break;
63
64 default:
65 break;
66 }
67
68 return RD_SUCCESS;
69}
70
80static bool ri_gatt_init_null_test (void)
81{
82 rd_status_t err_code = RD_SUCCESS;
83 err_code |= ri_gatt_init ();
84 err_code |= ri_gatt_nus_init (NULL);
85 return (RD_ERROR_NULL != err_code);
86}
87
88static bool ri_gatt_init_twice_test (void)
89{
90 rd_status_t err_code = RD_SUCCESS;
91 err_code |= ri_gatt_init ();
92 err_code |= ri_gatt_init ();
93 return (RD_ERROR_INVALID_STATE != err_code);
94}
95
96static bool ri_gatt_init_norad_test (void)
97{
98 rd_status_t err_code = RD_SUCCESS;
99 err_code |= ri_gatt_init ();
100 return (RD_ERROR_INVALID_STATE != err_code);
101}
102
103static bool ri_gatt_init_test (const rd_test_print_fp printfp,
104 const ri_radio_modulation_t modulation)
105{
106 bool status = false;
107 rd_status_t err_code = RD_SUCCESS;
108 printfp ("\"init\":");
109 status |= ri_gatt_init_norad_test();
110 err_code |= ri_timer_init();
111 err_code |= ri_flash_init();
112 err_code |= ri_radio_init (modulation);
113 err_code |= ri_gatt_init ();
114 // nRF SDK requires complete radio re-init.
115 err_code |= ri_radio_uninit ();
116 err_code |= ri_gatt_uninit ();
117 err_code |= ri_radio_init (modulation);
118
119 if (RD_SUCCESS == err_code)
120 {
121 status |= ri_gatt_init_null_test();
122 status |= ri_gatt_init_twice_test();
123 }
124 else
125 {
126 status |= true;
127 }
128
129 if (status)
130 {
131 printfp ("\"fail\",\r\n");
132 }
133 else
134 {
135 printfp ("\"pass\",\r\n");
136 }
137
138 ri_gatt_nus_uninit (&m_channel);
143 return status;
144}
145
146/* Send data slowfly for 10 s to verify power consumption when little data is sent */
147static bool tx_slow_test (void)
148{
149 rd_status_t err_code = RD_SUCCESS;
150 const char test_data[] = "Test slow tx: ";
151 ri_comm_message_t msg = {0};
152 uint16_t msg_index = 0U;
153
154 for (uint8_t ii = 0U; ii < 10U; ii++)
155 {
156 snprintf ( (char *) & msg.data, RI_COMM_MESSAGE_MAX_LENGTH, "%s%d", test_data,
157 msg_index++);
158 msg.data_length = strlen (test_data);
159 msg.repeat_count = 1U;
160 err_code |= m_channel.send (&msg);
161 ri_delay_ms (1000U);
162 }
163
164 return (RD_SUCCESS != err_code);
165}
166
167/* Check throughput, return throughput- */
168static float tx_throughput_test (void)
169{
170 rd_status_t err_code = RD_SUCCESS;
171 const char test_data[] = "msg: "; // 5 chars
172 ri_comm_message_t msg = {0};
173 uint64_t test_start = ri_rtc_millis();
174
175 for (uint16_t ii = 0U; ii < TEST_GATT_PACKET_NUM;)
176 {
177 err_code = RD_SUCCESS;
178
179 while (RD_SUCCESS == err_code)
180 {
181 // 5 + 5 + 3 + 5 + 1 + NULL = 20 bytes
182 snprintf ( (char *) & msg.data, RI_COMM_MESSAGE_MAX_LENGTH, "%s%05d / %05d.", test_data,
185 msg.repeat_count = 1U;
186 err_code |= m_channel.send (&msg);
187
188 if (RD_SUCCESS == err_code)
189 {
190 ii++;
191 }
192 }
193
194 ri_yield();
195 }
196
197 uint64_t test_end = ri_rtc_millis();
198 return ( (float) (TEST_GATT_PACKET_NUM * TEST_GATT_PACKET_LEN)) / ( ( (float) (
199 test_end - test_start)) / 1000.0F);
200}
201
202bool ri_gatt_tx_test (const rd_test_print_fp printfp,
203 const ri_radio_modulation_t modulation)
204{
205 bool status = false;
206 m_has_connected = false;
207 uint64_t start_time = 0;
208 bool timeout = false;
209 rd_status_t err_code = RD_SUCCESS;
210 float throughput = 0;
211 char throughput_string[100];
212 printfp ("\"tx\":");
213 // RTC + timer required for low-power yield.
214 err_code |= ri_rtc_init();
215 err_code |= ri_timer_init();
216 err_code |= ri_yield_low_power_enable (true);
217 err_code |= ri_flash_init();
218 err_code |= ri_radio_init (modulation);
219 // Advertise NUS to tester.
220 err_code |= ri_adv_init (&m_adv);
221 err_code |= ri_adv_scan_response_setup ("RuuviTest", true);
223 err_code |= ri_adv_tx_interval_set (100U);
224 err_code |= ri_gatt_init ();
225 err_code |= ri_gatt_nus_init (&m_channel);
226 const char test_data[] = "Lorem Ipsum";
227 ri_comm_message_t msg = {0};
228 snprintf ( (char *) & msg.data, RI_COMM_MESSAGE_MAX_LENGTH, "%s", test_data);
229 msg.data_length = strlen (test_data);
230 msg.repeat_count = 200U; // 200 * 100ms => 20 s to connect.
231 err_code |= m_adv.send (&msg);
232
233 if (RD_SUCCESS == err_code)
234 {
235 m_channel.on_evt = ble_isr;
236 start_time = ri_rtc_millis();
237
238 while (! (m_has_connected))
239 {
240 if ( (start_time + GATT_TX_TEST_TIMEOUT_MS) < ri_rtc_millis())
241 {
242 timeout = true;
243 break;
244 }
245 }
246
247 if (false == timeout)
248 {
249 status |= tx_slow_test ();
250 throughput = tx_throughput_test();
251
252 if (0 == throughput)
253 {
254 status = true;
255 }
256 }
257 }
258 else
259 {
260 status = true;
261 }
262
263 if (timeout)
264 {
265 printfp ("\"timeout\",\r\n");
266 }
267 else
268 {
269 if (status)
270 {
271 printfp ("\"fail\",\r\n");
272 }
273 else
274 {
275 printfp ("\"pass\",\r\n");
276 }
277 }
278
279 snprintf (throughput_string, sizeof (throughput_string),
280 "\"throughput\":\"%.3f bps\"\r\n",
281 throughput);
282 printfp (throughput_string);
283 ri_gatt_nus_uninit (&m_channel);
284 ri_adv_uninit (&m_adv);
285 ri_delay_ms (2000);
287 ri_gatt_uninit (); // GATT can only be uninit after radio.
288 err_code |= ri_flash_uninit();
292 return status;
293}
294
296 const ri_radio_modulation_t modulation)
297{
298 rd_status_t status = false;
299 printfp ("\"ble_gatt_");
300 print_modulation (printfp, modulation);
301 printfp ("\":{\r\n");
302 status |= ri_gatt_init_test (printfp, modulation);
303 status |= ri_gatt_tx_test (printfp, modulation);
304 printfp ("},\r\n");
305 return status;
306}
307#endif
#define TEST_GATT_PACKET_NUM
Number of packets to send in throughput test.
bool ri_communication_ble_gatt_run_integration_test(const rd_test_print_fp printfp, const ri_radio_modulation_t modulation)
#define TEST_GATT_PACKET_LEN
Bytes of GATT test packet.
#define RD_ERROR_NULL
Null Pointer.
uint32_t rd_status_t
bitfield for representing errors
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
rd_status_t ri_flash_uninit(void)
Unintialize flash. After uninitialization only initialization can be used.
rd_status_t ri_flash_init(void)
void print_modulation(const rd_test_print_fp printfp, const ri_radio_modulation_t modulation)
Print used modulation to printfp.
rd_status_t ri_radio_init(const ri_radio_modulation_t modulation)
Enable radio stack for an user. This function also starts radio activity callbacks internally.
rd_status_t ri_radio_uninit()
Release radio stack.
ri_radio_modulation_t
type of radio modulation to be used.
void(* rd_test_print_fp)(const char *const msg)
function pointer to print test information
rd_status_t ri_timer_uninit(void)
rd_status_t ri_timer_init(void)
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Functions for testing drivers.
#define RI_COMM_MESSAGE_MAX_LENGTH
The maximum length for the application message for sending over BLE, which depends on whether extende...
ri_comm_evt_t
Communication event type.
@ RI_COMM_CONNECTED
Connection established, OK to send, may receive data.
@ RI_COMM_RECEIVED
New data received, available to read with read function.
@ RI_COMM_SENT
One queued message was sent with all repetitions.
@ RI_COMM_DISCONNECTED
Connection lost, cannot send, may not receive data.
@ CONNECTABLE_SCANNABLE
Connectable, scannable.
rd_status_t ri_adv_init(ri_comm_channel_t *const channel)
Initialize Advertising module and scanning module.
rd_status_t ri_adv_scan_response_setup(const char *const name, const bool advertise_nus)
Configure advertising data with a scan response.
rd_status_t ri_adv_uninit(ri_comm_channel_t *const channel)
rd_status_t ri_adv_type_set(ri_adv_type_t type)
Configure the type of advertisement.
rd_status_t ri_adv_tx_interval_set(const uint32_t ms)
rd_status_t ri_gatt_init(void)
Initializes GATT stack. Uses default values from sdk_config.h, these can be overridden in nrf5_sdk15_...
rd_status_t ri_gatt_nus_uninit(ri_comm_channel_t *const _channel)
Uninitialize Nordic UART Service as a communication channel.
rd_status_t ri_gatt_uninit(void)
Uninitializes GATT stack.
rd_status_t ri_gatt_nus_init(ri_comm_channel_t *const channel)
Initialize Nordic UART Service as a communication channel. ri_communication_radio_init(RI_COMMUNICATI...
Interface functions to persistent flash storage.
rd_status_t ri_rtc_init(void)
Initializes RTC at 0 ms.
rd_status_t ri_rtc_uninit(void)
Stop RTC if applicable.
uint64_t ri_rtc_millis(void)
Get milliseconds since init.
Interface functions to timer.
rd_status_t ri_yield(void)
Function which will release execution.
rd_status_t ri_delay_ms(uint32_t time)
Delay a given number of milliseconds.
rd_status_t ri_yield_low_power_enable(const bool enable)
Initializes yielding functions.
control API for communication via outside world
ri_comm_evt_handler_fp_t on_evt
Callback to application-level event handler, must be set in application.
ri_comm_xfer_fp_t send
Asynchronous send function.
ri_comm_xfer_fp_t read
Asynchronous read function.
Application message structure used for communication.
uint8_t data[RI_COMM_MESSAGE_MAX_LENGTH]
Data payload.
uint8_t repeat_count
Number of times to repeat the message,.
uint8_t data_length
Length of data.