Exemplo n.º 1
0
 async def load(self) -> SocketMessageResponse:
     log().info("loading filament...")
     for cmd in ['M109 S210', 'G92 E0', 'G1 E100 F150', 'M109 S0']:
         log().info("executing command from load command chain " + cmd +
                    "...")
         await self.octoapi.post_command(cmd)
     return SocketMessageResponse(0, "ok")
Exemplo n.º 2
0
    async def loop(self):
        last_connection_try = 0
        while True:
            await self.updateActualState()
            status = self.actualState["status"]["state"][
                "text"] if "status" in self.actualState and "state" in self.actualState[
                    "status"] and "text" in self.actualState["status"][
                        "state"] else "unknown"
            error = self.actualState[
                "error"] if "error" in self.actualState else 0
            if time.time() - last_connection_try > 20 and (status == 'Closed'
                                                           or error == 409):
                log().warning("closed status detected, forcing connection...")
                last_connection_try = time.time()
                try:
                    await self.octoapi.connect()
                    log().info(f"printer connected correctly")

                except HttpException:
                    log().warning(
                        f"could not connect printer, trying again in {20}s")

                except ClientConnectorError as e:
                    log().error(
                        f"client connection error with octoprint server while trying to connect printer: "
                        + str(e))

                except Exception as e:
                    log().error(
                        f"unknown error while trying to connect printer: " +
                        str(e))

            if self.connected and self.transmitting:
                await self.syncWithUlab()
            await asyncio.sleep(1)
Exemplo n.º 3
0
 async def syncWithUlab(self):
     spec = self.diffengine.diff(self.actualState, self.sentState)
     if len(spec):
         try:
             await self.ulabapi.update_status(spec)
             self.sentState = copy.deepcopy(self.actualState)
         except Exception as e:
             log().error(e)
Exemplo n.º 4
0
 async def instruction(data: str) -> SocketMessageResponse:
     log().info("incoming instruction: " + data)
     response = await self.listener(data)
     if response.status:
         log().warning(
             f"response for instruction with status {response.status}: {response.message}"
         )
     return response
Exemplo n.º 5
0
    async def cancel(self) -> SocketMessageResponse:
        log().info("cancelling print...")
        if not self.actualState["status"]["state"]['flags']['printing']:
            return SocketMessageResponse(
                1, "pandora is not in an printing state")

        await self.octoapi.cancel()
        await self.octoapi.post_command("G1 Z140")
        return SocketMessageResponse(0, "ok")
Exemplo n.º 6
0
 async def _print_file(self, gcode: str) -> None:
     log().info("printing file " + gcode + '...')
     if "init_gcode" in self.actualState['settings']:
         for pre_cmd in self.actualState['settings']["init_gcode"].split(
                 ";"):
             if len(pre_cmd) < 2:
                 continue
             log().info("executing init gcode " + pre_cmd)
             await self.octoapi.post_command(pre_cmd)
     await self.octoapi.print(gcode.split('/')[-1])
Exemplo n.º 7
0
            async def download_and_print():
                self.actualState["download"]["file"] = data['file']
                self.actualState["download"]["completion"] = 0.0
                r = await self.ulabapi.download(data['file'])

                if not r.status == 200:
                    log().warning("error downloading file " + data['file'] +
                                  " from url: " + str(r.status))
                    self.actualState["download"]["file"] = None
                    self.actualState["download"]["completion"] = -1

                await self._download_file(r, gcode)
                await self._print_file(gcode)
Exemplo n.º 8
0
    async def wifi(self, data: Dict[str, str]) -> SocketMessageResponse:
        log().info("changing wifi...")
        for k in ['ssid', 'psk']:
            if k not in data:
                return SocketMessageResponse(1, k + " parameter not specified")

        log().info("new wifi data: ssid=" + data['ssid'] + " psk=" +
                   data['psk'])
        wifi = 'network={\n  ssid="' + data['ssid'] + '"\n  psk="' + data[
            'psk'] + '"\n}\n'
        wpa_supplicant_txt = open("/boot/octopi-wpa-supplicant.txt").read()
        open("/boot/octopi-wpa-supplicant.txt",
             "w").write(wifi + wpa_supplicant_txt)
        return SocketMessageResponse(0, "ok")
Exemplo n.º 9
0
    async def move(self, data: Dict[str, str]) -> SocketMessageResponse:
        log().info("moving...")
        for k in ['axis', 'distance']:
            if k not in data:
                return SocketMessageResponse(1, k + " not specified")

        for cmd in [
                'G91', 'G1 {}{} F1000'.format(data['axis'], data['distance']),
                'G90'
        ]:
            log().info("executing command from move command chain " + cmd +
                       "...")
            await self.octoapi.post_command(cmd)
        return SocketMessageResponse(0, "ok")
