Browse Source

detect known device types and read their serial number

Thomas Buck 1 year ago
parent
commit
00e30acf5d
7 changed files with 150 additions and 25 deletions
  1. 1
    0
      CMakeLists.txt
  2. 3
    0
      include/ble.h
  3. 33
    0
      include/models.h
  4. 47
    22
      src/ble.c
  5. 10
    3
      src/console.c
  6. 53
    0
      src/models.c
  7. 3
    0
      src/state.c

+ 1
- 0
CMakeLists.txt View File

63
     src/volcano.c
63
     src/volcano.c
64
     src/serial.c
64
     src/serial.c
65
     src/ring.c
65
     src/ring.c
66
+    src/models.c
66
 
67
 
67
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ff.c
68
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ff.c
68
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ffunicode.c
69
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ffunicode.c

+ 3
- 0
include/ble.h View File

22
 #include "btstack.h"
22
 #include "btstack.h"
23
 
23
 
24
 #define BLE_MAX_NAME_LENGTH 32
24
 #define BLE_MAX_NAME_LENGTH 32
25
+#define BLE_MAX_DATA_LENGTH 26
25
 #define BLE_MAX_SCAN_RESULTS 32
26
 #define BLE_MAX_SCAN_RESULTS 32
26
 #define BLE_MAX_VALUE_LEN 64
27
 #define BLE_MAX_VALUE_LEN 64
27
 
28
 
39
     bd_addr_type_t type;
40
     bd_addr_type_t type;
40
     int8_t rssi;
41
     int8_t rssi;
41
     char name[BLE_MAX_NAME_LENGTH + 1];
42
     char name[BLE_MAX_NAME_LENGTH + 1];
43
+    uint8_t data[BLE_MAX_DATA_LENGTH];
44
+    size_t data_len;
42
 };
45
 };
43
 
46
 
44
 void ble_init(void);
47
 void ble_init(void);

+ 33
- 0
include/models.h View File

