Private
Public Access
1
0

Merge branch 'develop' into feature/stravaapi

This commit is contained in:
2024-12-06 17:29:02 +01:00
2 changed files with 96 additions and 2 deletions

View File

@@ -254,6 +254,8 @@ urlpatterns = [
name='strokedatajson_v3'), name='strokedatajson_v3'),
re_path(r'^api/TCX/workouts/$', views.strokedata_tcx, re_path(r'^api/TCX/workouts/$', views.strokedata_tcx,
name='strokedata_tcx'), name='strokedata_tcx'),
re_path(r'^api/FIT/workouts/$', views.strokedata_fit,
name='strokedata_fit'),
re_path(r'^api/rowingdata/workouts/$', views.strokedata_rowingdata, re_path(r'^api/rowingdata/workouts/$', views.strokedata_rowingdata,
name='strokedata_rowingdata'), name='strokedata_rowingdata'),
re_path(r'^api/rowingdata/$', views.strokedata_rowingdata_apikey, re_path(r'^api/rowingdata/$', views.strokedata_rowingdata_apikey,

View File

@@ -20,10 +20,25 @@ from datetime import datetime as dt
import rowingdata.tcxtools as tcxtools import rowingdata.tcxtools as tcxtools
from rowingdata import TCXParser, rowingdata from rowingdata import TCXParser, rowingdata
from rowingdata import FITParser as FP
import arrow import arrow
import base64 import base64
# create a FITParser which parses the application/octet-stream and creates a fit file
class FITParser(BaseParser):
media_type = "application/octet-stream"
def parse(self, stream, media_type=None, parser_context=None):
try:
return stream.read()
except Exception as e:
dologging("apilog.log", "FIT Parser")
dolofging("apilog.log", e)
raise ValueError(f"Failed to read FIT file: {str(e)}")
return stream.read()
class XMLParser(BaseParser): class XMLParser(BaseParser):
media_type = "application/xml" media_type = "application/xml"
@@ -32,10 +47,10 @@ class XMLParser(BaseParser):
try: try:
s = ET.parse(stream).getroot() s = ET.parse(stream).getroot()
except ET.XMLSyntaxError: except ET.XMLSyntaxError:
return HttpResponse(status=400) raise ValueError("XML Syntax Error")
except Exception as e: # pragma: no cover except Exception as e: # pragma: no cover
dologging("apilog.log",e) dologging("apilog.log",e)
return HttpResponse(status=500) raise ValueError(f"Failed to parse XML file: {str(e)}")
return s return s
# Stroke data form to test API upload # Stroke data form to test API upload
@@ -530,6 +545,83 @@ def strokedata_rowingdata_apikey(request):
response.status_code = 201 response.status_code = 201
return response return response
@csrf_exempt
@api_view(["POST"])
@permission_required('rower.is_not_freecoach', fn=get_user_by_userid, raise_exception=True)
@permission_classes([IsAuthenticated])
@parser_classes([FITParser])
def strokedata_fit(request):
"""
Handle a POST request to upload a binary FIT file and save it locally.
"""
if request.method != 'POST':
return HttpResponseBadRequest("Only POST requests are allowed.")
try:
fit_data = request.data
# Ensure the media directory exists
media_dir = 'media'
os.makedirs(media_dir, exist_ok=True)
# Generate a unique filename for the FIT file
fit_filename = os.path.join(media_dir, f'{uuid4().hex[:16]}.fit')
# Save the FIT file locally
with open(fit_filename, 'wb') as fit_file:
fit_file.write(fit_data)
except Exception as e:
return JsonResponse({
"status": "error",
"message": f"An error occurred while saving the FIT file: {str(e)}"
}, status=500)
try:
# Parse the FIT file
row = FP(fit_filename)
rowdata = rowingdata(df=row.df)
duration = totaltime_sec_to_string(rowdata.duration)
title = "ActiveSpeed water"
w = Workout.objects.create(user=request.user.rower,
duration=duration,
name=title,)
uploadoptions = {
'secret': UPLOAD_SERVICE_SECRET,
'user': request.user.id,
'file': fit_filename,
'workouttype': 'water',
'boattype': '1x',
'title': title,
'rpe': 0,
'notes': '',
'workoutid': w.id,
'offline': False,
}
url = UPLOAD_SERVICE_URL
_ = myqueue(queuehigh,
handle_request_post,
url,
uploadoptions)
return JsonResponse(
{"status": "success",
"workout public id": encoder.encode_hex(w.id),
"workout id": w.id,
})
except Exception as e:
dologging('apilog.log','FIT API endpoint')
dologging('apilog.log',e)
_ = myqueue(queuehigh, handle_sendemail_unrecognized, fit_filename, "fit parser")
return HttpResponse(status=500)
@csrf_exempt @csrf_exempt
#@login_required() #@login_required()