Exemplo n.º 10
0
async def main(loop: asyncio.AbstractEventLoop):
    if not os.path.isfile(args.ulab_token_path):
        log().error(
            "token file " + args.ulab_token_path +
            " does not exists, create it with the ulab token inside and restart the system"
        )
        while True:
            time.sleep(10)
    ulab_token = open(args.ulab_token_path).read().replace('\n', "").replace(
        " ", "")
    octoapi = OctoApi(args.octoprint_url, args.octoprint_config_path)
    ulabapi = UlabApi(args.ulab_socket_url, args.ulab_backend_url, ulab_token)
    printer = Printer(octoapi, ulabapi)
    await printer.ulabapi.connect(loop)
    await printer.loop()
Exemplo n.º 11
0
    async def settings(self, data: Dict[str, str]) -> SocketMessageResponse:
        log().info("changing settings...")
        keys = [x for x in data if x not in ['instruction']]
        if not len(keys):
            return SocketMessageResponse(1, "no new settings has been sent")

        for k in keys:
            if k not in self.actualState['settings']:
                return SocketMessageResponse(1,
                                             "setting " + k + " not supported")

        for k in keys:
            self.actualState['settings'][k] = data[k]
        json.dump(self.actualState['settings'], open("../store.json", "w"))
        await self.syncWithUlab()
        return SocketMessageResponse(0, "ok")
Exemplo n.º 12
0
 async def _download_file(self, r: aiohttp.ClientResponse,
                          gcode: str) -> None:
     f = await aiofiles.open(gcode, mode='wb')
     readed = 0
     while True:
         if r.content_length:
             self.actualState["download"][
                 "completion"] = readed / r.content_length
         chunk = await r.content.read(1024)
         if not chunk:
             break
         await f.write(chunk)
         readed += 1024
     log().info("file " + gcode +
                ' downloaded successfully, printing it...')
     self.actualState["download"]["file"] = None
     self.actualState["download"]["completion"] = -1
     await self.syncWithUlab()
Exemplo n.º 13
0
    async def print(self, data: Dict[str, str]) -> SocketMessageResponse:
        log().info("printing...")
        if 'file' not in data:
            return SocketMessageResponse(1, "file not specified")

        if self.actualState['download']['file'] is not None:
            return SocketMessageResponse(
                1, "file " + self.actualState['download']['file'] +
                " has already been sheduled to download and print")

        if not self.actualState["status"]["state"]['text'] == 'Operational':
            return SocketMessageResponse(
                1, "pandora is not in an operational state")

        upload_path = get_args().octoprint_upload_path
        if not os.path.isdir(upload_path):
            os.mkdir(upload_path)
        gcode = upload_path + '/' + (data['file'] if data['file'].endswith(
            '.gcode') else data['file'] + '.gcode')

        if not os.path.isfile(gcode):
            log().info("file " + gcode + " not found, downloading it...")

            async def download_and_print():
                self.actualState["download"]["file"] = data['file']
                self.actualState["download"]["completion"] = 0.0
                r = await self.ulabapi.download(data['file'])

                if not r.status == 200:
                    log().warning("error downloading file " + data['file'] +
                                  " from url: " + str(r.status))
                    self.actualState["download"]["file"] = None
                    self.actualState["download"]["completion"] = -1

                await self._download_file(r, gcode)
                await self._print_file(gcode)

            asyncio.get_running_loop().create_task(download_and_print(
            ))  # todo: get running loop from somewhere cleaner
            return SocketMessageResponse(
                0, "file was not on ucloud, downloading it and printing it...")

        await self._print_file(gcode)
        return SocketMessageResponse(0, "ok")
Exemplo n.º 14
0
    async def updateActualState(self):
        try:
            self.actualState["status"] = await self.octoapi.get_status()
            self.actualState["job"] = await self.octoapi.get_job()
            self.actualState["error"] = None

        except HttpException as e:
            self.actualState["status"] = {"state": {"text": "Disconnected"}}
            self.actualState["error"] = e.code

        except ClientConnectorError as e:
            log().error("error connecting to octoprint server: " + str(e))
            self.actualState["status"] = {"state": {"text": "Disconnected"}}
            self.actualState["error"] = 450

        except Exception as e:
            log().error("unknown error updating status: " + str(e))
            self.actualState["status"] = {"state": {"text": "Disconnected"}}
            self.actualState["error"] = 500
