npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

incyclist-devices

v2.3.0

Published

Library used by the [Incyclist](https://incyclist.com) Indoor Cycling App to communicate with devices (Smart Trainers, Sensors)

Downloads

504

Readme

incyclist-devices

Library used by the Incyclist Indoor Cycling App to communicate with devices (Smart Trainers, Sensors)

It currently support the following Interfaces/Devices

ANT

  • Smart Trainers (ANT+ FE)
  • Power Meters (ANT+PWR)
  • Heartrate Monitors (ANT+HR)
  • Cadence Sensors (ANT+CAD)
  • Speed Sensors (ANT+SPD)
  • Speed + Cadence Sensors (ANT+SC)

BLE

  • Smart Trainers (BLE FTMS)
  • Power Meters (BLE CP)
  • Heartrate Monitors (BLE HR)
  • Wahoo Smart Trainers (Wahoo specific service)
  • Tacx FE-C over BLE

Serial

  • Daum Classic Ergo Bikes
  • Daum Premium Ergo Bikes (also over TCP/IP)
  • Kettler Ergo Racer Ergo Bikes

Install

npm install incyclist-devices

Usage

Setup Interfaces and Bindings

Interface classes are used to enable basic communication (transport layer).

As this library supports various OS( Linux, Windows, Mac) and Incyclist is based on Electron, which requires to clearly separate between rendering and main process, Bindings need to be provided for each of the Interfaces. The specifications of these bindings are specific to the interface:

Ant Example

const {EventLogger,ConsoleAdapter} = require( 'gd-eventlog');
const {AntDevice} = require('incyclist-ant-plus/lib/bindings');

const logger = new EventLogger('AntSample')
const ant = InterfaceFactory.create('ant',{logger, log:true, binding:AntDevice})

Serial Example

const {EventLogger,ConsoleAdapter} = require( 'gd-eventlog');
const { autoDetect } = require('@serialport/bindings-cpp')


const logger = new EventLogger('SerialSample')
const serial = InterfaceFactory.create('serial',{logger, log:true, binding:autodetect()})

BLE Example

const {EventLogger,ConsoleAdapter} = require( 'gd-eventlog');
const {WinrtBindings} = require('./bindings')
const Noble = require('noble/lib/noble');


const noble = new Noble(new WinrtBindings())
const logger = new EventLogger('BLESample')
const ble = InterfaceFactory.create('ble',{logger, log:true, binding:noble})

Check availability of interface

For some interfaces (ANT and BLE) it cannot be guaranteed that the underlying hardware supports the interface ( e.g. a USB stick might be required). Therefore this library offers a connect method, that allows to check if the interface is availabe

Ant Example

    const connected = await ant.connect() // tries to establish communication and blocks USB stick for usage with other apps
    if (connect) {
        .... 
        await ant.disconnect() // closes communication and unblocks USB stick
    }
    else {
        ... 
    }

Scan for devices

Every interface offers a method scan that allows to scan for devices. The timeout for the scan can be specified in the properties. If those are not provided, a default will apply.

The scan method returns a Promise<DeviceSettings[]> containing the settings of all detected devices.

In addition to that, all devices that are detected, will be emitted as device event during the scan.

The method stopScancan be used to stop an ongoing scan.

Examples

  • Example 1: wait for teh result of the scan

    _interface.on('device',(deviceSettings:DeviceSettings)=>{console.log('Device found', DeviceSettings)})
    const devices = await _interface_.scan({timeout:20000})
    console.log(devices)
  • Example 2: stop scan as soon as one device was found

    _interface.on('device',async (deviceSettings:DeviceSettings)=>{
        console.log('Device found', DeviceSettings)
        await _interface.stopScan()
    })
    _interface_.scan({timeout:20000})    

Create a device

The Devices library provides and AdapterFactory, which allows you to create a device adapters, based on the specifications provided in a DeviceSettings object.

The exact content if this object varies between the interfaces:

  • Ant: interface ('ant'), profile( one of 'HR','PWR', 'FE'), deviceID

  • BLE: interface ('ble'), protocol( one of 'fm','cp,'hr', 'tacx', 'wahoo'), name, id or address

  • Serial: interface('serial' or 'tcpip'), protocol( one of 'Daum Premium', 'Daum Classic', 'Kettler Racer'), name, port, host (only for TCP/IP)

These device adapters are used by Incyclist to communicate with the devices. The AdapterFactory will ensure that for a given device only one instance of a device adapter will be provided, to avoid that two classes will concurrently communicate with the same physical device.

At the point where a device adapter is created, the constructor will not try to communicate with the device. I.e. the adapter can be created even if no such device is available/connected.

Example

const {AdapterFactory} = require('incyclist-devices')

const device = AdapterFactory.create({interface:'ble, protocol:'fm', name:'KICKR BIKE 1234'})

Communicate with a device

In order to commuicate with the device, the device firstly has to be started

start( props?: DeviceProperties):Promise<boolean>

you then should register for events:

  • data (device:DeviceSettings, data: DeviceData): is emitted whenever a device/sensor has sent data

    • device: describes the device that has sent data
    • data: provides the data that the device/sensor has provided (power, speed, cadence,slope, heartrate, timestamp,... )
  • disconnected (device:DeviceSettings): is emitted when the library has not recieved any udate for a configurable time or the underlying interface has recognized a connection loss

    • device: describes the device that has sent data
  • device-info- (device:DeviceSettings, info:): signals that additional information about the device was received ( e.g. manufacturer, additional features/capabilities)

    • device: describes the device that has sent data
try {
    await device.start({timeout:5000, userWeight:90,bikeWeight:10})
    device.on('data',(deviceInfo,data)=> { console.log('device data', deviceInfo,data) })
    device.on('disconnected',(deviceInfo)=> { 
        console.log('device disconnected', deviceInfo) 
        // check if reconnect makes sense
        device.disconnect()
    })
}
catch(err) {
    console.log('device could not be started, reason', err.message)
}

setMaxUpdateFrequency(ms:number):void

getMaxUpdateFrequency():number

BLE and ANT devices might send data more frequently than you mihgt want to process in your app. Therefore you can control how often you want to receive updates from a device.

Default value is 1s

A value of -1 indicates that the app wants to receive any data without delays

device.setMaxUpdateFrequency(1000) // send update every 1000ms
const updateFrequency = device.getMaxUpdateFrequency()

setPullFrequency(ms:number):void

getPullFrequency():number

Serial Devices are typically not automatically sending data, but the app has to actively pull. Therefore the Serial device adapters also offer the capability to control how often the library will pull data from the device

Default value is 1s

Warning: Setting this value to low might overload the serial port and you might not receive any data

stop():Promise<boolean>

Once the commeunication is not required anymore, you can call stop() to close the connection. This will also automatically unregister the event listeners.

pause():Promise<boolean>

resume():Promise<boolean>

In some cases it might sense to not further receive any update from the device, but still keep the communication open. In thise case, pause() and resume() can be called.

During a paused state, no event will be emitted

sendUpdate(request:UpdateRequest):Promise<boolean>

Allows to send data to the device, typically one of the following data will be sent

slope: (SIM Mode) sets the slope/incline. The smart trainer then will adjust power accordingly

targetPower: (ERG Mode) sets the power that the smart trainer should

reset: returns to the default settings at the start of the training

resfresh: repeats the previous update

This method should only be called for SmartTrainers or PowerMeters

Examples

Please have a look at the example code