1
+/*
2
+ * models.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 __MODELS_H__
20
+#define __MODELS_H__
21
+
22
+#include <stdint.h>
23
+
24
+enum known_devices {
25
+    DEV_UNKNOWN = 0,
26
+    DEV_VOLCANO,
27
+    DEV_CRAFTY,
28
+};
29
+
30
+enum known_devices models_filter_name(const char *name);
31
+int8_t models_get_serial(const uint8_t *data, size_t data_len, char *buff, size_t buff_len);
32
+
33
+#endif // __MODELS_H__

+ 47
- 22
src/ble.c View File

24
 
24
 
25
 #include "config.h"
25
 #include "config.h"
26
 #include "log.h"
26
 #include "log.h"
27
+#include "main.h"
27
 #include "util.h"
28
 #include "util.h"
28
 #include "ble.h"
29
 #include "ble.h"
29
 
30
 
104
     scans[unused].type = type;
105
     scans[unused].type = type;
105
     scans[unused].rssi = rssi;
106
     scans[unused].rssi = rssi;
106
     scans[unused].name[0] = '\0';
107
     scans[unused].name[0] = '\0';
108
+    scans[unused].data_len = 0;
107
 }
109
 }
108
 
110
 
109
 static void hci_scan_result_add_name(bd_addr_t addr, const uint8_t *data, uint8_t data_size) {
111
 static void hci_scan_result_add_name(bd_addr_t addr, const uint8_t *data, uint8_t data_size) {
128
     debug("no matching entry for %s to add name '%.*s' to", bd_addr_to_str(addr), data_size, data);
130
     debug("no matching entry for %s to add name '%.*s' to", bd_addr_to_str(addr), data_size, data);
129
 }
131
 }
130
 
132
 
133
+static void hci_scan_result_add_data(bd_addr_t addr, const uint8_t *data, uint8_t data_size) {
134
+    for (uint i = 0; i < BLE_MAX_SCAN_RESULTS; i++) {
135
+        if (!scans[i].set) {
136
+            continue;
137
+        }
138
+        if (memcmp(addr, scans[i].addr, sizeof(bd_addr_t)) != 0) {
139
+            continue;
140
+        }
141
+
142
+        uint8_t len = data_size;
143
+        if (len > BLE_MAX_DATA_LENGTH) {
144
+            len = BLE_MAX_DATA_LENGTH;
145
+        }
146
+        memcpy(scans[i].data, data, len);
147
+        scans[i].data_len = len;
148
+        scans[i].time = to_ms_since_boot(get_absolute_time());
149
+        return;
150
+    }
151
+
152
+    debug("no matching entry for %s to add data to", bd_addr_to_str(addr));
153
+}
154
+
131
 static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
155
 static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
132
     UNUSED(size);
156
     UNUSED(size);
133
     UNUSED(channel);
157
     UNUSED(channel);
189
                 hci_scan_result_add_name(addr, data, data_size);
213
                 hci_scan_result_add_name(addr, data, data_size);
190
                 break;
214
                 break;
191
 
215
 
216
+            case BLUETOOTH_DATA_TYPE_SERVICE_DATA:
217
+            case BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
218
+                // TODO ugly
219
+                if (data_size == 12) {
220
+                    // Crafty+
221
+                    hci_scan_result_add_data(addr, data, data_size);
222
+                } else if (data_size == 26) {
223
+                    // Volcano
224
+                    hci_scan_result_add_data(addr, data, data_size);
225
+                }
226
+                break;
227
+
192
             default:
228
             default:
193
                 //debug("Unexpected advertisement type 0x%02X from %s", data_type, bd_addr_to_str(addr));
229
                 //debug("Unexpected advertisement type 0x%02X from %s", data_type, bd_addr_to_str(addr));
194
                 //hexdump(data, data_size);
230
                 //hexdump(data, data_size);
399
             continue;
435
             continue;
400
         }
436
         }
401
 
437
 
402
-        uint32_t diff = to_ms_since_boot(get_absolute_time()) - scans[i].time;
403
-        if (diff >= BLE_MAX_SCAN_AGE_MS) {
404
-            //debug("removing %s due to age", bd_addr_to_str(scans[i].addr));
405
-            scans[i].set = false;
438
+        // only age out entries while scanning, otherwise keep results cached
439
+        if (state == TC_W4_SCAN) {
440
+            uint32_t diff = to_ms_since_boot(get_absolute_time()) - scans[i].time;
441
+            if (diff >= BLE_MAX_SCAN_AGE_MS) {
442
+                //debug("removing %s due to age", bd_addr_to_str(scans[i].addr));
443
+                scans[i].set = false;
444
+            }
406
         }
445
         }
407
 
446
 
408
         memcpy(buf + pos, scans + i, sizeof(struct ble_scan_result));
447
         memcpy(buf + pos, scans + i, sizeof(struct ble_scan_result));
497
     uint32_t start_time = to_ms_since_boot(get_absolute_time());
536
     uint32_t start_time = to_ms_since_boot(get_absolute_time());
498
     while (1) {
537
     while (1) {
499
         sleep_ms(1);
538
         sleep_ms(1);
539
+        main_loop_hw();
500
 
540
 
501
         uint32_t now = to_ms_since_boot(get_absolute_time());
541
         uint32_t now = to_ms_since_boot(get_absolute_time());
502
         if ((now - start_time) >= BLE_READ_TIMEOUT_MS) {
542
         if ((now - start_time) >= BLE_READ_TIMEOUT_MS) {
503
             debug("timeout waiting for read");
543
             debug("timeout waiting for read");
504
             return -3;
544
             return -3;
505
         }
545
         }
506
-#if BLE_READ_TIMEOUT_MS >= (WATCHDOG_PERIOD_MS / 2)
507
-        watchdog_update();
508
-#endif
509
 
546
 
510
         cyw43_thread_enter();
547
         cyw43_thread_enter();
511
         enum ble_state state_cached = state;
548
         enum ble_state state_cached = state;
585
         uint32_t start_time = to_ms_since_boot(get_absolute_time());
622
         uint32_t start_time = to_ms_since_boot(get_absolute_time());
586
         while (1) {
623
         while (1) {
587
             sleep_ms(1);
624
             sleep_ms(1);
625
+            main_loop_hw();
588
 
626
 
589
             uint32_t now = to_ms_since_boot(get_absolute_time());
627
             uint32_t now = to_ms_since_boot(get_absolute_time());
590
             if ((now - start_time) >= BLE_SRVC_TIMEOUT_MS) {
628
             if ((now - start_time) >= BLE_SRVC_TIMEOUT_MS) {
591
                 debug("timeout waiting for service");
629
                 debug("timeout waiting for service");
592
                 return -3;
630
                 return -3;
593
             }
631
             }
594
-#if BLE_SRVC_TIMEOUT_MS >= (WATCHDOG_PERIOD_MS / 2)
595
-            watchdog_update();
596
-#endif
597
 
632
 
598
             cyw43_thread_enter();
633
             cyw43_thread_enter();
599
             enum ble_state state_cached = state;
634
             enum ble_state state_cached = state;
604
             }
639
             }
605
         }
640
         }
606
 
641
 
607
-        // allow some time for service discovery
608
-        watchdog_update();
609
-
610
         cyw43_thread_enter();
642
         cyw43_thread_enter();
611
     }
643
     }
612
 
644
 
654
         uint32_t start_time = to_ms_since_boot(get_absolute_time());
686
         uint32_t start_time = to_ms_since_boot(get_absolute_time());
655
         while (1) {
687
         while (1) {
656
             sleep_ms(1);
688
             sleep_ms(1);
689
+            main_loop_hw();
657
 
690
 
658
             uint32_t now = to_ms_since_boot(get_absolute_time());
691
             uint32_t now = to_ms_since_boot(get_absolute_time());
659
             if ((now - start_time) >= BLE_CHAR_TIMEOUT_MS) {
692
             if ((now - start_time) >= BLE_CHAR_TIMEOUT_MS) {
660
                 debug("timeout waiting for characteristic");
693
                 debug("timeout waiting for characteristic");
661
                 return -5;
694
                 return -5;
662
             }
695
             }
663
-#if BLE_CHAR_TIMEOUT_MS >= (WATCHDOG_PERIOD_MS / 2)
664
-            watchdog_update();
665
-#endif
666
 
696
 
667
             cyw43_thread_enter();
697
             cyw43_thread_enter();
668
             enum ble_state state_cached = state;
698
             enum ble_state state_cached = state;
673
             }
703
             }
674
         }
704
         }
675
 
705
 
676
-        // allow some time for characteristic discovery
677
-        watchdog_update();
678
-
679
         cyw43_thread_enter();
706
         cyw43_thread_enter();
680
     }
707
     }
681
 
708
 
700
     uint32_t start_time = to_ms_since_boot(get_absolute_time());
727
     uint32_t start_time = to_ms_since_boot(get_absolute_time());
701
     while (1) {
728
     while (1) {
702
         sleep_ms(1);
729
         sleep_ms(1);
730
+        main_loop_hw();
703
 
731
 
704
         uint32_t now = to_ms_since_boot(get_absolute_time());
732
         uint32_t now = to_ms_since_boot(get_absolute_time());
705
         if ((now - start_time) >= BLE_WRTE_TIMEOUT_MS) {
733
         if ((now - start_time) >= BLE_WRTE_TIMEOUT_MS) {
706
             debug("timeout waiting for write");
734
             debug("timeout waiting for write");
707
             return -7;
735
             return -7;
708
         }
736
         }
709
-#if BLE_WRTE_TIMEOUT_MS >= (WATCHDOG_PERIOD_MS / 2)
710
-        watchdog_update();
711
-#endif
712
 
737
 
713
         cyw43_thread_enter();
738
         cyw43_thread_enter();
714
         enum ble_state state_cached = state;
739
         enum ble_state state_cached = state;

+ 10
- 3
src/console.c View File

30
 #include "usb_cdc.h"
30
 #include "usb_cdc.h"
31
 #include "usb_msc.h"
31
 #include "usb_msc.h"
32
 #include "debug_disk.h"
32
 #include "debug_disk.h"
33
-#include "console.h"
34
 #include "lipo.h"
33
 #include "lipo.h"
35
 #include "ble.h"
34
 #include "ble.h"
36
 #include "text.h"
35
 #include "text.h"
39
 #include "volcano.h"
38
 #include "volcano.h"
40
 #include "serial.h"
39
 #include "serial.h"
41
 #include "main.h"
40
 #include "main.h"
41
+#include "models.h"
42
+#include "console.h"
42
 
43
 
43
 #define CNSL_BUFF_SIZE 64
44
 #define CNSL_BUFF_SIZE 64
44
 #define CNSL_REPEAT_MS 500
45
 #define CNSL_REPEAT_MS 500
141
         } else {
142
         } else {
142
             println("%d results", n);
143
             println("%d results", n);
143
             for (int i = 0; i < n; i++) {
144
             for (int i = 0; i < n; i++) {
145
+                char info[32] = "";
146
+                enum known_devices dev = models_filter_name(results[i].name);
147
+                if (dev != DEV_UNKNOWN) {
148
+                    models_get_serial(results[i].data, results[i].data_len,
149
+                                      info, sizeof(info));
150
+                }
144
                 uint32_t age = to_ms_since_boot(get_absolute_time()) - results[i].time;
151
                 uint32_t age = to_ms_since_boot(get_absolute_time()) - results[i].time;
145
-                println("addr=%s type=%d rssi=%d age=%.1fs name='%s'",
152
+                println("addr=%s type=%d rssi=%d age=%.1fs name='%s' info='%s'",
146
                         bd_addr_to_str(results[i].addr),
153
                         bd_addr_to_str(results[i].addr),
147
                         results[i].type, results[i].rssi,
154
                         results[i].type, results[i].rssi,
148
-                        age / 1000.0, results[i].name);
155
+                        age / 1000.0, results[i].name, info);
149
             }
156
             }
150
         }
157
         }
151
     } else if (str_startswith(line, "con ")) {
158
     } else if (str_startswith(line, "con ")) {

+ 53
- 0
src/models.c View File

1
+/*
2
+ * models.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 <stddef.h>
20
+#include <string.h>
21
+
22
+#include "config.h"
23
+#include "log.h"
24
+#include "util.h"
25
+#include "models.h"
26
+
27
+enum known_devices models_filter_name(const char *name) {
28
+    if (name == NULL) {
29
+        return DEV_UNKNOWN;
30
+    } else if (strcmp(name, "S&B VOLCANO H") == 0) {
31
+        return DEV_VOLCANO;
32
+    } else if (strcmp(name, "STORZ&BICKEL") == 0) {
33
+        return DEV_VOLCANO;
34
+    } else {
35
+        return DEV_UNKNOWN;
36
+    }
37
+}
38
+
39
+int8_t models_get_serial(const uint8_t *data, size_t data_len, char *buff, size_t buff_len) {
40
+    if ((data == NULL) || (data_len <= 0) || (buff == NULL) || (buff_len <= 0)) {
41
+        return -1;
42
+    }
43
+
44
+    const size_t serial_len = 8;
45
+    const size_t serial_off = 2;
46
+    if ((data_len < (serial_len + serial_off)) || (buff_len < (serial_len + 1))) {
47
+        return -2;
48
+    }
49
+    memcpy(buff, data + serial_off, serial_len);
50
+    buff[serial_len] = '\0';
51
+
52
+    return 0;
53
+}

+ 3
- 0
src/state.c View File

90
     };
90
     };
91
 
91
 
92
     switch (state) {
92
     switch (state) {
93
+    case STATE_INIT:
94
+        break;
95
+
93
     case STATE_SCAN: {
96
     case STATE_SCAN: {
94
         struct ble_scan_result results[BLE_MAX_SCAN_RESULTS] = {0};
97
         struct ble_scan_result results[BLE_MAX_SCAN_RESULTS] = {0};
95
         int n = ble_get_scan_results(results, BLE_MAX_SCAN_RESULTS);
98
         int n = ble_get_scan_results(results, BLE_MAX_SCAN_RESULTS);

Loading…
Cancel
Save