parent
79d339a4d3
commit
2777cd69aa
@ -0,0 +1,15 @@
|
||||
const CadenceQuality = Object.freeze({
|
||||
HIGH: "high",
|
||||
MEDIUM: "medium",
|
||||
LOW: "low",
|
||||
UNKNOWN: "unknown",
|
||||
});
|
||||
|
||||
function validateCadenceQuality(v) {
|
||||
const set = CadenceQuality;
|
||||
if (!v) return set.UNKNOWN;
|
||||
const vals = Object.values(set);
|
||||
return vals.includes(v) ? v : set.UNKNOWN;
|
||||
}
|
||||
|
||||
export { validateCadenceQuality, CadenceQuality };
|
||||
@ -0,0 +1,34 @@
|
||||
import { deepFreeze, isFiniteNumber } from "../../utils";
|
||||
import { CyclingPowerCapabilities } from "./cyclingPower.js";
|
||||
|
||||
export class Control {
|
||||
constructor({
|
||||
supportsERG = false,
|
||||
controlCharacteristic,
|
||||
maxPowerWatts,
|
||||
minPowerWatts,
|
||||
ergRampRateWattsPerSec,
|
||||
cyclingPower,
|
||||
} = {}) {
|
||||
this.supportsERG = Boolean(supportsERG);
|
||||
this.controlCharacteristic = controlCharacteristic;
|
||||
this.maxPowerWatts = isFiniteNumber(maxPowerWatts)
|
||||
? Number(maxPowerWatts)
|
||||
: undefined;
|
||||
this.minPowerWatts = isFiniteNumber(minPowerWatts)
|
||||
? Number(minPowerWatts)
|
||||
: undefined;
|
||||
this.ergRampRateWattsPerSec = isFiniteNumber(ergRampRateWattsPerSec)
|
||||
? Number(ergRampRateWattsPerSec)
|
||||
: undefined;
|
||||
this.cyclingPower =
|
||||
cyclingPower instanceof CyclingPowerCapabilities
|
||||
? cyclingPower
|
||||
: cyclingPower
|
||||
? new CyclingPowerCapabilities(cyclingPower)
|
||||
: undefined;
|
||||
deepFreeze(this);
|
||||
}
|
||||
|
||||
merge = (partial) => new Control(Object.assign({}, this, partial));
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
import { deepFreeze } from "../../utils";
|
||||
|
||||
export class Core {
|
||||
constructor({
|
||||
supportsBattery = false,
|
||||
supportsManufacturerData = false,
|
||||
gattServices,
|
||||
gattCharacteristics,
|
||||
manufacturer,
|
||||
model,
|
||||
firmwareVersion,
|
||||
serial,
|
||||
reconnectOnDisconnect = true,
|
||||
requiresPairing = false,
|
||||
} = {}) {
|
||||
this.supportsBattery = Boolean(supportsBattery);
|
||||
this.supportsManufacturerData = Boolean(supportsManufacturerData);
|
||||
this.gattServices = Array.isArray(gattServices)
|
||||
? gattServices.slice()
|
||||
: undefined;
|
||||
this.gattCharacteristics =
|
||||
gattCharacteristics && typeof gattCharacteristics === "object"
|
||||
? Object.assign({}, gattCharacteristics)
|
||||
: undefined;
|
||||
this.manufacturer = manufacturer;
|
||||
this.model = model;
|
||||
this.firmwareVersion = firmwareVersion;
|
||||
this.serial = serial;
|
||||
this.reconnectOnDisconnect = Boolean(reconnectOnDisconnect);
|
||||
this.requiresPairing = Boolean(requiresPairing);
|
||||
deepFreeze(this);
|
||||
}
|
||||
|
||||
merge = (partial) => new Core(Object.assign({}, this, partial));
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
import { Control } from "./control";
|
||||
import { Sensors } from "./sensors";
|
||||
import { Core } from "./core";
|
||||
|
||||
export { Control, Sensors, Core };
|
||||
@ -0,0 +1,31 @@
|
||||
import { deepFreeze, isFiniteNumber } from "../../utils";
|
||||
import { validateCadenceQuality } from "../cadence";
|
||||
|
||||
export class Sensors {
|
||||
constructor({
|
||||
supportsHeartRate = false,
|
||||
supportsCadence = false,
|
||||
supportsPower = false,
|
||||
hrSamplingHz,
|
||||
cadenceSamplingHz,
|
||||
powerSamplingHz,
|
||||
cadenceSourceQuality,
|
||||
} = {}) {
|
||||
this.supportsHeartRate = Boolean(supportsHeartRate);
|
||||
this.supportsCadence = Boolean(supportsCadence);
|
||||
this.supportsPower = Boolean(supportsPower);
|
||||
this.hrSamplingHz = isFiniteNumber(hrSamplingHz)
|
||||
? Number(hrSamplingHz)
|
||||
: undefined;
|
||||
this.cadenceSamplingHz = isFiniteNumber(cadenceSamplingHz)
|
||||
? Number(cadenceSamplingHz)
|
||||
: undefined;
|
||||
this.powerSamplingHz = isFiniteNumber(powerSamplingHz)
|
||||
? Number(powerSamplingHz)
|
||||
: undefined;
|
||||
this.cadenceSourceQuality = validateCadenceQuality(cadenceSourceQuality);
|
||||
deepFreeze(this);
|
||||
}
|
||||
|
||||
merge = (partial) => new Sensors(Object.assign({}, this, partial));
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
import { Control, Sensors, Core } from "./capabilities";
|
||||
import { deepFreeze } from "../utils";
|
||||
|
||||
const DeviceType = Object.freeze({
|
||||
HEART_RATE: "heart_rate",
|
||||
CADENCE: "cadence",
|
||||
TRAINER: "trainer",
|
||||
UNKNOWN: "unknown",
|
||||
});
|
||||
|
||||
export class Device {
|
||||
constructor({
|
||||
id,
|
||||
name,
|
||||
type,
|
||||
core,
|
||||
sensors,
|
||||
control,
|
||||
connected = false,
|
||||
lastSeen,
|
||||
} = {}) {
|
||||
if (!id) throw new Error("Device requires id");
|
||||
this.id = id;
|
||||
this.name = name || id;
|
||||
this.type = type;
|
||||
this.core = core instanceof Core ? core : core ? new Core(core) : undefined;
|
||||
this.sensors =
|
||||
sensors instanceof Sensors
|
||||
? sensors
|
||||
: sensors
|
||||
? new Sensors(sensors)
|
||||
: undefined;
|
||||
this.control =
|
||||
control instanceof Control
|
||||
? control
|
||||
: control
|
||||
? new Control(control)
|
||||
: undefined;
|
||||
this.connected = Boolean(connected);
|
||||
this.lastSeen = lastSeen;
|
||||
deepFreeze(this);
|
||||
}
|
||||
|
||||
withCore = (partial) =>
|
||||
new Device(
|
||||
Object.assign({}, this, {
|
||||
core: this.core ? this.core.merge(partial) : new Core(partial),
|
||||
}),
|
||||
);
|
||||
withSensors = (partial) =>
|
||||
new Device(
|
||||
Object.assign({}, this, {
|
||||
sensors: this.sensors
|
||||
? this.sensors.merge(partial)
|
||||
: new Sensors(partial),
|
||||
}),
|
||||
);
|
||||
withControl = (partial) =>
|
||||
new Device(
|
||||
Object.assign({}, this, {
|
||||
control: this.control
|
||||
? this.control.merge(partial)
|
||||
: new Control(partial),
|
||||
}),
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
const deepFreeze = (obj) => {
|
||||
if (obj && typeof obj === "object" && !Object.isFrozen(obj)) {
|
||||
Object.getOwnPropertyNames(obj).forEach((prop) => {
|
||||
const value = obj[prop];
|
||||
if (value && typeof value === "object") deepFreeze(value);
|
||||
});
|
||||
Object.freeze(obj);
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
const isFiniteNumber = (v) => typeof v === "number" && Number.isFinite(v);
|
||||
|
||||
export { deepFreeze, isFiniteNumber };
|
||||
Loading…
Reference in new issue