From 1308ae2542226e46b3a21fc56f40376a6a2a4a4d Mon Sep 17 00:00:00 2001 From: schneider <schneider@blinkenlichts.net> Date: Tue, 13 Oct 2020 02:01:55 +0200 Subject: [PATCH] feat(ble): Show peer device name in BLE app --- epicardium/ble/ble_main.c | 11 +++++ epicardium/ble/profiles/gap_api.h | 3 ++ epicardium/ble/profiles/gap_main.c | 18 +++++++ epicardium/epicardium.h | 17 +++++++ preload/apps/ble/__init__.py | 77 +++++++++++++++++------------- pycardium/modules/qstrdefs.h | 1 + pycardium/modules/sys_ble.c | 19 ++++++++ 7 files changed, 113 insertions(+), 33 deletions(-) diff --git a/epicardium/ble/ble_main.c b/epicardium/ble/ble_main.c index 6c69a9f44..a807a3573 100644 --- a/epicardium/ble/ble_main.c +++ b/epicardium/ble/ble_main.c @@ -38,6 +38,7 @@ #include "bas/bas_api.h" #include "hrps/hrps_api.h" #include "rscp/rscp_api.h" +#include "profiles/gap_api.h" #include "cccd.h" #include "ble_api.h" @@ -462,6 +463,7 @@ static void bleClose(bleMsg_t *pMsg) { /* stop battery measurement */ BasMeasBattStop((dmConnId_t) pMsg->hdr.param); + GapClearDeviceName(); } /*************************************************************************************************/ @@ -593,6 +595,15 @@ uint32_t epic_ble_get_compare_value(void) return pair_confirm_value; } +int epic_ble_get_peer_device_name(char *buf, size_t buf_size) +{ + if (AppConnIsOpen() != DM_CONN_ID_NONE) { + return GapGetDeviceName(buf, buf_size); + } else { + return -ENOENT; + } +} + int epic_ble_get_last_pairing_name(char *buf, size_t buf_size) { if(last_pairing == NULL) { diff --git a/epicardium/ble/profiles/gap_api.h b/epicardium/ble/profiles/gap_api.h index 912e9759f..7603dec67 100644 --- a/epicardium/ble/profiles/gap_api.h +++ b/epicardium/ble/profiles/gap_api.h @@ -45,6 +45,9 @@ enum Function Declarations **************************************************************************************************/ +int GapGetDeviceName(char *buf, size_t buf_size); +void GapClearDeviceName(void); + /*************************************************************************************************/ /*! * \brief Perform service and characteristic discovery for GAP service. Note that pHdlList diff --git a/epicardium/ble/profiles/gap_main.c b/epicardium/ble/profiles/gap_main.c index d11aabe1b..c37834c0f 100644 --- a/epicardium/ble/profiles/gap_main.c +++ b/epicardium/ble/profiles/gap_main.c @@ -24,6 +24,8 @@ #include "app_api.h" #include "gap_api.h" +#include <string.h> + /* card10: * copied from lib/sdk/Libraries/BTLE/stack/ble-profiles/sources/profiles/gap/gap_main.c */ @@ -33,6 +35,7 @@ /************************************************************************************************** Local Variables **************************************************************************************************/ +static char dn_value[ATT_DEFAULT_PAYLOAD_LEN + 1]; /*! GAP service characteristics for discovery */ static const attcDiscChar_t gapDn = @@ -66,6 +69,18 @@ static const attcDiscChar_t *gapDiscCharList[] = /* sanity check: make sure handle list length matches characteristic list length */ WSF_CT_ASSERT(GAP_HDL_LIST_LEN == ((sizeof(gapDiscCharList) / sizeof(attcDiscChar_t *)))); +int GapGetDeviceName(char *buf, size_t buf_size) +{ + memset(buf, 0, buf_size); + strncpy(buf, dn_value, buf_size - 1); + return 0; +} + +void GapClearDeviceName(void) +{ + dn_value[0] = 0; +} + /*************************************************************************************************/ /*! * \brief Perform service and characteristic discovery for GAP service. Note that pHdlList @@ -105,6 +120,9 @@ uint8_t GapValueUpdate(uint16_t *pHdlList, attEvt_t *pMsg) /* device name string */ if (pMsg->handle == pHdlList[GAP_DN_HDL_IDX]) { + int len = (pMsg->valueLen < (sizeof(dn_value) - 1)) ? pMsg->valueLen : (sizeof(dn_value) - 1); + memcpy(dn_value, pMsg->pValue, len); + dn_value[len] = '\0'; } /* Central Address Resolution */ else if (pMsg->handle == pHdlList[GAP_CAR_HDL_IDX]) diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h index 92e4ce82d..842714028 100644 --- a/epicardium/epicardium.h +++ b/epicardium/epicardium.h @@ -156,6 +156,8 @@ typedef _Bool bool; #define API_BLE_GET_EVENT 0x143 #define API_BLE_GET_SCAN_REPORT 0x144 #define API_BLE_GET_LAST_PAIRING_NAME 0x145 +#define API_BLE_GET_PEER_DEVICE_NAME 0x146 + /* clang-format on */ @@ -2249,6 +2251,21 @@ API(API_BLE_GET_COMPARE_VALUE, uint32_t epic_ble_get_compare_value(void)); */ API(API_BLE_GET_LAST_PAIRING_NAME, int epic_ble_get_last_pairing_name(char *buf, size_t buf_size)); +/** + * Retrieve the name of the peer to which we are connected + * + * The name might be empty if the peer device does not expose it or + * if it has not yet been read from it. + * + * :return: `0` on success or a negative value if an error occured. Possible + * errors: + * + * - ``-ENOENT``: There is no active connection at the moment. + * + * .. versionadded:: 1.16 + */ +API(API_BLE_GET_PEER_DEVICE_NAME, int epic_ble_get_peer_device_name(char *buf, size_t buf_size)); + /** * Indicate wether the user confirmed the compare value. * diff --git a/preload/apps/ble/__init__.py b/preload/apps/ble/__init__.py index 0287ea5e0..b50a69808 100644 --- a/preload/apps/ble/__init__.py +++ b/preload/apps/ble/__init__.py @@ -7,6 +7,12 @@ import interrupt import config ble_event = None +is_active = False + +STATE_IDLE = 1 +STATE_NUMERIC_COMPARISON = 2 +STATE_WAIT_FOR_COMPLETION = 3 +STATE_FAIL = 4 def ble_callback(_): @@ -36,7 +42,7 @@ def triangle(disp, x, y, left): def toggle(): - if is_active(): + if is_active: config.set_string("ble_enable", "false") else: config.set_string("ble_enable", "true") @@ -49,26 +55,21 @@ def toggle(): os.reset() -def is_active(): - try: - active = config.get_string("ble_enable") - if active == "true" or active == "1": - return True - except OSError: - pass - - return False - - def headline(): disp.print("BLE", posy=0, fg=[0, 255, 255]) - if is_active(): - disp.print("active", posy=20, fg=[0, 255, 0]) + if is_active: + try: + dn = sys_ble.get_peer_device_name() + disp.print("Active", posy=0, posx=50, fg=[0, 255, 0]) + disp.print(dn[:11], posy=20, posx=0, fg=[0, 255, 0]) + except OSError: + disp.print("Ready", posy=0, posx=50, fg=[0, 255, 0]) + mac = load_mac() if mac is not None: disp.print(mac[9:], posy=60, fg=[0, 0, 255]) else: - disp.print("inactive", posy=20, fg=[255, 0, 0]) + disp.print("Off", posy=0, posx=50, fg=[255, 0, 0]) def selector(): @@ -76,9 +77,17 @@ def selector(): disp.print("toggle", posx=25, posy=40, fg=[255, 255, 255]) +try: + active = config.get_string("ble_enable") + if active.lower() == "true" or active == "1": + is_active = True +except OSError: + pass + + init() disp = display.open() -state = 1 +state = STATE_IDLE v_old = buttons.read() while True: @@ -86,55 +95,57 @@ while True: v = ~v_old & v_new v_old = v_new - if state == 1: + if state == STATE_IDLE: # print config screen disp.clear() headline() selector() disp.update() - state = 2 - elif state == 2: + # wait for button press or ble_event if ble_event == sys_ble.EVENT_HANDLE_NUMERIC_COMPARISON: ble_event = None - state = 3 + state = STATE_NUMERIC_COMPARISON if v & buttons.TOP_RIGHT: toggle() - state = 1 - elif state == 3: + elif state == STATE_NUMERIC_COMPARISON: # print confirmation value compare_value = sys_ble.get_compare_value() disp.clear() - disp.print("BLE: Pair?", posy=0, fg=[0, 0, 255]) - disp.print("Code:", posy=20, fg=[0, 255, 255]) + + try: + dn = sys_ble.get_peer_device_name() + disp.print(dn[:11], posy=0, fg=[0, 0, 255]) + except OSError: + pass + disp.print("Pair Code:", posy=20, fg=[0, 255, 255]) disp.print(" %06d" % compare_value, posy=40, fg=[255, 255, 255]) disp.print("Yes", posy=60, fg=[0, 255, 0]) disp.print("No", posx=120, posy=60, fg=[255, 0, 0]) disp.update() - state = 4 - elif state == 4: + # wait for button press or ble_event if ble_event == sys_ble.EVENT_PAIRING_FAILED: ble_event = None - state = 6 + state = STATE_FAIL if v & buttons.BOTTOM_LEFT: sys_ble.confirm_compare_value(True) disp.clear() disp.print("BLE Pairing", posy=0, fg=[0, 0, 255]) disp.print("Please Wait", posy=40, fg=[255, 255, 255]) disp.update() - state = 5 + state = STATE_WAIT_FOR_COMPLETION elif v & (buttons.BOTTOM_RIGHT | buttons.TOP_RIGHT): sys_ble.confirm_compare_value(False) - state = 6 + state = STATE_FAIL - elif state == 5: + elif state == STATE_WAIT_FOR_COMPLETION: # Wait for pairing to complete if ble_event == sys_ble.EVENT_PAIRING_FAILED: ble_event = None - state = 6 + state = STATE_FAIL elif ble_event == sys_ble.EVENT_PAIRING_COMPLETE: ble_event = None pairing_name = sys_ble.get_last_pairing_name().split("/")[-1].split(".")[0] @@ -147,13 +158,13 @@ while True: time.sleep(5) os.exec("main.py") - elif state == 6: + elif state == STATE_FAIL: # display fail screen and wait 5 seconds disp.clear() disp.print("BLE Pairing", posy=0, fg=[0, 0, 255]) disp.print(" Fail", posy=40, fg=[255, 0, 0]) disp.update() time.sleep(5) - state = 1 + state = STATE_IDLE time.sleep(0.1) diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h index da9ba34be..b145dc118 100644 --- a/pycardium/modules/qstrdefs.h +++ b/pycardium/modules/qstrdefs.h @@ -200,6 +200,7 @@ Q(BLE) Q(ble) Q(get_compare_value) Q(get_last_pairing_name) +Q(get_peer_device_name) Q(get_scan_report) Q(confirm_compare_value) Q(set_bondable) diff --git a/pycardium/modules/sys_ble.c b/pycardium/modules/sys_ble.c index 760cae186..7b95d8d4d 100644 --- a/pycardium/modules/sys_ble.c +++ b/pycardium/modules/sys_ble.c @@ -42,6 +42,23 @@ static MP_DEFINE_CONST_FUN_OBJ_0( ble_get_last_pairing_name_obj, mp_ble_get_last_pairing_name ); +static mp_obj_t mp_ble_get_peer_device_name(void) +{ + char device_name_str[32]; + int status = epic_ble_get_peer_device_name( + device_name_str, sizeof(device_name_str) + ); + if (status < 0) { + mp_raise_OSError(-status); + } + + mp_obj_t ret = mp_obj_new_str(device_name_str, strlen(device_name_str)); + return ret; +} +static MP_DEFINE_CONST_FUN_OBJ_0( + ble_get_peer_device_name_obj, mp_ble_get_peer_device_name +); + static mp_obj_t mp_ble_get_scan_report(void) { struct epic_scan_report scan_report; @@ -94,6 +111,8 @@ static const mp_rom_map_elem_t ble_module_globals_table[] = { MP_ROM_PTR(&ble_get_compare_value_obj) }, { MP_ROM_QSTR(MP_QSTR_get_last_pairing_name), MP_ROM_PTR(&ble_get_last_pairing_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_peer_device_name), + MP_ROM_PTR(&ble_get_peer_device_name_obj) }, { MP_ROM_QSTR(MP_QSTR_get_scan_report), MP_ROM_PTR(&ble_get_scan_report_obj) }, { MP_ROM_QSTR(MP_QSTR_get_event), MP_ROM_PTR(&ble_get_event_obj) }, -- GitLab