extmod/modbluetooth: Add event for "indicate acknowledgement".
This commit adds the IRQ_GATTS_INDICATE_DONE BLE event which will be raised with the status of gatts_indicate (unlike notify, indications require acknowledgement). An example of its use is added to ble_temperature.py, and to the multitests in ble_characteristic.py. Implemented for btstack and nimble bindings, tested in both directions between unix/btstack and pybd/nimble.
This commit is contained in:
parent
3c7ca2004c
commit
9d823a5d9a
@ -13,13 +13,14 @@ from micropython import const
|
|||||||
|
|
||||||
_IRQ_CENTRAL_CONNECT = const(1)
|
_IRQ_CENTRAL_CONNECT = const(1)
|
||||||
_IRQ_CENTRAL_DISCONNECT = const(2)
|
_IRQ_CENTRAL_DISCONNECT = const(2)
|
||||||
|
_IRQ_GATTS_INDICATE_DONE = const(20)
|
||||||
|
|
||||||
# org.bluetooth.service.environmental_sensing
|
# org.bluetooth.service.environmental_sensing
|
||||||
_ENV_SENSE_UUID = bluetooth.UUID(0x181A)
|
_ENV_SENSE_UUID = bluetooth.UUID(0x181A)
|
||||||
# org.bluetooth.characteristic.temperature
|
# org.bluetooth.characteristic.temperature
|
||||||
_TEMP_CHAR = (
|
_TEMP_CHAR = (
|
||||||
bluetooth.UUID(0x2A6E),
|
bluetooth.UUID(0x2A6E),
|
||||||
bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,
|
bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY | bluetooth.FLAG_INDICATE,
|
||||||
)
|
)
|
||||||
_ENV_SENSE_SERVICE = (
|
_ENV_SENSE_SERVICE = (
|
||||||
_ENV_SENSE_UUID,
|
_ENV_SENSE_UUID,
|
||||||
@ -52,15 +53,21 @@ class BLETemperature:
|
|||||||
self._connections.remove(conn_handle)
|
self._connections.remove(conn_handle)
|
||||||
# Start advertising again to allow a new connection.
|
# Start advertising again to allow a new connection.
|
||||||
self._advertise()
|
self._advertise()
|
||||||
|
elif event == _IRQ_GATTS_INDICATE_DONE:
|
||||||
|
conn_handle, value_handle, status, = data
|
||||||
|
|
||||||
def set_temperature(self, temp_deg_c, notify=False):
|
def set_temperature(self, temp_deg_c, notify=False, indicate=False):
|
||||||
# Data is sint16 in degrees Celsius with a resolution of 0.01 degrees Celsius.
|
# Data is sint16 in degrees Celsius with a resolution of 0.01 degrees Celsius.
|
||||||
# Write the local value, ready for a central to read.
|
# Write the local value, ready for a central to read.
|
||||||
self._ble.gatts_write(self._handle, struct.pack("<h", int(temp_deg_c * 100)))
|
self._ble.gatts_write(self._handle, struct.pack("<h", int(temp_deg_c * 100)))
|
||||||
if notify:
|
if notify or indicate:
|
||||||
for conn_handle in self._connections:
|
for conn_handle in self._connections:
|
||||||
# Notify connected centrals to issue a read.
|
if notify:
|
||||||
self._ble.gatts_notify(conn_handle, self._handle)
|
# Notify connected centrals.
|
||||||
|
self._ble.gatts_notify(conn_handle, self._handle)
|
||||||
|
if indicate:
|
||||||
|
# Indicate connected centrals.
|
||||||
|
self._ble.gatts_indicate(conn_handle, self._handle)
|
||||||
|
|
||||||
def _advertise(self, interval_us=500000):
|
def _advertise(self, interval_us=500000):
|
||||||
self._ble.gap_advertise(interval_us, adv_data=self._payload)
|
self._ble.gap_advertise(interval_us, adv_data=self._payload)
|
||||||
@ -76,7 +83,7 @@ def demo():
|
|||||||
while True:
|
while True:
|
||||||
# Write every second, notify every 10 seconds.
|
# Write every second, notify every 10 seconds.
|
||||||
i = (i + 1) % 10
|
i = (i + 1) % 10
|
||||||
temp.set_temperature(t, notify=i == 0)
|
temp.set_temperature(t, notify=i == 0, indicate=False)
|
||||||
# Random walk the temperature.
|
# Random walk the temperature.
|
||||||
t += random.uniform(-0.5, 0.5)
|
t += random.uniform(-0.5, 0.5)
|
||||||
time.sleep_ms(1000)
|
time.sleep_ms(1000)
|
||||||
|
@ -238,6 +238,37 @@ STATIC mp_btstack_pending_op_t *btstack_finish_pending_operation(uint16_t op_typ
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// This needs to be separate to btstack_packet_handler otherwise we get
|
||||||
|
// dual-delivery of the HCI_EVENT_LE_META event.
|
||||||
|
STATIC void btstack_packet_handler_att_server(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
|
||||||
|
(void)channel;
|
||||||
|
(void)size;
|
||||||
|
DEBUG_EVENT_printf("btstack_packet_handler_att_server(packet_type=%u, packet=%p)\n", packet_type, packet);
|
||||||
|
if (packet_type != HCI_EVENT_PACKET) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t event_type = hci_event_packet_get_type(packet);
|
||||||
|
|
||||||
|
if (event_type == ATT_EVENT_CONNECTED) {
|
||||||
|
DEBUG_EVENT_printf(" --> att connected\n");
|
||||||
|
// The ATT_EVENT_*CONNECTED events are fired for both peripheral and central role, with no way to tell which.
|
||||||
|
// So we use the HCI_EVENT_LE_META event directly in the main packet handler.
|
||||||
|
} else if (event_type == ATT_EVENT_DISCONNECTED) {
|
||||||
|
DEBUG_EVENT_printf(" --> att disconnected\n");
|
||||||
|
} else if (event_type == ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE) {
|
||||||
|
DEBUG_EVENT_printf(" --> att indication complete\n");
|
||||||
|
uint16_t conn_handle = att_event_handle_value_indication_complete_get_conn_handle(packet);
|
||||||
|
uint16_t value_handle = att_event_handle_value_indication_complete_get_attribute_handle(packet);
|
||||||
|
uint8_t status = att_event_handle_value_indication_complete_get_status(packet);
|
||||||
|
mp_bluetooth_gatts_on_indicate_complete(conn_handle, value_handle, status);
|
||||||
|
} else if (event_type == HCI_EVENT_LE_META || event_type == HCI_EVENT_DISCONNECTION_COMPLETE) {
|
||||||
|
// Ignore, duplicated by att_server.c.
|
||||||
|
} else {
|
||||||
|
DEBUG_EVENT_printf(" --> hci att server event type: unknown (0x%02x)\n", event_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t irq) {
|
STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t irq) {
|
||||||
DEBUG_EVENT_printf("btstack_packet_handler(packet_type=%u, packet=%p)\n", packet_type, packet);
|
DEBUG_EVENT_printf("btstack_packet_handler(packet_type=%u, packet=%p)\n", packet_type, packet);
|
||||||
if (packet_type != HCI_EVENT_PACKET) {
|
if (packet_type != HCI_EVENT_PACKET) {
|
||||||
@ -245,11 +276,8 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t event_type = hci_event_packet_get_type(packet);
|
uint8_t event_type = hci_event_packet_get_type(packet);
|
||||||
if (event_type == ATT_EVENT_CONNECTED) {
|
|
||||||
DEBUG_EVENT_printf(" --> att connected\n");
|
if (event_type == HCI_EVENT_LE_META) {
|
||||||
} else if (event_type == ATT_EVENT_DISCONNECTED) {
|
|
||||||
DEBUG_EVENT_printf(" --> att disconnected\n");
|
|
||||||
} else if (event_type == HCI_EVENT_LE_META) {
|
|
||||||
DEBUG_EVENT_printf(" --> hci le meta\n");
|
DEBUG_EVENT_printf(" --> hci le meta\n");
|
||||||
if (hci_event_le_meta_get_subevent_code(packet) == HCI_SUBEVENT_LE_CONNECTION_COMPLETE) {
|
if (hci_event_le_meta_get_subevent_code(packet) == HCI_SUBEVENT_LE_CONNECTION_COMPLETE) {
|
||||||
uint16_t conn_handle = hci_subevent_le_connection_complete_get_connection_handle(packet);
|
uint16_t conn_handle = hci_subevent_le_connection_complete_get_connection_handle(packet);
|
||||||
@ -277,7 +305,7 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
|
|||||||
mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;
|
mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;
|
||||||
}
|
}
|
||||||
} else if (event_type == HCI_EVENT_TRANSPORT_PACKET_SENT) {
|
} else if (event_type == HCI_EVENT_TRANSPORT_PACKET_SENT) {
|
||||||
DEBUG_EVENT_printf(" --> hci transport packet set\n");
|
DEBUG_EVENT_printf(" --> hci transport packet sent\n");
|
||||||
} else if (event_type == HCI_EVENT_COMMAND_COMPLETE) {
|
} else if (event_type == HCI_EVENT_COMMAND_COMPLETE) {
|
||||||
DEBUG_EVENT_printf(" --> hci command complete\n");
|
DEBUG_EVENT_printf(" --> hci command complete\n");
|
||||||
} else if (event_type == HCI_EVENT_COMMAND_STATUS) {
|
} else if (event_type == HCI_EVENT_COMMAND_STATUS) {
|
||||||
@ -288,6 +316,8 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
|
|||||||
DEBUG_EVENT_printf(" --> btstack # conns changed\n");
|
DEBUG_EVENT_printf(" --> btstack # conns changed\n");
|
||||||
} else if (event_type == HCI_EVENT_VENDOR_SPECIFIC) {
|
} else if (event_type == HCI_EVENT_VENDOR_SPECIFIC) {
|
||||||
DEBUG_EVENT_printf(" --> hci vendor specific\n");
|
DEBUG_EVENT_printf(" --> hci vendor specific\n");
|
||||||
|
} else if (event_type == GATT_EVENT_MTU) {
|
||||||
|
DEBUG_EVENT_printf(" --> hci MTU\n");
|
||||||
} else if (event_type == HCI_EVENT_DISCONNECTION_COMPLETE) {
|
} else if (event_type == HCI_EVENT_DISCONNECTION_COMPLETE) {
|
||||||
DEBUG_EVENT_printf(" --> hci disconnect complete\n");
|
DEBUG_EVENT_printf(" --> hci disconnect complete\n");
|
||||||
uint16_t conn_handle = hci_event_disconnection_complete_get_connection_handle(packet);
|
uint16_t conn_handle = hci_event_disconnection_complete_get_connection_handle(packet);
|
||||||
@ -500,6 +530,9 @@ int mp_bluetooth_init(void) {
|
|||||||
// Register for HCI events.
|
// Register for HCI events.
|
||||||
hci_add_event_handler(&hci_event_callback_registration);
|
hci_add_event_handler(&hci_event_callback_registration);
|
||||||
|
|
||||||
|
// Register for ATT server events.
|
||||||
|
att_server_register_packet_handler(&btstack_packet_handler_att_server);
|
||||||
|
|
||||||
// Set a timeout for HCI initialisation.
|
// Set a timeout for HCI initialisation.
|
||||||
btstack_run_loop_set_timer(&btstack_init_deinit_timeout, BTSTACK_INIT_DEINIT_TIMEOUT_MS);
|
btstack_run_loop_set_timer(&btstack_init_deinit_timeout, BTSTACK_INIT_DEINIT_TIMEOUT_MS);
|
||||||
btstack_run_loop_set_timer_handler(&btstack_init_deinit_timeout, btstack_init_deinit_timeout_handler);
|
btstack_run_loop_set_timer_handler(&btstack_init_deinit_timeout, btstack_init_deinit_timeout_handler);
|
||||||
@ -816,7 +849,8 @@ int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) {
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, &data, &len);
|
mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, &data, &len);
|
||||||
|
|
||||||
// TODO: Handle ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE to generate acknowledgment event.
|
// Indicate will raise ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE when
|
||||||
|
// acknowledged (or timeout/error).
|
||||||
|
|
||||||
// Attempt to send immediately, will copy buffer.
|
// Attempt to send immediately, will copy buffer.
|
||||||
MICROPY_PY_BLUETOOTH_ENTER
|
MICROPY_PY_BLUETOOTH_ENTER
|
||||||
|
@ -800,6 +800,7 @@ STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table[] = {
|
|||||||
{ MP_ROM_QSTR(MP_QSTR_FLAG_READ), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ) },
|
{ MP_ROM_QSTR(MP_QSTR_FLAG_READ), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_FLAG_WRITE), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE) },
|
{ MP_ROM_QSTR(MP_QSTR_FLAG_WRITE), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_FLAG_NOTIFY), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY) },
|
{ MP_ROM_QSTR(MP_QSTR_FLAG_NOTIFY), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_FLAG_INDICATE), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_INDICATE) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_FLAG_WRITE_NO_RESPONSE), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_NO_RESPONSE) },
|
{ MP_ROM_QSTR(MP_QSTR_FLAG_WRITE_NO_RESPONSE), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_NO_RESPONSE) },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -887,6 +888,9 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) {
|
|||||||
} else if (event == MP_BLUETOOTH_IRQ_GATTS_WRITE) {
|
} else if (event == MP_BLUETOOTH_IRQ_GATTS_WRITE) {
|
||||||
// conn_handle, value_handle
|
// conn_handle, value_handle
|
||||||
ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, NULL, NULL);
|
ringbuf_extract(&o->ringbuf, data_tuple, 2, 0, NULL, 0, NULL, NULL);
|
||||||
|
} else if (event == MP_BLUETOOTH_IRQ_GATTS_INDICATE_DONE) {
|
||||||
|
// conn_handle, value_handle, status
|
||||||
|
ringbuf_extract(&o->ringbuf, data_tuple, 2, 1, NULL, 0, NULL, NULL);
|
||||||
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
|
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
|
||||||
} else if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT) {
|
} else if (event == MP_BLUETOOTH_IRQ_SCAN_RESULT) {
|
||||||
// addr_type, addr, adv_type, rssi, adv_data
|
// addr_type, addr, adv_type, rssi, adv_data
|
||||||
@ -999,6 +1003,17 @@ void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle) {
|
|||||||
schedule_ringbuf(atomic_state);
|
schedule_ringbuf(atomic_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mp_bluetooth_gatts_on_indicate_complete(uint16_t conn_handle, uint16_t value_handle, uint8_t status) {
|
||||||
|
MICROPY_PY_BLUETOOTH_ENTER
|
||||||
|
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
|
||||||
|
if (enqueue_irq(o, 2 + 2 + 1, MP_BLUETOOTH_IRQ_GATTS_INDICATE_DONE)) {
|
||||||
|
ringbuf_put16(&o->ringbuf, conn_handle);
|
||||||
|
ringbuf_put16(&o->ringbuf, value_handle);
|
||||||
|
ringbuf_put(&o->ringbuf, status);
|
||||||
|
}
|
||||||
|
schedule_ringbuf(atomic_state);
|
||||||
|
}
|
||||||
|
|
||||||
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
|
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
|
||||||
void mp_bluetooth_gap_on_scan_complete(void) {
|
void mp_bluetooth_gap_on_scan_complete(void) {
|
||||||
MICROPY_PY_BLUETOOTH_ENTER
|
MICROPY_PY_BLUETOOTH_ENTER
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_NO_RESPONSE (1 << 2)
|
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_NO_RESPONSE (1 << 2)
|
||||||
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE (1 << 3)
|
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE (1 << 3)
|
||||||
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY (1 << 4)
|
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY (1 << 4)
|
||||||
|
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_INDICATE (1 << 5)
|
||||||
|
|
||||||
// For mp_bluetooth_gattc_write, the mode parameter
|
// For mp_bluetooth_gattc_write, the mode parameter
|
||||||
#define MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE (0)
|
#define MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE (0)
|
||||||
@ -107,6 +108,7 @@
|
|||||||
#define MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE (17)
|
#define MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE (17)
|
||||||
#define MP_BLUETOOTH_IRQ_GATTC_NOTIFY (18)
|
#define MP_BLUETOOTH_IRQ_GATTC_NOTIFY (18)
|
||||||
#define MP_BLUETOOTH_IRQ_GATTC_INDICATE (19)
|
#define MP_BLUETOOTH_IRQ_GATTC_INDICATE (19)
|
||||||
|
#define MP_BLUETOOTH_IRQ_GATTS_INDICATE_DONE (20)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
These aren't included in the module for space reasons, but can be used
|
These aren't included in the module for space reasons, but can be used
|
||||||
@ -132,6 +134,7 @@ _IRQ_GATTC_READ_DONE = const(16)
|
|||||||
_IRQ_GATTC_WRITE_DONE = const(17)
|
_IRQ_GATTC_WRITE_DONE = const(17)
|
||||||
_IRQ_GATTC_NOTIFY = const(18)
|
_IRQ_GATTC_NOTIFY = const(18)
|
||||||
_IRQ_GATTC_INDICATE = const(19)
|
_IRQ_GATTC_INDICATE = const(19)
|
||||||
|
_IRQ_GATTS_INDICATE_DONE = const(20)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Common UUID type.
|
// Common UUID type.
|
||||||
@ -245,6 +248,9 @@ void mp_bluetooth_gap_on_connected_disconnected(uint8_t event, uint16_t conn_han
|
|||||||
// Call this when a characteristic is written to.
|
// Call this when a characteristic is written to.
|
||||||
void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle);
|
void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle);
|
||||||
|
|
||||||
|
// Call this when an acknowledgment is received for an indication.
|
||||||
|
void mp_bluetooth_gatts_on_indicate_complete(uint16_t conn_handle, uint16_t value_handle, uint8_t status);
|
||||||
|
|
||||||
#if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK
|
#if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK
|
||||||
// Call this when a characteristic is read from. Return false to deny the read.
|
// Call this when a characteristic is read from. Return false to deny the read.
|
||||||
bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle);
|
bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle);
|
||||||
|
@ -248,6 +248,15 @@ STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) {
|
|||||||
reverse_addr_byte_order(addr, event->disconnect.conn.peer_id_addr.val);
|
reverse_addr_byte_order(addr, event->disconnect.conn.peer_id_addr.val);
|
||||||
mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, event->disconnect.conn.conn_handle, event->disconnect.conn.peer_id_addr.type, addr);
|
mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, event->disconnect.conn.conn_handle, event->disconnect.conn.peer_id_addr.type, addr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BLE_GAP_EVENT_NOTIFY_TX: {
|
||||||
|
DEBUG_EVENT_printf("gap_event_cb: notify_tx: %d %d\n", event->notify_tx.indication, event->notify_tx.status);
|
||||||
|
// This event corresponds to either a sent notify/indicate (status == 0), or an indication confirmation (status != 0).
|
||||||
|
if (event->notify_tx.indication && event->notify_tx.status != 0) {
|
||||||
|
// Map "done/ack" to 0, otherwise pass the status directly.
|
||||||
|
mp_bluetooth_gatts_on_indicate_complete(event->notify_tx.conn_handle, event->notify_tx.attr_handle, event->notify_tx.status == BLE_HS_EDONE ? 0 : event->notify_tx.status);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -603,8 +612,8 @@ int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) {
|
|||||||
if (!mp_bluetooth_is_active()) {
|
if (!mp_bluetooth_is_active()) {
|
||||||
return ERRNO_BLUETOOTH_NOT_ACTIVE;
|
return ERRNO_BLUETOOTH_NOT_ACTIVE;
|
||||||
}
|
}
|
||||||
// TODO: catch BLE_GAP_EVENT_NOTIFY_TX to raise an event for completed
|
// This will raise BLE_GAP_EVENT_NOTIFY_TX with a status when it is
|
||||||
// indication transaction.
|
// acknowledged (or timeout/error).
|
||||||
return ble_hs_err_to_errno(ble_gattc_indicate(conn_handle, value_handle));
|
return ble_hs_err_to_errno(ble_gattc_indicate(conn_handle, value_handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,12 +17,13 @@ _IRQ_GATTC_READ_DONE = const(16)
|
|||||||
_IRQ_GATTC_WRITE_DONE = const(17)
|
_IRQ_GATTC_WRITE_DONE = const(17)
|
||||||
_IRQ_GATTC_NOTIFY = const(18)
|
_IRQ_GATTC_NOTIFY = const(18)
|
||||||
_IRQ_GATTC_INDICATE = const(19)
|
_IRQ_GATTC_INDICATE = const(19)
|
||||||
|
_IRQ_GATTS_INDICATE_DONE = const(20)
|
||||||
|
|
||||||
SERVICE_UUID = bluetooth.UUID("A5A5A5A5-FFFF-9999-1111-5A5A5A5A5A5A")
|
SERVICE_UUID = bluetooth.UUID("A5A5A5A5-FFFF-9999-1111-5A5A5A5A5A5A")
|
||||||
CHAR_UUID = bluetooth.UUID("00000000-1111-2222-3333-444444444444")
|
CHAR_UUID = bluetooth.UUID("00000000-1111-2222-3333-444444444444")
|
||||||
CHAR = (
|
CHAR = (
|
||||||
CHAR_UUID,
|
CHAR_UUID,
|
||||||
bluetooth.FLAG_READ | bluetooth.FLAG_WRITE | bluetooth.FLAG_NOTIFY,
|
bluetooth.FLAG_READ | bluetooth.FLAG_WRITE | bluetooth.FLAG_NOTIFY | bluetooth.FLAG_INDICATE,
|
||||||
)
|
)
|
||||||
SERVICE = (
|
SERVICE = (
|
||||||
SERVICE_UUID,
|
SERVICE_UUID,
|
||||||
@ -62,6 +63,8 @@ def irq(event, data):
|
|||||||
print("_IRQ_GATTC_NOTIFY", data[-1])
|
print("_IRQ_GATTC_NOTIFY", data[-1])
|
||||||
elif event == _IRQ_GATTC_INDICATE:
|
elif event == _IRQ_GATTC_INDICATE:
|
||||||
print("_IRQ_GATTC_INDICATE", data[-1])
|
print("_IRQ_GATTC_INDICATE", data[-1])
|
||||||
|
elif event == _IRQ_GATTS_INDICATE_DONE:
|
||||||
|
print("_IRQ_GATTS_INDICATE_DONE", data[-1])
|
||||||
|
|
||||||
if waiting_event is not None:
|
if waiting_event is not None:
|
||||||
if (isinstance(waiting_event, int) and event == waiting_event) or (
|
if (isinstance(waiting_event, int) and event == waiting_event) or (
|
||||||
@ -128,6 +131,9 @@ def instance0():
|
|||||||
print("gatts_indicate")
|
print("gatts_indicate")
|
||||||
ble.gatts_indicate(conn_handle, char_handle)
|
ble.gatts_indicate(conn_handle, char_handle)
|
||||||
|
|
||||||
|
# Wait for the indicate ack.
|
||||||
|
wait_for_event(_IRQ_GATTS_INDICATE_DONE, TIMEOUT_MS)
|
||||||
|
|
||||||
# Wait for the central to disconnect.
|
# Wait for the central to disconnect.
|
||||||
wait_for_event(_IRQ_CENTRAL_DISCONNECT, TIMEOUT_MS)
|
wait_for_event(_IRQ_CENTRAL_DISCONNECT, TIMEOUT_MS)
|
||||||
finally:
|
finally:
|
||||||
|
@ -9,6 +9,7 @@ gatts_notify
|
|||||||
_IRQ_GATTS_WRITE b'central2'
|
_IRQ_GATTS_WRITE b'central2'
|
||||||
gatts_write
|
gatts_write
|
||||||
gatts_indicate
|
gatts_indicate
|
||||||
|
_IRQ_GATTS_INDICATE_DONE 0
|
||||||
_IRQ_CENTRAL_DISCONNECT
|
_IRQ_CENTRAL_DISCONNECT
|
||||||
--- instance1 ---
|
--- instance1 ---
|
||||||
gap_connect
|
gap_connect
|
||||||
|
Loading…
Reference in New Issue
Block a user