#!D:/IDE/anaconda3/envs/Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName：ManipulatorFrame.py
@Description：
@Author：XSH
@Time：2025/11/15 17:18
@Department：研发部
@Copyright：©2025 乐辰生物
"""
import numpy as np
import cv2
from PyQt5                              import Qt
from AppSettings.Settings               import *
from AppCore.Levels                     import *
from AppUtils.UiUtils                   import UiUtils
from AppInterfaces.UiInterface          import UiInterface, AppUiProperty, AppUtils, AppConvert
from AppInterfaces.ReaderInterfaces     import *
from AppInterfaces.ImplInterfaces       import *
from AppBackEnd.AppBusinessInterface    import AppBusinessInterface
from AppHeadEnd.ControllerViews.ManipulatorController   import ManipulatorController   #
from AppHeadEnd.ControllerViews.HookController          import HookController          #
from AppHeadEnd.ControllerViews.CameraController        import CameraController        #
from AppHeadEnd.ControllerFrames.ControlFrameInterface import ControlFrameInterface
from AppUtils.ImageUtils import ImageUtils
class ManipulatorFrame(Qt.QWidget, ControlFrameInterface):
    Controller              : ManipulatorController         #
    Hook                    : HookController                #
    CameraView              : CameraController              #
    CameraTimer             : Qt.QTimer                     #

    def __init__(self, business: AppBusinessInterface, parent: Qt.QObject = None):
        super(ManipulatorFrame, self).__init__(parent=parent)
        self.Business = business if isinstance(business, AppBusinessInterface) else None
        self.Initialization('ManipulatorFrame', self, parent)
        self.initWidgetStyle()



    def initValue(self):
        super(ManipulatorFrame, self).initValue()
        self.initController ()
        self.initHook       ()
        self.initCamera     ()
        self.initBusiness   ()

    def initConnect(self):
        super(ManipulatorFrame, self).initConnect()
        TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
        self.Controller.YPlusButton           .clicked.connect(slot=self.SlotYPlusButton           , type=TYPE)
        self.Controller.YMinusButton          .clicked.connect(slot=self.SlotYMinusButton          , type=TYPE)
        self.Controller.XPlusButton           .clicked.connect(slot=self.SlotXPlusButton           , type=TYPE)
        self.Controller.XMinusButton          .clicked.connect(slot=self.SlotXMinusButton          , type=TYPE)
        self.Controller.ZPlusButton           .clicked.connect(slot=self.SlotZPlusButton           , type=TYPE)
        self.Controller.ZMinusButton          .clicked.connect(slot=self.SlotZMinusButton          , type=TYPE)
        self.Controller.MicPlusButton         .clicked.connect(slot=self.SlotMicPlusButton         , type=TYPE)
        self.Controller.MicMinusButton        .clicked.connect(slot=self.SlotMicMinusButton        , type=TYPE)
        self.Controller.HPlusButton           .clicked.connect(slot=self.SlotHPlusButton           , type=TYPE)
        self.Controller.HMinusButton          .clicked.connect(slot=self.SlotHMinusButton          , type=TYPE)
        self.Controller.ScanCodeButton        .clicked.connect(slot=self.SlotScanCodeButton        , type=TYPE)
        self.Controller.CodeCompleteButton    .clicked.connect(slot=self.SlotCodeCompleteButton    , type=TYPE)
        self.Controller.CameraSwitch          .clicked.connect(slot=self.SlotCameraSwitch          , type=TYPE)
        self.Controller.CameraButton          .clicked.connect(slot=self.SlotCameraButton          , type=TYPE)
        self.Controller.InitXYButton          .clicked.connect(slot=self.SlotInitXYButton          , type=TYPE)
        self.Controller.InitZButton           .clicked.connect(slot=self.SlotInitZButton           , type=TYPE)
        self.Controller.InitHButton           .clicked.connect(slot=self.SlotInitHButton           , type=TYPE)
        self.Controller.InitMicButton         .clicked.connect(slot=self.SlotInitMicButton         , type=TYPE)
        self.Controller.InitCodeButton        .clicked.connect(slot=self.SlotInitCodeButton        , type=TYPE)
        self.Controller.InitCameraButton      .clicked.connect(slot=self.SlotInitCameraButton      , type=TYPE)
        self.Controller.DebugButton           .clicked.connect(slot=self.SlotDebugButton           , type=TYPE)
        self.Controller.ObjectiveLabel        .clicked.connect(slot=self.SlotObjectiveEdit         , type=TYPE)

        # Button_HookClearZero                     : Qt.QPushButton            #  M3      '挂钩电机清零　　'
        # Button_ForceQuit                         : Qt.QPushButton            #  M59     '设置强制退出功能'
        # Button_PickTray                          : Qt.QPushButton            #  M60     '片仓取出托盘功能'
        # Button_DropTray                          : Qt.QPushButton            #  M61     '托盘放回片仓功能'
        # Button_Detector                          : Qt.QPushButton            #  M62     '检测指定托盘功能'
        # Button_DetectorChamber                   : Qt.QPushButton            #  M63     '检测片仓托盘功能'
        # Button_ScanCodePick                      : Qt.QPushButton            #  M64     '扫码托片功能　　'
        # Button_EmptyTrayReturn                   : Qt.QPushButton            #  M65     '空挂返回功能　　'
        # Button_Forward                           : Qt.QPushButton            #  M72     '挂钩电机前进功能'
        # Button_Backward                          : Qt.QPushButton            #  M73     '挂钩电机后退功能'
        # Button_ScanCodeCompleteMove              : Qt.QPushButton            #  M81     '扫码完成前进功能'
        # Button_HookReset                         : Qt.QPushButton            #  M423    '挂钩电机复位功能'

        self.Hook.Button_HookClearZero        .clicked.connect(slot=self.SlotButton_HookClearZero                , type=TYPE)
        self.Hook.Button_ForceQuit            .clicked.connect(slot=self.SlotButton_ForceQuit                    , type=TYPE)
        self.Hook.Button_PickTray             .clicked.connect(slot=self.SlotButton_PickTray                     , type=TYPE)
        self.Hook.Button_DropTray             .clicked.connect(slot=self.SlotButton_DropTray                     , type=TYPE)
        self.Hook.Button_Detector             .clicked.connect(slot=self.SlotButton_Detector                     , type=TYPE)
        self.Hook.Button_DetectorChamber      .clicked.connect(slot=self.SlotButton_DetectorChamber              , type=TYPE)
        self.Hook.Button_ScanCodePick         .clicked.connect(slot=self.SlotButton_ScanCodePick                 , type=TYPE)
        self.Hook.Button_EmptyTrayReturn      .clicked.connect(slot=self.SlotButton_EmptyTrayReturn              , type=TYPE)
        self.Hook.Button_Forward              .clicked.connect(slot=self.SlotButton_Forward                      , type=TYPE)
        self.Hook.Button_Backward             .clicked.connect(slot=self.SlotButton_Backward                     , type=TYPE)
        self.Hook.Button_ScanCodeCompleteMove .clicked.connect(slot=self.SlotButton_ScanCodeCompleteMove         , type=TYPE)
        self.Hook.Button_HookReset            .clicked.connect(slot=self.SlotButton_HookReset                    , type=TYPE)

        self.Hook.Read_Position                   .clicked.connect(slot=self.SlotRead_Position                   , type=TYPE)
        self.Hook.Read_Velocity                   .clicked.connect(slot=self.SlotRead_Velocity                   , type=TYPE)
        self.Hook.Read_SetLayerHoverHeight        .clicked.connect(slot=self.SlotRead_SetLayerHoverHeight        , type=TYPE)
        self.Hook.Read_SetLayerDragHoverHeight    .clicked.connect(slot=self.SlotRead_SetLayerDragHoverHeight    , type=TYPE)
        self.Hook.Read_SetLayerSpacingHeight      .clicked.connect(slot=self.SlotRead_SetLayerSpacingHeight      , type=TYPE)
        self.Hook.Read_SetAxisXPickPosition       .clicked.connect(slot=self.SlotRead_SetAxisXPickPosition       , type=TYPE)
        self.Hook.Read_SetAxisYPickPosition       .clicked.connect(slot=self.SlotRead_SetAxisYPickPosition       , type=TYPE)
        self.Hook.Read_SetScanCodePosition        .clicked.connect(slot=self.SlotRead_SetScanCodePosition        , type=TYPE)
        self.Hook.Read_SetScanCodeSpacing         .clicked.connect(slot=self.SlotRead_SetScanCodeSpacing         , type=TYPE)
        self.Hook.Read_SetAxisXDetectorPosition   .clicked.connect(slot=self.SlotRead_SetAxisXDetectorPosition   , type=TYPE)
        self.Hook.Read_SetAxisYDetectorPosition   .clicked.connect(slot=self.SlotRead_SetAxisYDetectorPosition   , type=TYPE)
        self.Hook.Read_SetLayerCount              .clicked.connect(slot=self.SlotRead_SetLayerCount              , type=TYPE)
        self.Hook.Read_SetDetectorLayerPosition   .clicked.connect(slot=self.SlotRead_SetDetectorLayerPosition   , type=TYPE)

        self.Hook.Send_Position                   .clicked.connect(slot=self.SlotSend_Position                    , type=TYPE)
        self.Hook.Send_Velocity                   .clicked.connect(slot=self.SlotSend_Velocity                    , type=TYPE)
        self.Hook.Send_SetLayerHoverHeight        .clicked.connect(slot=self.SlotSend_SetLayerHoverHeight         , type=TYPE)
        self.Hook.Send_SetLayerDragHoverHeight    .clicked.connect(slot=self.SlotSend_SetLayerDragHoverHeight     , type=TYPE)
        self.Hook.Send_SetLayerSpacingHeight      .clicked.connect(slot=self.SlotSend_SetLayerSpacingHeight       , type=TYPE)
        self.Hook.Send_SetAxisXPickPosition       .clicked.connect(slot=self.SlotSend_SetAxisXPickPosition        , type=TYPE)
        self.Hook.Send_SetAxisYPickPosition       .clicked.connect(slot=self.SlotSend_SetAxisYPickPosition        , type=TYPE)
        self.Hook.Send_SetScanCodePosition        .clicked.connect(slot=self.SlotSend_SetScanCodePosition         , type=TYPE)
        self.Hook.Send_SetScanCodeSpacing         .clicked.connect(slot=self.SlotSend_SetScanCodeSpacing          , type=TYPE)
        self.Hook.Send_SetAxisXDetectorPosition   .clicked.connect(slot=self.SlotSend_SetAxisXDetectorPosition    , type=TYPE)
        self.Hook.Send_SetAxisYDetectorPosition   .clicked.connect(slot=self.SlotSend_SetAxisYDetectorPosition    , type=TYPE)
        self.Hook.Send_SetLayerCount              .clicked.connect(slot=self.SlotSend_SetLayerCount               , type=TYPE)
        self.Hook.Send_SetDetectorLayerPosition   .clicked.connect(slot=self.SlotSend_SetDetectorLayerPosition    , type=TYPE)
        self.Hook.StatusButton                    .clicked.connect(slot=self.SlotStatusButton                     , type=TYPE)
        self.Hook.ChamberStatusButton             .clicked.connect(slot=self.SlotChamberStatusButton              , type=TYPE)

    def SlotButton_HookClearZero                (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        self.axis_h.get_h_position()

    def SlotButton_ForceQuit                    (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return

        self.axis_h.set_h_force_quit()


    def SlotButton_PickTray                     (self):
        """取N号托盘"""
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        chamber_number: int = self.Hook.chamber_number
        self.axis_h.wait_pick_tray(chamber_number)


    def SlotButton_DropTray                     (self):
        """放N号托盘"""
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        chamber_number: int = self.Hook.chamber_number
        self.axis_h.wait_drop_tray(chamber_number)

    def SlotButton_Detector                     (self):
        """检测N号托盘"""
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        chamber_number: int = self.Hook.chamber_number
        self.axis_h.wait_check_tray(chamber_number)
        self.SlotChamberStatusButton()

    def SlotButton_DetectorChamber              (self):
        """检测片仓"""
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        chamber_number: int = self.Hook.chamber_number
        self.axis_h.wait_check_chamber(chamber_number)
        self.SlotChamberStatusButton()

    def SlotButton_ScanCodePick                 (self):
        """取片并移动到扫码位置"""
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        chamber_number: int = self.Hook.chamber_number
        self.axis_h.waitmove_scan_code_position(chamber_number)

    def SlotButton_EmptyTrayReturn              (self):
        """空钩返回"""
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return

        self.axis_h.wait_empty_hook_return()

    def SlotButton_Forward                      (self):
        """挂钩前进开关"""
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        enable: bool = self.axis_h.get_forward_status()
        self.axis_h.forward(not enable)

    def SlotButton_Backward                     (self):
        """挂钩后退开关"""
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        enable: bool = self.axis_h.get_backward_status()
        self.axis_h.forward(not enable)

    def SlotButton_ScanCodeCompleteMove         (self):
        """扫码完成继续前进"""
        if not self.isAvailable():
            return
        if not self.hasAxisH or not self.hasScanCode:
            return
        self.scancode.StartScanningCode()
        code: str = self.scancode.ReadScanningCode()
        print(code)
        self.axis_h.waitmove_scan_code_complete()

    def SlotButton_HookReset                    (self):
        """挂钩重置"""
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        self.axis_h.Reset(True)


    def SlotYPlusButton        (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_y.rel_waitmove(step)

    def SlotYMinusButton       (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_y.rel_waitmove(-step)

    def SlotXPlusButton        (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_x.rel_waitmove(step)

    def SlotXMinusButton       (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_x.rel_waitmove(-step)

    def SlotZPlusButton        (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_z.rel_waitmove(step)

    def SlotZMinusButton       (self):
        if not self.isAvailable():
            return
        step: float = abs(self.Controller.get_step())
        self.axis_z.rel_waitmove(-step)

    def SlotMicPlusButton      (self):
        if not self.isAvailable():
            return
        if not self.hasMicroscope:
            return

    def SlotMicMinusButton     (self):
        if not self.isAvailable():
            return
        if not self.hasMicroscope:
            return

    def SlotHPlusButton        (self):
        if not self.isAvailable():
            return

    def SlotHMinusButton       (self):
        if not self.isAvailable():
            return

    def SlotScanCodeButton     (self):
        if not self.isAvailable():
            return

    def SlotCodeCompleteButton (self):
        if not self.isAvailable():
            return

    def SlotCameraSwitch       (self):
        if not self.isAvailable():
            return
        self.initCameraTimer()
        if self.CameraTimer.isActive():
            self.CameraTimer.stop()
            if self.hasCamera:
                self.camera.StopGrabbing()
            self.CameraView.SlotClearImageListSignal()
            return
        if not self.hasCamera:
            self.business.devices.initCamera()
        if not self.hasCamera:
            return
        level: int = self.Controller.ObjectiveEdit.value()
        if not self.camera.IsOpen:
            self.camera.ReOpen(level)
        if not self.camera.IsOpen:
            return
        self.camera.setModel(level)
        self.camera.StartGrabbing()
        if self.camera.IsGrabbing:
            self.CameraTimer.start(200)

    def SlotCameraTimer(self):
        if not self.hasCamera:
            return
        image: np.ndarray = self.camera.GetNumpyData()
        if image is None:
            return
        img  : Qt.QImage = ImageUtils.cv2_to_QImage(image)
        if img is None or img.isNull():
            return
        self.CameraView.CameraUiSignal.emit(img, '')


    def SlotCameraButton       (self):
        if not self.isAvailable():
            return

    def SlotDebugButton        (self):
        if not self.isAvailable():
            return

    def SlotInitXYButton          (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return
        self.manipulator.waithome_xy()

    def SlotInitZButton           (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return
        self.manipulator.waithome_z()

    def SlotInitHButton           (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return
        if not self.axis_h.isAvailable:
            self.manipulator.initManager()

    def SlotInitMicButton         (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return
        self.microscope.waithome()

    def SlotInitCodeButton        (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return
        self.scancode.waithome()

    def SlotInitCameraButton      (self):
        if not self.isAvailable:
            return
        if not self.hasManipulator:
            return

        self.camera.waithome()


    def SlotObjectiveEdit(self):
        if not self.isAvailable():
            return
        if not self.hasMicroscope:
            return
        if not self.microscope.isAvailable:
            self.microscope.ReOpen()
        if self.microscope.isAvailable:
            objective: int = self.Controller.get_objective_value()
            self.microscope.set_objective(objective)

    def SlotRead_Position                   (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.getPosition()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_Position.setValue(float(position))

    def SlotRead_Velocity                   (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.getVelocity()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_Velocity.setValue(float(position))

    def SlotRead_SetLayerHoverHeight        (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_layer_hover_height()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_SetLayerHoverHeight.setValue(float(position))

    def SlotRead_SetLayerDragHoverHeight    (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_layer_hover_height()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_SetLayerHoverHeight.setValue(float(position))

    def SlotRead_SetLayerSpacingHeight      (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_layer_spacing_height()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_SetLayerSpacingHeight.setValue(float(position))

    def SlotRead_SetAxisXPickPosition       (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_layer_axis_x_position()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_SetAxisXPickPosition.setValue(float(position))

    def SlotRead_SetAxisYPickPosition       (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_layer_axis_y_position()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_SetAxisYPickPosition.setValue(float(position))

    def SlotRead_SetScanCodePosition        (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_layer_scancode_position()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_SetScanCodePosition.setValue(float(position))

    def SlotRead_SetScanCodeSpacing         (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_layer_scancode_spacing()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_SetScanCodeSpacing.setValue(float(position))

    def SlotRead_SetAxisXDetectorPosition   (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_layer_axis_x_detector_position()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_SetAxisXDetectorPosition.setValue(float(position))

    def SlotRead_SetAxisYDetectorPosition   (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_layer_axis_y_detector_position()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_SetAxisYDetectorPosition.setValue(float(position))

    def SlotRead_SetLayerCount              (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_layer_index()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_SetLayerCount.setValue(float(position))

    def SlotRead_SetDetectorLayerPosition   (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_layer_detector_position()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_SetDetectorLayerPosition.setValue(float(position))

    def SlotSend_Position                    (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_h_position()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_Position.setValue(float(position))

    def SlotSend_Velocity                    (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        isWrong, position = self.axis_h.get_h_speed()
        if RECODE_SUCCEED == isWrong and isinstance(position, (int, float)):
            self.Hook.Edit_Velocity.setValue(float(position))

    def SlotSend_SetLayerHoverHeight         (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return

        value: float = self.Hook.Edit_SetLayerHoverHeight.value()
        self.axis_h.set_layer_hover_height(value)

    def SlotSend_SetLayerDragHoverHeight     (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        value: float = self.Hook.Edit_SetLayerDragHoverHeight.value()
        self.axis_h.set_layer_drag_height(value)


    def SlotSend_SetLayerSpacingHeight       (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return

        value: float = self.Hook.Edit_SetLayerSpacingHeight.value()
        self.axis_h.set_layer_spacing_height(value)

    def SlotSend_SetAxisXPickPosition        (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        value: float = self.Hook.Edit_SetAxisXPickPosition.value()
        self.axis_h.set_layer_axis_x_position(value)

    def SlotSend_SetAxisYPickPosition        (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        value: float = self.Hook.Edit_SetAxisYPickPosition.value()
        self.axis_h.set_layer_axis_y_position(value)

    def SlotSend_SetScanCodePosition         (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        value: float = self.Hook.Edit_SetScanCodePosition.value()
        self.axis_h.set_layer_scancode_position(value)

    def SlotSend_SetScanCodeSpacing          (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        value: float = self.Hook.Edit_SetScanCodeSpacing.value()
        self.axis_h.set_layer_scancode_spacing(value)

    def SlotSend_SetAxisXDetectorPosition    (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        value: float = self.Hook.Edit_SetAxisXDetectorPosition.value()
        self.axis_h.set_layer_axis_x_detector_position(value)

    def SlotSend_SetAxisYDetectorPosition    (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        value: float = self.Hook.Edit_SetAxisYDetectorPosition .value()
        self.axis_h.set_layer_axis_y_detector_position(value)

    def SlotSend_SetLayerCount               (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        value: int = self.Hook.Edit_SetLayerCount.value()
        self.axis_h.set_layer_index(value)


    def SlotSend_SetDetectorLayerPosition    (self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        value: float = self.Hook.Edit_SetDetectorLayerPosition.value()
        self.axis_h.set_layer_detector_position(value)

    def SlotChamberStatusButton(self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        status: list = self.axis_h.get_layer_status()
        self.Hook.setChamberStatus(status)

    def SlotStatusButton(self):
        if not self.isAvailable():
            return
        if not self.hasAxisH:
            return
        index: int = self.Hook.StatusEdit.currentIndex()
        status: bool = False
        isWrong: int = RECODE_FAILURE
        """
        0   FrontLimit                          : ModBusRegister            #  M14     '挂钩前面限位　　'
        1   BackLimit                           : ModBusRegister            #  M15     '挂钩后面限位　　'
        2   PlaceRegister                       : ModBusRegister            #  M16     '托盘到位状态　　'
        3   DetectorRegister                    : ModBusRegister            #  M17     '检测托盘状态　　'
        4   PickTrayCompleteRegister            : ModBusRegister            #  M44     '取片完成状态　　'
        5   DropTrayCompleteRegister            : ModBusRegister            #  M45     '放片完成状态　　'
        6   DetectorTrayCompleteRegister        : ModBusRegister            #  M46     '检测托盘完成状态'
        7   DetectorChamberCompleteRegister     : ModBusRegister            #  M47     '扫描片仓完成状态'
        8   ScanCodePickTrayCompleteRegister    : ModBusRegister            #  M48     '扫码取片到位状态'
        9   EmptyTrayReturnStatusRegister       : ModBusRegister            #  M50     '空挂退出完成状态'
        10  ForwardMalfunction                  : ModBusRegister            #  M406    '挂钩前进故障状态'
        11  BackwardMalfunction                 : ModBusRegister            #  M407    '挂钩后退故障状态'
        
        """
        if index == 0:
             status = self.axis_h.get_lower_limit_status()
        elif index == 1:
             status = self.axis_h.get_upper_limit_status()
        elif index == 2:
             status = self.axis_h.get_place_status()
        elif index == 3:
             status = self.axis_h.get_detector_status()
        elif index == 4:
             status = self.axis_h.get_pick_tray_status()
        elif index == 5:
             status = self.axis_h.get_drop_tray_status()
        elif index == 6:
             status = self.axis_h.get_tray_detector_status()
        elif index == 7:
             status = self.axis_h.get_chamber_detector_status()
        elif index == 8:
             status = self.axis_h.get_pick_scan_code_status()
        elif index == 9:
             status = self.axis_h.get_empty_tray_return_status()
        elif index == 10:
             status = self.axis_h.get_forward_warning_status()
        elif index == 11:
             status = self.axis_h.get_backward_warning_status()
        self.Hook.setStatus(status)


    def initLayouts(self):
        super(ManipulatorFrame, self).initLayouts()
        if not self.hasControl or self.layout() is not None:
            return
        main_layout: Qt.QGridLayout = Qt.QGridLayout()
        main_layout.setSpacing(5)  # 设置布局间距
        main_layout.setContentsMargins(1, 1, 1, 1)
        h_layout: Qt.QHBoxLayout = Qt.QHBoxLayout()
        h_layout.setSpacing(5)  # 设置布局间距
        h_layout.setContentsMargins(1, 1, 1, 1)


        h_layout.addWidget(self.Controller                      )
        h_layout.addWidget(self.CameraView                      )
        main_layout.addLayout(h_layout      , 0, 0, 1   , -1)
        main_layout.addWidget(self.Hook     , 1, 0 , -1 , -1)


        # 设置主布局
        self.setLayout(main_layout)



    def initController (self):
        if not self.hasController:
            self.Controller = ManipulatorController(self)

    def initHook(self):
        if not self.hasHook:
            self.Hook = HookController(self)

    def initCamera(self):
        if not self.hasCameraView:
            self.CameraView = CameraController(self)

    def initCameraTimer(self):
        if not self.hasCameraTimer:
            self.CameraTimer = Qt.QTimer(self)
            self.CameraTimer.timeout.connect(slot=self.SlotCameraTimer, type=Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection))

    @property
    def hasController (self) -> bool:
        return hasattr(self, 'Controller'   ) and isinstance(self.Controller , ManipulatorController)

    @property
    def hasHook(self) -> bool:
        return hasattr(self, 'Hook') and isinstance(self.Hook, HookController)

    @property
    def hasCameraView(self) -> bool:
        return hasattr(self, 'CameraView') and isinstance(self.CameraView, CameraController)

    @property
    def hasCameraTimer(self) -> bool:
        return hasattr(self, 'CameraTimer') and isinstance(self.CameraTimer, Qt.QTimer)

