コード例 #1
0
class CloudTask(object):
    def __init__(self, plugin):
        self.plugin = plugin
        self.websocket = None
        self.printer = None
        self.printer_info = PrinterInfo(plugin)
        self.printer_manager = printer_manager_instance(plugin)
        self.sqlite_server = SqliteServer(plugin)

    def _send_ws_data(self, data, message_type=None):
        if not self.websocket:
            return
        try:
            self.websocket.send_text(data)
        except:
            import traceback
            traceback.print_exc()

    def _set_token(self, token):
        """
    status: receive job status
    """
        sql = 'UPDATE profile SET token = ? WHERE id = ? '
        data = [(token, 1)]
        self.sqlite_server.update(sql, data)

    def _get_token(self):
        """
        :return: "{}
        token": cloud_api_token,
        """
        fetchone_sql = 'SELECT token FROM profile WHERE ID = ? '
        res = self.sqlite_server.fetchone(fetchone_sql, 1)
        return {"token": res[0]} if res else {}

    def _get_machine_id(self):
        """
        :return: {}
        "machine_id": machine_id,
        """
        fetchone_sql = 'SELECT machine_id FROM profile WHERE ID = ? '
        res = self.sqlite_server.fetchone(fetchone_sql, 1)
        return {"machine_id": res[0]} if res else {}

    def _set_receive_job(self, status):
        """
        status: receive job status
        """
        sql = 'UPDATE profile SET receive_job = ? WHERE id = ? '
        data = [(status, 1)]
        self.sqlite_server.update(sql, data)

    def _get_receive_job(self):
        """
        :return: receive job status  accept or refuse
        """
        sql = 'SELECT receive_job FROM profile WHERE ID = ? '
        res = self.sqlite_server.fetchone(sql, 1)
        return {"status": res[0]} if res and res[0] else {"status": "accept"}

    def _other_info(self):
        """
        :return: {}
        raise_touch_version
        queue_state
        """
        return {
            "raise_touch_version": "1.0.1",
            "queue_state":
            1 if self._get_receive_job()["status"] == "accept" else 0,
            "machine_id": self._get_machine_id()["machine_id"],
            "token": self._get_token()["token"]
        }

    def _get_send_data(self):
        """
        send_dict = {
        "message_type": 1,
        "machine_id": machine_id,
        "token": cloud_api_token,
        "data" :
            {
                "machine_id": machine_id,
                "token": cloud_api_token,
                "raise_touch_version": "",
                "queue_state":"",
                self.get_printer_info
            }
        }
        :return: send_dict
        """
        try:
            data = self.printer_info.get_printer_info()
            if self.printer_manager.downloading:
                data["cur_print_state"] = "busy"
            data.update(self._other_info())
            return {
                "message_type": 1,
                "machine_id": self._get_machine_id()["machine_id"],
                "token": self._get_token()["token"],
                "data": data
            }
        except Exception as e:
            _logger.error(e)
            _logger.error("get printer info error ...")

    def on_event(self, state):
        if state == 2:
            # update task_id
            self.printer_manager.task_id = "not_remote_tasks"
            # reboot 消息
            reboot_data = {
                "message_type": 11,
                "machine_id": self._get_machine_id()["machine_id"],
                "token": self._get_token()["token"],
                "data": {
                    "machine_id": self._get_machine_id()["machine_id"],
                    "reboot": True
                }
            }
            self.websocket.send_text(reboot_data)
            _logger.info("reboot remote raisecloud.")
            return

        if state == 1:
            process_data = {
                "message_type": 1,
                "machine_id": self._get_machine_id()["machine_id"],
                "token": self._get_token()["token"],
                "data": {
                    "machine_id": self._get_machine_id()["machine_id"],
                    "print_progress": "100.00"
                }
            }
            self.websocket.send_text(process_data)
            _logger.info("remote task printing process completed.")
        if self.printer_manager.task_id == "not_remote_tasks":
            return
        result = {
            "message_type": 3,
            "machine_id": self._get_machine_id()["machine_id"],
            "token": self._get_token()["token"],
            "state": state,
            "data": {
                "task_id": self.printer_manager.task_id,
                "continue_code": "complete",
                "machine_id": self._get_machine_id()["machine_id"],
            }
        }
        _logger.info("remote task printing completed")
        self.websocket.send_text(result)
        # clean up task_id
        self.printer_manager.task_id = "not_remote_tasks"

    def task_event_run(self):
        try:
            self.event_loop()
        except Exception as e:
            _logger.error("task event error...")
            _logger.error(e)

    def event_loop(self):
        policy = ReconnectionPolicy()
        disconnect_status = False
        while True:
            _logger.info("websocket connecting ...")
            try:
                self.websocket = WebsocketServer(
                    url="wss://api.raise3d.com/octoprod-v1.1/websocket",
                    on_server_ws_msg=self._on_server_ws_msg,
                    on_client_ws_msg=self._on_client_ws_msg)
                wst = threading.Thread(target=self.websocket.run)
                wst.daemon = True
                wst.start()
                time.sleep(2)

                while self.websocket.connected():
                    status = self.sqlite_server.check_login_status()
                    if status == "logout":
                        _logger.info(
                            "user has logged out, websocket is about to disconnect ..."
                        )
                        disconnect_status = True
                        self.websocket.disconnect()
                        wst.join()
                        break
                    policy.reset()
                    time.sleep(5)
            finally:
                try:
                    self.websocket.disconnect()
                    if self.sqlite_server.check_login_status() == "logout":
                        break
                except:
                    pass
                policy.more()
            # if disconnect_status:
            #     break

    def _send_heart_beat_event(self):
        index = 0
        while True:
            try:
                if self.websocket.connected():
                    time.sleep(5)
                    index += 1
                else:
                    _logger.info("raisecloud heartbeat over.")
                    break
                if index % 60 == 0:
                    _logger.info("ping to raisecloud.")
                    self.websocket.send_text(data="ping", ping=True)
            except Exception as e:
                _logger.error("socket printer ping error ...")
                _logger.error(e)
                time.sleep(5)

    def _send_printer_info_event(self):
        diff_dict = dict()
        previous_dict = dict()
        while True:
            try:
                if not self.websocket.connected():
                    _logger.info("raisecloud printer info over.")
                    break
                send_data = self._get_send_data()
                tmp_data = send_data["data"]
                if previous_dict:
                    for key, value in send_data["data"].items():
                        if key == "storage_avl_kb" and abs(previous_dict[key] -
                                                           value) < 1024:
                            continue  # 变化小于1M
                        # profile 更改配置,增加属性nozzle等
                        if key not in previous_dict:
                            diff_dict[key] = value
                            continue
                        if previous_dict[key] != value:
                            diff_dict[key] = value
                    if diff_dict:
                        send_data["data"] = diff_dict
                        send_data["data"].update({
                            "machine_id":
                            self._get_machine_id()["machine_id"]
                        })
                        # 防止网络异常丢失当前状态
                        if "cur_print_state" not in send_data["data"].keys():
                            send_data["data"]["cur_print_state"] = tmp_data[
                                "cur_print_state"]
                        #_logger.info("update printer info to raisecloud.")
                        self._send_ws_data(send_data)
                        diff_dict = {}

                else:
                    # _logger.info("update printer info to raisecloud.")
                    self._send_ws_data(send_data)
                previous_dict = tmp_data
                time.sleep(5)
            except Exception as e:
                _logger.error("socket printer info error ...")
                _logger.error(e)
                time.sleep(5)

    def _on_client_ws_msg(self, ws):
        send_heart_beat_thread = threading.Thread(
            target=self._send_heart_beat_event)
        send_heart_beat_thread.daemon = True
        send_heart_beat_thread.start()

        send_printer_info_thread = threading.Thread(
            target=self._send_printer_info_event)
        send_printer_info_thread.daemon = True
        send_printer_info_thread.start()

    def _load_thread(self, download_url, filename):
        success_data = {
            "state": 1,
            "message_type": 2,
            "machine_id": self._get_machine_id()["machine_id"],
            "token": self._get_token()["token"],
            "data": {
                "task_id": self.printer_manager.task_id,
                "print_state": 1,
                "machine_id": self._get_machine_id()["machine_id"],
            }
        }
        failed_data = {
            "state": 0,
            "message_type": 9,
            "machine_id": self._get_machine_id()["machine_id"],
            "token": self._get_token()["token"],
            "data": {
                "task_id": self.printer_manager.task_id,
                "download_state": 0,
                "machine_id": self._get_machine_id()["machine_id"],
            }
        }
        load_thread = threading.Thread(target=self.printer_manager.load_thread,
                                       args=(download_url, filename,
                                             success_data, failed_data,
                                             self.websocket))
        load_thread.daemon = True
        load_thread.start()

    def _on_server_ws_msg(self, ws, message):
        # 处理远程消息
        # _logger.info("receive message from raisecloud: %s" % message)
        mes = json.loads(message)
        if mes["message_type"] == 2:
            try:
                if self._get_receive_job()["status"] == "accept":  # 状态为接受状态
                    download_url = mes["data"]["download_url"].encode('utf-8')
                    self.printer_manager.task_id = mes["data"][
                        "task_id"].encode('utf-8')
                    filename = hex_str_2_unicode(
                        mes["data"]["print_file"].encode(
                            'utf-8'))  # display name
                    self._load_thread(download_url, filename)
            except Exception as e:
                _logger.error("cloud file printing error ...")
                _logger.error(e)

        if mes["message_type"] == 4:
            # 接受 终止 暂停
            try:
                command = mes["data"]["push_down"].encode('utf-8')
                if command == "pause":
                    self.plugin._printer.pause_print()
                if command == "resume":
                    self.plugin._printer.resume_print()
                if command == "stop":
                    self.plugin._printer.cancel_print()
                result = {
                    "message_type": 4,
                    "state": 1,
                    "machine_id": self._get_machine_id()["machine_id"],
                    "token": self._get_token()["token"],
                    "data": {
                        "machine_id": self._get_machine_id()["machine_id"]
                    }
                }
                _logger.info("printer pause or resume or stop done.")
                self.websocket.send_text(result)
            except Exception as e:
                _logger.error("printer setting push down error ...")
                _logger.error(e)

        if mes["message_type"] == 5:
            try:
                data = mes["data"]
                if data:
                    invalid = "0.00"
                    if "bed_temp" in data:
                        bed_temp = data["bed_temp"].encode('utf-8')
                        if bed_temp != invalid:
                            self.plugin._printer.set_temperature(
                                "bed", int(bed_temp[:-3]))
                    if "nozzle_temp_1" in data:
                        temp_1 = data["nozzle_temp_1"].encode('utf-8')
                        if temp_1 != invalid:
                            self.plugin._printer.set_temperature(
                                "tool0", int(temp_1[:-3]))
                    if "nozzle_temp_2" in data:
                        temp_2 = data["nozzle_temp_2"].encode('utf-8')
                        if temp_2 != invalid:
                            self.plugin._printer.set_temperature(
                                "tool1", int(temp_2[:-3]))

                    if "flow_rate_1" in data:  # 挤出机挤出速率
                        flow_rate1 = data["flow_rate_1"].encode('utf-8')
                        if flow_rate1 != invalid:
                            self.plugin._printer.change_tool("tool0")
                            self.plugin._printer.flow_rate(int(
                                flow_rate1[:-3]))
                    if "flow_rate_2" in data:
                        flow_rate2 = data["flow_rate_2"].encode('utf-8')
                        if flow_rate2 != invalid:
                            self.plugin._printer.change_tool("tool1")
                            self.plugin._printer.flow_rate(int(
                                flow_rate2[:-3]))

                    if "fan_speed" in data:
                        fan_speed = data["fan_speed"].encode('utf-8')
                        command = "M106 S{}".format(int(fan_speed[:-3]))
                        self.plugin._printer.commands(command)  # args str

                    if "print_speed" in data:  # printer head移动速度
                        feed_rate = data["print_speed"].encode('utf-8')
                        if feed_rate != invalid:
                            self.plugin._printer.feed_rate(int(feed_rate[:-3]))

                    if "jog" in data:
                        jog = data["jog"]
                        if jog:
                            self.plugin._printer.jog(jog)  # args dict

                    if "home" in data:
                        axes = []
                        if "x" in data["home"] and data["home"]["x"].encode(
                                'utf-8') == "reset":
                            axes.append("x")
                        if "y" in data["home"] and data["home"]["y"].encode(
                                'utf-8') == "reset":
                            axes.append("y")
                        if "z" in data["home"] and data["home"]["z"].encode(
                                'utf-8') == "reset":
                            axes.append("z")
                        self.plugin._printer.home(axes)

                result = {
                    "state": 1,
                    "message_type": 5,
                    "machine_id": self._get_machine_id()["machine_id"],
                    "token": self._get_token()["token"],
                    "data": {
                        "machine_id": self._get_machine_id()["machine_id"],
                    }
                }
                _logger.info("printer setting parameters done.")
                self.websocket.send_text(result)
            except Exception as e:
                _logger.error("printer setting error,")
                _logger.error(e)

        if mes["message_type"] == 6:
            start = int(mes["data"]["start"])
            length = int(mes["data"]["length"])
            keyword = mes["data"]["keyword"]
            if keyword:
                keyword = keyword.encode('utf-8')
            dir_path = mes["data"]["dir_path"].encode('utf-8')
            try:
                file_data = self.printer_manager.get_files(path=dir_path,
                                                           keyword=keyword,
                                                           start=start,
                                                           length=length)
                file_data.update(
                    {"machine_id": self._get_machine_id()["machine_id"]})
                result = {
                    "state": 1,
                    "message_type": 6,
                    "machine_id": self._get_machine_id()["machine_id"],
                    "token": self._get_token()["token"],
                    "data": file_data
                }
                _logger.info("synchronization file message to remote.")
                self.websocket.send_text(result)
            except Exception as e:
                _logger.error("get file data error ...")
                _logger.error(e)

        if mes["message_type"] == 7:
            if self._get_receive_job()["status"] == "accept":  # 状态为接受状态
                print_file = mes["data"]["print_file"].encode('utf-8').replace(
                    "/local/", "")
                try:
                    self.printer_manager.task_id = ""
                    local_abs_path = self.plugin._file_manager.path_on_disk(
                        "local", "").encode('utf-8')  # local绝对路径
                    path = os.path.join(local_abs_path, print_file)
                    self.plugin._printer.select_file(path,
                                                     sd=False,
                                                     printAfterSelect=True)
                    result = {
                        "message_type": "7",
                        "state": 1,
                        "machine_id": self._get_machine_id()["machine_id"],
                        "data": {
                            "machine_id": self._get_machine_id()["machine_id"]
                        }
                    }
                    _logger.info("printing local files remotely .")
                    self.websocket.send_text(result)

                except Exception as e:
                    _logger.error("start print local file error ...")
                    _logger.error(e)

        if mes["message_type"] == 8:
            try:
                receive = int(mes["data"]["receive_job_set"].encode('utf-8'))
                self._set_receive_job(
                    "accept") if receive else self._set_receive_job("refuse")
                reply_message = {
                    "message_type": 8,
                    "source": 1,
                    "machine_id": self._get_machine_id()["machine_id"],
                    "token": self._get_token()["token"],
                    "data": {
                        "machine_id": self._get_machine_id()["machine_id"],
                        "queue_state": 1 if receive else 0,  # 0禁用 1启用
                    }
                }

                _logger.info("set up remote task acceptance .")
                self.websocket.send_text(reply_message)

            except Exception as e:
                _logger.error("set accept or refuse job error ...")
                _logger.error(e)

        if mes["message_type"] == 10:
            webcam = webcam_instance(self.plugin)
            webcam.upload_snapshot(self._get_machine_id()["machine_id"],
                                   self._get_token()["token"])

        if mes["message_type"] == 11:
            try:
                error_code = int(mes["data"]["error_code"])
                if error_code == 5:
                    # 强制下线
                    self.plugin.status = "logout"
                    self.sqlite_server.delete_content()
                    _logger.info("remotely force users to go offline .")
                    self.plugin._logout()

                if error_code == 2:
                    # 刷新token
                    _logger.info("remotely force users to flash token .")
                    token = flash_token(
                        machine_id=self._get_machine_id()["machine_id"])
                    # 写入token
                    if token:
                        self._set_token(token.encode('utf-8'))
            except Exception as e:
                _logger.error(e)