openrowingmonitor/app/ble/pm5/characteristic/GeneralStatus.js

72 lines
3.0 KiB
JavaScript

'use strict'
/*
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
Implementation of the GeneralStatus as defined in:
https://www.concept2.co.uk/files/pdf/us/monitors/PM5_BluetoothSmartInterfaceDefinition.pdf
*/
import bleno from '@abandonware/bleno'
import { getFullUUID } from '../Pm5Constants.js'
import log from 'loglevel'
import BufferBuilder from '../../BufferBuilder.js'
export default class GeneralStatus extends bleno.Characteristic {
constructor (multiplexedCharacteristic) {
super({
// id for GeneralStatus as defined in the spec
uuid: getFullUUID('0031'),
value: null,
properties: ['notify']
})
this._updateValueCallback = null
this._multiplexedCharacteristic = multiplexedCharacteristic
}
onSubscribe (maxValueSize, updateValueCallback) {
log.debug(`GeneralStatus - central subscribed with maxSize: ${maxValueSize}`)
this._updateValueCallback = updateValueCallback
return this.RESULT_SUCCESS
}
onUnsubscribe () {
log.debug('GeneralStatus - central unsubscribed')
this._updateValueCallback = null
return this.RESULT_UNLIKELY_ERROR
}
notify (data) {
if (this._updateValueCallback || this._multiplexedCharacteristic.centralSubscribed()) {
const bufferBuilder = new BufferBuilder()
// elapsedTime: UInt24LE in 0.01 sec
bufferBuilder.writeUInt24LE(Math.round(data.totalMovingTime * 100))
// distance: UInt24LE in 0.1 m
bufferBuilder.writeUInt24LE(Math.round(data.totalLinearDistance * 10))
// workoutType: UInt8 0 WORKOUTTYPE_JUSTROW_NOSPLITS, 2 WORKOUTTYPE_FIXEDDIST_NOSPLITS, 4 WORKOUTTYPE_FIXEDTIME_NOSPLITS
bufferBuilder.writeUInt8(data.sessiontype === 'Distance' ? 2 : (data.sessiontype === 'Time' ? 4 : 0))
// intervalType: UInt8 will always use 255 (NONE)
bufferBuilder.writeUInt8(255)
// workoutState: UInt8 0 WAITTOBEGIN, 1 WORKOUTROW, 10 WORKOUTEND
bufferBuilder.writeUInt8(data.sessionStatus === 'Rowing' ? 1 : (data.sessionStatus === 'WaitingForStart' ? 0 : 10))
// rowingState: UInt8 0 INACTIVE, 1 ACTIVE
bufferBuilder.writeUInt8(data.sessionStatus === 'Rowing' ? 1 : 0)
// strokeState: UInt8 2 DRIVING, 4 RECOVERY
bufferBuilder.writeUInt8(data.strokeState === 'WaitingForDrive' ? 0 : (data.strokeState === 'Drive' ? 2 : 4))
// totalWorkDistance: UInt24LE in 1 m
bufferBuilder.writeUInt24LE(Math.round(data.totalLinearDistance))
// workoutDuration: UInt24LE in 0.01 sec (if type TIME)
bufferBuilder.writeUInt24LE(Math.round(data.totalMovingTime * 100))
// workoutDurationType: UInt8 0 TIME, 0x40 CALORIES, 0x80 DISTANCE, 0xC0 WATTS
bufferBuilder.writeUInt8(data.sessiontype === 'Distance' ? 0x80 : 0)
// dragFactor: UInt8
bufferBuilder.writeUInt8(Math.round(Math.min(data.dragFactor, 255)))
if (this._updateValueCallback) {
this._updateValueCallback(bufferBuilder.getBuffer())
} else {
this._multiplexedCharacteristic.notify(0x31, bufferBuilder.getBuffer())
}
return this.RESULT_SUCCESS
}
}
}