Example #1
0
def jobs_current(id):
    """
        Jobs Current
        Get current job information
        ---
        tags:
          - printer
        parameters:
          - in: path
            description: ID of the printer
            required: true
            type: integer
            name: id
        responses:
          200:
            description: Returns current status of job
            schema:
              $ref: "#/definitions/Web_Job"
        """

    printer = Printer.get_by_id(id)
    if printer:
        job = printer.current_job()
        if job:
            return json.jsonify(job.to_web())
        else:
            return json.jsonify({})
    abort(404)
Example #2
0
def nodes_trigger_callback():
    """
        Trigger Callback
        Called when node gpio triggered
        ---
        tags:
          - nodemcu
        responses:
          200:
            description: Returns node data
        """
    payload = request.get_json()
    id   = int(payload.get("id"))
    data = payload.get("data")
    node = Node.get_by_id(id)
    if node.printer_id:
        printer = Printer.get_by_id(node.printer_id)
        if printer.status in ["completed", "cancelled"]:
            t = Command(printer.id, hub.log, "clear", hub.Webapi)
        else:
            t = Command(printer.id, hub.log, "cancel", hub.Webapi)
        t.start()
        for sensor in node.sensors:
            if sensor.sensor_type == "LED":
                url = sensor.led_on()
                t = threading.Thread(target=requests.get,
                                     args=(url,))
                t.start()
        #r = requests.get(url, timeout=10)
    d = {'id': id,
         'data': data}
    return json.jsonify(d)
Example #3
0
def print_status(id):
    """
        Print Status
        Get printer status
        ---
        tags:
          - printer
        parameters:
          - in: path
            description: ID of the printer
            required: true
            type: integer
            name: id
        responses:
          200:
            description: returns printer information
            schema:
              $ref: "#/definitions/Web_Printer"

    """
    internal = request.args.get("internal", "false")
    if internal.lower() == "true":
        printer = Printer.get_by_id(id)
        if printer == None:
            abort(404)
        return json.jsonify(printer.to_dict())
    printer = Printer.get_by_webid(id)
    if printer == None:
        abort(404)
    return json.jsonify(printer.to_web())
Example #4
0
 def __init__(self, printer_id, webapi, log):
     """TODO: to be defined1. """
     threading.Thread.__init__(self)
     self.printer_id = printer_id
     printer = Printer.get_by_id(printer_id)
     status = printer.status
     self.stopped = False
     self.webapi = webapi
     self.log = log
     self.lock = threading.Lock()
Example #5
0
 def __init__(self, printer_id, webapi, log):
     """TODO: to be defined1. """
     threading.Thread.__init__(self)
     self.printer_id = printer_id
     job = Printer.get_by_id(printer_id, fresh=True).current_job()
     self.stopped = False
     self.webapi = webapi
     if job:
         self.status = job.status
     else:
         self.status = None
     self.log = log
Example #6
0
def delete_job(job_id):
    """
        Delete Job Action
        Stops and Deletes Job
        ---
        tags:
          - printer
        parameters:
          - in: path
            type: integer
            name: id
            description: ID of the Job
            required: true
        responses:
          200:
            description: TODO
        """

    job = Job.get_by_webid(job_id)
    if job:
        printer_id = job.printer_id
        if printer_id != None:
            printer = Printer.get_by_id(printer_id)
            if printer != None:
                if job.position == 0:
                    if printer.state("cancelled"):
                        printer.cancel_job()
                        payload = printer.to_web()
                        hub.Webapi.patch_printer(payload)
                else:
                    printer.remove_job(job.id)
        if job.state("cancelled"):
            payload = job.to_web()
            hub.Webapi.patch_job(payload)
    return json.jsonify(
        {"message": "Job " + str(job_id) + " has been deleted"}), 200
