@hangtime/grip-connect-capacitor
Version:
Capacitor plugin for Grip Connect devices
118 lines (98 loc) • 3.94 kB
text/typescript
import { BleClient, type BleDevice } from "@capacitor-community/bluetooth-le"
import { Directory, Filesystem } from "@capacitor/filesystem"
import { WHC06 as WHC06Base } from "@hangtime/grip-connect"
/**
* Represents a Weiheng - WH-C06 (or MAT Muscle Meter) device.
* To use this device enable: `chrome://flags/#enable-experimental-web-platform-features`.
* {@link https://googlechrome.github.io/samples/web-bluetooth/scan.html| Web Bluetooth}
* {@link https://weihengmanufacturer.com}
*/
export class WHC06 extends WHC06Base {
device?: BleDevice
private readonly weightOffset: number = 10
override connect = async (
onSuccess: () => void = () => console.log("Connected successfully"),
onError: (error: Error) => void = (error) => console.error(error),
): Promise<void> => {
try {
await BleClient.initialize()
const filterOptions = Object.assign({}, ...this.filters)
await BleClient.requestLEScan(
{
...filterOptions,
allowDuplicates: true,
},
(result) => {
if (result && (result.device.name === "IF_B7" || result.localName === "IF_B7")) {
// Update timestamp
this.updateTimestamp()
// Device has no services / characteristics, so we directly call onSuccess
onSuccess()
const manufacturerData = result.manufacturerData
if (!manufacturerData) return
// Check if manufacturerData is set
const dataArray = Object.values(manufacturerData)
if (!dataArray.length) return
const data = dataArray[0]
if (!data) return
// Handle received data
this.currentSamplesPerPacket = 1
this.recordPacketReceived()
const weight = (data.getUint8(this.weightOffset) << 8) | data.getUint8(this.weightOffset + 1)
const receivedTime: number = Date.now()
const receivedData = weight / 100
const numericData = receivedData - this.applyTare(receivedData) * -1
const currentMassTotal = Math.max(-1000, numericData)
// Update session stats before building packet
this.peak = Math.max(this.peak, numericData)
this.min = Math.min(this.min, Math.max(-1000, numericData))
this.sum += currentMassTotal
this.dataPointCount++
this.mean = this.sum / this.dataPointCount
// Add data to downloadable Array
this.downloadPackets.push(
this.buildDownloadPacket(currentMassTotal, [numericData], {
timestamp: receivedTime,
sampleIndex: this.dataPointCount,
}),
)
// Check if device is being used
this.activityCheck(numericData)
// Notify with weight data
this.notifyCallback(this.buildForceMeasurement(currentMassTotal))
}
},
)
} catch (error) {
onError(error as Error)
}
}
override download = async (format: "csv" | "json" | "xml" = "csv"): Promise<void> => {
let content = ""
if (format === "csv") {
content = this.downloadToCSV()
} else if (format === "json") {
content = this.downloadToJSON()
} else if (format === "xml") {
content = this.downloadToXML()
}
const now = new Date()
// YYYY-MM-DD
const date = now.toISOString().split("T")[0]
// HH-MM-SS
const time = now.toTimeString().split(" ")[0].replace(/:/g, "-")
const fileName = `data-export-${date}-${time}.${format}`
try {
await Filesystem.writeFile({
path: fileName,
data: btoa(content),
directory: Directory.Documents,
recursive: true,
})
console.log(`File saved as ${fileName} in Documents directory`)
} catch (error) {
console.error("Error saving file:", error)
throw error
}
}
}