#ifndef MACHINE_H
#define MACHINE_H

#define BN_PROTOCOL_HEAD		0x05	// 机头板通讯协议（N5，N5A）
#define BN_PROTOCOL_HCPS		0x06	// 勾剪扣换等（N6，N6A）
#define BN_PROTOCOL_DCUT		0x10	// 剪线控制协议(D86)


#include "tcpclient.h"
#include "comport.h"

#include <QThread>
#include <QTimer>
#include <QDebug>

#include "comm/datadef.h"
#include "comm/protocol.h"

#define USE_TCP_COMM    0
#define USE_SERIAL_COMM 1

class Machine: public QObject
{
    Q_OBJECT

public:
    explicit Machine(QObject *parent = NULL);
    virtual ~Machine();

public:
    void initConnectMode(s16 val = 0);//初始化通讯连接方式
    void setConfigFileName(QString configfilename);
    void setComportName(QString portName);//设置串口名称
    QString getConfigFileName();
    int startCommunication();

private:
    QString m_configFileName;

private:
    s16 m_connectMode;  //通讯连接方式 0:网口，1:串口
    // 通讯线程和网络连接
    QThread * m_pTcpThread;
    TcpClient * m_pTcpClient;
    QThread * m_pComThread;
    ComPort * m_pComPort;

    // 连接
public:
    inline int isConnected() const  {  return m_connected; }

private:
    int m_startComm;
    int m_connected;        // 机器连接状态. 0, 未连接; 1, 连接中; 2,

signals:            // 发送数据到机器的信号
    void siSendData(QByteArray dat);
    void siSendDataDone();

private slots:      // 和线程通讯的槽
    void slotConnectSta(int sta);           // 连接状态改变的槽函数
    void slotConnectErr(QString errinfo);   // 接收到通讯错误槽函数
    void slotReceiveData(QByteArray dat);   // 接收到数据的槽函数

//----------------------------------------
// 通讯命令

    // 机器信息
public:
private:

    // 机器状态
public:
    inline int isStatusEn() const   {   return m_statusEn;  }
    inline const MCStatus & getMcStatus() {m_statusEn = 0;   return m_mcStatus;  }
    void setMcStatusAsMc(u8 * buff, u16 len, int toggle);

    //机器信息
    inline const MCInfo &getMcInfo(){return m_mcInfo;}
    //调试信息
    inline const DebugInfo &getDebugInfo(){return m_debugInfo;}
    //外围板版本信息
    inline const ExBoardInfo &getEXBInfo(){return m_exboardInfo;}
    //物联数据
    inline const McLotData &getMcLotData(){return m_lotData;}
    //文件头
    inline const DataDs16FileHead &getFileInfo(){return m_ds16Head;}

private:
    int m_statusEn;         // 状态有效标志
    int m_statusToggle;
    MCStatus m_mcStatus;      // 机器状态
    MCInfo m_mcInfo;   // 机器信息
    DebugInfo m_debugInfo;//调试信息
    ExBoardInfo m_exboardInfo;      // 外围板信息
    McLotData m_lotData;  // 物联数据
    DataDs16FileHead m_ds16Head;    //文件头

    // 机器参数
public:
    inline const ParaStruct & getMcPara() {/*m_mcParaEn = 0; */  return m_mcPara;  }
    inline const ParaStruct & getWkPara() {/*m_wkParaEn = 0; */  return m_wkPara;  }
    inline const ParaStruct & getPreMcPara() {/*m_mcParaEn = 0; */  return m_mcPrePara;  }
    inline const ParaStruct & getPreWkPara() {/*m_wkParaEn = 0; */  return m_wkPrePara;  }
    inline const EmbMvAng & getFrameAnglePara() {/*m_wkParaEn = 0; */  return m_frameAnglePara;  }

