From 6c5c1b8cb855ef812e8d1728c9ef73a762442960 Mon Sep 17 00:00:00 2001 From: Lars Berning <151194+laberning@users.noreply.github.com> Date: Sat, 13 Mar 2021 19:20:36 +0000 Subject: [PATCH] adds linting pre commit hook, cleans documentation --- .gitignore | 4 +- .husky/.gitignore | 1 + .husky/pre-commit | 4 + .markdownlint.json | 4 + README.md | 4 +- app/ble/RowingMachinePeripheral.js | 1 - app/client/app.js | 5 +- app/server.js | 2 +- doc/attribution.md | 4 +- doc/backlog.md | 11 ++- doc/installation.md | 8 +- package-lock.json | 154 +++++++++++++++++++++++++++-- package.json | 7 +- 13 files changed, 184 insertions(+), 25 deletions(-) create mode 100644 .husky/.gitignore create mode 100755 .husky/pre-commit create mode 100644 .markdownlint.json diff --git a/.gitignore b/.gitignore index 20ea6b8..2eb535f 100644 --- a/.gitignore +++ b/.gitignore @@ -70,7 +70,9 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser +.vscode + node_modules .DS_Store ._* -tmp/ \ No newline at end of file +tmp/ diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 0000000..31354ec --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..20d0d06 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npm run lint diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..b077f0e --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,4 @@ +{ + "default": true, + "MD013": false +} diff --git a/README.md b/README.md index d328273..9b747ce 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Open Rowing Monitor implements a physics model to simulate the typical metrics o ### Web Interface -The web interface visualizes the rowing metrics on any device that can run a browser (i.e. a smartphone that you attach to your rowing machine while training). It uses websockets to show the rowing status in realtime. Besides that it does not do much (yet). +The web interface visualizes the rowing metrics on any device that can run a browser (i.e. a smartphone that you attach to your rowing machine while training). It uses websockets to show the rowing status in Realtime. Besides that it does not do much (yet).
@@ -46,7 +46,7 @@ FTMS supports different types of fitness machines. Open Rowing Monitor currently I originally started this project, because my rowing machine (Sportstech WRX700) has a very simple computer and I wanted to build something with a clean and simple interface that calculates more realistic metrics. Also, this was a good reason to learn a bit more about Bluetooth and all its specifics. -The original proof of concept version started as a sketch on an ardunio, but when I started adding things like a web frontend and BLE I moved it to the much more powerful Raspberry Pi. Maybe using a Raspi for this small IoT-project is a bit of an overkill, but it has the capacity for further features such as syncing training data or rowing games. And it has USB-Ports that I can use to charge my phone while rowing :-) +The original proof of concept version started as a sketch on an Arduino, but when I started adding things like a web frontend and BLE I moved it to the much more powerful Raspberry Pi. Maybe using a Raspberry Pi for this small IoT-project is a bit of an overkill, but it has the capacity for further features such as syncing training data or rowing games. And it has USB-Ports that I can use to charge my phone while rowing :-) ## Further information diff --git a/app/ble/RowingMachinePeripheral.js b/app/ble/RowingMachinePeripheral.js index e5eb3d2..5972aa9 100644 --- a/app/ble/RowingMachinePeripheral.js +++ b/app/ble/RowingMachinePeripheral.js @@ -50,7 +50,6 @@ function createRowingMachinePeripheral (options) { bleno.on('accept', (clientAddress) => { log.debug(`ble central connected: ${clientAddress}`) - // todo: do we need this? bleno.updateRssi() }) diff --git a/app/client/app.js b/app/client/app.js index 4b9ef3b..ce7edf3 100644 --- a/app/client/app.js +++ b/app/client/app.js @@ -8,6 +8,7 @@ // eslint-disable-next-line no-unused-vars export function createApp () { const fields = ['strokesTotal', 'distanceTotal', 'caloriesTotal', 'power', 'splitFormatted', 'strokesPerMinute', 'durationTotal'] + let socket initWebsocket() resetFields() @@ -16,7 +17,7 @@ export function createApp () { function initWebsocket () { // use the native websocket implementation of browser to communicate with backend // eslint-disable-next-line no-undef - const socket = new WebSocket(`ws://${location.host}`) + socket = new WebSocket(`ws://${location.host}`) socket.addEventListener('open', (event) => { console.log('websocket openend') @@ -96,7 +97,7 @@ export function createApp () { function reset () { resetFields() - socket.send(JSON.stringify({ command: 'reset' })) + if (socket)socket.send(JSON.stringify({ command: 'reset' })) } return { diff --git a/app/server.js b/app/server.js index e3c3abd..b5a6588 100644 --- a/app/server.js +++ b/app/server.js @@ -22,7 +22,7 @@ import { recordRowingSession, replayRowingSession } from './tools/RowingRecorder log.setLevel(log.levels.INFO) const peripheral = createRowingMachinePeripheral({ - simulateIndoorBike: true + simulateIndoorBike: false }) peripheral.on('controlPoint', (event) => { diff --git a/doc/attribution.md b/doc/attribution.md index f0ee565..0ec60b8 100644 --- a/doc/attribution.md +++ b/doc/attribution.md @@ -1,6 +1,6 @@ # Attribution -Open Rowing Monitor uses some great work by others. Thank you for all the great ressources that helped me to make this project possible. I especially would like to thank: +Open Rowing Monitor uses some great work by others. Thank you for all the great resources that helped me to make this project possible. I especially would like to thank: * A lot of helpful information for building the physics engine of the rowing machine was found in this scientific work by Anu Dudhia: [The Physics of Ergometers](http://eodg.atm.ox.ac.uk/user/dudhia/rowing/physics/ergometer.html). @@ -8,4 +8,4 @@ Open Rowing Monitor uses some great work by others. Thank you for all the great * The app icon is based on this [image of a rowing machine](https://thenounproject.com/term/rowing-machine/659265) by [Gan Khoon Lay](https://thenounproject.com/leremy/) licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/). -* Bluetooth is quite a complex biest, luckily the Bluetooth SIG releases all the [specifications here](https://www.bluetooth.com/specifications/specs) +* Bluetooth is quite a complex beast, luckily the Bluetooth SIG releases all the [specifications here](https://www.bluetooth.com/specifications/specs) diff --git a/doc/backlog.md b/doc/backlog.md index cfac5fd..4991836 100644 --- a/doc/backlog.md +++ b/doc/backlog.md @@ -4,17 +4,21 @@ This is the very minimalistic Backlog for further development of this project. ## Soon -* check todo markers in code and add them to this backlog * cleanup of the server.js start file * figure out where to set the Service Advertising Data (FTMS.pdf p 15) -* Web UI: replace fullscreen button with exit Button when started from homescreen +* Web UI: replace fullscreen button with exit Button when started from home screen * investigate bug: crash, when one unsubscribe to BLE "Generic Attribute", probably a bleno bug "handleAttribute.emit is not a function" -* set up a raspi with the installation instructions to see if they are correct +* add photo of wired device to installation instructions +* what value should we use for split, if we are in a rowing pause? technically should be infinity... +* set up a Raspberry Pi with the installation instructions to see if they are correct ## Later +* implement the proprietary Concept2 PM BLE protocol as described here [Concept2 PM Bluetooth Smart Communication Interface](https://www.concept2.co.uk/files/pdf/us/monitors/PM5_BluetoothSmartInterfaceDefinition.pdf) +* add some attributes to BLE DeviceInformationService * add a config file * presets for rowing machine specific config parameters +* improve the physics model for waterrowers * validate FTMS with more training applications and harden implementation * make Web UI a proper Web Application (tooling and SPA framework) * record the workout and show a visual graph of metrics @@ -26,3 +30,4 @@ This is the very minimalistic Backlog for further development of this project. * add video playback in background of Web UI * implement or integrate some rowing games * add possibility to define workouts (i.e. training intervals with goals) +* directly attach a touchscreen to the Raspberry Pi and automatically show WebUI on this in kiosk mode diff --git a/doc/installation.md b/doc/installation.md index 4b75f23..b2cee1b 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -7,9 +7,9 @@ This guide roughly explains how to set up your device. I will probably build an * A Raspberry Pi that supports Bluetooth Low Energy (Pi 3 or Pi 4). Probably this also runs on other devices. * An SD Card, any size above 4GB should be fine * A rowing machine (obviously) with some way to measure the rotation of the flywheel - * the WRX700 has a build in reed sensor that I can directly connect to the GPIO pins of the raspi + * the WRX700 has a build in reed sensor that I can directly connect to the GPIO pins of the Raspberry Pi * if your machine doesn't have a sensor, it should be easy to build something similar (magnetically or optical) -* Some dupont wires to connect the GPIO pins to the sensor +* Some Dupont cables to connect the GPIO pins to the sensor ## Software Installation @@ -79,11 +79,11 @@ WantedBy=multi-user.target ## Hardware Installation -Basically all thats left to do is hook up your reed sensor to the GPIO pins of the Raspberry Pi. +Basically all that's left to do is hook up your reed sensor to the GPIO pins of the Raspberry Pi. todo: add a photo of the wired device -Open Rowing Monitor reads the sensor signal from GPIO port 17 and expects it to pull on GND if the sensor is closed. To get a stable reading you should add a pull-up resistor to that pin. I prefer to use the internal resitor of the raspi to keep the wiring simple but of course you can also go with an external circuit. +Open Rowing Monitor reads the sensor signal from GPIO port 17 and expects it to pull on GND if the sensor is closed. To get a stable reading you should add a pull-up resistor to that pin. I prefer to use the internal resistor of the Raspberry Pi to keep the wiring simple but of course you can also go with an external circuit. The internal pull-up can be enabled as described [here](https://www.raspberrypi.org/documentation/configuration/config-txt/gpio.md). So its as simple as adding the following to `/boot/config.txt` and then rebooting the device. diff --git a/package-lock.json b/package-lock.json index 905a886..9ca13fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -441,6 +441,12 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz", + "integrity": "sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -515,8 +521,7 @@ "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "optional": true + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, "deep-is": { "version": "0.1.3", @@ -614,6 +619,12 @@ "ansi-colors": "^4.1.1" } }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true + }, "epoll": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/epoll/-/epoll-4.0.0.tgz", @@ -1220,6 +1231,12 @@ "has-symbols": "^1.0.1" } }, + "get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "dev": true + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -1348,6 +1365,12 @@ "sshpk": "^1.7.0" } }, + "husky": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-5.1.3.tgz", + "integrity": "sha512-fbNJ+Gz5wx2LIBtMweJNY1D7Uc8p1XERi5KNRMccwfQA+rXlxWNSdUxswo0gT8XqxywTIw7Ywm/F4v/O35RdMg==", + "dev": true + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1411,8 +1434,7 @@ "ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "optional": true + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "is-arrayish": { "version": "0.2.1", @@ -1572,6 +1594,12 @@ "minimist": "^1.2.0" } }, + "jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -1594,6 +1622,15 @@ "type-check": "~0.4.0" } }, + "linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -1627,6 +1664,18 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" }, + "lodash.differencewith": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.differencewith/-/lodash.differencewith-4.5.0.tgz", + "integrity": "sha1-uvr7yRi1UVTheRdqALsK76rIVLc=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, "loglevel": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", @@ -1649,6 +1698,93 @@ } } }, + "markdown-it": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.4.tgz", + "integrity": "sha512-34RwOXZT8kyuOJy25oJNJoulO8L0bTHYWXcdZBYZqFnjIy3NgjeoM3FmPXIOFQ26/lSHYMr8oc62B6adxXcb3Q==", + "dev": true, + "requires": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + } + } + }, + "markdownlint": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.23.1.tgz", + "integrity": "sha512-iOEwhDfNmq2IJlaA8mzEkHYUi/Hwoa6Ss+HO5jkwUR6wQ4quFr0WzSx+Z9rsWZKUaPbyirIdL1zGmJRkWawr4Q==", + "dev": true, + "requires": { + "markdown-it": "12.0.4" + } + }, + "markdownlint-cli": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.27.1.tgz", + "integrity": "sha512-p1VV6aSbGrDlpUWzHizAnSNEQAweVR3qUI/AIUubxW7BGPXziSXkIED+uRtSohUlRS/jmqp3Wi4es5j6fIrdeQ==", + "dev": true, + "requires": { + "commander": "~7.1.0", + "deep-extend": "~0.6.0", + "get-stdin": "~8.0.0", + "glob": "~7.1.6", + "ignore": "~5.1.8", + "js-yaml": "^4.0.0", + "jsonc-parser": "~3.0.0", + "lodash.differencewith": "~4.5.0", + "lodash.flatten": "~4.4.0", + "markdownlint": "~0.23.1", + "markdownlint-rule-helpers": "~0.14.0", + "minimatch": "~3.0.4", + "minimist": "~1.2.5", + "rc": "~1.2.8" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + } + } + }, + "markdownlint-rule-helpers": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.14.0.tgz", + "integrity": "sha512-vRTPqSU4JK8vVXmjICHSBhwXUvbfh/VJo+j7hvxqe15tLJyomv3FLgFdFgb8kpj0Fe8SsJa/TZUAXv7/sN+N7A==", + "dev": true + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -2209,7 +2345,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "optional": true, "requires": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -2604,8 +2739,7 @@ "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "optional": true + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "supports-color": { "version": "5.5.0", @@ -2796,6 +2930,12 @@ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index 912cee5..61d6e7f 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "node": ">=12" }, "scripts": { - "eslint": "eslint ./app", + "prepare": "husky install", + "lint": "eslint ./app && markdownlint '**/*.md' --ignore node_modules", "start": "node app/server.js", "test": "" }, @@ -32,6 +33,8 @@ "eslint-config-standard": "^16.0.2", "eslint-plugin-import": "^2.22.1", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^4.3.1" + "eslint-plugin-promise": "^4.3.1", + "husky": "^5.1.3", + "markdownlint-cli": "^0.27.1" } }