diff --git a/app/engine/RowingEngine.test.js b/app/engine/RowingEngine.test.js new file mode 100644 index 0000000..8aeb734 --- /dev/null +++ b/app/engine/RowingEngine.test.js @@ -0,0 +1,69 @@ +'use strict' +/* + Open Rowing Monitor, https://github.com/laberning/openrowingmonitor +*/ +import { test } from 'uvu' +import * as assert from 'uvu/assert' +import loglevel from 'loglevel' + +import rowerProfiles from '../../config/rowerProfiles.js' +import { createRowingEngine } from './RowingEngine.js' +import { replayRowingSession } from '../tools/RowingRecorder.js' + +const log = loglevel.getLogger('RowingEngine.test') +log.setLevel('warn') + +const createWorkoutEvaluator = function () { + const strokes = [] + + function handleStroke (stroke) { + strokes.push(stroke) + log.info(`stroke: ${strokes.length}, power: ${Math.round(stroke.power)}w, duration: ${stroke.duration.toFixed(2)}s, ` + + ` drivePhase: ${stroke.durationDrivePhase.toFixed(2)}s, distance: ${stroke.distance.toFixed(2)}m`) + } + function handleStrokeStateChanged () {} + function handlePause () {} + function getNumOfStrokes () { + return strokes.length + } + function getMaxStrokePower () { + return strokes.map((stroke) => stroke.power).reduce((acc, power) => Math.max(acc, power)) + } + function getMinStrokePower () { + return strokes.map((stroke) => stroke.power).reduce((acc, power) => Math.max(acc, power)) + } + return { + handleStroke, + handleStrokeStateChanged, + handlePause, + getNumOfStrokes, + getMaxStrokePower, + getMinStrokePower + } +} + +test('sample data for WRX700 should produce plausible results with rower profile', async () => { + const rowingEngine = createRowingEngine(rowerProfiles.WRX700) + const workoutEvaluator = createWorkoutEvaluator() + rowingEngine.notify(workoutEvaluator) + await replayRowingSession(rowingEngine.handleRotationImpulse, { filename: 'recordings/WRX700_2magnets.csv' }) + assert.is(workoutEvaluator.getNumOfStrokes(), 16, 'number of strokes does not meet expectation') + // todo: maximum power of the first stroke is too high because it does not contain a recovery part + // should fix that in the RowingEngine and adjust the maximum power here to 220 + assert.ok(workoutEvaluator.getMaxStrokePower() < 370, `maximum stroke power should be below 370w, but is ${workoutEvaluator.getMaxStrokePower()}w`) + assert.ok(workoutEvaluator.getMinStrokePower() > 50, `minimum stroke power should be above 50w, but is ${workoutEvaluator.getMinStrokePower()}w`) +}) + +test('sample data for DKNR320 should produce plausible results with rower profile', async () => { + const rowingEngine = createRowingEngine(rowerProfiles.DKNR320) + const workoutEvaluator = createWorkoutEvaluator() + rowingEngine.notify(workoutEvaluator) + await replayRowingSession(rowingEngine.handleRotationImpulse, { filename: 'recordings/DKNR320.csv' }) + assert.is(workoutEvaluator.getNumOfStrokes(), 10, 'number of strokes does not meet expectation') + // todo: maximum power of the first stroke is too high because it does not contain a recovery part + // should fix that in the RowingEngine and adjust the maximum power here to 200 + assert.ok(workoutEvaluator.getMaxStrokePower() < 370, `maximum stroke power should be below 370w, but is ${workoutEvaluator.getMaxStrokePower()}w`) + assert.ok(workoutEvaluator.getMinStrokePower() > 75, `minimum stroke power should be above 75w, but is ${workoutEvaluator.getMinStrokePower()}w`) +}) + +test.run() diff --git a/app/server.js b/app/server.js index 6a58d0f..c954722 100644 --- a/app/server.js +++ b/app/server.js @@ -62,7 +62,7 @@ peripheralManager.on('control', (event) => { const gpioTimerService = fork('./app/gpio/GpioTimerService.js') gpioTimerService.on('message', (dataPoint) => { rowingEngine.handleRotationImpulse(dataPoint) - // fs.appendFile('recordings/wrx700_2magnets_long.csv', `${dataPoint}\n`, (err) => { if (err) log.error(err) }) + // fs.appendFile('recordings/WRX700_2magnets.csv', `${dataPoint}\n`, (err) => { if (err) log.error(err) }) }) const rowingEngine = createRowingEngine(config.rowerSettings) diff --git a/docs/backlog.md b/docs/backlog.md index d17b984..3332832 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -8,7 +8,6 @@ This is the very minimalistic Backlog for further development of this project. * validate FTMS with more training applications and harden implementation (i.e. Holofit and Coxswain) * record a longer rowing session and analyze two encountered problems: 1) rarely the stroke rate doubles for a short duration (might be a problem with stroke detection when measurements are imprecise), 2) in one occasion the measured power jumped to a very high value after a break (40000 watts) * add support for ANT+ heart rate monitors with USB dongles -* presets for rowing machine specific config parameters * add an option to automatically feed the measured damping constant back into the rowing engine ## Later diff --git a/recordings/DKNR320.csv b/recordings/DKNR320.csv new file mode 100644 index 0000000..27aab29 --- /dev/null +++ b/recordings/DKNR320.csv @@ -0,0 +1,81 @@ +0.54800057 +0.268049458 +0.216636979 +0.231423722 +0.284531614 +0.360516235 +0.482000949 +0.43154357 +0.211636619 +0.183476903 +0.211438686 +0.258253277 +0.322601712 +0.419122022 +0.503416119 +0.247547705 +0.183943279 +0.18996022 +0.22674499 +0.280166413 +0.353291919 +0.465764768 +0.399939714 +0.194878642 +0.164347067 +0.183165805 +0.221021301 +0.270787329 +0.340818407 +0.445469766 +0.387934208 +0.195407159 +0.166335799 +0.186449225 +0.226147521 +0.277143086 +0.349279683 +0.460192588 +0.370720743 +0.188971811 +0.163149731 +0.182686216 +0.220796962 +0.270990489 +0.340495458 +0.445263279 +0.451159591 +0.202756547 +0.158435164 +0.164154601 +0.199352942 +0.243400048 +0.301640659 +0.3847461 +0.509093228 +0.298548183 +0.17824294 +0.162219424 +0.186324723 +0.22541504 +0.278458293 +0.350756165 +0.462008358 +0.405086177 +0.19120966 +0.162582118 +0.18241563 +0.220221933 +0.269459088 +0.339834293 +0.443984581 +0.462005699 +0.21064753 +0.161225062 +0.167056112 +0.20001449 +0.243339132 +0.301283162 +0.385138631 +0.520107711 +0.822650475 diff --git a/recordings/wrx700_1magnet.csv b/recordings/WRX700_1magnet.csv similarity index 100% rename from recordings/wrx700_1magnet.csv rename to recordings/WRX700_1magnet.csv diff --git a/recordings/wrx700_2magnets.csv b/recordings/WRX700_2magnets.csv similarity index 99% rename from recordings/wrx700_2magnets.csv rename to recordings/WRX700_2magnets.csv index 5e086f8..0fe2f3e 100644 --- a/recordings/wrx700_2magnets.csv +++ b/recordings/WRX700_2magnets.csv @@ -1,4 +1,3 @@ -3.47124274 0.370380355 0.211917846 0.169332723 diff --git a/recordings/wrx700_2magnets_session.csv b/recordings/WRX700_2magnets_session.csv similarity index 100% rename from recordings/wrx700_2magnets_session.csv rename to recordings/WRX700_2magnets_session.csv