    //获取索引外围板的参数，目前读取的是第一块的(所有外围板参数都和第一块的相同)
    //inline const HeadInfo & getHeadPara(int idx = 0) {/*m_mcParaEn = 0; */  return m_exboardInfo.headInfo[idx];  }
    inline const HcpsInfo & getHcpsPara(int idx) {/*m_wkParaEn = 0; */  return m_exboardInfo.hcpsInfo[idx];  }//毛巾的idx是1，平绣是0

private:
    ParaStruct m_mcPara;    // 机器参数信息 配置信息
    ParaStruct m_wkPara;    // 工作参数信息
    ParaStruct m_mcPrePara;    // 机器预留参数
    ParaStruct m_wkPrePara;    // 工作预留参数
    EmbMvAng m_frameAnglePara;    // 动框角度参数
    int m_mcParaEn;
    int m_wkParaEn;
    int m_mcPreParaEn;
    int m_wkPreParaEn;
    int m_frameAngleParaEn;

public:
    inline int isSensorBmpEn() const   {   return m_sensorBmpEn;  }
    inline const SensorsBitmap & getSensorDat() {/* m_sensorStaEn = 0; */  return m_sensorsStaDat;  }
    inline const SensorsBitmap & getSensorBmp() {/* m_sensorBmpEn = 0; */  return m_sensorEnBmp;    }
    inline int getTotalSendNum() { return m_totalSendNum; }
    inline int getTotalPacketNum() { return m_totalPacketNum; }

private:
    SensorsBitmap m_sensorsStaDat;    // 传感器信号状态位图
    SensorsBitmap m_sensorEnBmp;      // 传感器信号有效位图
    int m_sensorStaEn;
    int m_sensorBmpEn;

public:
    void setTcpConnectState(int state);
    void setMacKey(unsigned char * p_dat ,  int i_size);              // 设置机器的密钥
    HeadInfo*  getHeadPara(int idx ,int nTpye);//得到毛巾和平绣的机头板参数 -rq
    // 文件传输结果
public:

private:
    QTimer * m_pSendTimer;
    FileTransCtrl m_transCtrl;
    int m_fileTransEn;
    int m_transBreak;
    int m_totalSendNum;//传输文件时总共发送的包数
    int m_totalPacketNum;//传输文件时总的包数

private slots:
    void onSendTimer(void);
    void slIfOpenSerialPort(int val);//串口是否打开

signals:            // 发送给UI的信号
    void siMcInfoChange();                      // 机器信息改变信号
    void siDebugInfo();                            //调试信息改变信号
    void siReceiveLotData();                    // 接收物联数据信号
    void siEXBInfoChange();                      // 外围板版本信息改变信号
    void siStatusChange(int);                   // 状态改变信号
    void siParaChange(int type, int id);        // 参数更新信号
    void siEXBParaChange();        // 机头板参数更新信号
    void siMemDataChange(int beginAddr);        // 内存数据更新信号
    void siSensorChange(SensorsBitmap map);                      // 传感信号更新信号
    void siFileInfoChange();                    // 文件信息更新信号
    void siTransResultChange();                 // 文件传输结果信号
    void siTransProgress(u8 fileType, int send, int total);  // 文件传输结果信号
    void siSensorEnBitmap(SensorsBitmap map);                    // 传感信号有效位图更新信号
    void siDataFilePos(DataFilePos pos);     //  边框检查时起绣点超出范围后下位机自动定新的起绣点后发给上位机

public slots:
    void breakFileTrans();      // 打断文件传输

public: // 机器执行命令，读取下位机数据
    void getInfoFromMachine();
    void getFileInfoFromMachine();//读取文件信息
    void getExboardInfoFromMachine();
    int  getStatusFromMachine();
    void getNetDataFromMachine();     // 读取机器物联数据
    void getParasFromMachine(int type = -1, int id = 0);     // 读取机器参数
    void getHeadParasFromMachine(int id ,int nodeType);     // 读取机头板参数
    void getHcpsParasFromMachine(int nodeType = 0);     // 读取换色板参数
    void restoreFactorySetting(int type = -1); // 恢复出厂设置
    void getSensorsFromMachine(int backtype = 0);
    void getTransResultFromMachine(int fileid);
    void getSensorEnBmpFromMachine();    // 获取传感器有效标志位图
    void sleep(int sec);
    //void getHeadPara();

public:     // 设置机器配置
// #define	UCMD_SET_MC_CONFIG		0x0101	VLDP	无		设置机器的配置，包括信号使用的端口等信息

public:    // 设置机器状态
    void setMcStatus(int stacode, int para = 0);
    void cleanError();                  // 清除错误    
    void setEnableWorkSta();            // 设置允许工作状态
    void setDisableWorkSta();           // 设置禁止工作状态
    void setEnableWorkTime();           // 设置允许工作时间状态
    void setDisableWorkTime();          // 设置禁止工作时间状态
    void resetOutput();                 // 重置产量
    void setToManualWork();             // 手动工作状态
    void setToAutoWork();               // 自动工作状态
    void switchWorkFile(int idx = 0);   // 文件切换
    void invalidateWorkFile(int idx = 0);	// 文件失效
    void cleanNewParaFlag();            // 清除新参数标志
    void setSimulateWork();             // 模拟工作状态
    void setNormalWork();               // 正常工作状态
    void exitTraverStates();            //退出遍历状态
    void exitDetectTest();               //退出断线测试
    void resetBobbinCounter();          // 底线计数复位
    void entrySensorScan();         	// 进入扫描传感器状态
    void exitSensorScan();          	// 退出扫描传感器状态
    void setElapsed(unsigned char i_type ,  unsigned char  i_time);    // 设置经过的时间
    void testThreadBK(int type,int needle,int headType); // 测试断线检测,1是面线，2是底线   //headType   1是平绣  4是缠绕
    void lockTest(int type,int para); // 测试锁头

public:    // 设置机器参数
    void setParasToMachine(int type, ParaStruct & para);
    void setFrameAngleParasToMachine(int type, EmbMvAng & para);
    void setAParasToMachine(int type, int idx, u32 value);
    void setEXBHeadParasToMachine(HeadInfo & para,int id = 0);//设置机头板板参数
    void setEXBHcpsParasToMachine(HcpsInfo & para ,int idx);//设置换色板参数
    void setHeadPatchParasToMachine(int type, ParaStruct & para, u16 packID);
    void setTowelHighParasToMachine(int type, ParaStruct & para, u16 packID);
    void setShutDownTime(u8 type, u32 time);

