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

@keiser/echip-webusb

v2.3.2

Published

Keiser Air eChip WebUSB Library

Downloads

7

Readme

Keiser Air eChip WebUSB Library

Publish

Project

This library handles communication with the Keiser eChip as a means of collecting workout information from Keiser Strength and Functional equipment. The library is written in TypeScript and supports modern browsers with WebUSB support.

For additional information about this project visit the Keiser Developer Zone.

Requirements

Required Hardware: USB to 1-Wire/iButton Adapter (DS9490)

Required Drivers: 1-Wire/iButton Drivers for Windows

Installation

Install with npm: npm install @keiser/echip-webusb

Usage

Import singleton instance from module using preferred module loading technique.

import ChipReaderWatcher from '@keiser/echip-webusb'

The ChipReaderWatcher handles permissions and USB connection events. On first load, the browser will not have provided a grant to the site to access the USB device, so the ChipReaderWatcher.start() method must be called by an event that originates from a user action. This may only be required once on the first visit to the site, or it may be required each time the site is loaded based on browser vendors preferred implementation.

connectButton.addEventListener('click', async () => {
  try {
    await ChipReaderWatcher.start()
  } catch (error) {
    console.error(error.message)
  }
})

Once the ChipReaderWatcher.start() method has been called the class will prompt the browser for permission and begin watching for devices matching the Chip Readers device signature. To be alerted when a device is found, pass a function to the ChipReaderWatcher.onConnect() method.

ChipReaderWatcher.onConnect((chipReader) => {
  console.log('Chip Reader Connected 😄')
})

The ChipReaderWatcher.onConnect() will pass in a ChipReader object which is the object bound to the physical device connected. This library is capable of handling multiple Chip Reader devices simultaneously, so the onConnect() method has potential for returning multiple ChipReader devices over the course of the application's life.

chipReader.onDisconnect(() => {
  console.log('Chip Reader Disconnected 😞')
})

The ChipReader object has an onDisconnect() method which will alert when the Chip Reader has been disconnected for some reason. Once a ChipReader object has been disconnected, it is disposed and cannot be used again. The next time the device is connected, a new ChipReader object will be returned.

chipReader.onChipDetect(async (chip) => {
  console.log('Chip Connected: ' + chip.id)
  if (chip instanceof DataChip) {
    chip.onData(data => console.log(data))
  }
})

The ChipReader object also has an onChipDetect() method which will alert when a valid chip has been placed into the reader. The event passes in a Chip object that can be used to interact with the chip data directly. Just like the ChipReaderWatcher.onConnect() method, the ChipReader.onChipDetect() method can be called multiple times for multiple chips all being handled concurrently. Once a chip is disconnected, the Chip object is disposed and cannot be reused.

Full example usage:

import ChipReaderWatcher, { DataChip } from '@keiser/echip-webusb'

document.addEventListener('DOMContentLoaded', event => {
  const connectButton = document.querySelector('#connect') as HTMLInputElement

  if (connectButton) {
    connectButton.addEventListener('click', async () => {
      try {
        await ChipReaderWatcher.start()
      } catch (error) {
        console.error(error.message)
      }
    })
  }

  ChipReaderWatcher.onConnect((chipReader) => {
    console.log('Chip Reader Connected 😄')

    chipReader.onChipDetect(async (chip) => {
      console.log('Chip Connected: ' + chip.id)
      if (chip instanceof DataChip) {
        chip.onData(data => console.log(data))
      }
    })

    chipReader.onDisconnect(() => {
      console.log('Chip Reader Disconnected 😞')
    })
  })
})

eChip Capabilities

A single eChip is capable of holding 200 workout sets worth of data from 24 distinct machines. If the eChip is full, machines will replace the oldest workout record on the eChip with new data. It is recommended to completely clear the eChip between uses and to only write the data required for targeting during the current workout session.

API

ChipReaderWatcher

The ChipReaderWatcher is a singleton class which handles the USB device monitoring and permissions handling. There can be only one ChipReaderWatcher instance created within a window scope, so the library instantiates the class during import and preserves a single instance for all imports.

Properties

| Name | Usage | | ---- | ----- | | browserSupported: boolean | Indicates if the browser supports WebUSB. |

Methods

| Name | Usage | | ---- | ----- | | onConnect(Listener<ChipReader>): Disposable | Adds an event listener for when a Chip Reader device is connected. Callback method will be passed the new ChipReader instance for the connected device. | | start(): Promise<void> | Initializes the watcher by first requesting permissions and then doing a hardware search. This method must be triggered by a user action such as a click event or the permission request will be denied. | | stop(): Promise<void> | Closes all active connections. |