Example #7
0
    def run(self):
        id = self.id
        log = self.log
        command = self.command
        webapi = self.webapi
        loc = octopi.local
        printer = Printer.get_by_id(id, fresh=True)
        ip = printer.ip
        port = printer.port
        key = printer.key
        status = printer.status
        url = ip + ":" + str(port)

        if command == "start":
            if status == "paused":
                i = 0
                r = octopi.toggle_pause(url, key)
                while r == None and i < 10:
                    log.log("ERROR: Could not pause printer " + str(id))
                    sleep(1)
                    r = octopi.toggle_pause(url, key)
                    i += 1
                if r and r.status_code == 204:
                    self.success = True
                elif r:
                    log.log("ERROR: Could not start printer " + str(id) +
                            ". Status code was " + str(r.status_code))
            elif status == "ready":
                cjob = printer.current_job()
                t = JobUploader(id, cjob.id, log, webapi)
                t.start()
                t.join()
                printer = Printer.get_by_id(id, fresh=True)
                cjob = printer.current_job()
                i = 0
                r = octopi.select_and_print(url, key, cjob.remote_name)
                while r == None and i < 10:
                    log.log("ERROR: Could not start printer " + str(id))
                    sleep(1)
                    r = octopi.select_and_print(url, key, cjob.remote_name)
                    i += 1
                if r and r.status_code == 204:
                    self.success = True
                elif r:
                    log.log("ERROR: Could not start printer " + str(id) +
                            ". Status code was " + str(r.status_code))
            else:
                log.log("ERROR: Printer " + str(id) + " was told to " +
                        "start but wasn't paused or ready")
        elif command == "pause":
            if status == "printing":
                i = 0
                r = octopi.toggle_pause(url, key)
                while r == None and i < 10:
                    log.log("ERROR: Could not pause printer " + str(id))
                    sleep(1)
                    r = octopi.toggle_pause(url, key)
                    i += 1
                if r and r.status_code == 204:
                    self.success = True
                elif r:
                    log.log("ERROR: Could not pause printer " + str(id) +
                            ". Status code was " + str(r.status_code))
            else:
                log.log("ERROR: Printer " + str(id) + " was told to " +
                        " pause but was not printing")
        elif command == "cancel":
            if status in ["printing", "paused"]:
                i = 0
                r = octopi.cancel(url, key)
                while r == None and i < 10:
                    log.log("ERROR: Could not cancel printer " + str(id))
                    sleep(1)
                    r = octopi.cancel(url, key)
                    i += 1
                if r and r.status_code == 204:
                    self.success = True
                    printer = Printer.get_by_id(id, fresh=True)
                    printer.state("cancelled")
                elif r:
                    log.log("ERROR: Could not cancel printer " + str(id) +
                            ". Status code was " + str(r.status_code))
            else:
                log.log("ERROR: Printer " + str(id) + " was told to " +
                        " cancel but isn't printing or paused")
        elif command == "clear":
            if status == "cancelled":
                if printer.cancel_job():
                    self.success = True
                    payload = printer.to_web()
                    i = 0
                    while not webapi.patch_printer(payload) and i < 10:
                        i += 1
                    if printer.current_job() != None:
                        c = Command(printer.id, log, "start", webapi)
                        c.start()
            elif status == "completed":
                if printer.complete_job():
                    self.success = True
                    self.success = True
                    payload = printer.to_web()
                    i = 0
                    while not webapi.patch_printer(payload) and i < 10:
                        i += 1
                    if printer.current_job() != None:
                        c = Command(printer.id, log, "start", webapi)
                        c.start()
            else:
                log.log("ERROR: Printer " + str(id) +
                        " received command bed is clear" +
                        " but current print isn't finished.")
        if self.command_id != None and self.webapi != None:
            d = {"id": self.command_id, "type": command}
            if self.success == True:
                d['status'] = 'executed'
            else:
                d['status'] = 'errored'
            i = 0
            while webapi.callback_command(d) == False and i < 10:
                i += 1
        return 0
Example #8
0
    def run(self):
        """Function that will upload a new file, slice it if needed,
        and delete stl files from the octopi. Should be used whenever
        a new job is uploaded to the hub
        :returns: boolean of success

        """
        id = self.id
        log = self.log
        job_id = self.job_id
        webapi = self.webapi
        loc = octopi.local
        printer = Printer.get_by_id(id, fresh=True)
        ip = printer.ip
        port = printer.port
        key = printer.key
        job = Job.get_by_id(job_id)
        log.log("Starting job upload to " + str(id) + " for job " +
                str(job.id))
        fpath = job.file.path
        job.state("processing")
        url = ip + ":" + str(port)
        r = octopi.upload_file(url, key, fpath, loc)
        if r == None:
            log.log("ERROR: Did not have a response from " + str(id) +
                    ". File upload canceled for " + fpath + ".")
            self.success = False
            return False
        if r.status_code != 201:
            log.log("ERROR: Could not upload file " + fpath +
                    ". Return code from printer " + str(r.status_code))
            return False
        data = r.json()
        fname = data['files']['local']['name']
        ext = get_extension(fname)
        if ext in ['stl']:
            job.state("slicing")
            webapi.patch_job(job.to_web())
            r = octopi.slice(url, key, fname, loc)
            if r == None:
                log.log("ERROR: Did not have a response from " + str(id) +
                        ". Job upload canceled for job " + str(job_id) + ".")
                self.success = False
                return False
            if r.status_code != 202:
                log.log("ERROR: Job upload failed for " + str(job_id) +
                        ". Return code from printer " + str(r.status_code))
                self.success = False
                return False
            j = r.json()
            rname = j.get('name')
            r = octopi.get_one_file_info(url, key, rname, loc)
            while r == None or r.status_code != 200:
                #This is really f*****g hacky
                log.log("Could not retrieve file info for " + str(job.id))
                sleep(10)
                r = octopi.get_one_file_info(url, key, rname, loc)
            job.set_remote_name(rname)
            r = octopi.delete_file(url, key, fname, loc)
            while r == None:
                sleep(10)
                r = octopi.delete_file(url, key, fname, loc)
        elif ext in ['gcode', 'gco']:
            r = octopi.get_one_file_info(url, key, fname, loc)
            while r == None or r.status_code != 200:
                #This is really f*****g hacky
                log.log("Could not retrieve file info for " + str(job.id))
                sleep(10)
                r = octopi.get_one_file_info(url, key, fname, loc)
            job.set_remote_name(fname)
        else:
            self.success = False
            return False
        log.log("Completed job upload to " + str(id) + " for job " +
                str(job.id))
        self.success = True
        return True
