diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py index 0d0fedfd..13f3e0e4 100644 --- a/rowers/c2stuff.py +++ b/rowers/c2stuff.py @@ -24,6 +24,9 @@ import pandas as pd import numpy as np from rowers.models import Rower,Workout import sys +import urllib +from requests import Request, Session + from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET @@ -233,6 +236,7 @@ def createc2workoutdata(w): return data def do_refresh_token(refreshtoken): + scope = "results:write,user:read" client_auth = requests.auth.HTTPBasicAuth(C2_CLIENT_ID, C2_CLIENT_SECRET) post_data = {"grant_type": "refresh_token", "client_secret": C2_CLIENT_SECRET, @@ -240,10 +244,19 @@ def do_refresh_token(refreshtoken): "refresh_token": refreshtoken, } headers = {'user-agent': 'sanderroosendaal'} - response = requests.post("https://log.concept2.com/oauth/access_token", - data=post_data, - headers=headers) + url = "https://log.concept2.com/oauth/access_token" + s = Session() + req = Request('POST',url, data=post_data, headers=headers) + # response = requests.post("https://log.concept2.com/oauth/access_token", + # data=post_data, + # data=post_data, + # headers=headers) + + prepped = req.prepare() + prepped.body+="&scope=" + prepped.body+=scope + response = s.send(prepped) token_json = response.json() try: thetoken = token_json['access_token'] @@ -263,17 +276,29 @@ def do_refresh_token(refreshtoken): def get_token(code): + scope = "user:read,results:write" client_auth = requests.auth.HTTPBasicAuth(C2_CLIENT_ID, C2_CLIENT_SECRET) post_data = {"grant_type": "authorization_code", "code": code, +# "scope": scope, "redirect_uri": C2_REDIRECT_URI, "client_secret": C2_CLIENT_SECRET, "client_id":C2_CLIENT_ID, } headers = {'user-agent': 'sanderroosendaal'} - response = requests.post("https://log.concept2.com/oauth/access_token", - data=post_data, - headers=headers) + url = "https://log.concept2.com/oauth/access_token" + s = Session() + req = Request('POST',url, data=post_data, headers=headers) + + prepped = req.prepare() + prepped.body+="&scope=" + prepped.body+=scope + + response = s.send(prepped) + +# response = requests.post("https://log.concept2.com/oauth/access_token", +# data=post_data, +# headers=headers) token_json = response.json() thetoken = token_json['access_token'] expires_in = token_json['expires_in'] @@ -286,13 +311,13 @@ def make_authorization_url(request): # Save it for use later to prevent xsrf attacks from uuid import uuid4 state = str(uuid4()) + scope = "user:read,results:write" params = {"client_id": CLIENT_ID, "response_type": "code", "redirect_uri": REDIRECT_URI} - import urllib url = "https://log.concept2.com/oauth/authorize?"+ urllib.urlencode(params) - # url = "https://ssl.reddit.com/api/v1/authorize?" + urllib.urlencode(params) + url += "&scope="+scope return HttpResponseRedirect(url) diff --git a/rowers/dataprep.py b/rowers/dataprep.py index e942da7e..9744b6b9 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -518,7 +518,7 @@ def dataprep(rowdatadf,id=0,bands=True,barchart=True,otwpower=True, try: drivespeed = drivelength/rowdatadf[' DriveTime (ms)']*1.0e3 except TypeError: - drivespeed = 0.0*drivelength + drivespeed = 0.0*rowdatadf['TimeStam (sec)'] drivespeed = drivespeed.fillna(value=0) driveenergy = drivelength*averageforce*4.44822 diff --git a/rowers/models.py b/rowers/models.py index 878929b4..303b4b76 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -532,5 +532,11 @@ class SiteAnnouncement(models.Model): self.expires = timezone.now()+datetime.timedelta(days=10) self.modified = timezone.now() if self.dotweet: - status = tweetapi.PostUpdate(self.announcement) + try: + status = tweetapi.PostUpdate(self.announcement) + except: + try: + status = tweetapi.PostUpdate(self.announcement[:135]) + except: + pass return super(SiteAnnouncement,self).save(*args, **kwargs) diff --git a/rowers/ownapistuff.py b/rowers/ownapistuff.py index 4a1754bf..3ec7088e 100644 --- a/rowers/ownapistuff.py +++ b/rowers/ownapistuff.py @@ -85,9 +85,9 @@ def get_token(code): client_auth = requests.auth.HTTPBasicAuth(TEST_CLIENT_ID, TEST_CLIENT_SECRET) post_data = {"grant_type": "authorization_code", "code": code, - "redirect_uri": TEST_REDIRECT_URI, - "client_secret": TEST_CLIENT_SECRET, - "client_id":TEST_CLIENT_ID, + "redirect_uri": "http://localhost:8000/rowers/test_callback", + "client_secret": "aapnootmies", + "client_id":1, } headers = {'Accept': 'application/json', 'Content-Type': 'application/json'} @@ -99,12 +99,12 @@ def get_token(code): data=json.dumps(post_data), headers=headers) - print response.text token_json = response.json() thetoken = token_json['access_token'] expires_in = token_json['expires_in'] refresh_token = token_json['refresh_token'] + return [thetoken,expires_in,refresh_token] def make_authorization_url(request): diff --git a/rowers/permissions.py b/rowers/permissions.py index 03c1652b..67afe16c 100644 --- a/rowers/permissions.py +++ b/rowers/permissions.py @@ -13,9 +13,10 @@ class IsOwnerOrReadOnly(permissions.BasePermission): return True # Write permissions are only allowed to the owner of the snippet. - return obj.owner == request.user + return obj.user == request.user class IsOwnerOrNot(permissions.BasePermission): + def has_object_permission(self, request, view, obj): r = Rower.objects.get(user=request.user) return (obj.user == r) diff --git a/rowers/serializers.py b/rowers/serializers.py index b0890f54..e0c8b560 100644 --- a/rowers/serializers.py +++ b/rowers/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from rowers.models import Workout,Rower +from rowers.models import Workout,Rower,StrokeData import datetime @@ -93,8 +93,8 @@ class WorkoutSerializer(serializers.ModelSerializer): class StrokeDataSerializer(serializers.Serializer): workoutid = serializers.IntegerField strokedata = serializers.JSONField - - def create(self, validated_data): + + def create(self, workoutid, strokedata): """ Create and enter a new set of stroke data into the DB """ @@ -103,3 +103,5 @@ class StrokeDataSerializer(serializers.Serializer): print "fake serializer" return 1 + + diff --git a/rowers/templates/about_us.html b/rowers/templates/about_us.html index 34c64464..e562c356 100644 --- a/rowers/templates/about_us.html +++ b/rowers/templates/about_us.html @@ -142,6 +142,7 @@ You will be taken to the secure PayPal payment site.
On this page, a work in progress, I will collect useful information + for developers of rowing data apps and hardware.
+ +I presume you have an app (smartphone app, dedicated hardware, web site) + where your users (customers) generate, collect or store their rowing + related workout data. You can now offer your users easy ways to get + their data on this site.
+ +There are three ways to allow your users to get data to Rowsandall.com.
+ +Enable export of TCX, FIT or CSV formatted files from your app. + The users + upload the file to Rowsandall.com.
+ +Similar as above, generate TCX, FIT or CSV formatted files and + email them + to workouts@rowsandall.com directly from your app. The From: field + should be the email address of the registered user.
+ +We are building a REST API which will allow you to post and + receive stroke + data from the site directly.
+ +The REST API is a work in progress.
+ +All files adhering to the standards TCX and FIT formats will be parsed.
+ +However, some rowing related parameters are not supported by TCX and FIT. Therefore, we are supporting the CSV format that is documented in the following link.
+ + + +Using this standard will guarantee that your user's data are accepted + without complaints.
+ +As a registered user, you can register an app.
+ + +Standard Oauth2 authentication. + Get authorization code by pointing your user to the authorization URL. + Exchange authorization code for an access token. When access token + expires, + use the refresh token to refresh it.
+ +The POST call must have content-type: x-www-form-urlencoded. + I set it this way to support the handy testing utility mentioned + belower. However, + I really would like to support application/json but with the + current framework I cannot support both at the same time. Expect + changes. Write to me if you want to be notified of changes.
+ +Once you have a registered app, you have gone through the authorization + and have successfully obtained an access token, you can use it to place + POST, GET and PUT requests.
+ +The workout summary data and the stroke data are obtained and sent + separately.
+ +You can only post stroke data to an existing workout with + workout number {id}. If the workout already has stroke data, you + will get a duplication error. This functionality will be expanded in the + future to enable updating stroke data. Stroke data for workout {id} are + posted to:
+ +The payload is application/json data and looks as follows:
+ +
+ {
+ "distance": [5,12,19,27,35,43,51,59,67,75,82,90,100],
+ "power": [112,221,511,673,744,754,754,749,729,729,726,709,707],
+ "hr": [132,131,131,132,133,136,139,142,145,147,150,152,153],
+ "pace": [145800,116400,88100,80400,77700,77400,77400,77600,78300,78300,78400,79000,79100],
+ "spm": [11,41,56,59,55,48,48,48,48,48,48,48,49],
+ "time": [0,2200,4599,7000,9599,12000,14400,16799,19400,21799,24200,26599,2900],
+}
+
+
+ Mandatory data fields are:
+Optional data fiels are:
+Consistency checks will be done and the stroke data will be + refused if the mandatory data fields don't pass the checks. + All mandatory data fields + must have the same number of records. If an optional data field + fails a test, its values are silently replaced by zeros.
+ +