Code Monkey home page Code Monkey logo

pyrow's Introduction

PyRow

NOTE: This code has not been thoroughly tested and may not function as advertised. This documentation my contain mistakes or incomplete information. Please report and findings to the author so that they may be addressed in a stable release.

ABOUT

PyRow is python code that allows one to interact with a Concept 2 Rowing Ergometer PM3 or PM4 monitor using python. PyRow sends and receives information from the Ergometer using csafe commands or built in functions (listed below). The goal of PyRow is to allow for multiple platforms to have easy access to the Ergometer.

For an explanation of the csafe commands please use the following documentation:

Need to download the SDK to get the document

Site: http://www.newhavenrowingclub.org/pyrow/

LICENSE

Licensed under the Simplified BSD License.

REQUIREMENTS

PyRow has been tested on an Ubuntu machine with the software versions listed below, PyRow should be able to work on any machine that can run Python & PyUSB but this has not been tested and confirmed.

Other versions of the PyRow library have been tested on Windows.

INSTALLING

After the software has become stable the software will be packaged as a module. For now copying pyrow.py, csafe_cmd.py, and csafe_dic.py into the same directory as your code will work.

Include PyRow in your code with the following line of code: import pyrow

RUNNING

pyrow.find() - returns an array of all the ergs currently connected to the computer


pyrow.pyrow(erg) - creates an object for communicating with the erg, erg is obtained from the pyrow.find() function ex: creating a pyrow object from the first erg found ergs = pyrow.find() erg = pyrow.pyrow(ergs[0])


pyrow.pyrow.getStatus() - returns status of machine as a number

  • 0 = 'Error'
  • 1 = 'Ready'
  • 2 = 'Idle'
  • 3 = 'Have ID'
  • 4 = 'N/A'
  • 5 = 'In Use'
  • 6 = 'Pause'
  • 7 = 'Finished'
  • 8 = 'Manual'
  • 9 = 'Offline'

pyrow.pyrow.getMonitor(forceplot=False) - returns data from the monitor in dictionary format, keys listed below with descriptions

  • time = Monitor time in seconds
  • distance = Monitor distance in meters
  • spm = Strokes per Minute
  • power = Power in watts
  • pace = /500m pace
  • calhr = Calories Burned per Hours
  • calories = Total Calories Burned
  • heartrate = Current Heart Rate
  • status = Machine Status If keyvalue forceplot is set to true
  • forceplot = Force Plot Data
  • strokestate = Stroke State

pyrow.pyrow.getForcePlot() - returns force plot data and stroke state in dictionary format, keys listed below with descriptions

  • forceplot = Force Plot Data (array varying in length from 0 to 16)
  • strokestate = Stroke State
  • status = Machine status

pyrow.pyrow.getWorkout() - returns data related to the overall workout in dictionary format, keys listed below with descriptions

  • userid = User ID
  • type = Workout Type
  • state = Workout State
  • inttype = Interval Type
  • intcount = Workout Interval Count
  • status = Machine Status

pyrow.pyrow.getErg() - returns non workout related data about the erg in dictionary format, keys listed below with descriptions

  • mfgid = Manufacturing ID
  • cid = CID
  • model = Erg Model
  • hwversion = Hardware Version
  • swversion = Software Version
  • serial = Ascii Serial Number
  • maxrx = Max Rx Frame
  • maxtx = Max Tx Frame
  • mininterframe = Min Interframe
  • status = Machine status

pyrow.pyrow.setClock() - sets the clock on the erg equal to the clock on the computer


pyrow.pyrow.setWorkout() - if machine is in the ready state function will set the workout and display the start workout screen, allowable parameters are listed below (the current PM SDK does not allow for setting invervaled workouts)

Choose one

program=programNumber - number from 0 to 10 (15 if the log card is installed), 1 thru 10 relate to workouts saved in the monitor.

time=[hours, minutes, seconds] - Min allowable is 20 sec & max allowable is 9:59:59.

distance=meters - Min allowable is 100 and max allowable is 20000.

Not required, can only chose if time or distance is set

split=seconds - If time is set or meters if distance is set, must be less than the total goal and greater than or equal to 20 seconds or 100 meters, cannot occur more then 30 times during the workout, time has a resolution of .01 sec

Not required, chose one

pace=seconds - Seconds for pace boat to complete 500 meters (/500m) powerpace=watts - Watts for pace boat to generate calpace=cal - Calories per hour for pace boat to burn

ex: set a 2000m workout with a 500m split and a pace boat with a 2 minute pace (120 seconds)