Example #9
0
def add_printer():
    """
        Add Printer
        Adds or updates printer
        ---
        tags:
          - printer
        parameters:
          - in: body
            name: Printer
            description: Printer object to be added/activated
            required: true
            schema:
              id: Post_Printer
              required:
                - id
                - ip
                - key
              properties:
                ip:
                  type: string
                  description: ip address of connecting printer
                key:
                  type: string
                  description: api key for octopi
                id:
                  type: integer
                  description: uid of the printer activating
                port:
                  type: integer
                  description: port number to communicate on
                box:
                  type: integer
                  description: UID of black box that pairs with the printer
        responses:
          201:
            description: Returns 201 created
        """

    log = hub.log
    listener = hub.printer_listeners
    id = int(request.form.get("id"))
    ip = str(request.form.get("ip"))
    port = int(request.form.get("port", 80))
    key = str(request.form.get("key"))
    box = int(request.form.get("box"))
    printer = Printer.get_by_id(id, box)
    listener = hub.printer_listeners
    if printer:
        printer.update(box=box, ip=ip, port=port, key=key)
        if not listener.is_alive(id):
            t = PrinterCollector(id, hub.Webapi, hub.log)
            t.start()
            listener.add_thread(id, t)
            log.log("Printer " + str(id) + " is now online.")
            return json.jsonify(
                {'message': 'Printer ' + str(id) + ' is now online.'}), 201
        if listener.is_alive(id):
            log.log("Printer " + str(id) + " is already online but tried" +
                    " to activate again. Updated it's data")
            return json.jsonify(
                {'message':
                 'Printer ' + str(id) + ' was already online.'}), 201
    else:
        #Add printer to database
        printer = Printer(id, box, key=key, ip=ip, port=port)
        t = PrinterCollector(id, hub.Webapi, hub.log)
        t.start()
        listener.add_thread(id, t)
        return json.jsonify({
            'message':
            'Printer ' + str(id) + ' has been added and is online.'
        }), 201
Example #10
0
def jobs_post(id):
    """
        Add a Job
        Add job to printer
        ---
        tags:
          - printer
        parameters:
          - in: path
            description: ID of the printer
            required: true
            type: integer
            name: id
          - in: body
            description: Job to add to the printer
            required: true
            name: Job
            schema:
              $ref: "#/definitions/Web_Job"
        responses:
          201:
            description: returns "(job) has been uploaded successfully"
          400:
            description: no file was provided
          404:
            description: printer isn't found
        """
    printer = Printer.get_by_webid(id)
    if printer == None:
        abort(404)
    id = printer.id
    f = request.files.get('file', None)
    if f:
        webid = request.form.get('id')
        job = Job.get_by_webid(webid)
        if not job:
            job = Job(int(webid))
            ext = f.filename.rsplit(".", 1)[1]
            name = str(job.id) + "." + ext
            fpath = os.path.join(app.config['UPLOAD_FOLDER'], name)
            f.save(fpath)
            file = File(f.filename, fpath)
            job.set_file(file)
        elif job.file == None:
            ext = f.filename.rsplit(".", 1)[1]
            name = str(job.id) + "." + ext
            fpath = os.path.join(app.config['UPLOAD_FOLDER'], name)
            f.save(fpath)
            file = File(f.filename, fpath)
            job.set_file(file)
        printer = Printer.get_by_id(id)
        printer.add_job(job)
        t = threading.Thread(target=hub.Webapi.patch_job,
                             args=(job.to_web(), ))
        t.start()


