You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.4 KiB

import { BaseInterface } from "./base";
import { BaseService, BaseCharacteritic, BaseApplication } from "./bluez-gatt";
export class FTMSService extends BaseService {
UUID = "00001826-0000-1000-8000-00805f9b34fb";
Primary = true;
constructor(bus, path) {
super(bus, path);
this.addCharacteristic(new FTMSFeature(bus, this.path + "/char0", this));
this.addCharacteristic(new IndoorBikeData(bus, this.path + "/char1", this));
this.addCharacteristic(
new FTMSControlPoint(bus, this.path + "/char2", this)
);
}
}
class FTMSFeature extends BaseCharacteritic {
constructor(bus, path, service) {
super(bus, path, service, "00002acc-0000-1000-8000-00805f9b34fb", ["read"]);
}
read() {
console.log("read FTMS Feature");
// 32bits features + 32bits target supported
// 0x0a 0x44 = feature: cadence (1), inclinaison (3), hr (10), power (14)
// 0x0a 0x20 = target: inclinaison (1), power (3), simulation parameters (13)
return [0x0a, 0x44, 0x00, 0x00, 0x0a, 0x20, 0x00, 0x00];
}
}
class FTMSControlPoint extends BaseCharacteritic {
wind = 0;
grade = 0;
crr = 0;
cw = 0;
constructor(bus, path, service) {
super(bus, path, service, "00002ad9-0000-1000-8000-00805f9b34fb", [
"write",
"indicate",
]);
}
write(value, options) {
console.log("FTMS Write Control Point");
console.log(value);
const arraybuf = value.buffer.slice(
value.byteOffset,
value.byteOffset + value.byteLength
);
const view = new DataView(arraybuf);
if (value[0] === 0x00) {
// take control
this.notify([0x80, 0x00, 0x01]);
} else if (value[0] === 0x01) {
// reset machine
this.notify([0x80, 0x01, 0x01]);
} else if (value[0] === 0x07) {
// start/resume
this.notify([0x80, 0x07, 0x01]);
} else if (value[0] === 0x11) {
// set simulations param (wind, grade, etc)
const wind = view.getInt16(1, true);
const grade = view.getInt16(3, true);
const crr = view.getUint8(5);
const cw = view.getUint8(6);
this.wind = wind * 0.001;
this.grade = grade * 0.01;
this.crr = crr * 0.001;
this.cw = cw * 0.01;
console.log(wind * 0.001);
console.log(grade * 0.01);
console.log(crr * 0.0001);
console.log(cw * 0.01);
this.notify([0x80, 0x11, 0x01]);
} else {
console.log("FTMS Control point op code " + value[0] + "not supported");
}
}
startNotify() {
console.log("FTMS Start Notify CP");
}
stopNotify() {
console.log("FTMS Stop Notify CP");
}
}
class IndoorBikeData extends BaseCharacteritic {
constructor(bus, path, service) {
super(bus, path, service, "00002ad2-0000-1000-8000-00805f9b34fb", [
"notify",
]);
}
startNotify() {
if (this.Notifying) {
return;
}
this.Notifying = true;
this.interval = setInterval(() => {
console.log("FTMS Notif Indoor Bike");
// 0x44 0x02 = fields included: cadence (2), power (6), hr (9)
// 0x00 0x00 = average speed, always included
// cadence is *2 (resolution 0.5 s^-1)
this.notify([
0x44,
0x02,
0x00,
0x00,
Math.round(160 + Math.random() * 10),
0x00,
Math.round(160 + Math.random() * 40),
0x00,
Math.round(120 + Math.random() * 10),
]);
}, 1000);
}
stopNotify() {
if (!this.Notifying) {
return;
}
this.Notifying = false;
clearInterval(this.interval);
}
}