Add support for notify (untested)
This commit is contained in:
parent
7e123b215e
commit
7aa22335ac
|
@ -65,6 +65,7 @@ static uint8_t *gadget_mfg;
|
||||||
static size_t gadget_mfg_len;
|
static size_t gadget_mfg_len;
|
||||||
|
|
||||||
static const struct ble_gatt_svc_def *gatt_svr_svcs;
|
static const struct ble_gatt_svc_def *gatt_svr_svcs;
|
||||||
|
static const uint16_t *notify_handles;
|
||||||
|
|
||||||
static task_handle_t task_handle;
|
static task_handle_t task_handle;
|
||||||
static QueueHandle_t response_queue;
|
static QueueHandle_t response_queue;
|
||||||
|
@ -401,7 +402,7 @@ cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lble_build_gatt_svcs(lua_State *L, struct ble_gatt_svc_def **resultp) {
|
lble_build_gatt_svcs(lua_State *L, struct ble_gatt_svc_def **resultp, const uint16_t **handlep) {
|
||||||
// We have to first figure out how big the allocated memory is.
|
// We have to first figure out how big the allocated memory is.
|
||||||
// This is the number of services (ns) + 1 * sizeof(ble_gatt_svc_def)
|
// This is the number of services (ns) + 1 * sizeof(ble_gatt_svc_def)
|
||||||
// + number of characteristics (nc) + ns * sizeof(ble_gatt_chr_def)
|
// + number of characteristics (nc) + ns * sizeof(ble_gatt_chr_def)
|
||||||
|
@ -434,7 +435,7 @@ lble_build_gatt_svcs(lua_State *L, struct ble_gatt_svc_def **resultp) {
|
||||||
|
|
||||||
MODLOG_DFLT(INFO, "Discovered %d services with %d characteristics\n", ns, nc);
|
MODLOG_DFLT(INFO, "Discovered %d services with %d characteristics\n", ns, nc);
|
||||||
|
|
||||||
int size = (ns + 1) * sizeof(struct ble_gatt_svc_def) + (nc + ns) * sizeof(struct ble_gatt_chr_def) + (ns + nc) * sizeof(ble_uuid_any_t);
|
int size = (ns + 1) * sizeof(struct ble_gatt_svc_def) + (nc + ns) * sizeof(struct ble_gatt_chr_def) + (ns + nc) * sizeof(ble_uuid_any_t) + (nc + 1) * sizeof(uint16_t);
|
||||||
|
|
||||||
|
|
||||||
struct ble_gatt_svc_def *svcs = malloc(size);
|
struct ble_gatt_svc_def *svcs = malloc(size);
|
||||||
|
@ -447,6 +448,9 @@ lble_build_gatt_svcs(lua_State *L, struct ble_gatt_svc_def **resultp) {
|
||||||
void *eom = ((char *) svcs) + size;
|
void *eom = ((char *) svcs) + size;
|
||||||
struct ble_gatt_chr_def *chrs = (struct ble_gatt_chr_def *) (svcs + ns + 1);
|
struct ble_gatt_chr_def *chrs = (struct ble_gatt_chr_def *) (svcs + ns + 1);
|
||||||
ble_uuid_any_t *uuids = (ble_uuid_any_t *) (chrs + ns + nc);
|
ble_uuid_any_t *uuids = (ble_uuid_any_t *) (chrs + ns + nc);
|
||||||
|
uint16_t *handles = (uint16_t *) (uuids + ns + nc);
|
||||||
|
|
||||||
|
handles[0] = 0; // number of slots used
|
||||||
|
|
||||||
// Now fill out the data structure
|
// Now fill out the data structure
|
||||||
// -1 is the services list
|
// -1 is the services list
|
||||||
|
@ -496,11 +500,11 @@ lble_build_gatt_svcs(lua_State *L, struct ble_gatt_svc_def **resultp) {
|
||||||
|
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
lua_getfield(L, -2, "read");
|
lua_getfield(L, -2, "read");
|
||||||
if (lua_isboolean(L, 1) && lua_toboolean(L, -1)) {
|
if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) {
|
||||||
flags = BLE_GATT_CHR_F_READ;
|
flags = BLE_GATT_CHR_F_READ;
|
||||||
}
|
}
|
||||||
lua_getfield(L, -3, "write");
|
lua_getfield(L, -3, "write");
|
||||||
if (lua_isboolean(L, 1) && lua_toboolean(L, -1)) {
|
if (lua_isboolean(L, -1) && lua_toboolean(L, -1)) {
|
||||||
flags |= BLE_GATT_CHR_F_WRITE;
|
flags |= BLE_GATT_CHR_F_WRITE;
|
||||||
}
|
}
|
||||||
if (flags) {
|
if (flags) {
|
||||||
|
@ -524,6 +528,16 @@ lble_build_gatt_svcs(lua_State *L, struct ble_gatt_svc_def **resultp) {
|
||||||
lua_pop(L, 3); // pop off value, read, write
|
lua_pop(L, 3); // pop off value, read, write
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lua_getfield(L, -1, "notify") != LUA_TNIL) {
|
||||||
|
chr->flags |= BLE_GATT_CHR_F_NOTIFY;
|
||||||
|
|
||||||
|
handles[0]++;
|
||||||
|
lua_pushinteger(L, handles[0]);
|
||||||
|
lua_setfield(L, -2, "notify");
|
||||||
|
chr->val_handle = &handles[handles[0]];
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
// -1 is now the characteristic again
|
// -1 is now the characteristic again
|
||||||
chr->arg = (void *) luaL_ref(L, LUA_REGISTRYINDEX);
|
chr->arg = (void *) luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
chr->access_cb = lble_access_cb;
|
chr->access_cb = lble_access_cb;
|
||||||
|
@ -534,6 +548,7 @@ lble_build_gatt_svcs(lua_State *L, struct ble_gatt_svc_def **resultp) {
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
*resultp = result;
|
*resultp = result;
|
||||||
|
*handlep = handles;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -546,7 +561,7 @@ gatt_svr_init(lua_State *L) {
|
||||||
|
|
||||||
|
|
||||||
struct ble_gatt_svc_def *svcs = NULL;
|
struct ble_gatt_svc_def *svcs = NULL;
|
||||||
lble_build_gatt_svcs(L, &svcs);
|
lble_build_gatt_svcs(L, &svcs, ¬ify_handles);
|
||||||
//free_gatt_svcs(L, gatt_svr_svcs);
|
//free_gatt_svcs(L, gatt_svr_svcs);
|
||||||
gatt_svr_svcs = svcs;
|
gatt_svr_svcs = svcs;
|
||||||
|
|
||||||
|
@ -736,7 +751,7 @@ lble_gap_event(struct ble_gap_event *event, void *arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lble_update_adv_fields() {
|
lble_update_adv_fields() {
|
||||||
struct ble_hs_adv_fields fields;
|
struct ble_hs_adv_fields fields;
|
||||||
const char *name = gadget_name;
|
const char *name = gadget_name;
|
||||||
|
@ -785,7 +800,7 @@ lble_update_adv_fields() {
|
||||||
fields.name_len = fields.name_len - 1;
|
fields.name_len = fields.name_len - 1;
|
||||||
fields.name_is_complete = 0;
|
fields.name_is_complete = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fields.name_is_complete) {
|
if (!fields.name_is_complete) {
|
||||||
struct ble_hs_adv_fields scan_response_fields;
|
struct ble_hs_adv_fields scan_response_fields;
|
||||||
memset(&scan_response_fields, 0, sizeof scan_response_fields);
|
memset(&scan_response_fields, 0, sizeof scan_response_fields);
|
||||||
|
@ -886,7 +901,7 @@ gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lble_update_adv_change(lua_State *L) {
|
lble_update_adv_change(lua_State *L) {
|
||||||
free((void *) gadget_mfg);
|
free((void *) gadget_mfg);
|
||||||
gadget_mfg = NULL;
|
gadget_mfg = NULL;
|
||||||
|
@ -906,7 +921,7 @@ lble_update_adv_change(lua_State *L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lble_update_adv(lua_State *L) {
|
lble_update_adv(lua_State *L) {
|
||||||
lua_pushvalue(L, 1);
|
lua_pushvalue(L, 1);
|
||||||
lble_update_adv_change(L);
|
lble_update_adv_change(L);
|
||||||
|
@ -918,6 +933,23 @@ lble_update_adv(lua_State *L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lble_notify(lua_State *L) {
|
||||||
|
if (inited != RUNNING) {
|
||||||
|
return luaL_error(L, "ble is not yet running");
|
||||||
|
}
|
||||||
|
int handle = luaL_checkinteger(L, 1);
|
||||||
|
|
||||||
|
luaL_argcheck(L, handle <= 0 || handle > notify_handles[0], 1, "handle out of range");
|
||||||
|
|
||||||
|
ble_gatts_chr_updated(notify_handles[handle]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (rc) {
|
||||||
|
return luaL_error(L, "Must supply a valid handle");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int lble_init(lua_State *L) {
|
static int lble_init(lua_State *L) {
|
||||||
if (inited != STOPPED) {
|
if (inited != STOPPED) {
|
||||||
|
@ -1020,6 +1052,7 @@ static int lble_shutdown(lua_State *L) {
|
||||||
|
|
||||||
LROT_BEGIN(lble, NULL, 0)
|
LROT_BEGIN(lble, NULL, 0)
|
||||||
LROT_FUNCENTRY( init, lble_init )
|
LROT_FUNCENTRY( init, lble_init )
|
||||||
|
LROT_FUNCENTRY( notify, lble_notify )
|
||||||
LROT_FUNCENTRY( advertise, lble_update_adv )
|
LROT_FUNCENTRY( advertise, lble_update_adv )
|
||||||
LROT_FUNCENTRY( shutdown, lble_shutdown )
|
LROT_FUNCENTRY( shutdown, lble_shutdown )
|
||||||
LROT_END(lble, NULL, 0)
|
LROT_END(lble, NULL, 0)
|
||||||
|
|
|
@ -36,6 +36,26 @@ local config = {name="MyGadget=", services={ myservice, battery }
|
||||||
ble.init(config)
|
ble.init(config)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## ble.notify()
|
||||||
|
|
||||||
|
This notifies the Bluetooth stack that a new value is available to be read from the characteristic.
|
||||||
|
|
||||||
|
#### Syntax
|
||||||
|
`ble.notify(characteristic)`
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- `characteristic` This is the table that was passed into the `init` method for the particular characteristic.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
`nil`
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```lua
|
||||||
|
ble.notify(config.services[1].characteristics[1])
|
||||||
|
```
|
||||||
|
|
||||||
## ble.advertise()
|
## ble.advertise()
|
||||||
|
|
||||||
Updates the advertising data field for future advertising frames.
|
Updates the advertising data field for future advertising frames.
|
||||||
|
@ -103,6 +123,7 @@ The characteristic table contains the following keys:
|
||||||
- `value` This is the actual value of the characteristic. This will be a string of bytes unless a `type` value is set.
|
- `value` This is the actual value of the characteristic. This will be a string of bytes unless a `type` value is set.
|
||||||
- `read` This is a function that will be invoked to read the value (and so does not need the `value` entry). It should return a string of bytes (unless `type` is set).
|
- `read` This is a function that will be invoked to read the value (and so does not need the `value` entry). It should return a string of bytes (unless `type` is set).
|
||||||
- `write` This is a function that will be invoked to write the value (and so does not need the `value` entry). It is given a string of bytes (unless `type` is set)
|
- `write` This is a function that will be invoked to write the value (and so does not need the `value` entry). It is given a string of bytes (unless `type` is set)
|
||||||
|
- `notify` If this attribute is present with the value `true` then notifications are supported on this characteristic.
|
||||||
|
|
||||||
If the `value` key is present, then the characteristic is read/write. However, if one or `read` or `write` is set to `true`, then it restricts access to that mode.
|
If the `value` key is present, then the characteristic is read/write. However, if one or `read` or `write` is set to `true`, then it restricts access to that mode.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue