def gcode_delete(org_uuid, uuid): validate_uuid(uuid) gcode = gcodes.get_gcode(uuid) if gcode is None or gcode["organization_uuid"] != org_uuid: return abort(make_response(jsonify(message="Not found"), 404)) user = get_current_user() org_role = organization_roles.get_organization_role(org_uuid, user["uuid"]) if (user["uuid"] != gcode["user_uuid"] and user["system_role"] != "admin" and org_role["role"] != "admin"): return abort( make_response( jsonify(message="G-Code does not belong to %s" % user["uuid"]), 401)) try: files.remove(gcode["absolute_path"]) except IOError: pass finally: printjobs.update_gcode_data( uuid, { "uuid": gcode["uuid"], "user_uuid": gcode["user_uuid"], "filename": gcode["filename"], "size": gcode["size"], "available": False, }, ) gcodes.delete_gcode(uuid) return "", 204
def test_upload_path(self, mocked_save, mocked_delay): with app.test_client() as c: c.set_cookie("localhost", "access_token_cookie", TOKEN_USER) data = dict(file=(io.BytesIO(b"my file contents"), "some.gcode"), path="/a/b") response = c.post( "/organizations/%s/gcodes" % UUID_ORG, data=data, content_type="multipart/form-data", headers={"x-csrf-token": TOKEN_USER_CSRF}, ) self.assertEqual(response.status_code, 201) args, kwargs = mocked_save.call_args self.assertEqual(args[2], "/a/b") self.assertTrue("uuid" in response.json) self.assertTrue("user_uuid" in response.json) self.assertEqual(response.json["user_uuid"], UUID_USER) self.assertTrue("path" in response.json) self.assertTrue("filename" in response.json) self.assertTrue("display" in response.json) self.assertTrue("absolute_path" in response.json) self.assertTrue("uploaded" in response.json) self.assertTrue("size" in response.json) gcode_db_data = gcodes.get_gcode(response.json["uuid"]) self.assertEqual(gcode_db_data["user_uuid"], UUID_USER)
def gcode_delete(id): gcode = gcodes.get_gcode(id) if gcode is None: return abort(make_response("", 404)) user = get_current_user() if user["uuid"] != gcode["user_uuid"] and user["role"] not in ["admin"]: return abort( make_response( jsonify(message="G-Code does not belong to %s" % user["uuid"]), 401)) try: files.remove(gcode["absolute_path"]) except IOError: pass finally: gcodes.delete_gcode(id) printjobs.update_gcode_data( gcode["id"], { "id": gcode["id"], "user_uuid": gcode["user_uuid"], "filename": gcode["filename"], "size": gcode["size"], "available": False, }, ) return "", 204
def test_delete(self): gcode_id = gcodes.add_gcode( path="delete-ab/c", filename="delete-gcode-specific-file1", display="file-display", absolute_path="/ab/a/b/c", size=123, user_uuid=UUID_USER, ) printjobs.add_printjob( gcode_id=gcode_id, gcode_data={"id": gcode_id}, printer_uuid="20e91c14-c3e4-4fe9-a066-e69d53324a20", printer_data={"host": "172.16.236.11:8080"}, ) printjobs.add_printjob( gcode_id=gcode_id, gcode_data={"id": gcode_id}, printer_uuid="20e91c14-c3e4-4fe9-a066-e69d53324a20", printer_data={"host": "172.16.236.11:8080"}, ) with app.test_client() as c: c.set_cookie("localhost", "access_token_cookie", TOKEN_USER) response = c.delete( "/gcodes/%s" % gcode_id, headers={"x-csrf-token": TOKEN_USER_CSRF}, ) self.assertEqual(response.status_code, 204) self.assertEqual(gcodes.get_gcode(gcode_id), None) pjs = [pj for pj in printjobs.get_printjobs() if pj["gcode_id"] == gcode_id] self.assertEqual(len(pjs), 2) for pj in pjs: self.assertFalse(pj["gcode_data"]["available"])
def gcode_detail(id): gcode = gcodes.get_gcode(id) if gcode is None: return abort(make_response("", 404)) user = users.get_by_uuid(gcode.get("user_uuid")) user_mapping = {} if user is not None: user_mapping[gcode.get("user_uuid")] = user.get("username") return jsonify(make_gcode_response(gcode, None, user_mapping))
def gcode_detail(org_uuid, uuid): validate_uuid(uuid) gcode = gcodes.get_gcode(uuid) if gcode is None or gcode["organization_uuid"] != org_uuid: return abort(make_response(jsonify(message="Not found"), 404)) user = users.get_by_uuid(gcode.get("user_uuid")) user_mapping = {} if user is not None: user_mapping[gcode.get("user_uuid")] = user.get("username") return jsonify(make_gcode_response(gcode, None, user_mapping))
def gcode_file(id): gcode = gcodes.get_gcode(id) if gcode is None: return abort(make_response("", 404)) try: return send_file( gcode["absolute_path"], as_attachment=True, attachment_filename=gcode["filename"], ) except FileNotFoundError: return abort(make_response("", 404))
def analyze_gcode(gcode_id): gcode = gcodes.get_gcode(gcode_id) if not gcode: app.logger.info("Gcode %s does not exist in database" % gcode_id) return if gcode.get("analysis", {}) != {}: app.logger.info("Gcode %s already has analysis data" % gcode_id) return try: result = { "filament": {}, "temperatures": {}, "time": {}, "slicer": None } # TODO this should be faster if we grep for only lines with ; in shell with open(gcode["absolute_path"]) as fp: for lno, rawline in enumerate(fp): stripped_line = rawline.rstrip() line = (stripped_line.decode("utf-8") if hasattr( stripped_line, "decode") else stripped_line) if not line or line[0] not in ";M": continue # TODO this supports only a single filament if not result["slicer"]: result["slicer"] = get_slicer(line) filament_props = [ ("length_mm", get_filament_used_length), ("volume_cm3", get_filament_used_volume), ("type", get_filament_type), ] for fprop, evaluator in filament_props: if not result["filament"].get(fprop, None): result["filament"][fprop] = evaluator(line) # TODO this supports only a single tool temperature_props = [ ("bed", get_temperature_bed), ("bed_first", get_temperature_bed_first), ("tool0", get_temperature_tool), ("tool0_first", get_temperature_tool_first), ] for fprop, evaluator in temperature_props: if not result["temperatures"].get(fprop, None): result["temperatures"][fprop] = evaluator(line) time_props = [("estimate_s", get_time_estimate)] for fprop, evaluator in time_props: if not result["time"].get(fprop, None): result["time"][fprop] = evaluator(line) gcodes.set_analysis(gcode_id, result) except FileNotFoundError: app.logger.error("Gcode file not found %s" % gcode["absolute_path"]) return
def gcode_file(org_uuid, uuid): validate_uuid(uuid) gcode = gcodes.get_gcode(uuid) if gcode is None or gcode["organization_uuid"] != org_uuid: return abort(make_response(jsonify(message="Not found"), 404)) try: return send_file( gcode["absolute_path"], as_attachment=True, attachment_filename=gcode["filename"], ) except FileNotFoundError: return abort(make_response(jsonify(message="File not found"), 404))
def printjob_create(): data = request.json if not data: return abort(make_response("", 400)) gcode_id = data.get("gcode", None) printer_uuid = data.get("printer", None) if not gcode_id or not printer_uuid: return abort(make_response("", 400)) printer = printers.get_printer(printer_uuid) if printer is None: return abort(make_response("", 404)) gcode = gcodes.get_gcode(gcode_id) if gcode is None: return abort(make_response("", 404)) try: printer_inst = clients.get_printer_instance(printer) uploaded = printer_inst.upload_and_start_job(gcode["absolute_path"], gcode["path"]) if not uploaded: return abort( make_response( jsonify(message="Cannot upload the g-code to the printer"), 500)) printjob_id = printjobs.add_printjob( gcode_id=gcode["id"], printer_uuid=printer["uuid"], user_uuid=get_current_user()["uuid"], gcode_data={ "id": gcode["id"], "filename": gcode["filename"], "size": gcode["size"], "available": True, }, printer_data={ "ip": printer["ip"], "port": printer["port"], "hostname": printer["hostname"], "name": printer["name"], "client": printer["client"], }, ) return ( jsonify({ "id": printjob_id, "user_uuid": get_current_user()["uuid"] }), 201, ) except clients.utils.PrinterClientException: return abort(make_response("", 409))
def gcode_delete(id): gcode = gcodes.get_gcode(id) if gcode is None: return abort(404) try: files.remove(gcode["absolute_path"]) except IOError: pass finally: gcodes.delete_gcode(id) printjobs.update_gcode_data( gcode["id"], { "id": gcode["id"], "filename": gcode["filename"], "size": gcode["size"], "available": False, }, ) return "", 204
def printjob_create(): data = request.json if not data: return abort(400) gcode_id = data.get("gcode", None) printer_ip = data.get("printer", None) if not gcode_id or not printer_ip: return abort(400) printer = printers.get_printer(printer_ip) if printer is None: return abort(404) gcode = gcodes.get_gcode(gcode_id) if gcode is None: return abort(404) try: printer_inst = drivers.get_printer_instance(printer) uploaded = printer_inst.upload_and_start_job(gcode["absolute_path"], gcode["path"]) if not uploaded: return abort(500, "Cannot upload the g-code to the printer") printjob_id = printjobs.add_printjob( gcode_id=gcode["id"], printer_ip=printer["ip"], gcode_data={ "id": gcode["id"], "filename": gcode["filename"], "size": gcode["size"], "available": True, }, printer_data={ "ip": printer["ip"], "name": printer["name"], "client": printer["client"], }, ) return jsonify({"id": printjob_id}), 201 except drivers.utils.PrinterDriverException: return abort(409)
def printjob_create(org_uuid): data = request.json if not data: return abort(make_response(jsonify(message="Missing payload"), 400)) gcode_uuid = data.get("gcode", None) printer_uuid = data.get("printer", None) if not gcode_uuid or not printer_uuid: return abort( make_response(jsonify(message="Missing gcode_uuid or printer_uuid"), 400) ) validate_uuid(gcode_uuid) validate_uuid(printer_uuid) printer = printers.get_printer(printer_uuid) if printer is None or printer["organization_uuid"] != org_uuid: return abort(make_response(jsonify(message="Not found"), 404)) gcode = gcodes.get_gcode(gcode_uuid) if gcode is None: return abort(make_response(jsonify(message="Not found"), 404)) try: network_client = network_clients.get_network_client( printer["network_client_uuid"] ) printer_data = dict(network_client) printer_data.update(dict(printer)) printer_inst = clients.get_printer_instance(printer_data) uploaded = printer_inst.upload_and_start_job( gcode["absolute_path"], gcode["path"] ) if not uploaded: return abort( make_response( jsonify(message="Cannot upload the g-code to the printer"), 500 ) ) printjob_uuid = guid.uuid4() printjobs.add_printjob( uuid=printjob_uuid, gcode_uuid=gcode["uuid"], organization_uuid=org_uuid, printer_uuid=printer["uuid"], user_uuid=get_current_user()["uuid"], gcode_data={ "uuid": gcode["uuid"], "filename": gcode["filename"], "size": gcode["size"], "available": True, }, printer_data={ "ip": printer_inst.ip, "port": printer_inst.port, "hostname": printer_inst.hostname, "name": printer_inst.name, "client": printer_inst.client, }, ) return ( jsonify({"uuid": printjob_uuid, "user_uuid": get_current_user()["uuid"]}), 201, ) except clients.utils.PrinterClientException as e: app.logger.error(e) return abort( make_response( jsonify(message="Cannot schedule a printjob: %s" % str(e)), 409 ) )
def printjob_create(org_uuid): data = request.json if not data: return abort(make_response(jsonify(message="Missing payload"), 400)) gcode_uuid = data.get("gcode", None) printer_uuid = data.get("printer", None) # FIXME: this should be part of the path if not gcode_uuid or not printer_uuid: return abort( make_response( jsonify(message="Missing gcode_uuid or printer_uuid"), 400)) printer = printers.get_printer(printer_uuid) if not printer or printer['organization_uuid'] != org_uuid: raise http_exceptions.UnprocessableEntity( f"Invalid printer {printer_uuid} - does not exist.") gcode = gcodes.get_gcode(gcode_uuid) if not gcode: raise http_exceptions.UnprocessableEntity( "Invalid gcode {gcode_uuid} - does not exist.") network_client = network_clients.get_network_client( printer["network_client_uuid"]) printer_data = dict(network_client) printer_data.update(dict(printer)) printer_inst = clients.get_printer_instance(printer_data) try: printer_inst.upload_and_start_job(gcode["absolute_path"], gcode["path"]) except DeviceInvalidState as e: raise http_exceptions.Conflict(*e.args) except DeviceCommunicationError as e: raise http_exceptions.GatewayTimeout(*e.args) # TODO: robin - add_printjob should be method of printer and printer a # method of organization printjob_uuid = printjobs.add_printjob( gcode_uuid=gcode["uuid"], organization_uuid=org_uuid, printer_uuid=printer["uuid"], user_uuid=get_current_user()["uuid"], gcode_data={ "uuid": gcode["uuid"], "filename": gcode["filename"], "size": gcode["size"], "available": True, }, # FIXME: printer data should be kept in printer object only printer_data={ "ip": printer_inst.ip, "port": printer_inst.port, "hostname": printer_inst.hostname, "name": printer_inst.name, "client": printer_inst.client, }, ) return ( jsonify({ "uuid": printjob_uuid, "user_uuid": get_current_user()["uuid"] }), 201, )
def gcode_detail(id): gcode = gcodes.get_gcode(id) if gcode is None: return abort(404) return jsonify(make_gcode_response(gcode))