erg.setWorkout(distance=2000, split=500, pace=120)


pyrow.pyrow.send(command) - sends a csafe command to the rowing machine and returns the result. The command is an array and results are returned as a dictionary with the key being the csafe command name

ex: setting a workout of 10 minutes with a split of 1 minute (60 seconds)

command = ['CSAFE_SETTWORK_CMD', 0, 10, 0,'CSAFE_PM_SET_SPLITDURATION', 0, 60]
erg.send(command)

ex: getting pace and printing it out

command = ['CSAFE_GETPACE_CMD',]
result = erg.send(command)
print "Stroke Pace = " + str(result['CSAFE_GETPACE_CMD'][0])
print "Stroke Units = " + str(result['CSAFE_GETPACE_CMD'][1])

FILES

strokelog.py - an example program that records time, distance, strokes per min, pace, and force plot data for each stroke to a csv file

statshow.py - an example program that displays the current machine, workout, and stroke status

pyrow.py - file to be loaded by user, used to connect to erg and send/receive data

csafe_cmd.py - converts between csafe commands and byte arrays for pyrow.py, user does not need to load this file directly

csafe_dic.py - contains dictionaries of the csafe commands to be used by csafe_cmd.py, user does not need to load this file directly

pyrow's People

Contributors

alexlongshaw avatar vjftw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyrow's Issues

User id returns 00000

Hi,
I just bought an old model concept D model with a PM3 running 108 firmware. I would like to develop a web application that shows the work done for each user each week in one graph. Many thanks for the work done!
With a Raspberry and PyRow I managed to get practically all the live data from the PM, except the userid. This always returns 00000. Does anyone how I can solve this and get the current user?

Someone who had the same with a PM5:
https://www.c2forum.com/viewtopic.php?f=15&t=104498
csafe_getid_cmd
same results for the pyrow.pyrow.getWorkout() command

Incompatible with Python 3.4

Current working version does not run under Python 3.4. Main issue is that the print statements are in the Python 2 syntax (print "hello") which results in errors when porting the code to Python3.X versions.

Concept2 PM5 Firmware Change In April 2023 Has Broken USB Functionality

I am the developer of the PM5 firmware, and have been contacted by a user of PyRow indicating the firmware versions released on or about April 2023 no long work properly. The PM5 firmware versions affected are v34.000/173.000/212.000/257.000.

To summarize, I see in the source code (csafe_command.py) that there is logic to map messages to USB reports using length (snippet) below. The PM5 firmware change obsoleted the 63 byte report and added a 500 byte report in it's place. This change is reflected in the USB enumeration for the HID class, but since you have it hard-coded I suspect this is the source of the failure.

I think the easiest change is just to eliminate the the logic block relating to the 63 byte report and just support 21 byte and 121 byte report lengths. For your application it will have zero impact on performance. I sure your users would appreciate the fix so that they can move forward for current and future firmware versions.

Any questions, please reach out to me at [email protected].

#report IDs
maxmessage = max(len(message) + 1, maxresponse)

if maxmessage <= 21:
    message.insert(0, 0x01)
    message += [0] * (21 - len(message))
elif maxmessage <= 63:
    message.insert(0, 0x04)
    message += [0] * (63 - len(message))
elif (len(message) + 1) <= 121:
    message.insert(0, 0x02)
    message += [0] * (121 - len(message))
    if maxresponse > 121:
        print "Response may be too long to recieve.  Max possible length " + str(maxresponse)
else:
    print "Message too long.  Message length " + str(len(message))
    message = []

CSAFE_PM_GET_STROKESTATS is missing

Hi

I'm looking for the strokestats, but they are missing in the file pyrow/csafe/csafe_dic.py
Add it there with 0x6E ends in a bug:

Traceback (most recent call last):
File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "/home/pi/src/pyrow/pyrow/ergmanager.py", line 147, in erg_monitor
monitor = self._pyerg.get_monitor(pretty=True, forceplot=True)
File "/home/pi/src/pyrow/pyrow/pyrow.py", line 223, in get_monitor
results2 = self.send(command)
File "/home/pi/src/pyrow/pyrow/pyrow.py", line 441, in send
csafe = csafe_cmd.write(message)
File "/home/pi/src/pyrow/pyrow/csafe/csafe_cmd.py", line 60, in write
value = __int2bytes(varbytes, intvalue)
File "/home/pi/src/pyrow/pyrow/csafe/csafe_cmd.py", line 12, in __int2bytes
if not 0 <= integer <= 2 ** (8 * numbytes):
TypeError: '<=' not supported between instances of 'int' and 'str'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.