diff --git a/libs/bluetooth/BLEHF2Service.cpp b/libs/bluetooth/BLEHF2Service.cpp
new file mode 100644
index 00000000..7911df26
--- /dev/null
+++ b/libs/bluetooth/BLEHF2Service.cpp
@@ -0,0 +1,50 @@
+#include "MicroBitConfig.h"
+#include "ble/UUID.h"
+#include "BLEHF2Service.h"
+#include "MicroBitEvent.h"
+
+BLEHF2Service::BLEHF2Service(BLEDevice &_ble) :
+ ble(_ble)
+{
+ GattCharacteristic txCharacteristic(BLEHF2TxCharacteristicUUID, (uint8_t *)&txCharacteristicMessage, 0,
+ sizeof(txCharacteristicMessage), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
+
+ // Initialise our characteristic values.
+ memset(&txCharacteristicMessage, 0, sizeof(txCharacteristicMessage));
+
+ // Set default security requirements
+ txCharacteristic.requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL);
+
+ // setup GATT table
+ GattCharacteristic *characteristics[] = {&txCharacteristic};
+ GattService service(BLEHF2ServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
+ ble.addService(service);
+
+ // retreive handles
+ txCharacteristicHandle = txCharacteristic.getValueHandle();
+
+ // initialize data
+ ble.gattServer().write(txCharacteristicHandle,(uint8_t *)&txCharacteristicMessage, sizeof(txCharacteristicMessage));
+}
+
+void BLEHF2Service::sendSerial(const char *data, int len, bool isError) {
+ if (ble.getGapState().connected)
+ {
+ int32_t sent = 0;
+ while(sent < len) {
+ int32_t n = min(BLEHF2_DATA_LENGTH, len - sent);
+ txCharacteristicMessage.command = (isError ? BLEHF2_FLAG_SERIAL_OUT : BLEHF2_FLAG_SERIAL_ERR) | n;
+ memcpy(&txCharacteristicMessage.data, data + sent, n);
+ ble.gattServer().notify(txCharacteristicHandle,(uint8_t *)&txCharacteristicMessage, sizeof(txCharacteristicMessage));
+ sent += n;
+ }
+ }
+}
+
+const uint8_t BLEHF2ServiceUUID[] = {
+ 0xb1,0x12,0xf5,0xe6,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x49
+};
+
+const uint8_t BLEHF2TxCharacteristicUUID[] = {
+ 0xb1,0x12,0xf5,0xe6,0x26,0x79,0x30,0xda,0xa2,0x6e,0x02,0x73,0xb6,0x04,0x38,0x4a
+};
\ No newline at end of file
diff --git a/libs/bluetooth/BLEHF2Service.h b/libs/bluetooth/BLEHF2Service.h
new file mode 100644
index 00000000..20c67788
--- /dev/null
+++ b/libs/bluetooth/BLEHF2Service.h
@@ -0,0 +1,54 @@
+#ifndef BLE_HF2_SERVICE_H
+#define BLE_HF2_SERVICE_H
+
+#include "MicroBitConfig.h"
+#include "ble/BLE.h"
+#include "MicroBitThermometer.h"
+#include "EventModel.h"
+#include "pxt.h"
+
+#define HF2_ID 9501
+
+#define BLEHF2_FLAG_SERIAL_OUT 0x80
+#define BLEHF2_FLAG_SERIAL_ERR 0xC0
+#define BLEHF2_DATA_LENGTH 19
+
+// UUIDs for our service and characteristics
+extern const uint8_t BLEHF2ServiceUUID[];
+extern const uint8_t BLEHF2TxCharacteristicUUID[];
+
+struct BLEHF2Packet {
+ uint8_t command;
+ uint8_t data[BLEHF2_DATA_LENGTH];
+};
+
+class BLEHF2Service
+{
+ public:
+
+ /**
+ * Constructor.
+ * Create a representation of the TemperatureService
+ * @param _ble The instance of a BLE device that we're running on.
+ */
+ BLEHF2Service(BLEDevice &_ble);
+
+ /**
+ * Sends text
+ */
+ void sendSerial(const char *data, int len, bool isError);
+
+ private:
+
+ // Bluetooth stack we're running on.
+ BLEDevice &ble;
+
+ // memory for buffers.
+ BLEHF2Packet txCharacteristicMessage;
+
+ // Handles to access each characteristic when they are held by Soft Device.
+ GattAttribute::Handle_t txCharacteristicHandle;
+};
+
+
+#endif
\ No newline at end of file
diff --git a/libs/bluetooth/bluetooth.cpp b/libs/bluetooth/bluetooth.cpp
index aa666e83..10b0be36 100644
--- a/libs/bluetooth/bluetooth.cpp
+++ b/libs/bluetooth/bluetooth.cpp
@@ -1,6 +1,7 @@
#include "pxt.h"
#include "MESEvents.h"
#include "MicroBitUARTService.h"
+#include "BLEHF2Service.h"
using namespace pxt;
@@ -10,6 +11,14 @@ using namespace pxt;
//% color=#0082FB weight=96 icon="\uf294"
namespace bluetooth {
MicroBitUARTService *uart = NULL;
+ BLEHF2Service* pHF2 = NULL;
+
+ //%
+ void __log(String msg) {
+ if (NULL == pHF2)
+ pHF2 = new BLEHF2Service(*uBit.ble);
+ pHF2->sendSerial(msg->data, msg->length, false);
+ }
/**
* Starts the Bluetooth accelerometer service
diff --git a/libs/bluetooth/bluetooth.ts b/libs/bluetooth/bluetooth.ts
index 5c5ccd82..a30cf399 100644
--- a/libs/bluetooth/bluetooth.ts
+++ b/libs/bluetooth/bluetooth.ts
@@ -1,8 +1,18 @@
+///
/**
* Support for additional Bluetooth services.
*/
//% color=#007EF4 weight=96 icon="\uf294"
namespace bluetooth {
+ /**
+ * Internal use
+ */
+ //% shim=bluetooth::__log
+ export function __log(msg: string) {
+ return;
+ }
+ console.addListener(function (msg) { __log(msg) });
+
/**
* Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.
*/
diff --git a/libs/bluetooth/pxt.json b/libs/bluetooth/pxt.json
index cc0f8575..f5818816 100644
--- a/libs/bluetooth/pxt.json
+++ b/libs/bluetooth/pxt.json
@@ -6,7 +6,9 @@
"enums.d.ts",
"shims.d.ts",
"bluetooth.ts",
- "bluetooth.cpp"
+ "bluetooth.cpp",
+ "BLEHF2Service.h",
+ "BLEHF2Service.cpp"
],
"icon": "./static/packages/bluetooth/icon.png",
"public": true,
diff --git a/libs/core/_locales/core-jsdoc-strings.json b/libs/core/_locales/core-jsdoc-strings.json
index 2f2b99c5..bc8dfeba 100644
--- a/libs/core/_locales/core-jsdoc-strings.json
+++ b/libs/core/_locales/core-jsdoc-strings.json
@@ -205,6 +205,12 @@
"basic.showString": "Display text on the display, one character at a time. If the string fits on the screen (i.e. is one letter), does not scroll.",
"basic.showString|param|interval": "how fast to shift characters; eg: 150, 100, 200, -100",
"basic.showString|param|text": "the text to scroll on the screen, eg: \"Hello!\"",
+ "console": "Reading and writing data to the console output.",
+ "console.addListener": "Adds a listener for the log messages",
+ "console.log": "Write a line of text to the console output.",
+ "console.logValue": "Write a name:value pair as a line of text to the console output.",
+ "console.logValue|param|name": "name of the value stream, eg: \"x\"",
+ "console.logValue|param|value": "to write",
"control": "Runtime and event utilities.",
"control.assert": "If the condition is false, display msg on serial console, and panic with code 098.",
"control.createBuffer": "Create a new zero-initialized buffer.",
diff --git a/libs/core/_locales/core-strings.json b/libs/core/_locales/core-strings.json
index fb6fd20c..f37d45e0 100644
--- a/libs/core/_locales/core-strings.json
+++ b/libs/core/_locales/core-strings.json
@@ -240,6 +240,7 @@
"basic.showNumber|block": "show|number %number",
"basic.showString|block": "show|string %text",
"basic|block": "basic",
+ "console|block": "console",
"control.deviceName|block": "device name",
"control.deviceSerialNumber|block": "device serial number",
"control.eventSourceId|block": "%id",
diff --git a/libs/core/codal.cpp b/libs/core/codal.cpp
index d389c14e..54c52673 100644
--- a/libs/core/codal.cpp
+++ b/libs/core/codal.cpp
@@ -228,8 +228,9 @@ void debuglog(const char *format, ...)
va_end(arg);
}
-
-
+void sendSerial(const char *data, int len) {
+ logwriten(data, len);
+}
} // namespace pxt
diff --git a/libs/core/console.ts b/libs/core/console.ts
new file mode 100644
index 00000000..d2754ad3
--- /dev/null
+++ b/libs/core/console.ts
@@ -0,0 +1,53 @@
+///
+
+/**
+ * Reading and writing data to the console output.
+ */
+//% weight=12 color=#002050 icon="\uf120"
+//% advanced=true
+namespace console {
+ type Listener = (text: string) => void;
+
+ //% whenUsed
+ let listeners: Listener[] = undefined;
+
+ /**
+ * Write a line of text to the console output.
+ * @param value to send
+ */
+ //% weight=90
+ //% help=console/log blockGap=8
+ //% text.shadowOptions.toString=true
+ export function log(text: string): void {
+ // pad text on the 32byte boundar
+ text += "\r\n";
+ control.__log(text);
+ // send to listeners
+ if (listeners)
+ for (let i = 0; i < listeners.length; ++i)
+ listeners[i](text);
+ }
+
+ /**
+ * Write a name:value pair as a line of text to the console output.
+ * @param name name of the value stream, eg: "x"
+ * @param value to write
+ */
+ //% weight=88 blockGap=8
+ //% help=console/log-value
+ export function logValue(name: string, value: number): void {
+ log(name ? `${name}: ${value}` : `${value}`)
+ }
+
+ /**
+ * Adds a listener for the log messages
+ * @param listener
+ */
+ //%
+ export function addListener(listener: (text: string) => void) {
+ if (!listener) return;
+ if (!listener)
+ listeners = [];
+ listeners.push(listener);
+ }
+}
\ No newline at end of file
diff --git a/libs/core/control.cpp b/libs/core/control.cpp
index f8e740e2..e528aeca 100644
--- a/libs/core/control.cpp
+++ b/libs/core/control.cpp
@@ -311,4 +311,13 @@ namespace control {
void __midiSend(Buffer buffer) {
// this is a stub to support the simulator
}
+
+ /**
+ *
+ */
+ //%
+ void __log(String text) {
+ if (NULL == text) return;
+ pxt::sendSerial(text->data, text->length);
+ }
}
diff --git a/libs/core/helpers.ts b/libs/core/helpers.ts
index 36cbf662..6caa902e 100644
--- a/libs/core/helpers.ts
+++ b/libs/core/helpers.ts
@@ -1,10 +1,3 @@
-namespace console {
- export function log(msg: string) {
- serial.writeString(msg);
- serial.writeString("\r\n");
- }
-}
-
namespace Math {
/**
* Generates a `true` or `false` value randomly, just like flipping a coin.
diff --git a/libs/core/pxt.json b/libs/core/pxt.json
index 678e06b1..1decedf8 100644
--- a/libs/core/pxt.json
+++ b/libs/core/pxt.json
@@ -29,6 +29,7 @@
"gestures.jres",
"control.ts",
"control.cpp",
+ "console.ts",
"game.ts",
"led.cpp",
"led.ts",
diff --git a/libs/core/shims.d.ts b/libs/core/shims.d.ts
index 56124c4d..000052ca 100644
--- a/libs/core/shims.d.ts
+++ b/libs/core/shims.d.ts
@@ -440,6 +440,12 @@ declare namespace control {
*/
//% part=midioutput blockHidden=1 shim=control::__midiSend
function __midiSend(buffer: Buffer): void;
+
+ /**
+ *
+ */
+ //% shim=control::__log
+ function __log(text: string): void;
}
diff --git a/sim/state/serial.ts b/sim/state/serial.ts
index bf7f7ed6..a117bdd9 100644
--- a/sim/state/serial.ts
+++ b/sim/state/serial.ts
@@ -28,6 +28,12 @@ namespace pxsim {
}
}
+namespace pxsim.control {
+ export function __log(s: string) {
+ board().writeSerial(s + "\r\n");
+ }
+}
+
namespace pxsim.serial {
export function writeString(s: string) {
board().writeSerial(s);