aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/js/hoverControlModule.js5
-rw-r--r--src/js/main.js91
-rw-r--r--src/js/uBit.js138
-rw-r--r--src/scss/styles.scss7
4 files changed, 184 insertions, 57 deletions
diff --git a/src/js/hoverControlModule.js b/src/js/hoverControlModule.js
index 44c06fb..4058e8c 100644
--- a/src/js/hoverControlModule.js
+++ b/src/js/hoverControlModule.js
@@ -1,5 +1,7 @@
import { notif_alert, notif_warn, notif_info, notif_success } from './notification';
+let n = 0;
+
export default class hoverControlModule {
#throttle = 0;
#throttleAcc = 0;
@@ -33,7 +35,8 @@ export default class hoverControlModule {
console.log(`Unkown acc: ${item}`);
}
});
- document.querySelector(".acc-string pre").innerHTML = `T: ${this.#throttleAcc}, R: ${this.#rudderAcc}`;
+ document.querySelector(".acc-string pre").innerHTML = `T: ${this.#throttleAcc}, R: ${this.#rudderAcc}, ${n}`;
+ n++;
}
reset() {
diff --git a/src/js/main.js b/src/js/main.js
index f42f268..3d7f494 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -1,6 +1,6 @@
import nipplejs from 'nipplejs';
-import { requestMicrobit, getServices } from 'microbit-web-bluetooth';
import hoverControlModule from './hoverControlModule';
+import uBitBLE from "./uBit";
import { notif_alert, notif_warn, notif_info, notif_success } from './notification';
let sw = "service-worker.js";
@@ -32,10 +32,13 @@ document.getElementById("btn_ignore_landscape_warning").addEventListener("click"
document.body.classList.add("ignore-landscape-warning");
});
+if (!navigator.bluetooth) {
+ alert("Bluetooth not enabled in your browser, this won't work...");
+}
+
/* Define and initialize things */
+let ubit = new uBitBLE();
let hoverControl = new hoverControlModule();
-let bluetoothDevice;
-let bluetoothDeviceServices;
let joystickLeft = nipplejs.create({
zone: document.querySelector(".joystick-left"),
@@ -56,7 +59,7 @@ let joystickRight = nipplejs.create({
joystickLeft.on("move", (evt, data) => {
let rudder = ((data.distance * 90) / 100);
if (data.angle.degree > 90) { rudder = rudder * -1; }
- hoverControl.setRudder(rudder);
+ hoverControl.setRudder(Math.round(rudder));
});
joystickLeft.on("end", (evt, data) => {
hoverControl.setRudder(0);
@@ -74,7 +77,7 @@ joystickRight.on("move", (evt, data) => {
}
}
}
- hoverControl.setThrottle(throttle);
+ hoverControl.setThrottle(Math.round(throttle));
});
joystickRight.on("end", (evt, data) => {
hoverControl.setThrottle(0);
@@ -90,45 +93,31 @@ document.getElementById("btn_disarm").addEventListener("click", () => {
document.querySelector("#btn_disconnect").addEventListener("click", () => {
hoverControl.reset();
- bluetoothDevice.gatt.disconnect();
+ ubit.disconnect();
});
-let intervalConnectionChecker = setInterval(() => {
- if (bluetoothDevice !== undefined && bluetoothDevice) {
- if (bluetoothDevice.gatt.connected) {
- document.body.classList.add("connected");
- } else {
- document.body.classList.remove("connected");
- document.body.classList.remove("armed");
- }
- } else if (bluetoothDevice !== undefined) {
- bluetoothDevice.gatt.reconnect();
- }
-}, 500);
+document.getElementById("btn_connect").addEventListener("click", () => {
+ ubit.searchDevice();
+});
-let intervalSendCommands = setInterval(async() => {
- if (bluetoothDevice !== undefined && bluetoothDevice) {
- if (bluetoothDevice.gatt.connected && bluetoothDeviceServices.uartService) {
- let command =
- "T" + hoverControl.getThrottle().toString() +
- "R" + hoverControl.getRudder().toString() +
- "A" + (hoverControl.getArm() ? "1" : "0") +
- "S0" +
- ":";
- await bluetoothDeviceServices.uartService.sendText(command);
- }
- }
-}, 70);
+ubit.onConnect(() => {
+ document.body.classList.add("connected");
+});
+
+ubit.onDisconnect(() => {
+ document.body.classList.remove("connected");
+ document.body.classList.remove("armed");
+});
-function receiveText(event) {
+ubit.onUartTx((text) => {
/* Just make the ping symbol reappear. */
var elm = document.querySelector(".ping i");
var newone = elm.cloneNode(true);
elm.parentNode.replaceChild(newone, elm);
/* Actually handle received text. */
- if ((event.detail).indexOf(":") != -1) {
- let parts = (event.detail).split(":");
+ if ((text).indexOf(":") != -1) {
+ let parts = (text).split(":");
if (parts[0] == "B") {
document.querySelector(".battery-status").innerHTML = parts[1] + "mV";
@@ -139,29 +128,19 @@ function receiveText(event) {
}
} else {
notif_warn("Received weird data from MICRO:BIT...");
- console.log(`Received unknown: ${event.detail}`);
+ console.log(`Received unknown: ${text}`);
}
-}
+});
-document.getElementById("btn_connect").onclick = async () => {
- if (bluetoothDevice !== undefined && bluetoothDevice.gatt.connected) {
- bluetoothDevice.disconnect();
+let intervalSendCommands = setInterval(async() => {
+ if (ubit.isConnected()) {
+ let command =
+ "T" + hoverControl.getThrottle().toString() +
+ "R" + hoverControl.getRudder().toString() +
+ "A" + (hoverControl.getArm() ? "1" : "0") +
+ "S0" +
+ ":";
+ await ubit.sendUart(command);
}
+}, 100);
- const device = await requestMicrobit(window.navigator.bluetooth);
- bluetoothDevice = device;
-
- if (device) {
- hoverControl.reset();
- const services = await getServices(device);
- bluetoothDeviceServices = services;
-
- if (bluetoothDeviceServices.deviceInformationService) {
- // logJson(await services.deviceInformationService.readDeviceInformation());
- }
-
- if (services.uartService) {
- services.uartService.addEventListener("receiveText", receiveText);
- }
- }
-}
diff --git a/src/js/uBit.js b/src/js/uBit.js
new file mode 100644
index 0000000..11cc7ac
--- /dev/null
+++ b/src/js/uBit.js
@@ -0,0 +1,138 @@
+/*
+ * This code is written with a lot of help from these resources:
+ * https://github.com/antefact/microBit.js/blob/master/src/microBit.js
+ * https://gist.github.com/kotobuki/7c67f8b9361e08930da1a5cfcfb0653f
+ * https://lancaster-university.github.io/microbit-docs/resources/bluetooth/bluetooth_profile.html
+ */
+const UART_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
+const UART_TX_CHARACTERISTIC_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e";
+const UART_RX_CHARACTERISTIC_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";
+
+export default class uBitBLE {
+
+ constructor() {
+ let device;
+
+ this.onConnectCallback = function() {};
+ this.onDisconnectCallback = function() {};
+ this.onUartTxCallback = function() {};
+
+ this.characteristic = {
+ UART_RX: {},
+ UART_TX: {}
+ }
+ }
+
+ onConnect(callbackFunction) {
+ this.onConnectCallback = callbackFunction;
+ }
+
+ onDisconnect(callbackFunction) {
+ this.onDisconnectCallback = callbackFunction;
+ }
+
+ onUartTx(callbackFunction) {
+ this.onUartTxCallback = callbackFunction;
+ }
+
+ sendUart(string) {
+ if (this.isConnected() && this.characteristic.UART_RX) {
+ let encoder = new TextEncoder();
+ this.characteristic.UART_RX.writeValue(
+ encoder.encode(string)
+ ).catch(error => {
+ console.log(error);
+ });
+ }
+ }
+
+ isConnected() {
+ if (this.device) {
+ return this.device.gatt.connected;
+ } else {
+ return false;
+ }
+ }
+
+ disconnect() {
+ if (this.isConnected()) {
+ this.device.gatt.disconnect();
+ }
+ }
+
+ searchDevice() {
+ navigator.bluetooth.requestDevice({
+ filters: [{namePrefix: "BBC micro:bit"}],
+ optionalServices: [UART_SERVICE_UUID]
+ })
+ .then(device => {
+ console.log('> Name: ' + device.name);
+ console.log('> Id: ' + device.id);
+ this.device = device;
+
+ device.addEventListener('gattserverdisconnected', this.onDisconnectCallback);
+
+ // Attempts to connect to remote GATT Server.
+ return device.gatt.connect();
+ })
+ .then(server => {
+ // Note that we could also get all services that match a specific UUID by
+ // passing it to getPrimaryServices().
+ this.onConnectCallback();
+ console.log('Getting Services...');
+ return server.getPrimaryServices();
+ })
+ .then(services => {
+ console.log('Getting Characteristics...');
+ let queue = Promise.resolve();
+ services.forEach(service => {
+ queue = queue.then(_ => service.getCharacteristics().then(characteristics => {
+ console.log('> Service: ' + service.uuid);
+ characteristics.forEach(characteristic => {
+ console.log('>> Characteristic: ' + characteristic.uuid + ' ' +
+ getSupportedProperties(characteristic));
+ switch (characteristic.uuid) {
+ case UART_RX_CHARACTERISTIC_UUID:
+ this.characteristic.UART_RX = characteristic;
+ break;
+
+ case UART_TX_CHARACTERISTIC_UUID:
+ this.characteristic.UART_TX = characteristic;
+ this.characteristic.UART_TX.startNotifications();
+ this.characteristic.UART_TX.addEventListener(
+ "characteristicvaluechanged",
+ (event) => { this.onUartTxCallback(eventByteArrayToString(event)) }
+ );
+ break;
+
+ default:
+ }
+ });
+ }));
+ });
+ return queue;
+ })
+ .catch(error => {
+ console.log('Argh! ' + error);
+ });
+ }
+
+}
+
+function getSupportedProperties(characteristic) {
+ let supportedProperties = [];
+ for (const p in characteristic.properties) {
+ if (characteristic.properties[p] === true) {
+ supportedProperties.push(p.toUpperCase());
+ }
+ }
+ return '[' + supportedProperties.join(', ') + ']';
+}
+
+function eventByteArrayToString(event) {
+ let receivedData = [];
+ for (var i = 0; i < event.target.value.byteLength; i++) {
+ receivedData[i] = event.target.value.getUint8(i);
+ }
+ return String.fromCharCode.apply(null, receivedData);
+}
diff --git a/src/scss/styles.scss b/src/scss/styles.scss
index e41b5fb..894ddf7 100644
--- a/src/scss/styles.scss
+++ b/src/scss/styles.scss
@@ -148,6 +148,13 @@ body {
.connected & { display: block; }
}
+button:hover {
+ filter: brightness(80%);
+}
+button:active {
+ filter: brightness(70%);
+}
+
.button-center {
position: absolute;
display: none;