Skip to content

Commit

Permalink
Added endpoints what are needed for orcaslicer integration
Browse files Browse the repository at this point in the history
  • Loading branch information
encetamasb committed Dec 8, 2023
1 parent a5513d6 commit b3d6710
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
5 changes: 5 additions & 0 deletions backend/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@

router.register(r'octo/g_code_files', octoprint_views.GCodeFileView, 'AgentGCodeFile')


urlpatterns = [
path('version', viewsets.SlicerApiVersionView.as_view()),
path('printers', viewsets.SlicerApiPrinterListView.as_view()),
path('files/local', viewsets.SlicerApiUploadView.as_view()),

path('v1/onetimeverificationcodes/verify/', # For compatibility with plugin <= 1.7.0
octoprint_views.OneTimeVerificationCodeVerifyView.as_view(),
),
Expand Down
89 changes: 89 additions & 0 deletions backend/api/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import logging
from binascii import hexlify
from rest_framework import viewsets, mixins
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.exceptions import ValidationError
from rest_framework.parsers import MultiPartParser, FormParser, JSONParser
from rest_framework import authentication
from rest_framework import status
from django.utils import timezone
from django.conf import settings
Expand Down Expand Up @@ -870,3 +872,90 @@ def list(self, request):

serializer = self.serializer_class(results, many=True)
return Response(serializer.data)


class SlicerApiVersionView(APIView):
authentication_classes = [authentication.TokenAuthentication]
permission_classes = (IsAuthenticated,)

def get(self, request, format=None):
return Response({"text": "Obico"})


class SlicerApiPrinterListView(APIView):
authentication_classes = [authentication.TokenAuthentication]
permission_classes = (IsAuthenticated,)

def get(self, request, format=None):
return Response({"printers": [{"id": str(p.id), "name": p.name} for p in request.user.printer_set.all()]})


class SlicerApiUploadView(APIView):
authentication_classes = [authentication.TokenAuthentication]
permission_classes = (IsAuthenticated,)

def post(self, request, format=None):
data = dict(**request.data)
file = request.data.get('file')
if file:
data['filename'] = file.name

serializer = GCodeFileDeSerializer(data=data, context={'request': request})
serializer.is_valid(raise_exception=True)
validated_data = serializer.validated_data

start_print = request.data.get('print') == 'true'

printer = None
if start_print:
raw_printer_id = request.data.get('printer_id')
if raw_printer_id:
try:
printer_id = int(re.match(r".*\[(\d+)\]", raw_printer_id).groups()[0])
except (ValueError, TypeError, IndexError):
raise ValidationError({'printer_id': 'invalid value'})

printer = request.user.printer_set.filter(id=printer_id).first()
if printer is None:
raise ValidationError({'printer_id': 'could not find printer'})

if 'file' in request.FILES:
file_size_limit = 500 * 1024 * 1024 if request.user.is_pro else 50 * 1024 * 1024
num_bytes=request.FILES['file'].size
if num_bytes > file_size_limit:
return Response({'error': 'File size too large'}, status=413)

gcode_file = GCodeFile.objects.create(**validated_data)

self.set_metadata(gcode_file, *gcode_metadata.parse(request.FILES['file'], num_bytes, request.encoding or settings.DEFAULT_CHARSET))

request.FILES['file'].seek(0)
_, ext_url = save_file_obj(self.path_in_storage(gcode_file), request.FILES['file'], settings.GCODE_CONTAINER)
gcode_file.url = ext_url
gcode_file.num_bytes = num_bytes
gcode_file.save()

if start_print:
# FIXME
return Response({"message": "print queued"})


return Response({"message": "uploaded successfully"})

raise ValidationError({"file": "Missing file body"})

def set_metadata(self, gcode_file, metadata, thumbnails):
gcode_file.metadata_json = json.dumps(metadata)
for key in ['estimated_time', 'filament_total']:
setattr(gcode_file, key, metadata.get(key))

thumb_num = 0
for thumb in sorted(thumbnails, key=lambda x: x.getbuffer().nbytes, reverse=True):
thumb_num += 1
if thumb_num > 3:
continue
_, ext_url = save_file_obj(f'gcode_thumbnails/{gcode_file.user.id}/{gcode_file.id}/{thumb_num}.png', thumb, settings.TIMELAPSE_CONTAINER)
setattr(gcode_file, f'thumbnail{thumb_num}_url', ext_url)

def path_in_storage(self, gcode_file):
return f'{gcode_file.user.id}/{gcode_file.id}'
1 change: 1 addition & 0 deletions backend/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def get_bool(key, default):
'simple_history',
'widget_tweaks',
'rest_framework',
'rest_framework.authtoken',
'jstemplate',
'pushbullet',
'corsheaders',
Expand Down

0 comments on commit b3d6710

Please sign in to comment.