#        if printer.current_job().id == job.id:
#            t = Command(printer.id, hub.log, "start",
#                        hub.Webapi)
#            t.start()
    else:
        abort(400)
    return json.jsonify(
        {"message":
         "Job " + str(webid) + " has been uploaded successfully"}), 201
Example #11
0
 def run(self):
     id = self.printer_id
     webapi = self.webapi
     log = self.log
     printer = Printer.get_by_id(id, fresh=True)
     # loop until the printer has a webid,
     # otherwise we can't update
     while printer.webid == None:
         webid = webapi.add_printer(printer.first_web())
         if webid:
             printer.set_webid(webid)
         else:
             sleep(10)
         printer = Printer.get_by_id(id, fresh=True)
     job_thread = JobCollector(id, webapi, log)
     job_thread.start()
     log.log("PrinterCollector starting for printer " + str(id))
     failures = 0
     #url          = "http://" + ip + ":" + port
     prev_data = {}
     while (True):
         printer = Printer.get_by_id(id, fresh=True)
         ip = printer.ip
         port = printer.port
         key = printer.key
         jobs = printer.jobs
         status = printer.status
         cjob = printer.current_job()
         if self.stopped:
             webapi.patch_printer(printer.to_web())
             log.log("PrinterCollector stop signal received for " +
                     str(id) + ". Telling JobCollector to stop.")
             job_thread.stop()
             job_thread.join()
             log.log("JobCollector stopped." + " Exiting PrinterCollector.")
             return 0
         # If status is set to completed, don't do anyting else
         if status in ["completed", "cancelled"]:
             if job_thread.is_alive():
                 job_thread.join(10)
                 if job_thread.is_alive():
                     job_thread.stop()
             data = printer.to_web()
             if cmp(prev_data, data):
                 prev_data = data.copy()
                 webapi.patch_printer(printer.to_web())
         if not job_thread.is_alive() and cjob != None\
                 and status not in ["errored", "cancelled",
                                                 "completed"]:
             log.log("JobCollector thread died for " + str(id) +
                     ". Starting new JobCollector.")
             job_thread = JobCollector(id, webapi, log)
             job_thread.start()
         url = ip + ":" + str(port)
         response = octopi.get_printer_info(url, key)
         if response != None:
             failures = 0
         else:
             failures += 1
             if failures > 2:
                 printer = Printer.get_by_id(id, fresh=True)
                 if printer.state("offline"):
                     data = printer.to_web()
                     if cmp(prev_data, data):
                         prev_data = data.copy()
                         webapi.patch_printer(data)
                     log.log("ERROR: Could not collect printer" +
                             " data from printer " + str(id))
                     job_thread.join()
                     log.log("JobCollector stopped." +
                             " Exiting PrinterCollector.")
                     return -1
             sleep(5)
             continue
         if response.status_code != 200:
             log.log("ERROR: Response from " + str(id) +
                     " returned status code " + str(response.status_code) +
                     " on " + response.url)
         else:
             #data = response.json()
             state = response.json()
             printer = Printer.get_by_id(id, fresh=True)
             if printer.state_from_octopi(state):
                 data = printer.to_web()
                 if prev_data.get("status") == "printing"\
                         and data.get("status") == "ready":
                     printer.state("completed")
                     continue
                 # Check to see if data is the same as last collected
                 # if so, do not send it
                 if cmp(prev_data, data):
                     prev_data = data.copy()
                     webapi.patch_printer(data)
         sleep(1)
