Ok, here is my report: what was expected to work within an hour (I am so naive!) finally took longer than a full day...
My idea was to program a Puck to send the keystrokes needed to start the dictate mode under macOS. With a BT headset and the puck in my shirt pocket, I can then dictate effortlessly without needing access to a keyboard while having full control over when the Mac is listening and when not.
As mentioned above, I lost an awful lot of time with macOS 13.6.1 where the HID emulation does not seem to work at all. With macOS 15.0.1 and the new 15.1, however, it seems to work good enough to be used. "Good enough" means, that pairing still works strange from time to time:
"forgetting" the device seems to be difficult, often you still have to connect the device once again in order to be actually forgotten
sometimes, the bluetooth section of the settings app crashes
sometimes, the "connect" buttons do no longer appear when hovering over the listed BT devices - in that case, just quit a settings app and open it again
sometimes, it's the best to "sudo pkill bluetoothd" from a terminal to reset the BT controller
That said, here is my code:
var Keyboard = require("ble_hid_keyboard");
LED1.write(0); // switch red LED off
LED2.write(0); // switch green LED off
LED3.write(0); // switch blue LED off
/**** configure Bluetooth keyboard ****/
NRF.setServices(undefined, { hid:Keyboard.report });
/**** configure advertising ****/
NRF.setAdvertising([
{}, {
0x01: [0x06],
0x02: [0x0A, 0x00],
0x03: [0x12, 0x18],
0x19: [0xC1, 0x03], // appearance: keyboard
}
], { name: "Dictate Trigger" });
/**** simulate keystrokes and give feedback in case of exceptions ****/
function sendHIDReport (Report) {
try {
NRF.sendHIDReport(Report);
LED1.write(LED1.read() > 0 ? 0 : 1);
} catch (Signal) {
LED1.write(1);
throw Signal;
}
}
/**** simulate key presses ****/
function simulateKeyPresses () {
LED1.write(0); // switch red LED off
sendHIDReport([1, 0, 0, 0, 0, 0, 0, 0]);
setTimeout(function () { sendHIDReport([0, 0, 0, 0, 0, 0, 0, 0]); }, 100);
setTimeout(function () { sendHIDReport([1, 0, 0, 0, 0, 0, 0, 0]); }, 300);
setTimeout(function () { sendHIDReport([0, 0, 0, 0, 0, 0, 0, 0]); }, 400);
} // red LED should now be off again
/**** run keyboard simulation when Puck button is pressed ****/
setWatch(function () {
if (isConnected) {
simulateKeyPresses();
}
}, BTN, {edge:"rising", debounce:50, repeat:true});
/**** light green for 5 seconds after connection is established ****/
var isConnected = false;
NRF.on('connect', function () {
isConnected = true;
LED1.write(0); // switch red LED off
LED2.write(0.2); // switch green LED on
LED3.write(0); // switch blue LED off
setTimeout(function () { // switch green LED off after 5 seconds
LED2.write(0);
}, 5000);
});
/**** start blinking blue again after disconnection ****/
NRF.on('disconnect', function () {
isConnected = false;
LED1.write(0); // switch red LED off
LED2.write(0); // switch green LED off
blinkBlueLED(); // start blinking blue again
});
/**** blink blue while advertising ****/
function blinkBlueLED () {
if (! isConnected) {
LED3.write(LED3.read() > 0 ? 0 : 0.2);
setTimeout(blinkBlueLED, 500);
} else {
LED3.write(0);
}
}
/**** start advertising ****/
NRF.setAdvertising(undefined, { connectable:true, discoverable:true });
blinkBlueLED();
As you can see, I added a lot of visual feedback in form of LED signals as there is no longer any console where one could report the current state or any exceptions...
Espruino is a JavaScript interpreter for low-power Microcontrollers. This site is both a support community for Espruino and a place to share what you are working on.
Ok, here is my report: what was expected to work within an hour (I am so naive!) finally took longer than a full day...
My idea was to program a Puck to send the keystrokes needed to start the dictate mode under macOS. With a BT headset and the puck in my shirt pocket, I can then dictate effortlessly without needing access to a keyboard while having full control over when the Mac is listening and when not.
As mentioned above, I lost an awful lot of time with macOS 13.6.1 where the HID emulation does not seem to work at all. With macOS 15.0.1 and the new 15.1, however, it seems to work good enough to be used. "Good enough" means, that pairing still works strange from time to time:
That said, here is my code:
As you can see, I added a lot of visual feedback in form of LED signals as there is no longer any console where one could report the current state or any exceptions...
Have fun!