    void setMcPara(ParaStruct * pPara);
    void setWkPara(ParaStruct * pPara);
    void setMcPrePara(ParaStruct * pPara);//预留参数
    void setWkPrePara(ParaStruct * pPara);//预留参数
    void setFrameAnglePara(EmbMvAng * pPara);//动框角度参数设置
    void setAMcPara(int id, u32 value);
    void setAWkPara(int id, u32 value);
    void setAMcPrePara(int id, u32 value);//预留参数
    void setAWkPrePara(int id, u32 value);//预留参数
    void setHeadBoardPara(HeadInfo * pPara, int id = 0);//设置机头板参数
    void setHcpsBoardPara(HcpsInfo * pPara, int idx = 0);//设置换色板参数

    void setHeadPara(ParaStruct * pPara,u16 ID);//设置机头参数
    void setPatchColorPara(ParaStruct * pPara);
    void setPatchNeedlePara(ParaStruct * pPara);
    void setTowelHeightPara(ParaStruct * pPara);//设置毛巾高度

public:    // 设置内存数据
// #define	UCMD_SET_MEM_DATA		0x0104		// 设置内存数据

public:    // 设置文件参数
    void setFilePara(int fileidx, int fileid, DataFilePara & filePara);

public:    // 设置执行进度
    void setFileExecProgress(int fileidx, int fileid, FileExecPara & fileExecPara);
    void setToDefaultParas(int type, u8 id = 0, u8 nodeType = 0);

public slots:    // 手动控制命令
    void actionByhand(int actcode, int para1, int para2 = 0, int para3 = 0);
    void motoToZero(int obj);                       // 电机归零（辅助调试的功能，无安全保护和逻辑关系）
    void motoMove(int obj, int dir, int spd);       // 电机移动（辅助调试的功能，无安全保护和逻辑关系）
    void outputCtrl(int obj, int act, int para);    // 输出控制（辅助调试的功能，无安全保护和逻辑关系）
    void motoServoCtrl(int obj, int onoff);         // 电机使能控制（辅助调试的功能，无安全保护和逻辑关系）

    void embMsServoOn();
    void embMsServoOff();       // 平绣主轴使能控制

    void towelMsServoOn();
    void towelMsServoOff();       // 毛巾主轴使能控制

    void towelMMsServoOn();
    void towelMMsServoOff();       // 毛巾M轴使能控制

    void towelRMMsServoOn();
    void towelRMMsServoOff();       // 毛巾打环轴使能控制

    void coilMsServoOn();
    void coilMsServoOff();       // 缠绕主轴使能控制

    void coilMMsServoOn();
    void coilMMsServoOff();       // 缠绕M轴使能控制

    void manualAction(int obj, int para2 = 0, int para3 = 0);  // 手动动作功能（日常使用功能，有安全保护和逻辑时序关系）

