Add OFF mode to BLE peripheral and refactoring

Add OFF mode to be able to turn BLE advertisement off. Rename
switchPeripheralMode function to include BLE in order to be more
descriptive.
This commit is contained in:
Abász 2022-12-17 21:35:22 +01:00
parent 7ef338d856
commit a3cd6e6f39
5 changed files with 49 additions and 43 deletions

View File

@ -65,7 +65,7 @@ export class DashboardActions extends AppElement {
return html` return html`
<button @click=${this.reset}>${icon_undo}</button> <button @click=${this.reset}>${icon_undo}</button>
${this.renderOptionalButtons()} ${this.renderOptionalButtons()}
<button @click=${this.switchPeripheralMode}>${icon_bluetooth}</button> <button @click=${this.switchBlePeripheralMode}>${icon_bluetooth}</button>
<div class="peripheral-mode">${this.peripheralMode()}</div> <div class="peripheral-mode">${this.peripheralMode()}</div>
${this.dialog ? this.dialog : ''} ${this.dialog ? this.dialog : ''}
` `
@ -116,7 +116,7 @@ export class DashboardActions extends AppElement {
case 'FTMS': case 'FTMS':
return 'FTMS Rower' return 'FTMS Rower'
default: default:
return '' return 'Off'
} }
} }
@ -135,8 +135,8 @@ export class DashboardActions extends AppElement {
this.sendEvent('triggerAction', { command: 'reset' }) this.sendEvent('triggerAction', { command: 'reset' })
} }
switchPeripheralMode () { switchBlePeripheralMode () {
this.sendEvent('triggerAction', { command: 'switchPeripheralMode' }) this.sendEvent('triggerAction', { command: 'switchBlePeripheralMode' })
} }
uploadTraining () { uploadTraining () {

View File

@ -130,8 +130,8 @@ export function createApp (app) {
function handleAction (action) { function handleAction (action) {
switch (action.command) { switch (action.command) {
case 'switchPeripheralMode': { case 'switchBlePeripheralMode': {
if (socket)socket.send(JSON.stringify({ command: 'switchPeripheralMode' })) if (socket)socket.send(JSON.stringify({ command: 'switchBlePeripheralMode' }))
break break
} }
case 'reset': { case 'reset': {

View File

@ -16,83 +16,88 @@ import child_process from 'child_process'
import AntManager from './ant/AntManager.js' import AntManager from './ant/AntManager.js'
import { createAntHrmPeripheral } from './ant/HrmPeripheral.js' import { createAntHrmPeripheral } from './ant/HrmPeripheral.js'
const modes = ['FTMS', 'FTMSBIKE', 'PM5', 'CSC', 'CPS'] const bleModes = ['FTMS', 'FTMSBIKE', 'PM5', 'CSC', 'CPS', 'OFF']
function createPeripheralManager () { function createPeripheralManager () {
const emitter = new EventEmitter() const emitter = new EventEmitter()
let peripheral let blePeripheral
let mode let bleMode
createPeripheral(config.bluetoothMode) createBlePeripheral(config.bluetoothMode)
function getPeripheral () { function getBlePeripheral () {
return peripheral return blePeripheral
} }
function getPeripheralMode () { function getBlePeripheralMode () {
return mode return bleMode
} }
function switchPeripheralMode (newMode) { function switchBlePeripheralMode (newMode) {
// if now mode was passed, select the next one from the list // if now mode was passed, select the next one from the list
if (newMode === undefined) { if (newMode === undefined) {
newMode = modes[(modes.indexOf(mode) + 1) % modes.length] newMode = bleModes[(bleModes.indexOf(bleMode) + 1) % bleModes.length]
} }
createPeripheral(newMode) createBlePeripheral(newMode)
} }
function notifyMetrics (type, metrics) { function notifyMetrics (type, metrics) {
peripheral.notifyData(type, metrics) blePeripheral.notifyData(type, metrics)
} }
function notifyStatus (status) { function notifyStatus (status) {
peripheral.notifyStatus(status) blePeripheral.notifyStatus(status)
} }
async function createPeripheral (newMode) { async function createBlePeripheral (newMode) {
if (peripheral) { if (blePeripheral) {
await peripheral.destroy() await blePeripheral.destroy()
} }
switch (newMode) { switch (newMode) {
case 'PM5': case 'PM5':
log.info('bluetooth profile: Concept2 PM5') log.info('bluetooth profile: Concept2 PM5')
peripheral = createPm5Peripheral(controlCallback) blePeripheral = createPm5Peripheral(controlCallback)
mode = 'PM5' bleMode = 'PM5'
break break
case 'FTMSBIKE': case 'FTMSBIKE':
log.info('bluetooth profile: FTMS Indoor Bike') log.info('bluetooth profile: FTMS Indoor Bike')
peripheral = createFtmsPeripheral(controlCallback, { blePeripheral = createFtmsPeripheral(controlCallback, {
simulateIndoorBike: true simulateIndoorBike: true
}) })
mode = 'FTMSBIKE' bleMode = 'FTMSBIKE'
break break
case 'CSC': case 'CSC':
log.info('bluetooth profile: Cycling Speed and Cadence') log.info('bluetooth profile: Cycling Speed and Cadence')
peripheral = createCscPeripheral() blePeripheral = createCscPeripheral()
mode = 'CSC' bleMode = 'CSC'
break break
case 'CPS': case 'CPS':
log.info('bluetooth profile: Cycling Power Meter') log.info('bluetooth profile: Cycling Power Meter')
peripheral = createCpsPeripheral() blePeripheral = createCpsPeripheral()
mode = 'CPS' bleMode = 'CPS'
break break
case 'FTMS': case 'FTMS':
default:
log.info('bluetooth profile: FTMS Rower') log.info('bluetooth profile: FTMS Rower')
peripheral = createFtmsPeripheral(controlCallback, { blePeripheral = createFtmsPeripheral(controlCallback, {
simulateIndoorBike: false simulateIndoorBike: false
}) })
mode = 'FTMS' bleMode = 'FTMS'
break break
default:
log.info('bluetooth profile: Off')
bleMode = 'OFF'
} }
peripheral.triggerAdvertising() if (bleMode.toLocaleLowerCase() !== 'OFF'.toLocaleLowerCase()) { blePeripheral.triggerAdvertising() }
emitter.emit('control', { emitter.emit('control', {
req: { req: {
name: 'peripheralMode', name: 'blePeripheralMode',
peripheralMode: mode peripheralMode: bleMode
} }
}) })
} }
@ -123,9 +128,9 @@ function createPeripheralManager () {
return Object.assign(emitter, { return Object.assign(emitter, {
startAntHeartRateService, startAntHeartRateService,
startBleHeartRateService, startBleHeartRateService,
getPeripheral, getBlePeripheral,
getPeripheralMode, getBlePeripheralMode,
switchPeripheralMode, switchBlePeripheralMode,
notifyMetrics, notifyMetrics,
notifyStatus notifyStatus
}) })

View File

@ -98,7 +98,7 @@ peripheralManager.on('control', (event) => {
peripheralManager.notifyStatus({ name: 'startedOrResumedByUser' }) peripheralManager.notifyStatus({ name: 'startedOrResumedByUser' })
event.res = true event.res = true
break break
case 'peripheralMode': case 'blePeripheralMode':
webServer.notifyClients('config', getConfig()) webServer.notifyClients('config', getConfig())
event.res = true event.res = true
break break
@ -216,8 +216,8 @@ workoutUploader.on('resetWorkout', () => {
const webServer = createWebServer() const webServer = createWebServer()
webServer.on('messageReceived', async (message, client) => { webServer.on('messageReceived', async (message, client) => {
switch (message.command) { switch (message.command) {
case 'switchPeripheralMode': case 'switchBlePeripheralMode':
peripheralManager.switchPeripheralMode() peripheralManager.switchBlePeripheralMode()
break break
case 'reset': case 'reset':
resetWorkout() resetWorkout()
@ -243,7 +243,7 @@ webServer.on('clientConnected', (client) => {
// todo: extract this into some kind of state manager // todo: extract this into some kind of state manager
function getConfig () { function getConfig () {
return { return {
peripheralMode: peripheralManager.getPeripheralMode(), peripheralMode: peripheralManager.getBlePeripheralMode(),
stravaUploadEnabled: !!config.stravaClientId && !!config.stravaClientSecret, stravaUploadEnabled: !!config.stravaClientId && !!config.stravaClientSecret,
shutdownEnabled: !!config.shutdownCommand shutdownEnabled: !!config.shutdownCommand
} }

View File

@ -78,6 +78,7 @@ export default {
// - FTMSBIKE: The FTMS profile is used by Smart Bike Trainers (please note: the speed and power are still aimed for rowing, NOT for a bike!) // - FTMSBIKE: The FTMS profile is used by Smart Bike Trainers (please note: the speed and power are still aimed for rowing, NOT for a bike!)
// - CPS: The BLE Cycling Power Profile simulates a bike for more modern Garmin watches // - CPS: The BLE Cycling Power Profile simulates a bike for more modern Garmin watches
// - CSC: The BLE Cycling Speed and Cadence Profile simulates a bike for older Garmin watches // - CSC: The BLE Cycling Speed and Cadence Profile simulates a bike for older Garmin watches
// - OFF: Turns Bluetooth advertisement off
bluetoothMode: 'FTMS', bluetoothMode: 'FTMS',
// Turn this on if you want support for Bluetooth Low Energy heart rate monitors // Turn this on if you want support for Bluetooth Low Energy heart rate monitors