mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
update esp-idf to v3.0. BLE support - thanks to @jumjum. 2500 vars. Erase flash before flashing
This commit is contained in:
parent
c5921bd803
commit
883000cf81
11
ChangeLog
11
ChangeLog
@ -1,4 +1,15 @@
|
||||
ESP32: update esp-idf to v3.0. BLE support - thanks to @jumjum. Erase flash before flashing
|
||||
Allow Crypto SHA1 without SHA256/512 (for Original & ESP8266 where flash is scarce)
|
||||
Add better docs for the form of Wifi callback functions
|
||||
Modify ESP8266/ESP32 callbacks to match the node.js style used elsewhere
|
||||
nRF52: fix pin.toggle() on software-negated pins
|
||||
Pixl.js: Reorder pins so 0..13 are also D0..13 for better Arduino compatibility
|
||||
Fix dump() when used with code written using E.setBootCode(..), (fix #1398)
|
||||
Allow parseInt/parseFloat to be used on very large strings if the number doesn't extend right to the end (fix #1397)
|
||||
nRF5x: Fix memory leak on NRF.connect
|
||||
Fix memory leak if an exception is thrown within a rejected promise
|
||||
ESP8266: rewrite wifi.save and restore to use the storage lib (imp #1380)
|
||||
ESP8266: Add missing option ssid_hidden for Wifi.startAP() (imp #1358)
|
||||
|
||||
1v97 : nRF52: fix NRF.on('connect',...) issue
|
||||
STM32: Fix setDeviceClockCmd error for USB.setConsole()
|
||||
|
||||
@ -19,7 +19,7 @@ info = {
|
||||
'espruino_page_link' : 'ESP32',
|
||||
'default_console' : "EV_SERIAL1",
|
||||
'default_console_baudrate' : "115200",
|
||||
'variables' : 3000,
|
||||
'variables' : 2500,
|
||||
'binary_name' : 'espruino_%v_esp32.bin',
|
||||
'build' : {
|
||||
'optimizeflags' : '-Og',
|
||||
|
||||
@ -24,7 +24,20 @@
|
||||
|
||||
/// Return true if two UUIDs are equal
|
||||
bool bleUUIDEqual(ble_uuid_t a, ble_uuid_t b) {
|
||||
return a.type==b.type && a.uuid==b.uuid;
|
||||
#ifdef NRF5X
|
||||
return a.type==b.type && a.uuid==b.uuid;
|
||||
#else
|
||||
switch(a.type){
|
||||
case BLE_UUID_TYPE_UNKNOWN:
|
||||
return a.type == b.type;
|
||||
case BLE_UUID_TYPE_BLE:
|
||||
return a.type == b.type && a.uuid == b.uuid;
|
||||
case BLE_UUID_TYPE_128:
|
||||
return a.type == b.type && a.uuid128 == b.uuid128;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
JsVar *bleUUID128ToStr(const uint8_t *data) {
|
||||
@ -52,8 +65,7 @@ JsVar *bleUUIDToStr(ble_uuid_t uuid) {
|
||||
assert(dataLen==16); // it should always be 16 as we checked above
|
||||
return bleUUID128ToStr(&data[0]);
|
||||
#else
|
||||
jsiConsolePrintf("FIXME\n");
|
||||
return 0;
|
||||
return bleUUID128ToStr(&uuid.uuid128);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -163,7 +175,10 @@ const char *bleVarToUUID(ble_uuid_t *uuid, JsVar *v) {
|
||||
}
|
||||
return err_code ? "BLE device error adding UUID" : 0;
|
||||
#else
|
||||
jsiConsolePrintf("FIXME\n");
|
||||
uuid->uuid = ((data[13]<<8) | data[12]);
|
||||
for(int i = 0; i < 16; i++){
|
||||
uuid->uuid128[i] = data[i];
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -44,6 +44,12 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ESP32
|
||||
#include "BLE/esp32_gap_func.h"
|
||||
#include "BLE/esp32_gatts_func.h"
|
||||
#include "BLE/esp32_gattc_func.h"
|
||||
#define BLE_CONN_HANDLE_INVALID -1
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------
|
||||
@ -141,14 +147,16 @@ void jswrap_nrf_init() {
|
||||
|
||||
|
||||
if (jsiStatus & JSIS_COMPLETELY_RESET) {
|
||||
#if defined(USE_NFC) && defined(NFC_DEFAULT_URL)
|
||||
#ifdef USE_NFC
|
||||
#ifdef PUCKJS
|
||||
// By default Puck.js's NFC will send you to the PuckJS website
|
||||
// address is included so Web Bluetooth can connect to the correct one
|
||||
JsVar *addr = jswrap_nrf_bluetooth_getAddress();
|
||||
JsVar *uri = jsvVarPrintf(NFC_DEFAULT_URL"?a=%v", addr);
|
||||
JsVar *uri = jsvVarPrintf("https://puck-js.com/go?a=%v", addr);
|
||||
jsvUnLock(addr);
|
||||
jswrap_nrf_nfcURL(uri);
|
||||
jsvUnLock(uri);
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
#ifdef USE_NFC
|
||||
@ -288,7 +296,7 @@ Called when a host device disconnects from Espruino.
|
||||
"type" : "event",
|
||||
"class" : "NRF",
|
||||
"name" : "servicesDiscover",
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
Called with discovered services when discovery is finished
|
||||
*/
|
||||
@ -296,7 +304,7 @@ Called with discovered services when discovery is finished
|
||||
"type" : "event",
|
||||
"class" : "NRF",
|
||||
"name" : "characteristicsDiscover",
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
Called with discovered characteristics when discovery is finished
|
||||
*/
|
||||
@ -644,9 +652,12 @@ void jswrap_nrf_bluetooth_setAdvertising(JsVar *data, JsVar *options) {
|
||||
err_code = sd_ble_gap_device_name_set(&sec_mode,
|
||||
(const uint8_t *)namePtr,
|
||||
nameLen);
|
||||
#else
|
||||
err_code = 0xDEAD;
|
||||
jsiConsolePrintf("FIXME\n");
|
||||
//#else
|
||||
// err_code = 0xDEAD;
|
||||
// jsiConsolePrintf("FIXME\n");
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
bluetooth_setDeviceName(v);
|
||||
#endif
|
||||
jsble_check_error(err_code);
|
||||
bleChanged = true;
|
||||
@ -728,9 +739,12 @@ void jswrap_nrf_bluetooth_setAdvertising(JsVar *data, JsVar *options) {
|
||||
jsble_advertising_stop();
|
||||
#ifdef NRF5X
|
||||
err_code = sd_ble_gap_adv_data_set((uint8_t *)dPtr, dLen, NULL, 0);
|
||||
#else
|
||||
err_code = 0xDEAD;
|
||||
jsiConsolePrintf("FIXME\n");
|
||||
//#else
|
||||
// err_code = 0xDEAD;
|
||||
// jsiConsolePrintf("FIXME\n");
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
err_code = bluetooth_gap_setAdvertizing(advArray);
|
||||
#endif
|
||||
jsvUnLock(initialArray);
|
||||
jsble_check_error(err_code);
|
||||
@ -754,6 +768,11 @@ the data, it returns the packet that would be advertised as an array.
|
||||
*/
|
||||
JsVar *jswrap_nrf_bluetooth_getAdvertisingData(JsVar *data, JsVar *options) {
|
||||
uint32_t err_code;
|
||||
#ifdef ESP32
|
||||
JsVar *r;
|
||||
r = bluetooth_gap_getAdvertisingData(data,options);
|
||||
return r;
|
||||
#endif
|
||||
#ifdef NRF5X
|
||||
ble_advdata_t advdata;
|
||||
jsble_setup_advdata(&advdata);
|
||||
@ -1922,7 +1941,7 @@ void jswrap_nrf_sendHIDReport(JsVar *data, JsVar *callback) {
|
||||
"type" : "staticmethod",
|
||||
"class" : "NRF",
|
||||
"name" : "requestDevice",
|
||||
"ifdef" : "NRF52",
|
||||
"ifdef" : "NRF52,ESP32",
|
||||
"generate" : "jswrap_nrf_bluetooth_requestDevice",
|
||||
"params" : [
|
||||
["options","JsVar","Options used to filter the device to use"]
|
||||
@ -2110,7 +2129,7 @@ JsVar *jswrap_nrf_bluetooth_requestDevice(JsVar *options) {
|
||||
"type" : "staticmethod",
|
||||
"class" : "NRF",
|
||||
"name" : "connect",
|
||||
"ifdef" : "NRF52",
|
||||
"ifdef" : "NRF52,ESP32",
|
||||
"generate" : "jswrap_nrf_bluetooth_connect",
|
||||
"params" : [
|
||||
["mac","JsVar","The MAC address to connect to"]
|
||||
@ -2213,7 +2232,7 @@ NRF.requestDevice({ filters: [{ name: 'Puck.js abcd' }] }).then(function(device)
|
||||
"type" : "property",
|
||||
"class" : "BluetoothDevice",
|
||||
"name" : "gatt",
|
||||
"ifdef" : "NRF52",
|
||||
"ifdef" : "NRF52,ESP32",
|
||||
"generate" : "jswrap_BluetoothDevice_gatt",
|
||||
"return" : ["JsVar", "A `BluetoothRemoteGATTServer` for this device" ]
|
||||
}
|
||||
@ -2238,7 +2257,7 @@ JsVar *jswrap_BluetoothDevice_gatt(JsVar *parent) {
|
||||
"type" : "method",
|
||||
"class" : "BluetoothRemoteGATTServer",
|
||||
"name" : "connect",
|
||||
"ifdef" : "NRF52",
|
||||
"ifdef" : "NRF52,ESP32",
|
||||
"generate" : "jswrap_nrf_BluetoothRemoteGATTServer_connect",
|
||||
"return" : ["JsVar", "A Promise that is resolved (or rejected) when the connection is complete" ]
|
||||
}
|
||||
@ -2292,7 +2311,7 @@ JsVar *jswrap_nrf_BluetoothRemoteGATTServer_connect(JsVar *parent) {
|
||||
/*JSON{
|
||||
"type" : "class",
|
||||
"class" : "BluetoothRemoteGATTServer",
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
Web Bluetooth-style GATT server - get this using `NRF.connect(address)`
|
||||
or `NRF.requestDevice(options)` and `response.gatt.connect`
|
||||
@ -2304,7 +2323,7 @@ https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattserver
|
||||
"class" : "BluetoothRemoteGATTServer",
|
||||
"name" : "disconnect",
|
||||
"generate" : "jswrap_BluetoothRemoteGATTServer_disconnect",
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
Disconnect from a previously connected BLE device connected with
|
||||
`NRF.connect` - this does not disconnect from something that has
|
||||
@ -2320,7 +2339,12 @@ void jswrap_BluetoothRemoteGATTServer_disconnect(JsVar *parent) {
|
||||
jsble_check_error(err_code);
|
||||
} else {
|
||||
// no connection - try and cancel the connect attempt (assume we have one)
|
||||
#ifdef NRF52
|
||||
err_code = sd_ble_gap_connect_cancel();
|
||||
#endif
|
||||
#ifdef ESP32
|
||||
jsWarn("connect cancel not implemented yet\n");
|
||||
#endif
|
||||
// maybe we don't, in which case we don't care about the error code
|
||||
}
|
||||
#else
|
||||
@ -2420,7 +2444,7 @@ JsVar *jswrap_nrf_BluetoothRemoteGATTServer_getSecurityStatus(JsVar *parent) {
|
||||
"generate" : "jswrap_BluetoothRemoteGATTServer_getPrimaryService",
|
||||
"params" : [ ["service","JsVar","The service UUID"] ],
|
||||
"return" : ["JsVar", "A Promise that is resolved (or rejected) when the primary service is found (the argument contains a `BluetoothRemoteGATTService`)" ],
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
See `NRF.connect` for usage examples.
|
||||
*/
|
||||
@ -2452,7 +2476,7 @@ JsVar *jswrap_BluetoothRemoteGATTServer_getPrimaryService(JsVar *parent, JsVar *
|
||||
"name" : "getPrimaryServices",
|
||||
"generate" : "jswrap_BluetoothRemoteGATTServer_getPrimaryServices",
|
||||
"return" : ["JsVar", "A Promise that is resolved (or rejected) when the primary services are found (the argument contains an array of `BluetoothRemoteGATTService`)" ],
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
*/
|
||||
JsVar *jswrap_BluetoothRemoteGATTServer_getPrimaryServices(JsVar *parent) {
|
||||
@ -2479,7 +2503,7 @@ JsVar *jswrap_BluetoothRemoteGATTServer_getPrimaryServices(JsVar *parent) {
|
||||
"params" : [
|
||||
["callback","JsVar","The callback to call with the RSSI value, or undefined to stop"]
|
||||
],
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
|
||||
Start/stop listening for RSSI values on the active GATT connection
|
||||
@ -2513,7 +2537,7 @@ void jswrap_BluetoothRemoteGATTServer_setRSSIHandler(JsVar *parent, JsVar *callb
|
||||
/*JSON{
|
||||
"type" : "class",
|
||||
"class" : "BluetoothRemoteGATTService",
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
Web Bluetooth-style GATT service - get this using `BluetoothRemoteGATTServer.getPrimaryService(s)`
|
||||
|
||||
@ -2526,7 +2550,7 @@ https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice
|
||||
"generate" : "jswrap_BluetoothRemoteGATTService_getCharacteristic",
|
||||
"params" : [ ["characteristic","JsVar","The characteristic UUID"] ],
|
||||
"return" : ["JsVar", "A Promise that is resolved (or rejected) when the characteristic is found (the argument contains a `BluetoothRemoteGATTCharacteristic`)" ],
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
See `NRF.connect` for usage examples.
|
||||
*/
|
||||
@ -2558,7 +2582,7 @@ JsVar *jswrap_BluetoothRemoteGATTService_getCharacteristic(JsVar *parent, JsVar
|
||||
"name" : "getCharacteristics",
|
||||
"generate" : "jswrap_BluetoothRemoteGATTService_getCharacteristics",
|
||||
"return" : ["JsVar", "A Promise that is resolved (or rejected) when the characteristic is found (the argument contains an array of `BluetoothRemoteGATTCharacteristic`)" ],
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
*/
|
||||
JsVar *jswrap_BluetoothRemoteGATTService_getCharacteristics(JsVar *parent) {
|
||||
@ -2581,7 +2605,7 @@ JsVar *jswrap_BluetoothRemoteGATTService_getCharacteristics(JsVar *parent) {
|
||||
/*JSON{
|
||||
"type" : "class",
|
||||
"class" : "BluetoothRemoteGATTCharacteristic",
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
Web Bluetooth-style GATT characteristic - get this using `BluetoothRemoteGATTService.getCharacteristic(s)`
|
||||
|
||||
@ -2639,11 +2663,10 @@ JsVar *jswrap_nrf_BluetoothRemoteGATTCharacteristic_writeValue(JsVar *characteri
|
||||
"name" : "readValue",
|
||||
"generate" : "jswrap_nrf_BluetoothRemoteGATTCharacteristic_readValue",
|
||||
"return" : ["JsVar", "A Promise that is resolved (or rejected) with a `DataView` when the characteristic is read" ],
|
||||
"ifdef" : "NRF52"
|
||||
"ifdef" : "NRF52,ESP32"
|
||||
}
|
||||
|
||||
Read a characteristic's value, return a promise containing a `DataView` with the data in it
|
||||
|
||||
Read a characteristic's value, return a promise containing a `DataView`
|
||||
|
||||
```
|
||||
var device;
|
||||
|
||||
@ -33,6 +33,7 @@ typedef enum {
|
||||
#define BLETASK_IS_CENTRAL(x) ((x)>=BLETASK_CENTRAL_START && ((x)<=BLETASK_CENTRAL_END))
|
||||
|
||||
extern JsVar *bleTaskInfo; // info related to the current task
|
||||
extern JsVar *blePromise; //defined here, used in jswrap_bluetooth.c and in ESP32 relevant bluetooth
|
||||
bool bleInTask(BleTask task);
|
||||
BleTask bleGetCurrentTask();
|
||||
bool bleNewTask(BleTask task, JsVar *taskInfo);
|
||||
|
||||
@ -121,3 +121,23 @@ $(ESP_IDF_PATH)/components/esp32/libhal.a \
|
||||
-lapp_update \
|
||||
-lstdc++ \
|
||||
-lgcc
|
||||
|
||||
#needed for using ifdef in wrapper JSON
|
||||
DEFINES += -DESP32
|
||||
|
||||
ifdef USE_BLUETOOTH
|
||||
SOURCES+= targets/esp32/bluetooth.c \
|
||||
targets/esp32/BLE/esp32_bluetooth_utils.c \
|
||||
targets/esp32/BLE/esp32_gap_func.c \
|
||||
targets/esp32/BLE/esp32_gatts_func.c \
|
||||
targets/esp32/BLE/esp32_gattc_func.c
|
||||
INCLUDE+= -I$(ESP_IDF_PATH)/components/bt/bluedroid/include \
|
||||
-I$(ESP_IDF_PATH)/components/bt/bluedroid/api/include \
|
||||
-I$(ESP_IDF_PATH)/components/bt/bluedroid/bta/include \
|
||||
-I$(ESP_IDF_PATH)/components/bt/bluedroid/stack/include \
|
||||
-I$(ESP_IDF_PATH)/components/bt/bluedroid/stack/gatt/include \
|
||||
-I$(ESP_IDF_PATH)/components/bt/bluedroid/osi/include
|
||||
LDFLAGS+= -L$(ESP_APP_TEMPLATE_PATH)/build/components/bt/bluedroid/api \
|
||||
-L$(ESP_APP_TEMPLATE_PATH)/build/components/bt/bluedroid/bta
|
||||
endif
|
||||
|
||||
|
||||
@ -176,15 +176,14 @@ def get_jsondata(is_for_document, parseArgs = True, board = False):
|
||||
if ("ifndef" in jsondata) and (jsondata["ifndef"] in defines):
|
||||
print(dropped_prefix+" because of #ifndef "+jsondata["ifndef"])
|
||||
drop = True
|
||||
if ("ifdef" in jsondata) and not (jsondata["ifdef"] in defines):
|
||||
print(dropped_prefix+" because of #ifdef "+jsondata["ifdef"])
|
||||
drop = True
|
||||
if ("ifdef" in jsondata):
|
||||
ifdefs = jsondata["ifdef"].encode('ascii','ignore').split(",")
|
||||
if(not [val for val in defines if val in ifdefs]):
|
||||
print(dropped_prefix+" because of #ifdef "+jsondata["ifdef"])
|
||||
drop = True
|
||||
if ("#ifdef" in jsondata) or ("#ifndef" in jsondata):
|
||||
sys.stderr.write( "'#ifdef' where 'ifdef' should be used in " + jsonstring + " - "+str(sys.exc_info()[0]) + "\n" )
|
||||
exit(1)
|
||||
if ("if" in jsondata):
|
||||
sys.stderr.write( "'if' where '#if' should be used in " + jsonstring + " - "+str(sys.exc_info()[0]) + "\n" )
|
||||
exit(1)
|
||||
if ("#if" in jsondata):
|
||||
expr = jsondata["#if"]
|
||||
for defn in defines:
|
||||
@ -371,8 +370,7 @@ def get_ifdef_description(d):
|
||||
if d=="SAVE_ON_FLASH_EXTREME": return "devices with extremely low flash memory (eg. HYSTM32_28)"
|
||||
if d=="STM32": return "STM32 devices (including Espruino Original, Pico and WiFi)"
|
||||
if d=="STM32F1": return "STM32F1 devices (including Original Espruino Board)"
|
||||
if d=="NRF52": return "NRF52 devices (like Puck.js, Pixl.js and MDBT42Q)"
|
||||
if d=="PIXLJS": return "Pixl.js boards"
|
||||
if d=="NRF52": return "NRF52 devices (like Puck.js and Pixl.js)"
|
||||
if d=="ESPRUINOWIFI": return "Espruino WiFi boards"
|
||||
if d=="ESP8266": return "ESP8266 devices running Espruino"
|
||||
if d=="ESP32": return "ESP32 devices"
|
||||
@ -380,15 +378,12 @@ def get_ifdef_description(d):
|
||||
if d=="USE_LCD_SDL": return "Linux with SDL support compiled in"
|
||||
if d=="USE_TLS": return "devices with TLS and SSL support (Espruino Pico and Espruino WiFi only)"
|
||||
if d=="RELEASE": return "release builds"
|
||||
if d=="DEBUG": return "debug builds"
|
||||
if d=="LINUX": return "Linux-based builds"
|
||||
if d=="BLUETOOTH": return "devices with Bluetooth LE capability"
|
||||
if d=="USB": return "devices with USB"
|
||||
if d=="USE_USB_HID": return "devices that support USB HID (Espruino Pico and Espruino WiFi)"
|
||||
if d=="USE_AES": return "devices that support AES (Espruino Pico, Espruino WiFi or Linux)"
|
||||
if d=="USE_SHA256": return "devices that support SHA256 (Espruino Pico, Espruino WiFi, Espruino BLE devices or Linux)"
|
||||
if d=="USE_SHA512": return "devices that support SHA512 (Espruino Pico, Espruino WiFi, Espruino BLE devices or Linux)"
|
||||
if d=="USE_CRYPTO": return "devices that support Crypto Functionality (Espruino Pico, Original, Espruino WiFi, Espruino BLE devices, Linux or ESP8266)"
|
||||
if d=="USE_CRYPTO": return "devices that support Crypto Functionality (Espruino Pico, Espruino WiFi, Linux or ESP8266)"
|
||||
if d=="USE_FLASHFS": return "devices with filesystem in Flash support enabled (ESP32 only)"
|
||||
if d=="USE_TERMINAL": return "devices with VT100 terminal emulation enabled (Pixl.js only)"
|
||||
print("WARNING: Unknown ifdef '"+d+"' in common.get_ifdef_description")
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
..\..\..\esp-idf\components\esptool_py\esptool\esptool.py --chip esp32 --port COM3 --baud 921600 --before esp32r0 --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x100000 blank.bin
|
||||
REM ..\..\..\esp-idf\components\esptool_py\esptool\esptool.py --chip esp32 --port COM3 --baud 921600 --after soft_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x100000 blank.bin
|
||||
..\..\..\esp-idf\components\esptool_py\esptool\esptool.py --chip esp32 --port COM3 --baud 921600 erase_region 0x100000 0x10000
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
pause
|
||||
)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
..\..\..\esp-idf\components\esptool_py\esptool\esptool.py --chip esp32 --baud 921600 --before esp32r0 --after hard_reset --port COM3 --baud 921600 erase_flash
|
||||
..\..\..\esp-idf\components\esptool_py\esptool\esptool.py --chip esp32 --baud 921600 --after hard_reset --port COM3 --baud 921600 erase_flash
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
pause
|
||||
)
|
||||
|
||||
292
targets/esp32/BLE/esp32_bluetooth_utils.c
Normal file
292
targets/esp32/BLE/esp32_bluetooth_utils.c
Normal file
@ -0,0 +1,292 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2017 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* ESP32 specific Bluetooth utils
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "BLE/esp32_bluetooth_utils.h"
|
||||
#include "BLE/esp32_gap_func.h"
|
||||
#include "BLE/esp32_gatts_func.h"
|
||||
#include "BLE/esp32_gattc_func.h"
|
||||
#include "bt.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_gatt_common_api.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "jsvariterator.h"
|
||||
|
||||
int bleEventDebug = 0;
|
||||
|
||||
typedef enum{
|
||||
ESP_BLE_DEBUG_GAP = 1,
|
||||
ESP_BLE_DEBUG_GATTS = 2,
|
||||
ESP_BLE_DEBUG_GATTC = 4
|
||||
} esp_ble_debug_t;
|
||||
|
||||
esp_err_t initController(){
|
||||
esp_err_t ret;
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
ret = esp_bt_controller_init(&bt_cfg);if(ret) {jsWarn("init controller failed:%x\n",ret); return ret;}
|
||||
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);if(ret) {jsWarn("enable controller failed:%x\n",ret); return ret;}
|
||||
return ret;
|
||||
}
|
||||
esp_err_t initBluedroid(){
|
||||
esp_err_t ret;
|
||||
ret = esp_bluedroid_init();if (ret) {jsWarn("init bluedroid failed:%x\n",ret);return ret;}
|
||||
ret = esp_bluedroid_enable();if (ret) {jsWarn("enable bluedroid failed:%x\n",ret);return ret;}
|
||||
return ret;
|
||||
}
|
||||
esp_err_t deinitController(){
|
||||
esp_err_t ret;
|
||||
ret = esp_bt_controller_disable(); if (ret) {jsWarn("disable bluetooth failed:%x\n"); return ret;}
|
||||
ret = esp_bt_controller_deinit(); if (ret) {jsWarn("deinit bluetooth failed:%x\n"); return ret;}
|
||||
return ret;
|
||||
}
|
||||
esp_err_t deinitBluedroid(){
|
||||
esp_err_t ret;
|
||||
ret = esp_bluedroid_disable();if (ret) {jsWarn("disable bluedroid failed:%x\n",ret);return ret;}
|
||||
ret = esp_bluedroid_deinit();if (ret) {jsWarn("deinit bluedroid failed:%x\n",ret);return ret;}
|
||||
return ret;
|
||||
}
|
||||
esp_err_t registerCallbacks(){
|
||||
esp_err_t ret;
|
||||
ret = esp_ble_gap_register_callback(gap_event_handler);if (ret){jsWarn("gap register error:%x\n", ret);return ret;}
|
||||
ret = esp_ble_gatts_register_callback(gatts_event_handler);if(ret){jsWarn("gatts register error:%x\n", ret);return ret;}
|
||||
ret = esp_ble_gattc_register_callback(gattc_event_handler);if(ret){jsWarn("gattc regigister error:%x\n",ret);return ret;}
|
||||
return ret;
|
||||
}
|
||||
esp_err_t setMtu(){
|
||||
esp_err_t ret;
|
||||
ret = esp_ble_gatt_set_local_mtu(500);if(ret)jsWarn("set local MTU failed:%x\n",ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JsVar *bda2JsVarString(esp_bd_addr_t bda){
|
||||
JsVar *s = jsvVarPrintf("%02x:%02x:%02x:%02x:%02x:%02x",bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]);
|
||||
return s;
|
||||
}
|
||||
|
||||
void ESP32_setBLE_Debug(int level){
|
||||
bleEventDebug = level;
|
||||
}
|
||||
static char *gattsEvent2String(esp_gatts_cb_event_t event){
|
||||
switch(event){
|
||||
case 0: return "REG";
|
||||
case 1: return "READ";
|
||||
case 2: return "WRITE";
|
||||
case 3: return "EXEC_WRITE";
|
||||
case 4: return "MTU";
|
||||
case 5: return "CONF";
|
||||
case 6: return "UNREG";
|
||||
case 7: return "CREATE";
|
||||
case 8: return "ADD_INCL_SRVC";
|
||||
case 9: return "ADD_CHAR";
|
||||
case 10: return "ADD_CHAR_DESCR";
|
||||
case 11: return "DELETE";
|
||||
case 12: return "START";
|
||||
case 13: return "STOP";
|
||||
case 14: return "CONNECT";
|
||||
case 15: return "DISCONNECT";
|
||||
case 16: return "OPEN";
|
||||
case 17: return "CANCEL_OPEN";
|
||||
case 18: return "CLOSE";
|
||||
case 19: return "LISTEN";
|
||||
case 20: return "CONGEST";
|
||||
case 21: return "RESPONSE";
|
||||
case 22: return "CREAT_ATTR_TAB";
|
||||
case 23: return "CREAT_ATTR_TAB";
|
||||
}
|
||||
return "unknown GattsEvent";
|
||||
}
|
||||
static char *gattcEvent2String(esp_gattc_cb_event_t event){
|
||||
switch(event){
|
||||
case 0: return "REG";
|
||||
case 1: return "UNREG";
|
||||
case 2: return "OPEN";
|
||||
case 3: return "READ_CHAR";
|
||||
case 4: return "WRITE_CHAR";
|
||||
case 5: return "CLOSE";
|
||||
case 6: return "SEARCH_CMPL";
|
||||
case 7: return "SEARCH_RES";
|
||||
case 8: return "READ_DESCR";
|
||||
case 9: return "WRITE_DESCR";
|
||||
case 10: return "NOTIFY";
|
||||
case 11: return "PREP_WRITE";
|
||||
case 12: return "EXEC";
|
||||
case 13: return "ACL";
|
||||
case 14: return "CANCEL_OPEN";
|
||||
case 15: return "SRVC_CHG";
|
||||
case 17: return "ENC_CMPL_CB";
|
||||
case 18: return "CFG_MTU";
|
||||
case 19: return "ADV_DATA";
|
||||
case 20: return "MULT_ADV_ENB";
|
||||
case 21: return "ADV_ADV_UPD";
|
||||
case 22: return "MULT_ADV_DATA";
|
||||
case 23: return "MULT_ADV_DIS";
|
||||
case 24: return "CONGEST";
|
||||
case 25: return "BTH_SCAN_ENB";
|
||||
case 26: return "BTH_SCAN_CFG";
|
||||
case 27: return "BTH_SCAN_RD";
|
||||
case 28: return "BTH_SCAN_THR";
|
||||
case 29: return "BTH_SCAN_PARAM";
|
||||
case 30: return "BTH_SCAN_DIS";
|
||||
case 31: return "SCAN_FLT_CFG";
|
||||
case 32: return "SCAN_FLT_PARAM";
|
||||
case 33: return "SCAN_FLT_STATUS";
|
||||
case 34: return "ADV_VSC";
|
||||
case 38: return "REG_FOR_NOTIFY";
|
||||
case 39: return "UNREG_FOR_NOTIFY";
|
||||
case 40: return "CONNECT";
|
||||
case 41: return "DISCONNECT";
|
||||
case 42: return "READ_MUTIPLE";
|
||||
case 43: return "QUEUE_FULL";
|
||||
}
|
||||
return "unknown GattcEvent";
|
||||
}
|
||||
static char *gapEvent2String(esp_gap_ble_cb_event_t event){
|
||||
switch(event){
|
||||
case 0: return "ADV_DATA_SET_COMPLETE";
|
||||
case 1: return "SCAN_RSP_DATA_SET_COMPLETE";
|
||||
case 2: return "SCAN_PARAM_SET_COMPLETE";
|
||||
case 3: return "SCAN_RESULT";
|
||||
case 4: return "ADV_DATA_RAW_SET_COMPLETE";
|
||||
case 5: return "SCAN_RSP_DATA_RAW_SET_COMPLETE";
|
||||
case 6: return "ADV_START_COMPLETE";
|
||||
case 7: return "SCAN_START_COMPLETE";
|
||||
case 8: return "AUTH_CMPL";
|
||||
case 9: return "KEY";
|
||||
case 10: return "SEC_REQ";
|
||||
case 11: return "PASSKEY_NOTIF";
|
||||
case 12: return "PASSKEY_REQ";
|
||||
case 13: return "OOB_REQ";
|
||||
case 14: return "LOCAL_IR";
|
||||
case 15: return "LOCAL_ER";
|
||||
case 16: return "NC_REQ";
|
||||
case 17: return "ADV_STOP_COMPLETE";
|
||||
case 18: return "SCAN_STOP_COMPLETE";
|
||||
case 19: return "SET_STATIC_RAND_ADDR";
|
||||
case 20: return "UPDATE_CONN_PARAMS";
|
||||
case 21: return "SET_PKT_LENGTH_COMPLETE";
|
||||
case 22: return "SET_LOCAL_PRIVACY_COMPLETE";
|
||||
case 23: return "REMOVE_BOND_DEV_COMPLETE";
|
||||
case 24: return "CLEAR_BOND_DEV_COMPLETE";
|
||||
case 25: return "GET_BOND_DEV_COMPLETE_EVT";
|
||||
case 26: return "READ_RSSI_COMPLETE";
|
||||
case 27: return "UPDATE_WHITELIST_COMPLETE";
|
||||
}
|
||||
return "unknown GapEvent";
|
||||
}
|
||||
|
||||
void jsWarnGattsEvent(esp_gatts_cb_event_t event,esp_gatt_if_t gatts_if){
|
||||
if(bleEventDebug & ESP_BLE_DEBUG_GATTS)
|
||||
jsWarn("Event:ESP_GATTS_%s_EVT gatts_if:%d\n",gattsEvent2String(event), gatts_if);
|
||||
}
|
||||
void jsWarnGattcEvent(esp_gattc_cb_event_t event,esp_gatt_if_t gattc_if){
|
||||
if(bleEventDebug & ESP_BLE_DEBUG_GATTC)
|
||||
jsWarn("Event:ESP_GATTC_%s_EVT gattc_if:%d\n",gattcEvent2String(event), gattc_if);
|
||||
}
|
||||
void jsWarnGapEvent(esp_gap_ble_cb_event_t event){
|
||||
if(bleEventDebug & ESP_BLE_DEBUG_GAP)
|
||||
jsWarn("Event:ESP_GAP_BLE_%s_EVT\n",gapEvent2String(event));
|
||||
}
|
||||
|
||||
void jsWarnUUID(esp_bt_uuid_t char_uuid){
|
||||
if (char_uuid.len == ESP_UUID_LEN_16) {
|
||||
jsWarn("- - - Char UUID16: %x", char_uuid.uuid.uuid16);
|
||||
} else if (char_uuid.len == ESP_UUID_LEN_32) {
|
||||
jsWarn("- - - Char UUID32: %x", char_uuid.uuid.uuid32);
|
||||
} else if (char_uuid.len == ESP_UUID_LEN_128) {
|
||||
jsWarn("- - - Char UUID128: %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", char_uuid.uuid.uuid128[0],
|
||||
char_uuid.uuid.uuid128[1], char_uuid.uuid.uuid128[2], char_uuid.uuid.uuid128[3],
|
||||
char_uuid.uuid.uuid128[4], char_uuid.uuid.uuid128[5], char_uuid.uuid.uuid128[6],
|
||||
char_uuid.uuid.uuid128[7], char_uuid.uuid.uuid128[8], char_uuid.uuid.uuid128[9],
|
||||
char_uuid.uuid.uuid128[10], char_uuid.uuid.uuid128[11], char_uuid.uuid.uuid128[12],
|
||||
char_uuid.uuid.uuid128[13], char_uuid.uuid.uuid128[14], char_uuid.uuid.uuid128[15]);
|
||||
} else {
|
||||
jsWarn("- - - Char UNKNOWN LEN %d\n", char_uuid.len);
|
||||
}
|
||||
}
|
||||
void jsWarnBDA(uint8_t *bda){
|
||||
jsWarn("bda %02x:%02x:%02x:%02x:%02x:%02x\n",bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]);
|
||||
}
|
||||
void jsWarnHeap(char * whereAmI){
|
||||
jsWarn("%s Heap:%d, jsVars:%d\n",whereAmI,esp_get_free_heap_size(),jsvGetMemoryUsage());
|
||||
}
|
||||
|
||||
void bleGetHiddenName(char *eventName, char *hiddenName, uint16_t pos){
|
||||
strcpy(eventName,hiddenName);
|
||||
itostr(pos,&eventName[strlen(eventName)],16);
|
||||
}
|
||||
bool bleRemoveChild(JsVar *parent, JsVar *blevar){
|
||||
bool ret = false;
|
||||
JsvObjectIterator it;
|
||||
jsvObjectIteratorNew(&it, parent);
|
||||
while (jsvObjectIteratorHasValue(&it)) {
|
||||
JsVar *child = jsvObjectIteratorGetKey(&it);
|
||||
JsVar *name = jsvNewFromStringVar(child, 0, 10);
|
||||
if(jsvIsEqual(name,blevar)){
|
||||
jsvRemoveChild(parent,child);
|
||||
ret = true;
|
||||
}
|
||||
jsvUnLock(child);
|
||||
jsvUnLock(name);
|
||||
jsvObjectIteratorNext(&it);
|
||||
}
|
||||
jsvObjectIteratorFree(&it);
|
||||
return ret;
|
||||
}
|
||||
void bleRemoveChilds(JsVar *parent){
|
||||
JsVar *blevar = jsvNewFromString(BLE_CHAR_VALUE);
|
||||
while(bleRemoveChild(parent,blevar)){}
|
||||
jsvUnLock(blevar);
|
||||
}
|
||||
|
||||
void bleuuid_TO_espbtuuid(ble_uuid_t ble_uuid,esp_bt_uuid_t *esp_uuid){
|
||||
switch(ble_uuid.type){
|
||||
case BLE_UUID_TYPE_UNKNOWN:
|
||||
jsError("empty UUID type\n");
|
||||
break;
|
||||
case BLE_UUID_TYPE_BLE:
|
||||
esp_uuid->len = ESP_UUID_LEN_16;
|
||||
esp_uuid->uuid.uuid16 = ble_uuid.uuid;
|
||||
break;
|
||||
case BLE_UUID_TYPE_128:
|
||||
esp_uuid->len = ESP_UUID_LEN_128;
|
||||
for(int i = 0; i < 16; i++){
|
||||
esp_uuid->uuid.uuid128[i] = ble_uuid.uuid128[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
jsError("unknown UUID TYPE\n");
|
||||
}
|
||||
}
|
||||
void bleuuid_To_uuid128(ble_uuid_t ble_uuid,uint8_t *ble128){
|
||||
uint8_t tmp[] = {0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00};
|
||||
switch (ble_uuid.type){
|
||||
case BLE_UUID_TYPE_UNKNOWN:
|
||||
jsError("empty UUID type\n");
|
||||
break;
|
||||
case BLE_UUID_TYPE_BLE:
|
||||
for(int i = 0; i < 16; i++){
|
||||
ble128[i] = tmp[i];
|
||||
}
|
||||
ble128[12] = ble_uuid.uuid & 0xff;
|
||||
ble128[13] = ble_uuid.uuid >> 8;
|
||||
break;
|
||||
case BLE_UUID_TYPE_128:
|
||||
for(int i = 0; i < 16; i++){
|
||||
ble128[i] = ble_uuid.uuid128[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
jsError("unknown UUID type\n");
|
||||
}
|
||||
}
|
||||
57
targets/esp32/BLE/esp32_bluetooth_utils.h
Normal file
57
targets/esp32/BLE/esp32_bluetooth_utils.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2017 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* ESP32 specific Bluetooth utils
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef ESP32_BLUETOOTH_UTILS_H_
|
||||
#define ESP32_BLUETOOTH_UTILS_H_
|
||||
|
||||
#include "jsvar.h"
|
||||
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_gatts_api.h"
|
||||
#include "esp_gattc_api.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
|
||||
#include "bluetooth.h"
|
||||
|
||||
#define BLE_WRITE_EVENT JS_EVENT_PREFIX"blewv"
|
||||
#define BLE_READ_EVENT JS_EVENT_PREFIX"blerv"
|
||||
#define BLE_CONNECT_EVENT JS_EVENT_PREFIX"connect"
|
||||
#define BLE_DISCONNECT_EVENT JS_EVENT_PREFIX"disconnect"
|
||||
|
||||
#define BLE_CHAR_VALUE "BLE_CHAR_V"
|
||||
|
||||
esp_err_t initController();
|
||||
esp_err_t initBluedroid();
|
||||
esp_err_t deinitController();
|
||||
esp_err_t deinitBluedroid();
|
||||
esp_err_t registerCallbacks();
|
||||
esp_err_t setMtu();
|
||||
|
||||
JsVar *bda2JsVarString(uint8_t *ble_adv);
|
||||
|
||||
void ESP32_setBLE_Debug(int level);
|
||||
void jsWarnGattsEvent(esp_gatts_cb_event_t event,esp_gatt_if_t gatts_if);
|
||||
void jsWarnGattcEvent(esp_gattc_cb_event_t event,esp_gatt_if_t gatts_if);
|
||||
void jsWarnGapEvent(esp_gap_ble_cb_event_t event);
|
||||
|
||||
void jsWarnBDA(uint8_t *bda);
|
||||
void jsWarnUUID(esp_bt_uuid_t char_uuid);
|
||||
void jsWarnHeap(char * whereAmI);
|
||||
|
||||
void bleGetHiddenName(char *eventName, char *hiddenName, uint16_t pos);
|
||||
void bleRemoveChilds(JsVar *parent);
|
||||
|
||||
void bleuuid_TO_espbtuuid(ble_uuid_t ble_uuid,esp_bt_uuid_t *esp_uuid);
|
||||
void bleuuid_To_uuid128(ble_uuid_t ble_uuid,uint8_t *ble128);
|
||||
|
||||
#endif /* ESP32_BLUETOOTH_UTILS_H_ */
|
||||
279
targets/esp32/BLE/esp32_gap_func.c
Normal file
279
targets/esp32/BLE/esp32_gap_func.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2017 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* ESP32 specific GAP functions
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "esp_wifi.h"
|
||||
#include "BLE/esp32_gap_func.h"
|
||||
#include "BLE/esp32_gatts_func.h"
|
||||
#include "BLE/esp32_bluetooth_utils.h"
|
||||
|
||||
#include "jsutils.h"
|
||||
#include "jsparse.h"
|
||||
#include "jsinteractive.h"
|
||||
#include "jshardware.h"
|
||||
#include "bluetooth_utils.h"
|
||||
|
||||
#define adv_config_flag (1 << 0)
|
||||
#define scan_rsp_config_flag (1 << 1)
|
||||
#define BT_BD_ADDR_HEX(addr) addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
|
||||
#define GAP_SCAN_FUNC "gap_scan_func"
|
||||
|
||||
static uint8_t adv_config_done = 0;
|
||||
|
||||
static esp_ble_adv_params_t adv_params = {
|
||||
.adv_int_min = 0x20,
|
||||
.adv_int_max = 0x40,
|
||||
.adv_type = ADV_TYPE_IND,
|
||||
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||
//.peer_addr =
|
||||
//.peer_addr_type =
|
||||
.channel_map = ADV_CHNL_ALL,
|
||||
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
|
||||
};
|
||||
|
||||
static esp_ble_scan_params_t ble_scan_params = {
|
||||
.scan_type = BLE_SCAN_TYPE_ACTIVE,
|
||||
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
||||
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
|
||||
.scan_interval = 0x50,
|
||||
.scan_window = 0x30
|
||||
};
|
||||
|
||||
static esp_ble_adv_data_t adv_data = {
|
||||
.set_scan_rsp = false,
|
||||
.include_name = true,
|
||||
.include_txpower = true,
|
||||
.min_interval = 0x20,
|
||||
.max_interval = 0x40,
|
||||
.appearance = 0x00,
|
||||
.manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN,
|
||||
.p_manufacturer_data = NULL, //&test_manufacturer[0],
|
||||
.service_data_len = 0,
|
||||
.p_service_data = NULL,
|
||||
.service_uuid_len = 0, //needs to be set before used
|
||||
.p_service_uuid = &adv_service_uuid128,
|
||||
.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
|
||||
};
|
||||
|
||||
static void execScanFunc(esp_ble_gap_cb_param_t *p){
|
||||
JsVar *evt = jsvNewObject();
|
||||
jsvObjectSetChildAndUnLock(evt, "id", bda2JsVarString(p->scan_rst.bda));
|
||||
jsvObjectSetChildAndUnLock(evt, "rssi",jsvNewFromInteger(p->scan_rst.rssi));
|
||||
JsVar *data = jsvNewStringOfLength(p->scan_rst.adv_data_len, (char*)p->scan_rst.ble_adv);
|
||||
if(data){
|
||||
JsVar *ab = jsvNewArrayBufferFromString(data,p->scan_rst.adv_data_len);
|
||||
jsvUnLock(data);
|
||||
jsvObjectSetChildAndUnLock(evt,"data",ab);
|
||||
}
|
||||
jsiQueueObjectCallbacks(execInfo.root, BLE_SCAN_EVENT, &evt,1);
|
||||
jsvUnLock(evt);
|
||||
jshHadEvent();
|
||||
}
|
||||
|
||||
void gap_event_scan_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param){
|
||||
uint8_t *adv_name = NULL;
|
||||
uint8_t adv_name_len = 0;
|
||||
esp_ble_gap_cb_param_t *p = (esp_ble_gap_cb_param_t *)param;
|
||||
switch(event){
|
||||
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:{
|
||||
if (param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {jsWarn("Scan start failed:d\n",param->scan_start_cmpl.status);}
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_SCAN_RESULT_EVT:{
|
||||
execScanFunc(param);
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:{
|
||||
if (param->scan_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){jsWarn("Scan stop failed");}
|
||||
else {jsWarn("Stop scan successfully");}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param){
|
||||
jsWarnGapEvent(event);
|
||||
switch (event) {
|
||||
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:{
|
||||
adv_config_done &= (~adv_config_flag);
|
||||
if (adv_config_done == 0){
|
||||
esp_ble_gap_start_advertising(&adv_params);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:{
|
||||
adv_config_done &= (~scan_rsp_config_flag);
|
||||
if (adv_config_done == 0){
|
||||
esp_ble_gap_start_advertising(&adv_params);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:{
|
||||
if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
|
||||
jsWarn("Advertising start failed\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:{
|
||||
if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) {
|
||||
jsWarn("Advertising stop failed\n");
|
||||
}
|
||||
else {
|
||||
jsWarn("Stop adv successfully\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:{
|
||||
jsWarn("update connetion params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d",
|
||||
param->update_conn_params.status,
|
||||
param->update_conn_params.min_int,
|
||||
param->update_conn_params.max_int,
|
||||
param->update_conn_params.conn_int,
|
||||
param->update_conn_params.latency,
|
||||
param->update_conn_params.timeout);
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
gap_event_scan_handler(event,param);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bluetooth_gap_setScan(bool enable){
|
||||
jsWarn("--- gap_setScan %x\n",enable);
|
||||
esp_err_t status;
|
||||
status = esp_ble_gap_set_scan_params(&ble_scan_params);
|
||||
if (status){ jsWarn("gap set scan error code = %x", status);return;}
|
||||
if(enable == true){
|
||||
status = esp_ble_gap_start_scanning(30);
|
||||
if (status != ESP_OK) jsWarn("esp_ble_gap_start_scanning: rc=%d", status);
|
||||
}
|
||||
else{
|
||||
status = esp_ble_gap_stop_scanning();
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t bluetooth_gap_startAdvertizing(bool enable){
|
||||
if(enable){
|
||||
return esp_ble_gap_start_advertising(&adv_params);
|
||||
}
|
||||
else{
|
||||
return esp_ble_gap_stop_advertising();
|
||||
}
|
||||
}
|
||||
|
||||
int addAdvertisingData(uint8_t *advData,int pnt,int idx,JsVar *value){
|
||||
int len = 0;
|
||||
JSV_GET_AS_CHAR_ARRAY(dPtr,dLen,value);
|
||||
len = 4 + dLen;
|
||||
advData[pnt++] = 3 + dLen;
|
||||
advData[pnt++] = 22;
|
||||
advData[pnt++] = idx & 255;
|
||||
advData[pnt++] = idx >> 8;
|
||||
for(int i = 0; i < dLen; i++){ advData[pnt++] = dPtr[i];}
|
||||
return len;
|
||||
}
|
||||
|
||||
int addAdvertisingDeviceName(uint8_t *advData,int pnt){
|
||||
JsVar *deviceName;
|
||||
deviceName = jsvObjectGetChild(execInfo.hiddenRoot, BLE_DEVICE_NAME, 0);
|
||||
JSV_GET_AS_CHAR_ARRAY(namePtr, nameLen, deviceName);
|
||||
if(nameLen > 0){
|
||||
if((nameLen + pnt + 2) > BLE_GAP_ADV_MAX_SIZE){
|
||||
nameLen = BLE_GAP_ADV_MAX_SIZE - 2 - pnt;
|
||||
advData[pnt] = nameLen + 1;
|
||||
advData[pnt + 1] = 8;
|
||||
}
|
||||
else{
|
||||
advData[pnt] = nameLen + 1;
|
||||
advData[pnt + 1] = 9;
|
||||
}
|
||||
for(int i = 0; i < nameLen; i++) advData[pnt + i + 2] = namePtr[i];
|
||||
}
|
||||
jsvUnLock(deviceName);
|
||||
return nameLen + 2;
|
||||
}
|
||||
|
||||
JsVar *bluetooth_gap_getAdvertisingData(JsVar *data, JsVar *options){
|
||||
uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE];
|
||||
int i = 0;
|
||||
if(jsvIsArray(data) || jsvIsArrayBuffer(data)){
|
||||
return jsvLockAgain(data);
|
||||
} else if(jsvIsObject(data)){
|
||||
encoded_advdata[i++] = 2;
|
||||
encoded_advdata[i++] = 1;
|
||||
encoded_advdata[i++] = 6; //todo add support of showName == false
|
||||
JsvObjectIterator it;
|
||||
jsvObjectIteratorNew(&it, data);
|
||||
while(jsvObjectIteratorHasValue(&it)){
|
||||
JsVar *value = jsvObjectIteratorGetValue(&it);
|
||||
int idx = jsvGetIntegerAndUnLock(jsvObjectIteratorGetKey(&it));
|
||||
i = i + addAdvertisingData(&encoded_advdata,i,idx,value);
|
||||
jsvUnLock(value);
|
||||
jsvObjectIteratorNext(&it);
|
||||
}
|
||||
jsvObjectIteratorFree(&it);
|
||||
//todo add support of manufacturerData
|
||||
i = i + addAdvertisingDeviceName(&encoded_advdata,i);
|
||||
}
|
||||
else if (!jsvIsUndefined(data)){
|
||||
jsExceptionHere(JSET_TYPEERROR, "Expecting object array or undefined, got %t",data);
|
||||
return 0;
|
||||
}
|
||||
return jsvNewArrayBufferWithData(i,encoded_advdata);
|
||||
}
|
||||
|
||||
esp_err_t bluetooth_gap_setAdvertizing(JsVar *advArray){
|
||||
esp_err_t ret;
|
||||
if(!advArray){
|
||||
adv_data.service_uuid_len = ble_service_cnt * 16;
|
||||
ret = esp_ble_gap_config_adv_data(&adv_data);
|
||||
}
|
||||
else{
|
||||
JSV_GET_AS_CHAR_ARRAY(advPtr, advLen, advArray);
|
||||
ret = esp_ble_gap_config_adv_data_raw(advPtr, advLen);
|
||||
}
|
||||
if (ret){
|
||||
jsWarn("config adv data failed, error code = %x", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t bluetooth_setDeviceName(JsVar *deviceName){
|
||||
esp_err_t r;
|
||||
jsvObjectSetOrRemoveChild(execInfo.hiddenRoot, BLE_DEVICE_NAME, deviceName);
|
||||
JSV_GET_AS_CHAR_ARRAY(namePtr, nameLen, deviceName);
|
||||
r = esp_ble_gap_set_device_name((uint8_t *)namePtr);
|
||||
return r;
|
||||
}
|
||||
|
||||
void bluetooth_initDeviceName(){
|
||||
char deviceName[14];
|
||||
strcpy(deviceName,"ESP32.js 0123");
|
||||
uint8_t macnr[6];
|
||||
esp_wifi_get_mac(WIFI_IF_STA, macnr);
|
||||
deviceName[9] = itoch((macnr[4]>>4)&15);
|
||||
deviceName[10] = itoch(macnr[4]&15);
|
||||
deviceName[11] = itoch((macnr[5]>>4)&15);
|
||||
deviceName[12] = itoch(macnr[5]&15);
|
||||
deviceName[13] = '\0';
|
||||
jsvObjectSetChild(execInfo.hiddenRoot, BLE_DEVICE_NAME,jsvNewFromString(deviceName));
|
||||
}
|
||||
|
||||
36
targets/esp32/BLE/esp32_gap_func.h
Normal file
36
targets/esp32/BLE/esp32_gap_func.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2017 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* ESP32 specific GAP functions
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef GAP_FUNC_H_
|
||||
#define GAP_FUNC_H_
|
||||
|
||||
#include "esp_gap_ble_api.h"
|
||||
|
||||
#include "jsvar.h"
|
||||
|
||||
#define BLE_DEVICE_NAME "BLE_DEV_N"
|
||||
|
||||
void bluetooth_gap_setScan(bool enabled);
|
||||
|
||||
//esp_err_t bluetooth_setDeviceName(uint8_t *deviceName);
|
||||
esp_err_t bluetooth_setDeviceName(JsVar *deviceName);
|
||||
void bluetooth_initDeviceName();
|
||||
|
||||
esp_err_t bluetooth_gap_startAdvertizing(bool enable);
|
||||
esp_err_t bluetooth_gap_setAdvertizing(JsVar *advArray);
|
||||
|
||||
JsVar *bluetooth_gap_getAdvertisingData(JsVar *data, JsVar *options);
|
||||
|
||||
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
|
||||
|
||||
#endif /* GAP_FUNC_H_ */
|
||||
247
targets/esp32/BLE/esp32_gattc_func.c
Normal file
247
targets/esp32/BLE/esp32_gattc_func.c
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2017 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* ESP32 specific GATT client functions
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "BLE/esp32_gattc_func.h"
|
||||
#include "BLE/esp32_bluetooth_utils.h"
|
||||
|
||||
#include "bluetooth_utils.h"
|
||||
#include "jswrap_bluetooth.h"
|
||||
|
||||
#include "jsvar.h"
|
||||
#include "jsutils.h"
|
||||
#include "jsparse.h"
|
||||
#include "jsinteractive.h"
|
||||
|
||||
#define GATTC_PROFILE 0
|
||||
#define INVALID_HANDLE 0
|
||||
|
||||
static struct gattc_profile_inst gattc_apps[1] = {
|
||||
[GATTC_PROFILE] = {
|
||||
.gattc_cb = gattc_event_handler,
|
||||
.gattc_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
|
||||
}
|
||||
};
|
||||
static esp_bt_uuid_t serviceFilter = {
|
||||
.len = ESP_UUID_LEN_16,
|
||||
.uuid = {.uuid16 = 0,},
|
||||
};
|
||||
static esp_bt_uuid_t charFilter = {
|
||||
.len = ESP_UUID_LEN_16,
|
||||
.uuid = {.uuid16 = 0}
|
||||
};
|
||||
static bool get_server = false;
|
||||
static esp_gattc_char_elem_t *char_elem_result = NULL;
|
||||
static esp_gattc_descr_elem_t *descr_elem_result = NULL;
|
||||
|
||||
void gattc_evt_reg(esp_gatt_if_t gattc_if,esp_ble_gattc_cb_param_t *param){
|
||||
gattc_apps[param->reg.app_id].gattc_if = gattc_if;
|
||||
}
|
||||
void gattc_evt_connect(esp_gatt_if_t gattc_if,esp_ble_gattc_cb_param_t *param){
|
||||
esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;
|
||||
gattc_apps[GATTC_PROFILE].conn_id = p_data->connect.conn_id;
|
||||
m_central_conn_handle = 0x01;
|
||||
memcpy(gattc_apps[GATTC_PROFILE].remote_bda, p_data->connect.remote_bda, sizeof(esp_bd_addr_t));
|
||||
esp_err_t mtu_ret = esp_ble_gattc_send_mtu_req (gattc_if, p_data->connect.conn_id);
|
||||
if (mtu_ret){jsWarn("config MTU error, error code = %x", mtu_ret);}
|
||||
}
|
||||
void gattc_evt_disconnect(esp_gatt_if_t gattc_if,esp_ble_gattc_cb_param_t *param){
|
||||
m_central_conn_handle = BLE_GATT_HANDLE_INVALID;
|
||||
}
|
||||
void gattc_evt_cfg_mtu(esp_gatt_if_t gattc_if,esp_ble_gattc_cb_param_t *param){
|
||||
if (!bleTaskInfo) bleTaskInfo = jsvNewEmptyArray();
|
||||
jsvObjectSetChildAndUnLock(bleTaskInfo,"connected", jsvNewFromBool(true));
|
||||
bleCompleteTaskSuccess(BLETASK_CONNECT, bleTaskInfo);
|
||||
}
|
||||
void gattc_evt_search_cmpl(){
|
||||
if(get_server){
|
||||
if (!bleTaskInfo) bleTaskInfo = jsvNewEmptyArray();
|
||||
JsVar *o = jspNewObject(0,"BluetoothRemoteGATTService");
|
||||
jsvObjectSetChildAndUnLock(o,"uuid",jsvVarPrintf("0x%04x",serviceFilter.uuid.uuid16));
|
||||
jsvObjectSetChildAndUnLock(o,"isPrimary",jsvNewFromBool(true));
|
||||
jsvObjectSetChildAndUnLock(o,"start_handle",jsvNewFromInteger(gattc_apps[GATTC_PROFILE].service_start_handle));
|
||||
jsvObjectSetChildAndUnLock(o,"end_handle",jsvNewFromInteger(gattc_apps[GATTC_PROFILE].service_end_handle));
|
||||
jsvArrayPushAndUnLock(bleTaskInfo,o);
|
||||
JsVar *t = jsvSkipNameAndUnLock(jsvArrayPopFirst(bleTaskInfo));
|
||||
jsvUnLock(bleTaskInfo);
|
||||
bleTaskInfo = t;
|
||||
if(bleTaskInfo) bleCompleteTaskSuccess(BLETASK_PRIMARYSERVICE,bleTaskInfo);
|
||||
else bleCompleteTaskFailAndUnLock(BLETASK_PRIMARYSERVICE,jsvNewFromString("No Services found"));
|
||||
}
|
||||
}
|
||||
void gattc_evt_search_res(esp_gatt_if_t gattc_if,esp_ble_gattc_cb_param_t *param){
|
||||
esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;
|
||||
esp_gatt_srvc_id_t *srvc_id =(esp_gatt_srvc_id_t *)&p_data->search_res.srvc_id;
|
||||
if (srvc_id->id.uuid.len == ESP_UUID_LEN_16 && srvc_id->id.uuid.uuid.uuid16 == serviceFilter.uuid.uuid16) {
|
||||
get_server = true;
|
||||
gattc_apps[GATTC_PROFILE].service_start_handle = p_data->search_res.start_handle;
|
||||
gattc_apps[GATTC_PROFILE].service_end_handle = p_data->search_res.end_handle;
|
||||
}
|
||||
}
|
||||
void gattc_evt_read_char(esp_gatt_if_t gattc_if,esp_ble_gattc_cb_param_t *param){
|
||||
esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;
|
||||
JsVar *data = jsvNewDataViewWithData(p_data->read.value_len,(unsigned char*)p_data->read.value);
|
||||
jsvObjectSetChild(bleTaskInfo,"value",data);
|
||||
bleCompleteTaskSuccessAndUnLock(BLETASK_CHARACTERISTIC_READ,data);
|
||||
}
|
||||
void gattc_evt_write_char(esp_gatt_if_t gattc_if,esp_ble_gattc_cb_param_t *param){
|
||||
bleCompleteTaskSuccess(BLETASK_CHARACTERISTIC_WRITE,0);
|
||||
}
|
||||
|
||||
void gattc_init(){
|
||||
esp_err_t ret;
|
||||
ret = esp_ble_gattc_app_register(GATTC_PROFILE);if(ret){jsWarn("gattc register app error:%x\n",ret);return;}
|
||||
}
|
||||
void gattc_reset(){
|
||||
esp_err_t ret;
|
||||
if(gattc_apps[GATTC_PROFILE].gattc_if != ESP_GATT_IF_NONE){
|
||||
ret = esp_ble_gattc_app_unregister(gattc_apps[GATTC_PROFILE].gattc_if);
|
||||
if(ret) jsWarn("could not unregister GATTC(%d)\n",ret);
|
||||
}
|
||||
m_central_conn_handle = BLE_GATT_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) {
|
||||
jsWarnGattcEvent(event,gattc_if);
|
||||
esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;
|
||||
JsVar *args[1];
|
||||
switch (event) {
|
||||
case ESP_GATTC_REG_EVT: gattc_evt_reg(gattc_if,param);break;
|
||||
case ESP_GATTC_CONNECT_EVT: gattc_evt_connect(gattc_if,param);break;
|
||||
case ESP_GATTC_CFG_MTU_EVT: gattc_evt_cfg_mtu(gattc_if,param);break;
|
||||
case ESP_GATTC_SEARCH_CMPL_EVT: gattc_evt_search_cmpl(gattc_if,param);break;
|
||||
case ESP_GATTC_SEARCH_RES_EVT: gattc_evt_search_res(gattc_if,param);break;
|
||||
case ESP_GATTC_READ_CHAR_EVT: gattc_evt_read_char(gattc_if,param);break;
|
||||
case ESP_GATTC_WRITE_CHAR_EVT: gattc_evt_write_char(gattc_if,param);break;
|
||||
|
||||
case ESP_GATTC_UNREG_EVT: break;
|
||||
case ESP_GATTC_OPEN_EVT: break;
|
||||
case ESP_GATTC_CLOSE_EVT: break;
|
||||
case ESP_GATTC_READ_DESCR_EVT: break;
|
||||
case ESP_GATTC_WRITE_DESCR_EVT: break;
|
||||
case ESP_GATTC_NOTIFY_EVT: break;
|
||||
case ESP_GATTC_PREP_WRITE_EVT: break;
|
||||
case ESP_GATTC_EXEC_EVT: break;
|
||||
case ESP_GATTC_ACL_EVT: break;
|
||||
case ESP_GATTC_CANCEL_OPEN_EVT: break;
|
||||
case ESP_GATTC_SRVC_CHG_EVT: break;
|
||||
case ESP_GATTC_ENC_CMPL_CB_EVT: break;
|
||||
case ESP_GATTC_ADV_DATA_EVT: break;
|
||||
case ESP_GATTC_MULT_ADV_ENB_EVT: break;
|
||||
case ESP_GATTC_MULT_ADV_UPD_EVT: break;
|
||||
case ESP_GATTC_MULT_ADV_DATA_EVT: break;
|
||||
case ESP_GATTC_MULT_ADV_DIS_EVT: break;
|
||||
case ESP_GATTC_CONGEST_EVT: break;
|
||||
case ESP_GATTC_BTH_SCAN_ENB_EVT: break;
|
||||
case ESP_GATTC_BTH_SCAN_CFG_EVT: break;
|
||||
case ESP_GATTC_BTH_SCAN_RD_EVT: break;
|
||||
case ESP_GATTC_BTH_SCAN_THR_EVT: break;
|
||||
case ESP_GATTC_BTH_SCAN_PARAM_EVT: break;
|
||||
case ESP_GATTC_BTH_SCAN_DIS_EVT: break;
|
||||
case ESP_GATTC_SCAN_FLT_CFG_EVT: break;
|
||||
case ESP_GATTC_SCAN_FLT_PARAM_EVT: break;
|
||||
case ESP_GATTC_SCAN_FLT_STATUS_EVT: break;
|
||||
case ESP_GATTC_ADV_VSC_EVT: break;
|
||||
case ESP_GATTC_REG_FOR_NOTIFY_EVT: break;
|
||||
case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: break;
|
||||
case ESP_GATTC_DISCONNECT_EVT: break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void reverseBDA(uint8_t *bda){
|
||||
int x,t,n;
|
||||
n = 5;
|
||||
for(x = 0; x < n;) {
|
||||
t = bda[x];
|
||||
bda[x] = bda[n];
|
||||
bda[n] = t;
|
||||
x++;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
void gattc_connect(uint8_t *addr){
|
||||
esp_err_t ret;
|
||||
reverseBDA(addr);
|
||||
jsError("new parameter in esp_ble_gattc_open ???\n");
|
||||
//ret = esp_ble_gattc_open(gattc_apps[GATTC_PROFILE].gattc_if,addr,true);
|
||||
}
|
||||
uint32_t gattc_disconnect(uint16_t conn_handle){
|
||||
esp_err_t ret;
|
||||
ret = esp_ble_gattc_close(gattc_apps[GATTC_PROFILE].gattc_if,gattc_apps[GATTC_PROFILE].conn_id);
|
||||
return ret;
|
||||
}
|
||||
void gattc_searchService(ble_uuid_t uuid){
|
||||
bleuuid_TO_espbtuuid(uuid,&serviceFilter);
|
||||
esp_ble_gattc_search_service(gattc_apps[GATTC_PROFILE].gattc_if, gattc_apps[GATTC_PROFILE].conn_id, &serviceFilter);
|
||||
}
|
||||
void gattc_getCharacteristic(ble_uuid_t char_uuid){
|
||||
uint16_t count = 0;
|
||||
bleuuid_TO_espbtuuid(char_uuid,&charFilter);
|
||||
esp_ble_gattc_get_attr_count(
|
||||
gattc_apps[GATTC_PROFILE].gattc_if, gattc_apps[GATTC_PROFILE].conn_id,ESP_GATT_DB_CHARACTERISTIC,
|
||||
gattc_apps[GATTC_PROFILE].service_start_handle,gattc_apps[GATTC_PROFILE].service_end_handle,
|
||||
INVALID_HANDLE,&count);
|
||||
if(count > 0) {
|
||||
if (!bleTaskInfo) bleTaskInfo = jsvNewEmptyArray();
|
||||
char_elem_result = (esp_gattc_char_elem_t *)malloc(sizeof(esp_gattc_char_elem_t) * count);
|
||||
esp_ble_gattc_get_char_by_uuid(
|
||||
gattc_apps[GATTC_PROFILE].gattc_if, gattc_apps[GATTC_PROFILE].conn_id,
|
||||
gattc_apps[GATTC_PROFILE].service_start_handle,gattc_apps[GATTC_PROFILE].service_end_handle,
|
||||
charFilter,char_elem_result,&count);
|
||||
if(count > 0){
|
||||
//check with more than one character in service
|
||||
gattc_apps[GATTC_PROFILE].char_handle = char_elem_result[0].char_handle;
|
||||
JsVar *o = jspNewObject(0,"BluetoothRemoteGATTCharacteristic");
|
||||
if(o) {
|
||||
jsvObjectSetChildAndUnLock(o,"uuid",jsvVarPrintf("%04x",char_elem_result[0].uuid.uuid.uuid16));
|
||||
jsvObjectSetChildAndUnLock(o,"handle_value",jsvNewFromInteger(char_elem_result[0].char_handle));
|
||||
JsVar *p = jsvNewObject();
|
||||
if(p){
|
||||
jsvObjectSetChildAndUnLock(p,"broadcast",jsvNewFromBool(char_elem_result[0].properties & ESP_GATT_CHAR_PROP_BIT_BROADCAST));
|
||||
jsvObjectSetChildAndUnLock(p,"read",jsvNewFromBool(char_elem_result[0].properties & ESP_GATT_CHAR_PROP_BIT_READ));
|
||||
jsvObjectSetChildAndUnLock(p,"writeWithoutResponse",jsvNewFromBool(char_elem_result[0].properties & ESP_GATT_CHAR_PROP_BIT_WRITE_NR));
|
||||
jsvObjectSetChildAndUnLock(p,"write",jsvNewFromBool(char_elem_result[0].properties & ESP_GATT_CHAR_PROP_BIT_WRITE));
|
||||
jsvObjectSetChildAndUnLock(p,"notify",jsvNewFromBool(char_elem_result[0].properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY));
|
||||
jsvObjectSetChildAndUnLock(p,"indicate",jsvNewFromBool(char_elem_result[0].properties & ESP_GATT_CHAR_PROP_BIT_INDICATE));
|
||||
jsvObjectSetChildAndUnLock(p,"authenticatedSignedWrites",jsvNewFromBool(char_elem_result[0].properties & ESP_GATT_CHAR_PROP_BIT_AUTH));
|
||||
jsvObjectSetChildAndUnLock(o,"properties",p);
|
||||
}
|
||||
}
|
||||
jsvArrayPushAndUnLock(bleTaskInfo,o);
|
||||
}
|
||||
free(char_elem_result);
|
||||
}
|
||||
JsVar *t = jsvSkipNameAndUnLock(jsvArrayPopFirst(bleTaskInfo));
|
||||
jsvUnLock(bleTaskInfo);
|
||||
bleTaskInfo = t;
|
||||
if (bleTaskInfo) bleCompleteTaskSuccess(BLETASK_CHARACTERISTIC, bleTaskInfo);
|
||||
else bleCompleteTaskFailAndUnLock(BLETASK_CHARACTERISTIC, jsvNewFromString("No Characteristics found"));
|
||||
}
|
||||
void gattc_readValue(uint16_t charHandle){
|
||||
// check for connected
|
||||
esp_ble_gattc_read_char(gattc_apps[GATTC_PROFILE].gattc_if,gattc_apps[GATTC_PROFILE].conn_id,
|
||||
charHandle,ESP_GATT_AUTH_REQ_NONE);
|
||||
}
|
||||
void gattc_writeValue(uint16_t charHandle,char *data,size_t dataLen){
|
||||
esp_ble_gattc_write_char(gattc_apps[GATTC_PROFILE].gattc_if,gattc_apps[GATTC_PROFILE].conn_id,
|
||||
charHandle,dataLen,data,ESP_GATT_WRITE_TYPE_RSP,ESP_GATT_AUTH_REQ_NONE);
|
||||
}
|
||||
void gattc_readDesc(uint16_t charHandle){
|
||||
esp_ble_gattc_read_char_descr (gattc_apps[GATTC_PROFILE].gattc_if,gattc_apps[GATTC_PROFILE].conn_id,
|
||||
charHandle,ESP_GATT_AUTH_REQ_NONE);
|
||||
}
|
||||
|
||||
46
targets/esp32/BLE/esp32_gattc_func.h
Normal file
46
targets/esp32/BLE/esp32_gattc_func.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2017 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* ESP32 specific GATT Client functions
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef GATTC_FUNC_H_
|
||||
#define GATTC_FUNC_H_
|
||||
|
||||
#include "esp_gattc_api.h"
|
||||
|
||||
#include "jsvar.h"
|
||||
|
||||
#include "bluetooth.h"
|
||||
|
||||
struct gattc_profile_inst {
|
||||
esp_gattc_cb_t gattc_cb;
|
||||
uint16_t gattc_if;
|
||||
uint16_t app_id;
|
||||
uint16_t conn_id;
|
||||
uint16_t service_start_handle;
|
||||
uint16_t service_end_handle;
|
||||
uint16_t char_handle;
|
||||
esp_bd_addr_t remote_bda;
|
||||
};
|
||||
|
||||
void gattc_init();
|
||||
void gattc_reset();
|
||||
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gattc_cb_param_t *param);
|
||||
void gattc_connect(uint8_t *addr);
|
||||
uint32_t gattc_disconnect(uint16_t conn_handle);
|
||||
//void gattc_searchService(uint16_t service_uuid);
|
||||
void gattc_searchService(ble_uuid_t uuid);
|
||||
void gattc_getCharacteristic(ble_uuid_t char_uuid);
|
||||
void gattc_readValue(uint16_t charHandle);
|
||||
void gattc_writeValue(uint16_t charHandle,char *data,size_t dataLen);
|
||||
void gattc_readDesc(uint16_t charHandle);
|
||||
|
||||
#endif /* GATTC_FUNC_H_ */
|
||||
554
targets/esp32/BLE/esp32_gatts_func.c
Normal file
554
targets/esp32/BLE/esp32_gatts_func.c
Normal file
@ -0,0 +1,554 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2017 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* ESP32 specific GATT functions
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "BLE/esp32_gatts_func.h"
|
||||
#include "BLE/esp32_gap_func.h"
|
||||
#include "BLE/esp32_bluetooth_utils.h"
|
||||
|
||||
#include "bluetooth.h"
|
||||
#include "bluetooth_utils.h"
|
||||
|
||||
#include "jsutils.h"
|
||||
#include "jsparse.h"
|
||||
#include "jsinteractive.h"
|
||||
|
||||
ble_uuid_t uart_service_uuid = {
|
||||
.type = BLE_UUID_TYPE_128,
|
||||
.uuid128 = {0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,0xa3,0xb5,0x01,0x00,0x40,0x6e}
|
||||
};
|
||||
esp_bt_uuid_t uart_char_rx_uuid = {
|
||||
.len = ESP_UUID_LEN_128,
|
||||
.uuid.uuid128 = {0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,0xa3,0xb5,0x02,0x00,0x40,0x6e}
|
||||
};
|
||||
esp_bt_uuid_t uart_char_tx_uuid = {
|
||||
.len = ESP_UUID_LEN_128,
|
||||
.uuid.uuid128 = {0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,0xa3,0xb5,0x03,0x00,0x40,0x6e}
|
||||
};
|
||||
esp_bt_uuid_t uart_tx_descr = {
|
||||
.len = ESP_UUID_LEN_16,
|
||||
.uuid.uuid16 = 0x2902
|
||||
};
|
||||
uint8_t uart_advice[18] = {0x11,0x07,0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,0xa3,0xb5,0x01,0x00,0x40,0x6e,};
|
||||
|
||||
JsVar *gatts_services;
|
||||
uint16_t ble_service_pos = -1;JsvObjectIterator ble_service_it;//ble_service_cnt is defined in .h
|
||||
uint16_t ble_char_pos = -1;JsvObjectIterator ble_char_it;uint16_t ble_char_cnt = 0;
|
||||
uint16_t ble_descr_pos = -1;JsvObjectIterator ble_descr_it;uint16_t ble_descr_cnt = 0;
|
||||
|
||||
struct gatts_service_inst *gatts_service = NULL;
|
||||
struct gatts_char_inst *gatts_char = NULL;
|
||||
struct gatts_descr_inst *gatts_descr = NULL;
|
||||
|
||||
bool _removeValues;
|
||||
|
||||
void jshSetDeviceInitialised(IOEventFlags device, bool isInit);
|
||||
|
||||
esp_gatt_if_t uart_gatts_if;
|
||||
uint16_t uart_tx_handle;
|
||||
bool uart_gatts_connected = false;
|
||||
|
||||
uint8_t *getUartAdvice(){
|
||||
return uart_advice;
|
||||
}
|
||||
void gatts_sendNotification(int c){
|
||||
uint8_t data[2];
|
||||
data[0] = (uint8_t)c;
|
||||
data[1] = 0;
|
||||
if(uart_gatts_if != ESP_GATT_IF_NONE){
|
||||
esp_ble_gatts_send_indicate(uart_gatts_if, 0, uart_tx_handle, 1, data, false);
|
||||
}
|
||||
}
|
||||
|
||||
void emitNRFEvent(char *event,JsVar *args,int argCnt){
|
||||
JsVar *nrf = jsvObjectGetChild(execInfo.root, "NRF", 0);
|
||||
if(nrf){
|
||||
JsVar *eventName = jsvNewFromString(event);
|
||||
JsVar *callback = jsvSkipNameAndUnLock(jsvFindChildFromVar(nrf,eventName,0));
|
||||
jsvUnLock(eventName);
|
||||
if(callback) jsiQueueEvents(nrf,callback,args,argCnt);
|
||||
jsvUnLock(nrf);
|
||||
jsvUnLock(callback);
|
||||
if(args) jsvUnLockMany(argCnt,args);
|
||||
}
|
||||
else {jsWarn("sorry, no NRF Object found"); }
|
||||
}
|
||||
|
||||
int getIndexFromGatts_if(esp_gatt_if_t gatts_if){
|
||||
for(int i = 0; i < ble_service_cnt;i++){
|
||||
if(gatts_service[i].gatts_if == gatts_if) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void gatts_read_value_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
|
||||
esp_gatt_rsp_t rsp; JsVar *charValue;
|
||||
memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
|
||||
rsp.attr_value.handle = param->read.handle;
|
||||
for (uint32_t pos=0;pos < ble_char_cnt;pos++) {
|
||||
if (gatts_char[pos].char_handle==param->read.handle) {
|
||||
char hiddenName[12];
|
||||
bleGetHiddenName(hiddenName,BLE_READ_EVENT,pos);
|
||||
JsVar *readCB = jsvObjectGetChild(execInfo.hiddenRoot,hiddenName,0);
|
||||
if(readCB){
|
||||
charValue = jspExecuteFunction(readCB,0,0,0);
|
||||
jsvUnLock(readCB);
|
||||
}
|
||||
else {
|
||||
char hiddenName[12];
|
||||
bleGetHiddenName(hiddenName,BLE_CHAR_VALUE,pos);
|
||||
charValue = jsvObjectGetChild(execInfo.hiddenRoot,hiddenName,0);
|
||||
}
|
||||
if(charValue){
|
||||
JSV_GET_AS_CHAR_ARRAY(vPtr,vLen,charValue);
|
||||
for(uint16_t valpos = 0; valpos < vLen; valpos++){
|
||||
rsp.attr_value.value[valpos] = vPtr[valpos];
|
||||
}
|
||||
rsp.attr_value.len = vLen;
|
||||
jsvUnLock(charValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (uint32_t pos=0;pos < ble_descr_cnt;pos++) {
|
||||
if (gatts_descr[pos].descr_handle==param->read.handle) {
|
||||
if(gatts_descr[pos].descrVal){
|
||||
JSV_GET_AS_CHAR_ARRAY(vPtr,vLen,gatts_descr[pos].descrVal);
|
||||
for(uint16_t descrpos = 0; descrpos < vLen; descrpos++){rsp.attr_value.value[descrpos] = vPtr[descrpos];}
|
||||
rsp.attr_value.len = vLen;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id, ESP_GATT_OK, &rsp);
|
||||
}
|
||||
static void gatts_write_value_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
|
||||
for(uint16_t pos = 0; pos < ble_char_cnt; pos++){
|
||||
if(gatts_char[pos].char_handle == param->write.handle){
|
||||
char hiddenName[12];
|
||||
bleGetHiddenName(hiddenName,BLE_CHAR_VALUE,pos);
|
||||
jsvObjectSetChildAndUnLock(execInfo.hiddenRoot,hiddenName,
|
||||
jsvNewStringOfLength(param->write.len,param->write.value));
|
||||
bleGetHiddenName(hiddenName,BLE_WRITE_EVENT,pos);
|
||||
JsVar *writeCB = jsvObjectGetChild(execInfo.hiddenRoot,hiddenName,0);
|
||||
if(writeCB){
|
||||
JsVar *tmp = jspExecuteFunction(writeCB,0,0,0);
|
||||
if(tmp) jsvUnLock(tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(uint16_t pos = 0; pos < ble_descr_cnt; pos++){
|
||||
if(gatts_descr[pos].descr_handle == param->write.handle){
|
||||
gatts_descr[pos].descrVal = jsvNewStringOfLength(param->write.len,param->write.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
|
||||
}
|
||||
static void gatts_write_nus_value_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
|
||||
jshPushIOCharEvents(EV_BLUETOOTH, (char*)param->write.value, param->write.len);
|
||||
jshHadEvent();
|
||||
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
|
||||
}
|
||||
static void gatts_connect_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
|
||||
int g = getIndexFromGatts_if(gatts_if);
|
||||
if(g >= 0){
|
||||
JsVar *args[1];
|
||||
gatts_service[g].conn_id = param->connect.conn_id;
|
||||
args[0] = bda2JsVarString(param->connect.remote_bda);
|
||||
m_conn_handle = 0x01;
|
||||
emitNRFEvent(BLE_CONNECT_EVENT,args,1);
|
||||
if(gatts_service[g].serviceFlag == BLE_SERVICE_NUS) uart_gatts_connected = true;
|
||||
}
|
||||
}
|
||||
static void gatts_disconnect_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
|
||||
int g = getIndexFromGatts_if(gatts_if);
|
||||
if(g >= 0){
|
||||
JsVar *args[1];
|
||||
gatts_service[g].gatts_if = ESP_GATT_IF_NONE;
|
||||
bluetooth_gap_startAdvertizing(true);
|
||||
args[0] = bda2JsVarString(param->disconnect.remote_bda);
|
||||
m_conn_handle = BLE_GATT_HANDLE_INVALID;
|
||||
emitNRFEvent(BLE_DISCONNECT_EVENT,args,1);
|
||||
if(gatts_service[g].serviceFlag == BLE_SERVICE_NUS) uart_gatts_connected = true;
|
||||
}
|
||||
}
|
||||
void gatts_reg_app(){
|
||||
esp_err_t r;
|
||||
if(ble_service_pos < ble_service_cnt){
|
||||
r = esp_ble_gatts_app_register(ble_service_pos);
|
||||
if(r) jsWarn("app_register error:%d\n",r);
|
||||
}
|
||||
else{
|
||||
bluetooth_gap_startAdvertizing(true);
|
||||
jshSetDeviceInitialised(EV_BLUETOOTH, true);
|
||||
}
|
||||
}
|
||||
void gatts_createService(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param){
|
||||
esp_err_t r;
|
||||
gatts_service[param->reg.app_id].service_id.is_primary = true;
|
||||
gatts_service[param->reg.app_id].service_id.id.inst_id = 0x00;
|
||||
gatts_service[param->reg.app_id].gatts_if = gatts_if;
|
||||
bleuuid_TO_espbtuuid(gatts_service[param->reg.app_id].ble_uuid,&gatts_service[param->reg.app_id].service_id.id);
|
||||
r = esp_ble_gatts_create_service(gatts_if, &gatts_service[param->reg.app_id].service_id, gatts_service[param->reg.app_id].num_handles);
|
||||
if(r) jsWarn("createService error:%d\n",r);
|
||||
}
|
||||
void gatts_add_char(){
|
||||
esp_err_t r;
|
||||
for(uint16_t pos=0; pos < ble_char_cnt; pos++){
|
||||
if(gatts_char[pos].service_pos == ble_service_pos && gatts_char[pos].char_handle == 0){
|
||||
ble_char_pos = pos;
|
||||
r = esp_ble_gatts_add_char(gatts_service[ble_service_pos].service_handle,&gatts_char[pos].char_uuid,
|
||||
gatts_char[pos].char_perm,gatts_char[pos].char_property,
|
||||
NULL,gatts_char[pos].char_control);
|
||||
if(r) jsWarn("add char error:%d\n",r);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ble_service_pos++;
|
||||
gatts_reg_app();
|
||||
}
|
||||
void gatts_add_descr(){
|
||||
esp_err_t r;
|
||||
for(uint16_t pos = 0;pos < ble_descr_cnt; pos++){
|
||||
if(gatts_descr[pos].descr_handle == 0 && gatts_descr[pos].char_pos == ble_char_pos){
|
||||
ble_descr_pos = pos;
|
||||
r = esp_ble_gatts_add_char_descr(gatts_service[ble_service_pos].service_handle,
|
||||
&gatts_descr[pos].descr_uuid,gatts_descr[pos].descr_perm,
|
||||
NULL,gatts_descr[pos].descr_control);
|
||||
if(r) jsWarn("add descr error:%d\n",r);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ble_char_pos++;
|
||||
gatts_add_char();
|
||||
}
|
||||
void gatts_check_add_descr(esp_bt_uuid_t descr_uuid, uint16_t attr_handle){
|
||||
if(attr_handle != 0){
|
||||
gatts_descr[ble_descr_pos].descr_handle=attr_handle;
|
||||
}
|
||||
gatts_add_descr(); // try to add more descriptors
|
||||
}
|
||||
static void gatts_check_add_char(esp_bt_uuid_t char_uuid, uint16_t attr_handle) {
|
||||
if (attr_handle != 0) {
|
||||
gatts_char[ble_char_pos].char_handle=attr_handle;
|
||||
gatts_add_descr(); // try to add descriptors to this characteristic
|
||||
}
|
||||
}
|
||||
static void gatts_delete_service(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if){
|
||||
esp_err_t r;
|
||||
r = esp_ble_gatts_app_unregister(gatts_service[getIndexFromGatts_if(gatts_if)].gatts_if);
|
||||
if(r) jsWarn("error in app_unregister:%d\n",r);
|
||||
}
|
||||
static void gatts_unreg_app(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if){
|
||||
gatts_service[getIndexFromGatts_if(gatts_if)].gatts_if = ESP_GATT_IF_NONE;
|
||||
for(int i = 0; i < ble_service_cnt; i++){
|
||||
if(gatts_service[i].gatts_if != ESP_GATT_IF_NONE) return;
|
||||
}
|
||||
free(adv_service_uuid128);adv_service_uuid128 = NULL;
|
||||
free(gatts_char);gatts_char = NULL;
|
||||
free(gatts_descr);gatts_descr = NULL;
|
||||
free(gatts_service);gatts_service = NULL;
|
||||
ble_service_cnt = 0;
|
||||
ble_char_cnt = 0;
|
||||
ble_descr_cnt = 0;
|
||||
if(_removeValues) bleRemoveChilds(execInfo.hiddenRoot);
|
||||
}
|
||||
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
|
||||
jsWarnGattsEvent(event,gatts_if);
|
||||
JsVar *args[1];
|
||||
switch (event) {
|
||||
case ESP_GATTS_REG_EVT:{gatts_createService(event,gatts_if,param);break;}
|
||||
case ESP_GATTS_CREATE_EVT:{
|
||||
gatts_service[ble_service_pos].service_handle = param->create.service_handle;
|
||||
esp_ble_gatts_start_service(gatts_service[ble_service_pos].service_handle);
|
||||
break;
|
||||
}
|
||||
case ESP_GATTS_ADD_CHAR_EVT: {
|
||||
if (param->add_char.status==ESP_GATT_OK) {
|
||||
gatts_check_add_char(param->add_char.char_uuid,param->add_char.attr_handle);
|
||||
}
|
||||
else{
|
||||
jsWarn("add char failed:%d\n",param->add_char.status);
|
||||
gatts_char[ble_char_pos].char_handle = -1;
|
||||
ble_char_pos++;
|
||||
gatts_add_char();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GATTS_START_EVT: {gatts_add_char();break;}
|
||||
case ESP_GATTS_DISCONNECT_EVT:{gatts_disconnect_handler(event,gatts_if,param); break;}
|
||||
case ESP_GATTS_ADD_CHAR_DESCR_EVT:{
|
||||
if (param->add_char_descr.status==ESP_GATT_OK) {
|
||||
gatts_check_add_descr(param->add_char.char_uuid,param->add_char.attr_handle);
|
||||
}
|
||||
else{jsWarn("add descr failed:%d\n",param->add_char_descr.status);}
|
||||
break;
|
||||
}
|
||||
case ESP_GATTS_CONNECT_EVT: {gatts_connect_handler(event,gatts_if,param); break;}
|
||||
case ESP_GATTS_READ_EVT: {gatts_read_value_handler(event, gatts_if, param);break;}
|
||||
case ESP_GATTS_WRITE_EVT:{
|
||||
if(gatts_service[getIndexFromGatts_if(gatts_if)].serviceFlag == BLE_SERVICE_NUS){
|
||||
gatts_write_nus_value_handler(event,gatts_if,param);
|
||||
}
|
||||
else{
|
||||
gatts_write_value_handler(event,gatts_if,param);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GATTS_DELETE_EVT:{gatts_delete_service(event,gatts_if);break;}
|
||||
case ESP_GATTS_UNREG_EVT:{gatts_unreg_app(event,gatts_if);break;}
|
||||
|
||||
case ESP_GATTS_EXEC_WRITE_EVT:break;
|
||||
case ESP_GATTS_MTU_EVT:break;
|
||||
case ESP_GATTS_CONF_EVT:break;
|
||||
case ESP_GATTS_ADD_INCL_SRVC_EVT:break;
|
||||
case ESP_GATTS_STOP_EVT:break;
|
||||
case ESP_GATTS_OPEN_EVT:break;
|
||||
case ESP_GATTS_CANCEL_OPEN_EVT:break;
|
||||
case ESP_GATTS_CLOSE_EVT:break;
|
||||
case ESP_GATTS_LISTEN_EVT:break;
|
||||
case ESP_GATTS_CONGEST_EVT:break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void add_ble_uart(){
|
||||
uint16_t handles = 1;
|
||||
ble_service_pos++;
|
||||
gatts_service[ble_service_pos].ble_uuid = uart_service_uuid;
|
||||
bleuuid_To_uuid128(gatts_service[ble_service_pos].ble_uuid,&adv_service_uuid128[ble_service_pos * 16]);
|
||||
gatts_service[ble_service_pos].uuid16 = gatts_service[ble_service_pos].ble_uuid.uuid;
|
||||
gatts_service[ble_service_pos].serviceFlag = BLE_SERVICE_NUS;
|
||||
ble_char_pos++;
|
||||
gatts_char[ble_char_pos].char_perm = 0;
|
||||
gatts_char[ble_char_pos].service_pos = ble_service_pos;
|
||||
gatts_char[ble_char_pos].char_uuid = uart_char_rx_uuid;
|
||||
gatts_char[ble_char_pos].char_perm += ESP_GATT_PERM_WRITE;
|
||||
gatts_char[ble_char_pos].char_property += ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_WRITE_NR;
|
||||
gatts_char[ble_char_pos].char_control = NULL;
|
||||
gatts_char[ble_char_pos].char_handle = 0;
|
||||
gatts_char[ble_char_pos].charFlag = BLE_CHAR_UART_RX;
|
||||
handles +=2;
|
||||
ble_char_pos++;
|
||||
gatts_char[ble_char_pos].char_perm = 0;
|
||||
gatts_char[ble_char_pos].service_pos = ble_service_pos;
|
||||
gatts_char[ble_char_pos].char_uuid = uart_char_tx_uuid;
|
||||
gatts_char[ble_char_pos].char_perm += ESP_GATT_PERM_READ;
|
||||
gatts_char[ble_char_pos].char_property += ESP_GATT_CHAR_PROP_BIT_NOTIFY;
|
||||
gatts_char[ble_char_pos].char_control = NULL;
|
||||
gatts_char[ble_char_pos].char_handle = 0;
|
||||
gatts_char[ble_char_pos].charFlag = BLE_CHAR_UART_TX;
|
||||
handles +=2;
|
||||
ble_descr_pos++;
|
||||
gatts_descr[ble_descr_pos].char_pos = ble_char_pos;
|
||||
gatts_descr[ble_descr_pos].descr_uuid = uart_tx_descr;
|
||||
gatts_descr[ble_descr_pos].descr_handle = 0;
|
||||
handles +=2;
|
||||
gatts_service[ble_service_pos].gatts_if = ESP_GATT_IF_NONE;
|
||||
gatts_service[ble_service_pos].num_handles = handles;
|
||||
}
|
||||
void setBleUart(){
|
||||
uart_gatts_if = ESP_GATT_IF_NONE;
|
||||
for(int i = 0; i < ble_service_cnt; i++){
|
||||
if(gatts_service[i].serviceFlag == BLE_SERVICE_NUS){
|
||||
uart_gatts_if = gatts_service[i].gatts_if;
|
||||
for(int j = 0; j < ble_char_cnt; j++){
|
||||
if(gatts_char[j].charFlag == BLE_CHAR_UART_TX){
|
||||
uart_tx_handle = gatts_char[j].char_handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gatts_char_init(){
|
||||
const char *errorStr;
|
||||
ble_uuid_t ble_uuid;
|
||||
gatts_char[ble_char_pos].service_pos = ble_service_pos;
|
||||
if((errorStr = bleVarToUUIDAndUnLock(&ble_uuid,jsvObjectIteratorGetKey(&ble_char_it)))){
|
||||
jsExceptionHere(JSET_ERROR,"invalid Char UUID:%s",errorStr);
|
||||
}
|
||||
JsVar *charVar = jsvObjectIteratorGetValue(&ble_char_it);
|
||||
gatts_char[ble_char_pos].char_uuid.len = ESP_UUID_LEN_16;
|
||||
gatts_char[ble_char_pos].char_uuid.uuid.uuid16 = ble_uuid.uuid;
|
||||
gatts_char[ble_char_pos].char_perm = 0;
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(charVar, "broadcast", 0)))
|
||||
gatts_char[ble_char_pos].char_property += ESP_GATT_CHAR_PROP_BIT_BROADCAST;
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(charVar, "notify", 0)))
|
||||
gatts_char[ble_char_pos].char_property += ESP_GATT_CHAR_PROP_BIT_NOTIFY;
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(charVar, "indicate", 0)))
|
||||
gatts_char[ble_char_pos].char_property += ESP_GATT_CHAR_PROP_BIT_INDICATE;
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(charVar, "readable", 0))){
|
||||
gatts_char[ble_char_pos].char_perm += ESP_GATT_PERM_READ;
|
||||
gatts_char[ble_char_pos].char_property += ESP_GATT_CHAR_PROP_BIT_READ;
|
||||
}
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(charVar, "writable", 0))){
|
||||
gatts_char[ble_char_pos].char_perm += ESP_GATT_PERM_WRITE;
|
||||
gatts_char[ble_char_pos].char_property += ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_WRITE_NR;
|
||||
}
|
||||
gatts_char[ble_char_pos].char_control = NULL;
|
||||
gatts_char[ble_char_pos].char_handle = 0;
|
||||
JsVar *readCB = jsvObjectGetChild(charVar, "onRead", 0);
|
||||
if(readCB){
|
||||
char hiddenName[12];
|
||||
bleGetHiddenName(hiddenName,BLE_READ_EVENT,ble_char_pos);
|
||||
jsvObjectSetChildAndUnLock(execInfo.hiddenRoot,hiddenName,readCB);
|
||||
}
|
||||
JsVar *writeCB = jsvObjectGetChild(charVar, "onWrite", 0);
|
||||
if(writeCB){
|
||||
char hiddenName[12];
|
||||
bleGetHiddenName(hiddenName,BLE_WRITE_EVENT,ble_char_pos);
|
||||
jsvObjectSetChildAndUnLock(execInfo.hiddenRoot,hiddenName,writeCB);
|
||||
}
|
||||
JsVar *charDescriptionVar = jsvObjectGetChild(charVar, "description", 0);
|
||||
if (charDescriptionVar && jsvHasCharacterData(charDescriptionVar)) {
|
||||
ble_descr_pos++;
|
||||
gatts_descr[ble_descr_pos].char_pos = ble_char_pos;
|
||||
gatts_descr[ble_descr_pos].descr_uuid.len = ESP_UUID_LEN_16;
|
||||
gatts_descr[ble_descr_pos].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_DESCRIPTION;
|
||||
gatts_descr[ble_descr_pos].descr_perm = ESP_GATT_PERM_READ;
|
||||
gatts_descr[ble_descr_pos].descrVal = charDescriptionVar;
|
||||
gatts_descr[ble_descr_pos].descr_control = NULL;
|
||||
gatts_descr[ble_descr_pos].descr_handle = 0;
|
||||
}
|
||||
jsvUnLock(charDescriptionVar);
|
||||
JsVar *charValue = jsvObjectGetChild(charVar,"value",0);
|
||||
if(charValue){
|
||||
char hiddenName[12];
|
||||
bleGetHiddenName(hiddenName,BLE_CHAR_VALUE,ble_char_pos);
|
||||
jsvObjectSetChildAndUnLock(execInfo.hiddenRoot,hiddenName,charValue);
|
||||
}
|
||||
jsvUnLock(charVar);
|
||||
}
|
||||
void gatts_service_struct_init(){
|
||||
ble_uuid_t ble_uuid;uint16_t handles;
|
||||
const char *errorStr;
|
||||
if((errorStr = bleVarToUUIDAndUnLock(&gatts_service[ble_service_pos].ble_uuid, jsvObjectIteratorGetKey(&ble_service_it)))){
|
||||
jsExceptionHere(JSET_ERROR,"invalid Service UUID:%s",errorStr);
|
||||
}
|
||||
handles = 1; //for service
|
||||
bleuuid_To_uuid128(gatts_service[ble_service_pos].ble_uuid,&adv_service_uuid128[ble_service_pos * 16]);
|
||||
gatts_service[ble_service_pos].uuid16 = gatts_service[ble_service_pos].ble_uuid.uuid;
|
||||
JsVar *serviceVar = jsvObjectIteratorGetValue(&ble_service_it);
|
||||
jsvObjectIteratorNew(&ble_char_it,serviceVar);
|
||||
while(jsvObjectIteratorHasValue(&ble_char_it)){
|
||||
ble_char_pos++;
|
||||
gatts_char_init();
|
||||
handles +=2; //2 for each char
|
||||
handles +=2; //placeholder for 2 descr
|
||||
jsvObjectIteratorNext(&ble_char_it);
|
||||
}
|
||||
gatts_service[ble_service_pos].num_handles = handles;
|
||||
jsvObjectIteratorFree(&ble_char_it);
|
||||
jsvUnLock(serviceVar);
|
||||
}
|
||||
void gatts_structs_init(JsVar *options){
|
||||
for(int i = 0; i < ble_service_cnt; i++){
|
||||
gatts_service[i].gatts_if = ESP_GATT_IF_NONE;
|
||||
gatts_service[i].num_handles = 0;
|
||||
gatts_service[i].serviceFlag = BLE_SERVICE_GENERAL;
|
||||
}
|
||||
for(int i = 0; i < ble_char_cnt;i++){
|
||||
gatts_char[i].service_pos = -1;
|
||||
gatts_char[i].charFlag = BLE_CHAR_GENERAL;
|
||||
}
|
||||
for(int i = 0; i < ble_descr_cnt;i++){
|
||||
gatts_descr[i].char_pos = -1;
|
||||
}
|
||||
jsvObjectIteratorNew(&ble_service_it,gatts_services);
|
||||
while(jsvObjectIteratorHasValue(&ble_service_it)){
|
||||
ble_service_pos++;
|
||||
gatts_service_struct_init();
|
||||
jsvObjectIteratorNext(&ble_service_it);
|
||||
}
|
||||
jsvObjectIteratorFree(&ble_service_it);
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(options, "uart", 0))){
|
||||
add_ble_uart();
|
||||
}
|
||||
}
|
||||
void gatts_getAdvServiceUUID(uint8_t *p_service_uuid, uint16_t service_len){
|
||||
p_service_uuid = adv_service_uuid128;
|
||||
service_len = 16 * ble_service_cnt - 16;
|
||||
}
|
||||
|
||||
void gatts_create_structs(JsVar *options){
|
||||
ble_service_cnt = 0; ble_char_cnt = 0; ble_descr_cnt = 0;
|
||||
ble_service_pos = -1; ble_char_pos = -1; ble_descr_pos = -1;
|
||||
jsvObjectIteratorNew(&ble_service_it,gatts_services);
|
||||
while(jsvObjectIteratorHasValue(&ble_service_it)){
|
||||
JsVar *serviceVar = jsvObjectIteratorGetValue(&ble_service_it);
|
||||
jsvObjectIteratorNew(&ble_char_it,serviceVar);
|
||||
while(jsvObjectIteratorHasValue(&ble_char_it)){
|
||||
JsVar *charVar = jsvObjectIteratorGetValue(&ble_char_it);
|
||||
JsVar *charDescriptionVar = jsvObjectGetChild(charVar, "description", 0);
|
||||
if (charDescriptionVar && jsvHasCharacterData(charDescriptionVar)) ble_descr_cnt++;
|
||||
jsvUnLock(charDescriptionVar);
|
||||
jsvUnLock(charVar);
|
||||
jsvObjectIteratorNext(&ble_char_it);
|
||||
ble_char_cnt++;
|
||||
}
|
||||
jsvUnLock(serviceVar);
|
||||
jsvObjectIteratorFree(&ble_char_it);
|
||||
jsvObjectIteratorNext(&ble_service_it);
|
||||
ble_service_cnt++;
|
||||
}
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(options, "uart", 0))){
|
||||
ble_service_cnt++;
|
||||
ble_char_cnt += 2;
|
||||
ble_descr_cnt += 2;
|
||||
}
|
||||
jsvObjectIteratorFree(&ble_service_it);
|
||||
adv_service_uuid128 = calloc(sizeof(uint8_t),(ble_service_cnt * 16));
|
||||
gatts_service = calloc(sizeof(struct gatts_service_inst),ble_service_cnt);
|
||||
gatts_char = calloc(sizeof(struct gatts_char_inst),ble_char_cnt);
|
||||
gatts_descr = calloc(sizeof(struct gatts_descr_inst),ble_descr_cnt);
|
||||
}
|
||||
|
||||
void gatts_set_services(JsVar *data){
|
||||
JsVar *options = jsvObjectGetChild(execInfo.hiddenRoot, BLE_NAME_SERVICE_OPTIONS,0);
|
||||
gatts_reset(true);
|
||||
gatts_services = data;
|
||||
if (jsvIsObject(gatts_services)) {
|
||||
gatts_create_structs(options);
|
||||
gatts_structs_init(options);
|
||||
ble_service_pos = 0;
|
||||
ble_char_pos = 0;
|
||||
ble_descr_pos = 0;
|
||||
gatts_reg_app(); //this starts tons of api calls creating gatts-events. Ends in gatts_reg_app
|
||||
if (jsvGetBoolAndUnLock(jsvObjectGetChild(options, "uart", 0))){
|
||||
setBleUart();
|
||||
}
|
||||
}
|
||||
jsvUnLock(options);
|
||||
}
|
||||
void gatts_reset(bool removeValues){
|
||||
esp_err_t r;
|
||||
_removeValues = removeValues;
|
||||
if(ble_service_cnt > 0){
|
||||
for(int i = 0; i < ble_service_cnt;i++){
|
||||
if(gatts_service[i].gatts_if != ESP_GATT_IF_NONE){
|
||||
r = esp_ble_gatts_delete_service(gatts_service[i].service_handle);
|
||||
if(r) jsWarn("delete service error:%d\n",r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
80
targets/esp32/BLE/esp32_gatts_func.h
Normal file
80
targets/esp32/BLE/esp32_gatts_func.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2017 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* ESP32 specific GATT functions
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef GATTS_FUNC_H_
|
||||
#define GATTS_FUNC_H_
|
||||
|
||||
#include "esp_gatts_api.h"
|
||||
#include "jsvar.h"
|
||||
#include "bluetooth.h"
|
||||
|
||||
#define GATTS_CHAR_VAL_LEN_MAX 22 // maximum length in bytes of a characteristic's value. TODO: find out how to determine this value?
|
||||
|
||||
typedef enum {
|
||||
BLE_SERVICE_GENERAL = 0,
|
||||
BLE_SERVICE_NUS = 1
|
||||
} BLEServiceFlags;
|
||||
|
||||
typedef enum {
|
||||
BLE_CHAR_GENERAL = 0,
|
||||
BLE_CHAR_UART_RX = 1,
|
||||
BLE_CHAR_UART_TX = 2
|
||||
} BLECharFlags;
|
||||
|
||||
struct gatts_service_inst {
|
||||
uint16_t gatts_if;
|
||||
uint16_t app_id;
|
||||
uint16_t conn_id;
|
||||
uint16_t service_handle;
|
||||
esp_gatt_srvc_id_t service_id;
|
||||
uint16_t num_handles;
|
||||
ble_uuid_t ble_uuid;
|
||||
uint16_t uuid16;
|
||||
BLEServiceFlags serviceFlag;
|
||||
};
|
||||
|
||||
struct gatts_char_inst {
|
||||
uint32_t service_pos;
|
||||
esp_bt_uuid_t char_uuid;
|
||||
esp_gatt_perm_t char_perm;
|
||||
esp_gatt_char_prop_t char_property;
|
||||
esp_attr_control_t *char_control;
|
||||
uint16_t char_handle;
|
||||
char char_nvs[16];
|
||||
BLECharFlags charFlag;
|
||||
};
|
||||
|
||||
struct gatts_descr_inst {
|
||||
uint32_t char_pos;
|
||||
esp_bt_uuid_t descr_uuid;
|
||||
esp_gatt_perm_t descr_perm;
|
||||
JsVar *descrVal;
|
||||
esp_attr_control_t *descr_control;
|
||||
uint16_t descr_handle;
|
||||
};
|
||||
|
||||
static uint8_t *adv_service_uuid128 = NULL;
|
||||
|
||||
static uint16_t ble_service_cnt = 0;
|
||||
|
||||
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
|
||||
void gatts_register_app(uint16_t id);
|
||||
void gatts_set_services(JsVar *data);
|
||||
void gatts_reset(bool removeValues);
|
||||
|
||||
uint8_t *getUartAdvice();
|
||||
void gatts_sendNotification(int c);
|
||||
|
||||
void gatts_test();
|
||||
|
||||
#endif /* GATTS_FUNC_H_ */
|
||||
203
targets/esp32/bluetooth.c
Normal file
203
targets/esp32/bluetooth.c
Normal file
@ -0,0 +1,203 @@
|
||||
/**
|
||||
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
||||
*
|
||||
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Utilities for converting Nordic datastructures to Espruino and vice versa
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bt.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_gatt_common_api.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#include "jswrap_bluetooth.h"
|
||||
#include "bluetooth.h"
|
||||
#include "jsutils.h"
|
||||
|
||||
#include "BLE/esp32_gap_func.h"
|
||||
#include "BLE/esp32_gatts_func.h"
|
||||
#include "BLE/esp32_gattc_func.h"
|
||||
#include "BLE/esp32_bluetooth_utils.h"
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
volatile BLEStatus bleStatus;
|
||||
uint16_t bleAdvertisingInterval; /**< The advertising interval (in units of 0.625 ms). */
|
||||
volatile uint16_t m_conn_handle; /**< Handle of the current connection. */
|
||||
volatile uint16_t m_central_conn_handle; /**< Handle of central mode connection */
|
||||
|
||||
/** Initialise the BLE stack */
|
||||
void jsble_init(){
|
||||
esp_err_t ret;
|
||||
ret = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
if(ret) {jsWarn("mem release failed:%x\n",ret); return;}
|
||||
|
||||
if(initController()) return;
|
||||
if(initBluedroid()) return;
|
||||
if(registerCallbacks()) return;
|
||||
setMtu();
|
||||
}
|
||||
/** Completely deinitialise the BLE stack */
|
||||
void jsble_kill(){
|
||||
jsWarn("kill not implemented yet\n");
|
||||
}
|
||||
|
||||
void jsble_queue_pending_buf(BLEPending blep, uint16_t data, char *ptr, size_t len){
|
||||
jsWarn("queue_pending_buf not implemented yet");
|
||||
UNUSED(blep);
|
||||
UNUSED(data);
|
||||
UNUSED(ptr);
|
||||
UNUSED(len);
|
||||
}
|
||||
|
||||
void jsble_queue_pending(BLEPending blep, uint16_t data){
|
||||
jsWarn("queue_pending not implemented yet");
|
||||
UNUSED(blep);
|
||||
UNUSED(data);
|
||||
}
|
||||
|
||||
int jsble_exec_pending(IOEvent *event){
|
||||
jsWarn("exec_pending not implemented yet");
|
||||
UNUSED(event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void jsble_restart_softdevice(){
|
||||
bleStatus &= ~(BLE_NEEDS_SOFTDEVICE_RESTART | BLE_SERVICES_WERE_SET);
|
||||
if (bleStatus & BLE_IS_SCANNING) {
|
||||
bluetooth_gap_setScan(false);
|
||||
}
|
||||
jswrap_nrf_reconfigure_softdevice();
|
||||
}
|
||||
|
||||
void jsble_advertising_start(){
|
||||
//jsWarn("advertising start\n");
|
||||
esp_err_t status;
|
||||
if (bleStatus & BLE_IS_ADVERTISING) return;
|
||||
status = bluetooth_gap_startAdvertizing(true);
|
||||
if(status) jsWarn("advertizing start problem:0X%x\n",status);
|
||||
}
|
||||
void jsble_advertising_stop(){
|
||||
esp_err_t status;
|
||||
status = bluetooth_gap_startAdvertizing(false);
|
||||
if(status) jsWarn("error in stop advertising:0X%x\n",status);
|
||||
}
|
||||
/** Is BLE connected to any device at all? */
|
||||
bool jsble_has_connection(){
|
||||
jsWarn("has connected not implemented yet\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Is BLE connected to a central device at all? */
|
||||
bool jsble_has_central_connection(){
|
||||
jsWarn("has central connection not implemented yet\n");
|
||||
return false;
|
||||
}
|
||||
/** Is BLE connected to a server device at all (eg, the simple, 'slave' mode)? */
|
||||
bool jsble_has_simple_connection(){
|
||||
jsWarn("has simple connection not implemented yet\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Checks for error and reports an exception if there was one. Return true on error
|
||||
bool jsble_check_error(uint32_t err_code){
|
||||
jsWarn("check error not implemented yet:%x\n",err_code);
|
||||
UNUSED(err_code);
|
||||
return false;
|
||||
}
|
||||
/// Scanning for advertisign packets
|
||||
uint32_t jsble_set_scanning(bool enabled){
|
||||
bluetooth_gap_setScan(enabled);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// returning RSSI values for current connection
|
||||
uint32_t jsble_set_rssi_scan(bool enabled){
|
||||
jsWarn("set rssi scan not implemeted yet\n");
|
||||
UNUSED(enabled);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Actually set the services defined in the 'data' object. Note: we can
|
||||
* only do this *once* - so to change it we must reset the softdevice and
|
||||
* then call this again */
|
||||
void jsble_set_services(JsVar *data){
|
||||
gatts_set_services(data);
|
||||
}
|
||||
|
||||
/// Disconnect from the given connection
|
||||
uint32_t jsble_disconnect(uint16_t conn_handle){
|
||||
return gattc_disconnect(conn_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// For BLE HID, send an input report to the receiver. Must be <= HID_KEYS_MAX_LEN
|
||||
void jsble_send_hid_input_report(uint8_t *data, int length){
|
||||
jsWarn("send hid input report not implemented yet\n");
|
||||
UNUSED(data);
|
||||
UNUSED(length);
|
||||
}
|
||||
|
||||
/// Connect to the given peer address. When done call bleCompleteTask
|
||||
void jsble_central_connect(ble_gap_addr_t peer_addr){
|
||||
gattc_connect(peer_addr.addr);
|
||||
}
|
||||
/// Get primary services. Filter by UUID unless UUID is invalid, in which case return all. When done call bleCompleteTask
|
||||
void jsble_central_getPrimaryServices(ble_uuid_t uuid){
|
||||
gattc_searchService(uuid);
|
||||
}
|
||||
/// Get characteristics. Filter by UUID unless UUID is invalid, in which case return all. When done call bleCompleteTask
|
||||
void jsble_central_getCharacteristics(JsVar *service, ble_uuid_t uuid){
|
||||
gattc_getCharacteristic(uuid);
|
||||
UNUSED(service);
|
||||
}
|
||||
// Write data to the given characteristic. When done call bleCompleteTask
|
||||
void jsble_central_characteristicWrite(JsVar *characteristic, char *dataPtr, size_t dataLen){
|
||||
uint16_t handle = jsvGetIntegerAndUnLock(jsvObjectGetChild(characteristic, "handle_value", 0));
|
||||
gattc_writeValue(handle,dataPtr,dataLen);
|
||||
}
|
||||
// Read data from the given characteristic. When done call bleCompleteTask
|
||||
void jsble_central_characteristicRead(JsVar *characteristic){
|
||||
uint16_t handle = jsvGetIntegerAndUnLock(jsvObjectGetChild(characteristic, "handle_value", 0));
|
||||
gattc_readValue(handle);
|
||||
}
|
||||
// Discover descriptors of characteristic
|
||||
void jsble_central_characteristicDescDiscover(JsVar *characteristic){
|
||||
jsWarn("Central characteristicDescDiscover not implemented yet\n");
|
||||
UNUSED(characteristic);
|
||||
}
|
||||
// Set whether to notify on the given characteristic. When done call bleCompleteTask
|
||||
void jsble_central_characteristicNotify(JsVar *characteristic, bool enable){
|
||||
jsWarn("central characteristic notify not implemented yet\n");
|
||||
UNUSED(characteristic);
|
||||
UNUSED(enable);
|
||||
}
|
||||
/// Start bonding on the current central connection
|
||||
void jsble_central_startBonding(bool forceRePair){
|
||||
jsWarn("central start bonding not implemented yet\n");
|
||||
UNUSED(forceRePair);
|
||||
}
|
||||
/// Get the security status of the current link
|
||||
JsVar *jsble_central_getSecurityStatus(){
|
||||
jsWarn("central getSecurityStatus not implemented yet\n");
|
||||
return 0;
|
||||
}
|
||||
/// RSSI monitoring in central mode
|
||||
uint32_t jsble_set_central_rssi_scan(bool enabled){
|
||||
jsWarn("central set rssi scan not implemented yet\n");
|
||||
return 0;
|
||||
}
|
||||
// Set whether or not the whitelist is enabled
|
||||
void jsble_central_setWhitelist(bool whitelist){
|
||||
jsWarn("central set Whitelist not implemented yet\n");
|
||||
return 0;
|
||||
}
|
||||
@ -32,6 +32,12 @@
|
||||
#include "jshardwarePWM.h"
|
||||
#include "jshardwarePulse.h"
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
#include "BLE/esp32_gap_func.h"
|
||||
#include "BLE/esp32_gattc_func.h"
|
||||
#include "BLE/esp32_gatts_func.h"
|
||||
#endif
|
||||
|
||||
#include "jsutils.h"
|
||||
#include "jstimer.h"
|
||||
#include "jsparse.h"
|
||||
@ -126,6 +132,9 @@ void jshPinDefaultPullup() {
|
||||
*/
|
||||
void jshInit() {
|
||||
esp32_wifi_init();
|
||||
#ifdef BLUETOOTH
|
||||
gattc_init();
|
||||
#endif
|
||||
jshInitDevices();
|
||||
BITFIELD_CLEAR(jshPinSoftPWM);
|
||||
if (JSHPINSTATE_I2C != 13 || JSHPINSTATE_GPIO_IN_PULLDOWN != 6 || JSHPINSTATE_MASK != 15) {
|
||||
@ -147,11 +156,14 @@ void jshInit() {
|
||||
void jshReset() {
|
||||
jshResetDevices();
|
||||
jshPinDefaultPullup() ;
|
||||
UartReset();
|
||||
// UartReset();
|
||||
RMTReset();
|
||||
ADCReset();
|
||||
SPIReset();
|
||||
I2CReset();
|
||||
#ifdef BLUETOOTH
|
||||
gatts_reset(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -505,12 +517,12 @@ bool jshIsEventForPin(
|
||||
|
||||
|
||||
void jshUSARTSetup(IOEventFlags device, JshUSARTInfo *inf) {
|
||||
|
||||
|
||||
if (inf->errorHandling) {
|
||||
jsExceptionHere(JSET_ERROR, "ESP32 Espruino builds can't handle framing/parity errors (errors:true)");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
initSerial(device,inf);
|
||||
}
|
||||
|
||||
@ -527,8 +539,21 @@ void jshUSARTKick(
|
||||
) {
|
||||
int c = jshGetCharToTransmit(device);
|
||||
while(c >= 0) {
|
||||
if(device == EV_SERIAL1) uart_tx_one_char((uint8_t)c);
|
||||
else writeSerial(device,(uint8_t)c);
|
||||
switch(device){
|
||||
#ifdef BLUETOOTH
|
||||
case EV_BLUETOOTH:
|
||||
gatts_sendNotification(c);
|
||||
break;
|
||||
#endif
|
||||
case EV_SERIAL1:
|
||||
uart_tx_one_char((uint8_t)c);
|
||||
break;
|
||||
default:
|
||||
writeSerial(device,(uint8_t)c);
|
||||
break;
|
||||
//if(device == EV_SERIAL1) uart_tx_one_char((uint8_t)c);
|
||||
//else writeSerial(device,(uint8_t)c);
|
||||
}
|
||||
c = jshGetCharToTransmit(device);
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,13 +12,24 @@
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include "jswrap_esp32.h"
|
||||
#include "jshardwareAnalog.h"
|
||||
#include "jsutils.h"
|
||||
#include "jsinteractive.h"
|
||||
#include "jsparse.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
#include "BLE/esp32_bluetooth_utils.h"
|
||||
#endif
|
||||
|
||||
#include "jsutils.h"
|
||||
#include "jsinteractive.h"
|
||||
#include "jsparse.h"
|
||||
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "ESP32",
|
||||
@ -27,7 +38,7 @@
|
||||
"params" : [
|
||||
["pin", "pin", "Pin for Analog read"],
|
||||
["atten", "int", "Attenuate factor"]
|
||||
]
|
||||
]
|
||||
}*/
|
||||
void jswrap_ESP32_setAtten(Pin pin,int atten){
|
||||
printf("Atten:%d\n",atten);
|
||||
@ -52,7 +63,7 @@ void jswrap_ESP32_reboot() {
|
||||
"class" : "ESP32",
|
||||
"name" : "deepSleep",
|
||||
"generate" : "jswrap_ESP32_deepSleep",
|
||||
"params" : [ ["us", "int", "Sleeptime in us"] ]
|
||||
"params" : [ ["us", "int", "Sleeptime in us"] ]
|
||||
}
|
||||
Put device in deepsleep state for "us" microseconds.
|
||||
*/
|
||||
@ -83,3 +94,20 @@ JsVar *jswrap_ESP32_getState() {
|
||||
jsvObjectSetChildAndUnLock(esp32State, "freeHeap", jsvNewFromInteger(esp_get_free_heap_size()));
|
||||
return esp32State;
|
||||
} // End of jswrap_ESP32_getState
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
/*JSON{
|
||||
"type" : "staticmethod",
|
||||
"class" : "ESP32",
|
||||
"name" : "setBLE_Debug",
|
||||
"generate" : "jswrap_ESP32_setBLE_Debug",
|
||||
"params" : [
|
||||
["level", "int", "which events should be shown (GATTS, GATTC, GAP)"]
|
||||
],
|
||||
"ifdef" : "BLUETOOTH"
|
||||
}
|
||||
*/
|
||||
void jswrap_ESP32_setBLE_Debug(int level){
|
||||
ESP32_setBLE_Debug(level);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -24,4 +24,8 @@ JsVar *jswrap_ESP32_setBoot(JsVar *jsPartitionName);
|
||||
void jswrap_ESP32_reboot();
|
||||
void jswrap_ESP32_deepSleep(int us);
|
||||
void jswrap_ESP32_setAtten(Pin pin,int atten);
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
void jswrap_ESP32_setBLE_Debug(int level);
|
||||
#endif
|
||||
#endif /* TARGETS_ESP32_JSWRAP_ESP32_H_ */
|
||||
|
||||
@ -18,6 +18,11 @@
|
||||
#include "jshardwareSpi.h"
|
||||
#include "jswrap_wifi.h" // jswrap_wifi_restore
|
||||
|
||||
#ifdef BLUETOOTH
|
||||
#include "libs/bluetooth/bluetooth.h"
|
||||
#include "BLE/esp32_gap_func.h"
|
||||
#endif
|
||||
|
||||
#include "esp_spi_flash.h"
|
||||
#include "spi_flash/include/esp_partition.h"
|
||||
#include "esp_log.h"
|
||||
@ -27,8 +32,8 @@ extern void initialise_wifi(void);
|
||||
static void uartTask(void *data) {
|
||||
initConsole();
|
||||
while(1) {
|
||||
consoleToEspruino();
|
||||
serialToEspruino();
|
||||
consoleToEspruino();
|
||||
serialToEspruino();
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,6 +48,9 @@ static void espruinoTask(void *data) {
|
||||
// not sure why this delay is needed?
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
jsiInit(true); // Initialize the interactive subsystem
|
||||
#ifdef BLUETOOTH
|
||||
bluetooth_initDeviceName();
|
||||
#endif
|
||||
while(1) {
|
||||
jsiLoop(); // Perform the primary loop processing
|
||||
}
|
||||
@ -58,6 +66,9 @@ int app_main(void)
|
||||
{
|
||||
esp_log_level_set("*", ESP_LOG_ERROR); // set all components to ERROR level - suppress Wifi Info
|
||||
nvs_flash_init();
|
||||
#ifdef BLUETOOTH
|
||||
jsble_init();
|
||||
#endif
|
||||
spi_flash_init();
|
||||
tcpip_adapter_init();
|
||||
timers_Init();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user