ChipReader

The ChipReader instance is passed into the onConnect callback function and is the interface to the connected Chip Reader device.

Properties

| Name | Usage | | ---- | ----- | | claimed: Promise<boolean> | Promise indicating if the USB device interface has been claimed. | | disposed: boolean | Indicates if the device connection has been severed and the class instance disposed. |

Methods

| Name | Usage | | ---- | ----- | | onChipDetect(Listener<Chip>): Disposable | Adds an event listener for when a chip is connected to the Chip Reader device. Callback method will be passed the new Chip instance for the connected chip. | | onDisconnect(Listener<null>): Disposable | Adds an event listener for when this Chip Reader device becomes disconnected. The instance will be disposed following this event. |

BaseChip

The BaseChip instance is passed into the onChipDetect callback function and is the interface to the connected chip device. There are several different extensions to the base BaseChip object that can identified by doing a instanceOf check or looking at the type property.

Properties

| Name | Usage | | ---- | ----- | | disposed: boolean | Indicates if the eChip connection has been severed and the class instance disposed. | | data: ChipObject | Generic object with the current data from the chip. | | id: string | UUID string of the eChip. | | type: ChipType | ChipType enum value corresponding to the type of chip. |

Methods

| Name | Usage | | ---- | ----- | | destroy(): void | Called to disconnect the eChip device. | | onDisconnect(Listener<null>): Disposable | Adds an event listener for when this chip becomes disconnected. The instance will be disposed following this event. | | onData(Listener<ChipObject>): Disposable | Adds an event listener for when the chip data has changed. |

TZChip and RTCChip

The TZChip and RTCChip are class extensions on the BaseChip class. They add no additional properties or methods, but allow the identification of chip type and will perform chip set operations automatically when detected. An event issued on the onData event indicates that the chips data has been successfully updated.

DataChip

The DataChip class extension on the BaseChip class adds additional properties and methods specific to the data chip.

Methods

| Name | Usage | | ---- | ----- | | clearData(): Promise<void> | Method clears the data on the chip and resolve the promise on successful write. An onData event will be issues for the blank chip data. | | setData({string: MachineObject}): Promise<void> | Method sets the data on the chip according to the data passed into the method. The method accepts an object with string keys corresponding to the machine's 4-digit model number with the MachineObject as the value of the property. Method resolve the promise on successful write. An onData event will be issues for the freshly written chip data. |

Data Structures

ChipObject

interface ChipObject {
  type: ChipType
}

DataChipObject

interface DataChipObject {
  type: ChipType
  machineData: {[index: string]: MachineObject}
  rawData: Uint8Array[]
  validStructure: boolean
}

MachineObject

interface MachineObject {
  position: MachinePosition
  sets: MachineSet[]
}

MachinePosition

interface MachinePosition {
  chest: number | null
  rom2: number | null
  rom1: number | null
  seat: number | null
}

MachineSet

interface MachineSet {
  version: string
  serial: string
  time: string
  resistance: number
  precision: Precision
  units: ForceUnit
  repetitions: number
  peak: number | null
  work: number | null
  distance: number | null
  chest: number | null
  rom2: number | null
  rom1: number | null
  seat: number | null
  test: MachineTest | null
}

MachineTest

interface MachineTest {
  type: TestType
  high: MachineTestResult | null
  low: MachineTestResult | null
}

MachineTestResult

interface MachineTestResult {
  power: number
  velocity: number
  force: number
  position: number
}

Constants

enum Precision {
  dec = 'dec',
  int = 'int'
 }

enum ForceUnit {
  lb = 'lb',
  kg = 'kg',
  ne = 'ne',
  er = 'er'
}

enum TestType {
  power6r = 'power6r',
  a4206r = 'a4206r',
  a42010r = 'a42010r'
}

enum ChipType {
  dataChip = 12,
  rtcChip = 36,
  tzChip = 45,
  unknown = 0
}

References

Maxim Integrated 1-Wire USB Android notes

Maxim Integrated 1-Wire USB Android project

Copyright and License

Copyright © 2020 Keiser Corporation.

The Keiser eChip WebUSB Library source code and library package are made available through the MIT license.

Using any of this library in connection with any Keiser eChip enabled equipment make you subject to the following agreements. Please read all documents in their entirety as they govern your use of the APIs.