Exemplo n.º 15
0
    async def command(self, data: Dict[str, str]) -> SocketMessageResponse:
        log().info("executing command...")
        if 'command' not in data:
            log().warning("command not specified")
            return SocketMessageResponse(1, "command not specified")

        for cmd in data['command'].split(";"):
            log().info(cmd)
            await self.octoapi.post_command(cmd)
        return SocketMessageResponse(0, "ok")
Exemplo n.º 16
0
    async def _updateActualState(self):
        try:
            self.actualState["status"] = await self.octoapi.get_status()
            self.actualState["job"] = await self.octoapi.get_job()
            if self.actualState["status"]["state"]['text'] == 'Closed':
                log().warning("closed status detected, forcing connection...")
                await self.octoapi.connect()

        except HttpException as e:
            self.actualState["status"] = {"state": {"text": "Disconnected"}}
            if e.code == 409:
                log().warning(
                    "octoprint returned 409 while requesting status, forcing connection..."
                )
                await self.octoapi.connect()

        except ClientConnectorError as e:
            log().error("error conectando con el servidor de octoprint: " +
                        str(e))
            self.actualState["status"] = {"state": {"text": "Disconnected"}}
Exemplo n.º 17
0
 async def start(self) -> SocketMessageResponse:
     log().info("starting transmission")
     self.transmitting = True
     return SocketMessageResponse(0, "ok")
Exemplo n.º 18
0
 async def init(data: str = ""):
     log().info("data initialization requested, starting transmission")
     await self.init()
     await self.syncWithUlab()
Exemplo n.º 19
0
 async def stop(data: str = ""):
     log().info("socket requested to stop transmission")
     self.transmitting = False
Exemplo n.º 20
0
 async def error(e: Exception):
     self.connected = False
     self.transmitting = False
     log().warning("error on Socket: " + str(e))
Exemplo n.º 21
0
 async def disconnect(data: str = ""):
     self.connected = False
     self.transmitting = False
     log().warning("socket disconnected, oh no! :(")
Exemplo n.º 22
0
 async def connect(data: str = ""):
     log().info("socket connected, yujuu! :)")
     self.connected = True
Exemplo n.º 23
0
    async def listener(self, data_raw: str) -> SocketMessageResponse:
        try:
            data: Dict[str, Union[str, int, float]] = json.loads(data_raw)
        except json.JSONDecodeError:
            log().error("error decoding instruction " + data_raw)
            return SocketMessageResponse(1, "cannot decode instruction")

        if 'instruction' not in data:
            log().warning(
                "received instruction without specifying an instruction name")
            return SocketMessageResponse(1, "instruction not specified")

        instruction = data['instruction']
        log().info("instruction " + instruction + " detected")
        if instruction in [
                "home", "start", "stop", "print", "command", "load", "unload",
                "move"
        ]:
            error_flag = False
            try:
                if self.actualState["status"]["state"]['text'] != 'Operational':
                    error_flag = True
            except KeyError:
                error_flag = True
            except TypeError:
                error_flag = True
            if error_flag:
                log().warning(
                    "instruction not allowed if pandora is not on an operational state"
                )
                return SocketMessageResponse(
                    1, "printer is not on an operational state")

        try:
            if instruction == "start":
                return await self.start()

            elif instruction == "stop":
                return await self.stop()

            if instruction == 'home':
                return await self.home()

            elif instruction == 'print':
                return await self.print(data)

            elif instruction == 'cancel':
                return await self.cancel()

            elif instruction == 'settings':
                return await self.settings(data)

            elif instruction == 'move':
                return await self.move(data)

            elif instruction == 'command':
                return await self.command(data)

            elif instruction == 'load':
                return await self.load()

            elif instruction == 'unload':
                return await self.unload()

            elif instruction == 'wifi':
                return await self.wifi(data)

            else:
                return SocketMessageResponse(
                    1, data['instruction'] + " instruction not supported")

        except HttpException as e:
            log().warning("octoapi responded " + str(e.code) + ", to " +
                          json.dumps(data))
            return SocketMessageResponse(1, "printer responded " + str(e.code))

        except Exception as e:
            log().error(str(e))
            return SocketMessageResponse(1, str(e))
Exemplo n.º 24
0
 async def stop(self) -> SocketMessageResponse:
     log().info("stopping transmission")
     self.transmitting = False
     return SocketMessageResponse(0, "ok")
Exemplo n.º 25
0
 async def home(self) -> SocketMessageResponse:
     log().info("homing...")
     await self.octoapi.post_command("G28")
     return SocketMessageResponse(0, "ok")