Skip to content

Commit

Permalink
Implementation of a watchdog
Browse files Browse the repository at this point in the history
Fixes an issue with flywheels that so fast that it will not reach a normal timeout on the rower.js
  • Loading branch information
JaapvanEkris authored Nov 4, 2024
1 parent 6afae08 commit bf15df6
Showing 1 changed file with 32 additions and 12 deletions.
44 changes: 32 additions & 12 deletions app/engine/SessionManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import { secondsToTimeString } from '../tools/Helper.js'
import loglevel from 'loglevel'
const log = loglevel.getLogger('RowingEngine')

function createSessionManager (config) {
export function createSessionManager (config) {
const numOfDataPointsForAveraging = config.numOfPhasesForAveragingScreenData
const emitter = new EventEmitter()
const rowingStatistics = createRowingStatistics(config)
let metrics
let watchdogTimer
const watchdogTimout = 2 * config.rowerSettings.maximumStrokeTimeBeforePause
let sessionState = 'WaitingForStart'
let lastSessionState = 'WaitingForStart'
let intervalSettings = []
Expand Down Expand Up @@ -97,6 +99,7 @@ function createSessionManager (config) {
}

function startOrResumeTraining () {
watchdogTimer = setTimeout(onWatchdogTimeout, watchdogTimout)
rowingStatistics.startOrResumeTraining()
}

Expand All @@ -105,13 +108,15 @@ function createSessionManager (config) {
}

function stopTraining () {
clearTimeout(watchdogTimer)
distanceOverTime.push(metrics.totalMovingTime, metrics.totalLinearDistance)
rowingStatistics.stopTraining()
}

// clear the metrics in case the user pauses rowing
function pauseTraining () {
log.debug('*** Paused rowing ***')
clearTimeout(watchdogTimer)
distanceOverTime.push(metrics.totalMovingTime, metrics.totalLinearDistance)
rowingStatistics.pauseTraining()
noSpontaneousPauses++
Expand Down Expand Up @@ -144,11 +149,6 @@ function createSessionManager (config) {

resetMetricsContext()

// ToDo: check if we need to update the projected end time of the interval
if (metrics.metricsContext.isMoving && (metrics.metricsContext.isDriveStart || metrics.metricsContext.isRecoveryStart)) {
distanceOverTime.push(metrics.totalMovingTime, metrics.totalLinearDistance)
}

// This is the core of the finite state machine that defines all state transitions
switch (true) {
case (lastSessionState === 'WaitingForStart' && metrics.strokeState === 'Drive'):
Expand Down Expand Up @@ -207,7 +207,13 @@ function createSessionManager (config) {
splitPrevAccumulatedDistance = intervalPrevAccumulatedDistance + (splitNumber * splitDistance)
metrics.metricsContext.isSplitEnd = true
break
case (lastSessionState === 'Rowing'):
case (lastSessionState === 'Rowing' && metrics.metricsContext.isMoving && (metrics.metricsContext.isDriveStart || metrics.metricsContext.isRecoveryStart)):
// ToDo: check if we need to update the projected end time of the interval
sessionState = 'Rowing'
resetWatchdogTimer()
distanceOverTime.push(metrics.totalMovingTime, metrics.totalLinearDistance)
break
case (lastSessionState === 'Rowing' && metrics.metricsContext.isMoving):
sessionState = 'Rowing'
break
default:
Expand Down Expand Up @@ -310,7 +316,7 @@ function createSessionManager (config) {
}
}

// initiated when a new heart rate value is received from heart rate sensor
// ToDo: REMOVE THIS INJECTION WHEN POSSIBLE
function handleHeartRateMeasurement (value) {
heartrate = value.heartrate
heartRateBatteryLevel = value.batteryLevel
Expand All @@ -334,15 +340,31 @@ function createSessionManager (config) {
metrics.splitLinearDistance = metrics.metricsContext.isSplitEnd ? splitDistance : metrics.totalLinearDistance - splitPrevAccumulatedDistance // This is needed to satisfy the RowingData recorder
metrics.cycleProjectedEndTime = intervalTargetDistance > 0 ? distanceOverTime.projectY(intervalTargetDistance) : intervalTargetTime
metrics.cycleProjectedEndLinearDistance = intervalTargetTime > 0 ? distanceOverTime.projectX(intervalTargetTime) : intervalTargetDistance
metrics.heartrate = heartrate > 30 ? heartrate : 0 // OPRUIMEN VAN DEZE INJECTIE
metrics.heartRateBatteryLevel = heartRateBatteryLevel // OPRUIMEN VAN DEZE INJECTIE
metrics.heartrate = heartrate > 30 ? heartrate : 0 // ToDo: REMOVE THIS INJECTION
metrics.heartRateBatteryLevel = heartRateBatteryLevel // ToDo: REMOVE THIS INJECTION
}

function getMetrics () { // TESTING PURPOSSES ONLY!
enrichMetrics()
return metrics
}

function resetWatchdogTimer () {
clearTimeout(watchdogTimer)
watchdogTimer = setTimeout(onWatchdogTimeout, watchdogTimout)
}

function onWatchdogTimeout () {
resetMetricsContext()
stopTraining()
metrics = rowingStatistics.getMetrics()
metrics.metricsContext.isSessionStop = true
sessionState = 'Stopped'
distanceOverTime.push(metrics.totalMovingTime, metrics.totalLinearDistance)
emitMetrics('metricsUpdate')
log.error(`Time: ${metrics.totalMovingTime}, Watchdog has forced a hard stop due to exceeding the twice maximumStrokeTimeBeforePause (i.e. ${watchdogTimout} seconds) without drive/recovery change`)
}

return Object.assign(emitter, {
handleCommand,
handleHeartRateMeasurement,
Expand All @@ -351,5 +373,3 @@ function createSessionManager (config) {
getMetrics
})
}

export { createSessionManager }

0 comments on commit bf15df6

Please sign in to comment.