Example #12
0
    def run(self):
        """TODO: Docstring for run.
        :returns: TODO

        """
        id = self.node_id
        webapi = self.webapi
        log = self.log
        node = Node.get_by_id(id)
        log.log("NodeCollector starting for node " + str(id))
        sleep(10)
        failures = 0
        while (True):
            node = Node.get_by_id(id, fresh=True)
            ip = node.ip
            sensors = node.sensors
            if self.stopped == True:
                log.log("NodeCollector for node " + str(id) +
                        " was requested to stop. Exiting...")
                return 0
            if ip != '0':
                for sensor in sensors:
                    pin = sensor.pin
                    webid = sensor.webid
                    sensor_type = sensor.sensor_type
                    if pin == None or sensor_type == None:
                        continue
                    if sensor_type in ["TEMP", "DOOR", "HUMI", "TRIG"]:
                        url = sensor.get_url()
                    elif sensor_type in ["LED"]:
                        printer = Printer.get_by_id(node.printer_id)
                        if printer:
                            if printer.status in ["completed", "cancelled"]:
                                url = sensor.led_flash()
                            else:
                                url = sensor.led_on()
                        else:
                            continue
                    elif sensor_type in ["POWER"]:
                        url = sensor.power_on()
                    else:
                        continue
                    try:
                        response = requests.get(url, timeout=10)
                    except requests.ConnectionError:
                        log.log("ERROR: Could not connect to " + url)
                        response = None
                    except requests.exceptions.Timeout:
                        log.log("ERROR: Timeout occured on " + url)
                        response = None
                    if response == None:
                        failures += 1
                        if failures > 10:
                            log.log("ERROR: Could not collect" +
                                    " sensor data from node " + str(id) +
                                    ". NodeCollector exiting...")
                            return -1
                        continue
                    if response.status_code != 200:
                        log.log("ERROR Response from " + str(id) +
                                " returned status code " +
                                str(response.status_code) + " on " +
                                response.url)
                    else:
                        recent_json = response.json()
                        ret = sensor.set_value(recent_json)
                        data = sensor.to_web()
                        if data != None and data.get("id") != None:
                            webapi.add_data(data)
                    sleep(3)
                sleep(3)
Example #13
0
    def run(self):
        id = self.printer_id
        webapi = self.webapi
        log = self.log
        log.log("JobCollector starting for printer " + str(id))
        failures = 0
        #url          = "http://" + ip + ":" + port
        prev_data = {}
        recent_json = None
        while (True):
            if self.stopped:
                log.log("JobCollector stop signal received for " + str(id) +
                        ", exiting.")
                return 0
            printer = Printer.get_by_id(id, fresh=True)
            ip = printer.ip
            port = printer.port
            key = printer.key
            jobs = printer.jobs
            status = printer.status
            cjob = printer.current_job()
            url = ip + ":" + str(port)
            #If no current job, simply stop tracking. PrinterCollector
            # will spawn a new job thread when needed
            if cjob == None:
                log.log("No current job exists for " + str(id) +
                        ". JobCollector exiting.")
                return 0
            if cjob.status == "completed":
                return 0
            if cjob.status == "cancelled":
                return 0
            if cjob.status == "queued":
                t = Command(id, log, "start", webapi)
                t.start()
            if cjob.status == "errored" and status == "ready":
                printer.remove_job(cjob.id)
            #If printer status is set to completed, cancelled,
            #or errored, exit. a new job thread will be spawned
            #by printer collector when needed
            if status == "offline":
                cjob.state("errored")
                data = cjob.to_web()
                i = 0
                # Try to update to web api 10 times
                while not webapi.patch_job(data) and i < 10:
                    i += 1
                    sleep(5)
                return 0
            if status == "completed" and prev_data\
                and prev_data.get("data")\
                    .get("progress").get("completion") == 100:
                # this ensures it will have updated to the web api
                cjob.state("completed")
                data = cjob.to_web()
                i = 0
                # Try to update to web api 10 times
                while not webapi.patch_job(data) and i < 10:
                    i += 1
                    sleep(5)
                return 0
            if status == "cancelled":
                cjob.state("cancelled")
                data = cjob.to_web()
                i = 0
                # Try to update to web api 10 times
                while not webapi.patch_job(data) and i < 10:
                    i += 1
                    sleep(5)
                return 0
            if status == "errored":
                cjob.state("errored")
                data = cjob.to_web()
                i = 0
                # Try to update to web api 10 times
                while not webapi.patch_job(data) and i < 10:
                    i += 1
                    sleep(5)
                return 0
            if status == "paused":
                cjob.state("paused")
            if status == "printing":
                cjob.state("printing")

            response = octopi.get_job_info(url, key)
            if response != None:
                failures = 0
            else:
                failures += 1
                log.log("ERROR: Could not collect" +
                        " job data from printer " + str(id) + " on " + url)
                if failures > 5:
                    cjob.state("errored")
                    webapi.patch_job(cjob.to_web())
                    return -1
                continue
            if response.status_code != 200:
                log.log("ERROR: Response from " + str(id) +
                        " returned status code " + str(response.status_code) +
                        " on " + response.url)
            else:
                recent_json = response.json()
                ret = cjob.set_meta(recent_json)
                data = cjob.to_web()
                if data != None:
                    # Check to see if data is the same as last collected
                    # if so, do not send it
                    if cmp(prev_data, data):
                        prev_data = data.copy()
                        webapi.patch_job(data)
                        #print(data)
                else:
                    log.log("ERROR: Did not get proper job data from " +
                            str(id))
                    sleep(10)
            sleep(1)