2016-06-14 15:30:07 +02:00
|
|
|
#include "pxt.h"
|
|
|
|
#include "MESEvents.h"
|
2016-06-23 09:05:49 +02:00
|
|
|
#include "MicroBitUARTService.h"
|
2019-12-02 05:58:26 +01:00
|
|
|
#include "BLEHF2Service.h"
|
2016-06-14 15:30:07 +02:00
|
|
|
|
|
|
|
using namespace pxt;
|
2016-06-21 20:17:34 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Support for additional Bluetooth services.
|
|
|
|
*/
|
2017-09-19 23:54:46 +02:00
|
|
|
//% color=#0082FB weight=96 icon="\uf294"
|
2016-06-14 15:30:07 +02:00
|
|
|
namespace bluetooth {
|
2016-06-24 17:12:52 +02:00
|
|
|
MicroBitUARTService *uart = NULL;
|
2019-12-02 05:58:26 +01:00
|
|
|
BLEHF2Service* pHF2 = NULL;
|
2016-06-24 17:12:52 +02:00
|
|
|
|
2019-12-02 05:58:26 +01:00
|
|
|
//%
|
|
|
|
void __log(String msg) {
|
|
|
|
if (NULL == pHF2)
|
|
|
|
pHF2 = new BLEHF2Service(*uBit.ble);
|
|
|
|
pHF2->sendSerial(msg->getUTF8Data(), msg->getUTF8Size(), false);
|
|
|
|
}
|
2016-10-19 06:36:42 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts the Bluetooth accelerometer service
|
|
|
|
*/
|
|
|
|
//% help=bluetooth/start-accelerometer-service
|
|
|
|
//% blockId=bluetooth_start_accelerometer_service block="bluetooth accelerometer service"
|
|
|
|
//% parts="bluetooth" weight=90 blockGap=8
|
|
|
|
void startAccelerometerService() {
|
|
|
|
new MicroBitAccelerometerService(*uBit.ble, uBit.accelerometer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts the Bluetooth button service
|
|
|
|
*/
|
|
|
|
//% help=bluetooth/start-button-service
|
|
|
|
//% blockId=bluetooth_start_button_service block="bluetooth button service" blockGap=8
|
|
|
|
//% parts="bluetooth" weight=89
|
|
|
|
void startButtonService() {
|
|
|
|
new MicroBitButtonService(*uBit.ble);
|
|
|
|
}
|
|
|
|
|
2016-06-14 15:30:07 +02:00
|
|
|
/**
|
2016-06-20 09:39:51 +02:00
|
|
|
* Starts the Bluetooth IO pin service.
|
2016-06-14 15:30:07 +02:00
|
|
|
*/
|
2016-06-14 22:17:20 +02:00
|
|
|
//% help=bluetooth/start-io-pin-service
|
2016-06-14 22:47:18 +02:00
|
|
|
//% blockId=bluetooth_start_io_pin_service block="bluetooth io pin service" blockGap=8
|
2016-10-19 06:36:42 +02:00
|
|
|
//% parts="bluetooth" weight=88
|
2016-06-14 15:30:07 +02:00
|
|
|
void startIOPinService() {
|
|
|
|
new MicroBitIOPinService(*uBit.ble, uBit.io);
|
|
|
|
}
|
2016-06-14 22:17:20 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts the Bluetooth LED service
|
|
|
|
*/
|
|
|
|
//% help=bluetooth/start-led-service
|
2016-06-14 22:47:18 +02:00
|
|
|
//% blockId=bluetooth_start_led_service block="bluetooth led service" blockGap=8
|
2016-10-19 06:36:42 +02:00
|
|
|
//% parts="bluetooth" weight=87
|
2016-06-14 22:17:20 +02:00
|
|
|
void startLEDService() {
|
|
|
|
new MicroBitLEDService(*uBit.ble, uBit.display);
|
|
|
|
}
|
2016-06-14 22:24:55 +02:00
|
|
|
|
|
|
|
/**
|
2016-06-20 09:39:51 +02:00
|
|
|
* Starts the Bluetooth temperature service
|
2016-06-14 22:24:55 +02:00
|
|
|
*/
|
|
|
|
//% help=bluetooth/start-temperature-service
|
2016-06-14 22:47:18 +02:00
|
|
|
//% blockId=bluetooth_start_temperature_service block="bluetooth temperature service" blockGap=8
|
2016-10-19 06:36:42 +02:00
|
|
|
//% parts="bluetooth" weight=86
|
2016-06-14 22:24:55 +02:00
|
|
|
void startTemperatureService() {
|
|
|
|
new MicroBitTemperatureService(*uBit.ble, uBit.thermometer);
|
|
|
|
}
|
2016-06-14 22:39:24 +02:00
|
|
|
|
|
|
|
/**
|
2016-06-20 09:39:51 +02:00
|
|
|
* Starts the Bluetooth magnetometer service
|
2016-06-14 22:39:24 +02:00
|
|
|
*/
|
|
|
|
//% help=bluetooth/start-magnetometer-service
|
2016-10-19 06:36:42 +02:00
|
|
|
//% blockId=bluetooth_start_magnetometer_service block="bluetooth magnetometer service"
|
|
|
|
//% parts="bluetooth" weight=85
|
2016-06-14 22:39:24 +02:00
|
|
|
void startMagnetometerService() {
|
|
|
|
new MicroBitMagnetometerService(*uBit.ble, uBit.compass);
|
|
|
|
}
|
2016-06-14 22:47:18 +02:00
|
|
|
|
2016-06-23 09:05:49 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Starts the Bluetooth UART service
|
|
|
|
*/
|
2016-08-09 17:10:53 +02:00
|
|
|
//% help=bluetooth/start-uart-service
|
2016-10-19 06:36:42 +02:00
|
|
|
//% blockId=bluetooth_start_uart_service block="bluetooth uart service"
|
|
|
|
//% parts="bluetooth" advanced=true
|
2016-06-23 09:05:49 +02:00
|
|
|
void startUartService() {
|
2016-06-24 17:12:52 +02:00
|
|
|
if (uart) return;
|
2016-06-23 12:38:23 +02:00
|
|
|
// 61 octet buffer size is 3 x (MTU - 3) + 1
|
|
|
|
// MTU on nRF51822 is 23 octets. 3 are used by Attribute Protocol header data leaving 20 octets for payload
|
2016-06-24 08:59:08 +02:00
|
|
|
// So we allow a RX buffer that can contain 3 x max length messages plus one octet for a terminator character
|
2016-06-23 12:38:23 +02:00
|
|
|
uart = new MicroBitUARTService(*uBit.ble, 61, 60);
|
2016-06-23 09:05:49 +02:00
|
|
|
}
|
2016-06-23 12:38:23 +02:00
|
|
|
|
2016-09-02 17:03:55 +02:00
|
|
|
//%
|
2019-12-02 05:58:26 +01:00
|
|
|
void uartWriteString(String data) {
|
2016-06-24 17:12:52 +02:00
|
|
|
startUartService();
|
2019-12-02 05:58:26 +01:00
|
|
|
uart->send(MSTR(data));
|
2016-06-23 12:38:23 +02:00
|
|
|
}
|
2016-06-24 08:59:08 +02:00
|
|
|
|
2016-09-02 17:03:55 +02:00
|
|
|
//%
|
2019-12-02 05:58:26 +01:00
|
|
|
String uartReadUntil(String del) {
|
2016-06-24 17:12:52 +02:00
|
|
|
startUartService();
|
2019-12-02 05:58:26 +01:00
|
|
|
return PSTR(uart->readUntil(MSTR(del)));
|
2016-06-24 09:46:05 +02:00
|
|
|
}
|
|
|
|
|
2019-12-02 05:58:26 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a buffer of data via Bluetooth UART
|
|
|
|
*/
|
|
|
|
//%
|
|
|
|
void uartWriteBuffer(Buffer buffer) {
|
|
|
|
startUartService();
|
|
|
|
uart->send(buffer->data, buffer->length);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads buffered UART data into a buffer
|
|
|
|
*/
|
|
|
|
//%
|
|
|
|
Buffer uartReadBuffer() {
|
|
|
|
startUartService();
|
|
|
|
int bytes = uart->rxBufferedSize();
|
|
|
|
auto buffer = mkBuffer(NULL, bytes);
|
|
|
|
int read = uart->read(buffer->data, buffer->length);
|
|
|
|
// read failed
|
|
|
|
if (read < 0) {
|
|
|
|
decrRC(buffer);
|
|
|
|
return mkBuffer(NULL, 0);
|
|
|
|
}
|
|
|
|
// could not fill the buffer
|
|
|
|
if (read != buffer->length) {
|
|
|
|
auto tmp = mkBuffer(buffer->data, read);
|
|
|
|
decrRC(buffer);
|
|
|
|
buffer = tmp;
|
|
|
|
}
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
2017-09-19 23:54:46 +02:00
|
|
|
/**
|
|
|
|
* Registers an event to be fired when one of the delimiter is matched.
|
|
|
|
* @param delimiters the characters to match received characters against.
|
|
|
|
*/
|
|
|
|
//% help=bluetooth/on-uart-data-received
|
|
|
|
//% weight=18 blockId=bluetooth_on_data_received block="bluetooth|on data received %delimiters=serial_delimiter_conv"
|
2019-12-02 05:58:26 +01:00
|
|
|
void onUartDataReceived(String delimiters, Action body) {
|
2017-09-19 23:54:46 +02:00
|
|
|
startUartService();
|
2019-12-02 05:58:26 +01:00
|
|
|
uart->eventOn(MSTR(delimiters));
|
2017-09-19 23:54:46 +02:00
|
|
|
registerWithDal(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_DELIM_MATCH, body);
|
|
|
|
}
|
|
|
|
|
2016-06-24 08:59:08 +02:00
|
|
|
/**
|
|
|
|
* Register code to run when the micro:bit is connected to over Bluetooth
|
|
|
|
* @param body Code to run when a Bluetooth connection is established
|
|
|
|
*/
|
2016-06-24 17:12:52 +02:00
|
|
|
//% help=bluetooth/on-bluetooth-connected weight=20
|
|
|
|
//% blockId=bluetooth_on_connected block="on bluetooth connected" blockGap=8
|
2016-08-22 17:48:48 +02:00
|
|
|
//% parts="bluetooth"
|
2016-06-24 08:59:08 +02:00
|
|
|
void onBluetoothConnected(Action body) {
|
|
|
|
registerWithDal(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_CONNECTED, body);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Register code to run when a bluetooth connection to the micro:bit is lost
|
|
|
|
* @param body Code to run when a Bluetooth connection is lost
|
|
|
|
*/
|
2016-06-24 17:12:52 +02:00
|
|
|
//% help=bluetooth/on-bluetooth-disconnected weight=19
|
2016-06-24 08:59:08 +02:00
|
|
|
//% blockId=bluetooth_on_disconnected block="on bluetooth disconnected"
|
2016-08-22 17:48:48 +02:00
|
|
|
//% parts="bluetooth"
|
2016-06-24 08:59:08 +02:00
|
|
|
void onBluetoothDisconnected(Action body) {
|
|
|
|
registerWithDal(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED, body);
|
2019-12-02 05:58:26 +01:00
|
|
|
}
|
2017-09-19 23:54:46 +02:00
|
|
|
|
|
|
|
const int8_t CALIBRATED_POWERS[] = {-49, -37, -33, -28, -25, -20, -15, -10};
|
|
|
|
/**
|
|
|
|
* Advertise an Eddystone URL
|
|
|
|
* @param url the url to transmit. Must be no longer than the supported eddystone url length, eg: "https://makecode.com"
|
|
|
|
* @param power power level between 0 and 7, eg: 7
|
|
|
|
* @param connectable true to keep bluetooth connectable for other services, false otherwise.
|
|
|
|
*/
|
|
|
|
//% blockId=eddystone_advertise_url block="bluetooth advertise url %url|with power %power|connectable %connectable"
|
|
|
|
//% parts=bluetooth weight=11 blockGap=8
|
|
|
|
//% help=bluetooth/advertise-url blockExternalInputs=1
|
2019-12-02 05:58:26 +01:00
|
|
|
void advertiseUrl(String url, int power, bool connectable) {
|
|
|
|
#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_URL)
|
2017-09-19 23:54:46 +02:00
|
|
|
power = min(MICROBIT_BLE_POWER_LEVELS-1, max(0, power));
|
|
|
|
int8_t level = CALIBRATED_POWERS[power];
|
2019-12-02 05:58:26 +01:00
|
|
|
uBit.bleManager.advertiseEddystoneUrl(MSTR(url), level, connectable);
|
2017-09-19 23:54:46 +02:00
|
|
|
uBit.bleManager.setTransmitPower(power);
|
2019-12-02 05:58:26 +01:00
|
|
|
#endif
|
2017-09-19 23:54:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Advertise an Eddystone UID
|
|
|
|
* @param nsAndInstance 16 bytes buffer of namespace (bytes 0-9) and instance (bytes 10-15)
|
|
|
|
* @param power power level between 0 and 7, eg: 7
|
|
|
|
* @param connectable true to keep bluetooth connectable for other services, false otherwise.
|
|
|
|
*/
|
|
|
|
//% parts=bluetooth weight=12 advanced=true
|
|
|
|
void advertiseUidBuffer(Buffer nsAndInstance, int power, bool connectable) {
|
2019-12-02 05:58:26 +01:00
|
|
|
#if CONFIG_ENABLED(MICROBIT_BLE_EDDYSTONE_UID)
|
|
|
|
auto buf = nsAndInstance;
|
|
|
|
if (buf->length != 16) return;
|
2017-09-19 23:54:46 +02:00
|
|
|
|
|
|
|
power = min(MICROBIT_BLE_POWER_LEVELS-1, max(0, power));
|
|
|
|
int8_t level = CALIBRATED_POWERS[power];
|
2019-12-02 05:58:26 +01:00
|
|
|
uBit.bleManager.advertiseEddystoneUid((const char*)buf->data, (const char*)buf->data + 10, level, connectable);
|
|
|
|
#endif
|
2017-09-19 23:54:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the bluetooth transmit power between 0 (minimal) and 7 (maximum).
|
|
|
|
* @param power power level between 0 (minimal) and 7 (maximum), eg: 7.
|
|
|
|
*/
|
|
|
|
//% parts=bluetooth weight=5 help=bluetooth/set-transmit-power advanced=true
|
|
|
|
//% blockId=bluetooth_settransmitpower block="bluetooth set transmit power %power"
|
|
|
|
void setTransmitPower(int power) {
|
|
|
|
uBit.bleManager.setTransmitPower(min(MICROBIT_BLE_POWER_LEVELS-1, max(0, power)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stops advertising Eddystone end points
|
|
|
|
*/
|
|
|
|
//% blockId=eddystone_stop_advertising block="bluetooth stop advertising"
|
|
|
|
//% parts=bluetooth weight=10
|
|
|
|
//% help=bluetooth/stop-advertising advanced=true
|
|
|
|
void stopAdvertising() {
|
|
|
|
uBit.bleManager.stopAdvertising();
|
2019-12-02 05:58:26 +01:00
|
|
|
}
|
2016-06-24 08:59:08 +02:00
|
|
|
}
|