    void setWorkRange();        // 定工作范围
    void manualOil(int nNum);  // 手动加油
    void resetRepeatNum();// 重置反复次数

    void shuttleCounter();//自动换梭
    void changeOneShuttle();//自动换一个梭

    void looseOnOff();                          // 松紧线

    void quantityMoveFrame(s32 x,s32 y); // 定量移框
    void moveFrameByHand(char xy, char dir, int spd); // 手动移框

    void embJog();                              // 平绣点动
    void testLockMoto(int para); //平绣锁头电机测试
    void chenilleJog();                        //毛巾点动
    void hoistCtrl(int gearValue);      //提升电机控制
    void elasticCtrl(int posValue);      //松紧线控制
    void testADC(int para ,int headNum = 0);       //测试电位器
    void embSwitchNeedle(int nNum);             // 平绣换色
    void chenilleSwitchNeedle(int nNum);      //毛巾换色
    void chenilleColorDebug(int nNum);//毛巾换色调试
    void sequinSwitchNeedle(int nNum, s16 sq);             // 亮片换色
    void embSpindleTest(s32 para1, s32 para2);                        // 平绣主轴研车
    void embCutThread();                        // 平绣剪线
    void chenilleCutThread();                        //毛巾剪线
    void headSwitch(int para);            //机头切换,para是切换的机头
    //进入或退出状态(遍历设置、断线检测、退出勾刀测试)
    void enterOrExitStates(int obj, int para1 = 0, int para2 = 0, int para3 = 0, int para4 = 0);

public:    // 机器工作命令
    void mcWorkCmd(int workcode, int para1 = 0 , int para2 = 0);

    void startWork();       // 启动工作
    void pauseWork();       // 暂停工作
    void allToReset();      // 流程复位
    void allToZero();       // 全部归零

    void gotoStartPos();    // 回起针点
    void setOffsetPos();     // 定偏移点
    void gotoOffsetPos();   // 回偏移点
    void setFeedPos();     // 定上料点
    void gotoFeedPos();     // 回上料点

    void checkFrame();      // 边框检查
    void simulateFrame();   // 空走边框
    void enterClothEmbroidery();//进入匹绣
    void exitClothEmbroidery();//退出匹绣
    void autoSetSoftLimit();//自动定软限位
    void embSpindleTest();//平绣主轴齿轮比测试
    void chenSpindleTest();//毛巾主轴齿轮比测试
    void ecdWidthTest();//测试平绣主轴编码器宽度
    void footTest(); // 独立压脚测试
    void headBoardBusDetect();//机头板总线检测
    void traceOffset();//线迹偏移
    void resetTraceOffset();//线迹偏移数据复位
    void clearCurTraceOffset();//清除当前索引的线迹偏移数据
    // 边框切割
    // 手动断布

    void fastJump(int idx); // 前进回退
    void gotoWorkPos();     // 回工作点
    void gotoFixPos();      // 回穿线点

    // 回换梭位
    // 进料退料
    // 画格子图
    // 回结束点

    void gotoZeroPos();     // 回零点
    void msRpmChange(int chgram,int flag);     // 速度改变
    void mainShaftJog();// 主轴点动

public:    // 移动到XY坐标命令
    void moveFrameTo(int x, int y);

public:     // 文件传输命令
    int sendFileProc(int type, int idx, int id, DataDs16FileHead * pfileHead, u8 * pDatBuff);
    int sendFileProc(int type, int idx, int id, DataDs16FileHead & fileHead, u8 * pDatBuff);
    int dySendFileProc(int type, int idx, int id, DataDs16FileHead * pfileHead, u8 * pDatBuff);    //动态传输文件
    int sendAPPFileProc(int type, int idx, int id, AppFileHead &fileHead, u8 *pDatBuff);
    int sendBoardFileProc(int type, int idx, int id, BoardFileHead &fileHead, u8 *pDatBuff);

private:
    void startFileTrans(FileTransCtrl & transCtrl);
    void startFileDyTrans(FileTransCtrl & transCtrl);//开始动态传输文件
    void transFileData(FileTransCtrl & transCtrl, int pktidx);

public:    // 下位机系统升级命令
    void updateFirmware();    // 下位机升级
    void updateExBoard(u8 protocolType, u8 nodeId, u8 nodeType);    // 外围板升级
};

#endif // MACHINE_H

