notifies PM5 central when stroke state changes
This commit is contained in:
parent
2e3654fabd
commit
e5e579f3fc
|
|
@ -12,14 +12,11 @@
|
|||
(Manufacturer Name String, Model Number String)
|
||||
*/
|
||||
import bleno from '@abandonware/bleno'
|
||||
import { EventEmitter } from 'events'
|
||||
import FitnessMachineService from './ftms/FitnessMachineService.js'
|
||||
import DeviceInformationService from './ftms/DeviceInformationService.js'
|
||||
import log from 'loglevel'
|
||||
|
||||
function createFtmsPeripheral (options) {
|
||||
const emitter = new EventEmitter()
|
||||
|
||||
function createFtmsPeripheral (controlCallback, options) {
|
||||
const peripheralName = options?.simulateIndoorBike ? 'OpenRowingBike' : 'OpenRowingMonitor'
|
||||
// const peripheralName = options?.simulateIndoorBike ? 'OpenRowingBike' : 'S1 Comms 1'
|
||||
const fitnessMachineService = new FitnessMachineService(options, controlPointCallback)
|
||||
|
|
@ -72,7 +69,7 @@ function createFtmsPeripheral (options) {
|
|||
req: event,
|
||||
res: {}
|
||||
}
|
||||
emitter.emit('controlPoint', obj)
|
||||
if (controlCallback) controlCallback(obj)
|
||||
return obj.res
|
||||
}
|
||||
|
||||
|
|
@ -99,22 +96,24 @@ function createFtmsPeripheral (options) {
|
|||
}
|
||||
}
|
||||
|
||||
// deliver current rowing metrics via BLE
|
||||
function notifyData (data) {
|
||||
fitnessMachineService.notifyData(data)
|
||||
// present current rowing metrics to FTMS central
|
||||
function notifyData (type, data) {
|
||||
if (type === 'strokeFinished' || type === 'rowingPaused') {
|
||||
fitnessMachineService.notifyData(data)
|
||||
}
|
||||
}
|
||||
|
||||
// deliver a status change via BLE
|
||||
// present current rowing status to FTMS central
|
||||
function notifyStatus (status) {
|
||||
fitnessMachineService.notifyStatus(status)
|
||||
}
|
||||
|
||||
return Object.assign(emitter, {
|
||||
return {
|
||||
triggerAdvertising,
|
||||
notifyData,
|
||||
notifyStatus,
|
||||
destroy
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { createFtmsPeripheral }
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ function createPeripheralManager () {
|
|||
}
|
||||
|
||||
function notifyMetrics (type, metrics) {
|
||||
peripheral.notifyData(metrics)
|
||||
peripheral.notifyData(type, metrics)
|
||||
}
|
||||
|
||||
function notifyStatus (status) {
|
||||
|
|
@ -46,29 +46,25 @@ function createPeripheralManager () {
|
|||
async function createPeripheral (newMode) {
|
||||
if (peripheral) {
|
||||
await peripheral.destroy()
|
||||
peripheral.off('controlPoint', emitControlPointEvent)
|
||||
}
|
||||
|
||||
if (newMode === 'PM5') {
|
||||
log.info('bluetooth profile: Concept2 PM5')
|
||||
peripheral = createPm5Peripheral()
|
||||
peripheral = createPm5Peripheral(controlCallback)
|
||||
mode = 'PM5'
|
||||
} else if (newMode === 'FTMSBIKE') {
|
||||
log.info('bluetooth profile: FTMS Indoor Bike')
|
||||
peripheral = createFtmsPeripheral({
|
||||
peripheral = createFtmsPeripheral(controlCallback, {
|
||||
simulateIndoorBike: true
|
||||
})
|
||||
mode = 'FTMSBIKE'
|
||||
} else {
|
||||
log.info('bluetooth profile: FTMS Rower')
|
||||
peripheral = createFtmsPeripheral({
|
||||
peripheral = createFtmsPeripheral(controlCallback, {
|
||||
simulateIndoorBike: false
|
||||
})
|
||||
mode = 'FTMS'
|
||||
}
|
||||
// todo: re-emitting is not that great, maybe use callbacks instead
|
||||
peripheral.on('control', emitControlPointEvent)
|
||||
|
||||
peripheral.triggerAdvertising()
|
||||
|
||||
emitter.emit('control', {
|
||||
|
|
@ -79,7 +75,7 @@ function createPeripheralManager () {
|
|||
})
|
||||
}
|
||||
|
||||
function emitControlPointEvent (event) {
|
||||
function controlCallback (event) {
|
||||
emitter.emit('control', event)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
see: https://www.concept2.co.uk/files/pdf/us/monitors/PM5_BluetoothSmartInterfaceDefinition.pdf
|
||||
*/
|
||||
import bleno from '@abandonware/bleno'
|
||||
import { EventEmitter } from 'events'
|
||||
import { constants } from './pm5/Pm5Constants.js'
|
||||
import DeviceInformationService from './pm5/DeviceInformationService.js'
|
||||
import GapService from './pm5/GapService.js'
|
||||
|
|
@ -16,9 +15,7 @@ import log from 'loglevel'
|
|||
import Pm5ControlService from './pm5/Pm5ControlService.js'
|
||||
import Pm5RowingService from './pm5/Pm5RowingService.js'
|
||||
|
||||
function createPm5Peripheral (options) {
|
||||
const emitter = new EventEmitter()
|
||||
|
||||
function createPm5Peripheral (controlCallback, options) {
|
||||
const peripheralName = constants.name
|
||||
const deviceInformationService = new DeviceInformationService()
|
||||
const gapService = new GapService()
|
||||
|
|
@ -90,23 +87,21 @@ function createPm5Peripheral (options) {
|
|||
}
|
||||
}
|
||||
|
||||
// deliver current rowing metrics via BLE
|
||||
function notifyData (data) {
|
||||
rowingService.notify(data)
|
||||
// fitnessMachineService.notifyData(data)
|
||||
// present current rowing metrics to C2-PM5 central
|
||||
function notifyData (type, data) {
|
||||
rowingService.notifyData(type, data)
|
||||
}
|
||||
|
||||
// deliver a status change via BLE
|
||||
// present current rowing status to C2-PM5 central
|
||||
function notifyStatus (status) {
|
||||
// fitnessMachineService.notifyStatus(status)
|
||||
}
|
||||
|
||||
return Object.assign(emitter, {
|
||||
return {
|
||||
triggerAdvertising,
|
||||
notifyData,
|
||||
notifyStatus,
|
||||
destroy
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { createPm5Peripheral }
|
||||
|
|
|
|||
|
|
@ -75,11 +75,16 @@ export default class PM5RowingService extends bleno.PrimaryService {
|
|||
this.multiplexedCharacteristic = multiplexedCharacteristic
|
||||
}
|
||||
|
||||
notify (data) {
|
||||
this.generalStatus.notify(data)
|
||||
this.additionalStatus.notify(data)
|
||||
this.additionalStatus2.notify(data)
|
||||
this.strokeData.notify(data)
|
||||
this.additionalStrokeData.notify(data)
|
||||
notifyData (type, data) {
|
||||
if (type === 'strokeFinished' || type === 'rowingPaused') {
|
||||
this.generalStatus.notify(data)
|
||||
this.additionalStatus.notify(data)
|
||||
this.additionalStatus2.notify(data)
|
||||
this.strokeData.notify(data)
|
||||
this.additionalStrokeData.notify(data)
|
||||
} else if (type === 'strokeStateChanged') {
|
||||
// the stroke state is delivered via the GeneralStatus Characteristic, so we only need to notify that one
|
||||
this.generalStatus.notify(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ function createRowingEngine () {
|
|||
}
|
||||
log.debug(`estimated kDamp: ${jMoment * (-1 * kDampEstimatorAverager.weightedAverage())}`)
|
||||
log.info(`estimated omegaDotDivOmegaSquare: ${-1 * kDampEstimatorAverager.weightedAverage()}`)
|
||||
workoutHandler.handleStrokeStateChange({
|
||||
workoutHandler.handleStrokeStateChanged({
|
||||
strokeState: 'DRIVING'
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,11 +62,11 @@ function createRowingStatistics () {
|
|||
}
|
||||
|
||||
// initiated when the stroke state changes
|
||||
function handleStrokeStateChange (state) {
|
||||
function handleStrokeStateChanged (state) {
|
||||
// todo: wee need a better mechanism to communicate strokeState updates
|
||||
// this is an initial hacky attempt to see if we can use it for the C2-pm5 protocol
|
||||
lastStrokeState = state.strokeState
|
||||
// emitter.emit('strokeFinished', getMetrics())
|
||||
emitter.emit('strokeStateChanged', getMetrics())
|
||||
}
|
||||
|
||||
function getMetrics () {
|
||||
|
|
@ -154,7 +154,7 @@ function createRowingStatistics () {
|
|||
return Object.assign(emitter, {
|
||||
handleStroke,
|
||||
handlePause,
|
||||
handleStrokeStateChange,
|
||||
handleStrokeStateChanged,
|
||||
reset: resetTraining
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,10 @@ rowingStatistics.on('rowingPaused', (data) => {
|
|||
peripheralManager.notifyMetrics('rowingPaused', metrics)
|
||||
})
|
||||
|
||||
rowingStatistics.on('strokeStateChanged', (metrics) => {
|
||||
peripheralManager.notifyMetrics('strokeStateChanged', metrics)
|
||||
})
|
||||
|
||||
rowingStatistics.on('durationUpdate', (data) => {
|
||||
webServer.notifyClients({
|
||||
durationTotalFormatted: data.durationTotalFormatted
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ This is the very minimalistic Backlog for further development of this project.
|
|||
|
||||
## Soon
|
||||
|
||||
* refactor Stroke Phase Handling in RowingStatistics and pm5Peripheral
|
||||
* Web UI: hint, when screen is not in always on mode
|
||||
* Web UI: replace fullscreen button with exit Button when started from home screen
|
||||
* investigate: occasionally stroke rate is too high - seems to happen after rowing pause
|
||||
|
|
|
|||
Loading…
Reference in New Issue