Browse Source

implement ble read

Thomas Buck 7 months ago
parent
commit
1b3e3e286b
7 changed files with 236 additions and 7 deletions
  1. 1
    0
      CMakeLists.txt
  2. 8
    1
      include/ble.h
  3. 29
    0
      include/volcano.h
  4. 105
    4
      src/ble.c
  5. 11
    1
      src/console.c
  6. 1
    1
      src/main.c
  7. 81
    0
      src/volcano.c

+ 1
- 0
CMakeLists.txt View File

@@ -60,6 +60,7 @@ target_sources(gadget PUBLIC
60 60
     src/text.c
61 61
     src/image.c
62 62
     src/state.c
63
+    src/volcano.c
63 64
 
64 65
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ff.c
65 66
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ffunicode.c

+ 8
- 1
include/ble.h View File

@@ -23,6 +23,7 @@
23 23
 
24 24
 #define BLE_MAX_NAME_LENGTH 32
25 25
 #define BLE_MAX_SCAN_RESULTS 32
26
+#define BLE_MAX_VALUE_LEN 64
26 27
 
27 28
 enum ble_scan_mode {
28 29
     BLE_SCAN_OFF    = 0,
@@ -42,9 +43,15 @@ struct ble_scan_result {
42 43
 
43 44
 void ble_init(void);
44 45
 bool ble_is_ready(void);
46
+
45 47
 void ble_scan(enum ble_scan_mode mode);
46
-int ble_get_scan_results(struct ble_scan_result *buf, uint len);
48
+int32_t ble_get_scan_results(struct ble_scan_result *buf, uint16_t len);
49
+
47 50
 void ble_connect(bd_addr_t addr, bd_addr_type_t type);
51
+bool ble_is_connected(void);
48 52
 void ble_disconnect(void);
49 53
 
54
+int32_t ble_read(const uint8_t *uuid, uint8_t *buff, uint16_t buff_len);
55
+int32_t ble_write(const uint8_t *uuid, uint8_t *buff, uint16_t buff_len);
56
+
50 57
 #endif // __BLE_H__

+ 29
- 0
include/volcano.h View File

@@ -0,0 +1,29 @@
1
+/*
2
+ * volcano.h
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __VOLCANO_H__
20
+#define __VOLCANO_H__
21
+
22
+// in 1/10th degrees C, or < 0 on error
23
+int16_t volcano_get_current_temp(void);
24
+int16_t volcano_get_target_temp(void);
25
+
26
+// v in 1/10th degrees C, returns < 0 on error
27
+int8_t volcano_set_target_temp(uint16_t v);
28
+
29
+#endif // __VOLCANO_H__

+ 105
- 4
src/ble.c View File

@@ -33,7 +33,9 @@ enum ble_state {
33 33
     TC_IDLE,
34 34
     TC_W4_SCAN,
35 35
     TC_W4_CONNECT,
36
-    TC_READY
36
+    TC_READY,
37
+    TC_W4_READ,
38
+    TC_READ_COMPLETE,
37 39
 };
38 40
 
39 41
 static btstack_packet_callback_registration_t hci_event_callback_registration;
@@ -41,6 +43,8 @@ static hci_con_handle_t connection_handle;
41 43
 
42 44
 static enum ble_state state = TC_OFF;
43 45
 static struct ble_scan_result scans[BLE_MAX_SCAN_RESULTS] = {0};
46
+static uint16_t read_len = 0;
47
+static uint8_t read_buff[BLE_MAX_VALUE_LEN] = {0};
44 48
 
45 49
 static void hci_add_scan_result(bd_addr_t addr, bd_addr_type_t type, int8_t rssi) {
46 50
     int unused = -1;
@@ -101,6 +105,9 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
101 105
     UNUSED(size);
102 106
     UNUSED(channel);
103 107
 
108
+    //debug("type=0x%02X size=%d", packet_type, size);
109
+    //hexdump(packet, size);
110
+
104 111
     if (packet_type != HCI_EVENT_PACKET) {
105 112
         //debug("unexpected packet 0x%02X", packet_type);
106 113
         return;
@@ -187,6 +194,30 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
187 194
         state = TC_IDLE;
188 195
         break;
189 196
 
197
+    case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT:
198
+        if (state != TC_W4_READ) {
199
+            debug("gatt query result in invalid state %d", state);
200
+            return;
201
+        }
202
+        uint16_t len = gatt_event_characteristic_value_query_result_get_value_length(packet);
203
+        if ((read_len + len) > BLE_MAX_VALUE_LEN) {
204
+            debug("not enough space for value (%d + %d > %d)", read_len, len, BLE_MAX_VALUE_LEN);
205
+            return;
206
+        }
207
+        memcpy(read_buff + read_len,
208
+               gatt_event_characteristic_value_query_result_get_value(packet),
209
+               len);
210
+        read_len += len;
211
+        break;
212
+
213
+    case GATT_EVENT_QUERY_COMPLETE:
214
+        if (state != TC_W4_READ) {
215
+            debug("gatt query complete in invalid state %d", state);
216
+            return;
217
+        }
218
+        state = TC_READ_COMPLETE;
219
+        break;
220
+
190 221
     default:
191 222
         //debug("unexpected event 0x%02X", hci_event_packet_get_type(packet));
192 223
         break;
@@ -272,7 +303,7 @@ void ble_scan(enum ble_scan_mode mode) {
272 303
     cyw43_thread_exit();
273 304
 }
274 305
 
275
-int ble_get_scan_results(struct ble_scan_result *buf, uint len) {
306
+int32_t ble_get_scan_results(struct ble_scan_result *buf, uint16_t len) {
276 307
     if (!buf || (len <= 0)) {
277 308
         return -1;
278 309
     }
@@ -284,8 +315,8 @@ int ble_get_scan_results(struct ble_scan_result *buf, uint len) {
284 315
         return -1;
285 316
     }
286 317
 
287
-    uint pos = 0;
288
-    for (uint i = 0; i < BLE_MAX_SCAN_RESULTS; i++) {
318
+    uint16_t pos = 0;
319
+    for (uint16_t i = 0; i < BLE_MAX_SCAN_RESULTS; i++) {
289 320
         if (!scans[i].set) {
290 321
             continue;
291 322
         }
@@ -337,6 +368,17 @@ void ble_connect(bd_addr_t addr, bd_addr_type_t type) {
337 368
     cyw43_thread_exit();
338 369
 }
339 370
 
371
+bool ble_is_connected(void) {
372
+    cyw43_thread_enter();
373
+
374
+    bool v = (state == TC_READY)
375
+             || (state == TC_W4_READ)
376
+             || (state == TC_READ_COMPLETE);
377
+
378
+    cyw43_thread_exit();
379
+    return v;
380
+}
381
+
340 382
 void ble_disconnect(void) {
341 383
     cyw43_thread_enter();
342 384
 
@@ -346,3 +388,62 @@ void ble_disconnect(void) {
346 388
 
347 389
     cyw43_thread_exit();
348 390
 }
391
+
392
+int32_t ble_read(const uint8_t *uuid, uint8_t *buff, uint16_t buff_len) {
393
+    cyw43_thread_enter();
394
+
395
+    if (state != TC_READY) {
396
+        cyw43_thread_exit();
397
+        debug("invalid state for read (%d)", state);
398
+        return -1;
399
+    }
400
+
401
+    uint8_t r = gatt_client_read_value_of_characteristics_by_uuid128(hci_event_handler,
402
+                                                                     connection_handle,
403
+                                                                     0x0001, 0xFFFF, uuid);
404
+    if (r != ERROR_CODE_SUCCESS) {
405
+        cyw43_thread_exit();
406
+        debug("gatt read failed %d", r);
407
+        return -2;
408
+    }
409
+
410
+    state = TC_W4_READ;
411
+    read_len = 0;
412
+    cyw43_thread_exit();
413
+
414
+    while (1) {
415
+        sleep_ms(1);
416
+
417
+        // TODO timeout
418
+
419
+        cyw43_thread_enter();
420
+        enum ble_state state_cached = state;
421
+        cyw43_thread_exit();
422
+
423
+        if (state_cached == TC_READ_COMPLETE) {
424
+            break;
425
+        }
426
+    }
427
+
428
+    cyw43_thread_enter();
429
+
430
+    state = TC_READY;
431
+
432
+    if (read_len > buff_len) {
433
+        debug("buffer too short (%d < %d)", buff_len, read_len);
434
+        cyw43_thread_exit();
435
+        return -3;
436
+    }
437
+
438
+    memcpy(buff, read_buff, read_len);
439
+
440
+    cyw43_thread_exit();
441
+    return read_len;
442
+}
443
+
444
+int32_t ble_write(const uint8_t *uuid, uint8_t *buff, uint16_t buff_len) {
445
+    UNUSED(uuid);
446
+    UNUSED(buff);
447
+    UNUSED(buff_len);
448
+    return -1;
449
+}

+ 11
- 1
src/console.c View File

@@ -34,6 +34,7 @@
34 34
 #include "text.h"
35 35
 #include "lcd.h"
36 36
 #include "image.h"
37
+#include "volcano.h"
37 38
 
38 39
 #define CNSL_BUFF_SIZE 1024
39 40
 #define CNSL_REPEAT_MS 500
@@ -89,6 +90,9 @@ static void cnsl_interpret(const char *line) {
89 90
         println("   text - draw text on screen");
90 91
         println("    bat - draw battery indicator");
91 92
         println("");
93
+        println("   vrct - Volcano read current temperature");
94
+        println("   vrtt - Volcano read target temperature");
95
+        println("");
92 96
         println("Press Enter with no input to repeat last command.");
93 97
         println("Use repeat to continuously execute last command.");
94 98
         println("Stop this by calling repeat again.");
@@ -106,7 +110,7 @@ static void cnsl_interpret(const char *line) {
106 110
                 volt, lipo_percentage(volt),
107 111
                 lipo_charging() ? "charging" : "draining");
108 112
     } else if (strcmp(line, "scan") == 0) {
109
-        ble_scan(2);
113
+        ble_scan(BLE_SCAN_TOGGLE);
110 114
     } else if (strcmp(line, "scanres") == 0) {
111 115
         struct ble_scan_result results[BLE_MAX_SCAN_RESULTS] = {0};
112 116
         int n = ble_get_scan_results(results, BLE_MAX_SCAN_RESULTS);
@@ -192,6 +196,12 @@ static void cnsl_interpret(const char *line) {
192 196
         }
193 197
     } else if (strcmp(line, "bat") == 0) {
194 198
         draw_battery_indicator();
199
+    } else if (strcmp(line, "vrct") == 0) {
200
+        int16_t r = volcano_get_current_temp();
201
+        println("volcano current temp: %.1f", r / 10.0);
202
+    } else if (strcmp(line, "vrtt") == 0) {
203
+        int16_t r = volcano_get_target_temp();
204
+        println("volcano target temp: %.1f", r / 10.0);
195 205
     } else {
196 206
         println("unknown command \"%s\"", line);
197 207
     }

+ 1
- 1
src/main.c View File

@@ -78,7 +78,7 @@ int main(void) {
78 78
 
79 79
     // wait for BLE stack to be ready before using it
80 80
     while (!ble_is_ready()) {
81
-        sleep_ms(10);
81
+        sleep_ms(1);
82 82
     }
83 83
 
84 84
     debug("starting app");

+ 81
- 0
src/volcano.c View File

@@ -0,0 +1,81 @@
1
+/*
2
+ * volcano.c
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include "config.h"
20
+#include "log.h"
21
+#include "util.h"
22
+#include "ble.h"
23
+#include "volcano.h"
24
+
25
+// Volcano UUIDs are always the same, except for the 4th byte
26
+
27
+#define UUID_CURRENT_TEMP 0x01
28
+#define UUID_TARGET_TEMP  0x03
29
+#define UUID_HEATER_ON    0x0F
30
+#define UUID_HEATER_OFF   0x10
31
+#define UUID_PUMP_ON      0x13
32
+#define UUID_PUMP_OFF     0x14
33
+
34
+// "101100FF-5354-4f52-5a26-4249434b454c"
35
+static uint8_t uuid_base[16] = {
36
+    0x10, 0x11, 0x00, 0xFF, 0x53, 0x54, 0x4f, 0x52,
37
+    0x5a, 0x26, 0x42, 0x49, 0x43, 0x4b, 0x45, 0x4c,
38
+};
39
+
40
+int16_t volcano_get_current_temp(void) {
41
+    uuid_base[3] = UUID_CURRENT_TEMP;
42
+
43
+    uint8_t buff[4];
44
+    int32_t r = ble_read(uuid_base, buff, 4);
45
+    if (r != 4) {
46
+        debug("ble_read unexpected value %ld", r);
47
+        return -1;
48
+    }
49
+
50
+    uint32_t *v = (uint32_t *)buff;
51
+    return *v;
52
+}
53
+
54
+int16_t volcano_get_target_temp(void) {
55
+    uuid_base[3] = UUID_TARGET_TEMP;
56
+
57
+    uint8_t buff[4];
58
+    int32_t r = ble_read(uuid_base, buff, 4);
59
+    if (r != 4) {
60
+        debug("ble_read unexpected value %ld", r);
61
+        return -1;
62
+    }
63
+
64
+    uint32_t *v = (uint32_t *)buff;
65
+    return *v;
66
+}
67
+
68
+int8_t volcano_set_target_temp(uint16_t value) {
69
+    uuid_base[3] = UUID_TARGET_TEMP;
70
+
71
+    uint8_t buff[4];
72
+    uint32_t *v = (uint32_t *)buff;
73
+    *v = value;
74
+
75
+    int32_t r = ble_write(uuid_base, buff, 4);
76
+    if (r != 4) {
77
+        debug("ble_write unexpected value %ld", r);
78
+        return -1;
79
+    }
80
+    return 0;
81
+}

Loading…
Cancel
Save