#pragma once #ifndef _INCLUDE_COREWORK_MANAGE_H #define _INCLUDE_COREWORK_MANAGE_H #include "sysapi.h" #include #include #include #include #include "corework.h" #include "simtest.h" #include "vision.h" #include "ipvar.h" using std::list; using std::vector; using std::string; using std::hash_map; #define VACMCNT 4 //吸嘴数量 #define TESTCNT 6 //治具数量 #define MINAEND 3 //最小A组分界值 #define STOCKCNT 5 //料仓数量 #define VERSION 2135 //版本号 #define CFG_KEY "work" #define ins CManage::Get_Instance() //#define REPORT(msg, ...) ins->Report(msg, __VA_ARGS__) #define REPORT(msg, ...) post_message(MSG_ASCII, msg, __VA_ARGS__) #define SPLIT "#" //分隔符 #define REG "Register" //客户端往服务器注册 #define STATUS "Status" //查询客户端状态 #define START "StartTest" //通知治具启动测试 #define RES "Result" //查询测试结果信息 #define ERR "ErrorCode" //查询报警代码+描述 #define GRIP "Grip" //通知治具打开夹爪 #define PAUSE "Pause" //通知治具暂停 #define GR "GR" //视觉处理请求 #define HOME "Home" //通知治具回原 #define RESET "Reset" //通知治具重置 #define RIO "ReadIO" //读取IO #define WIO "WriteIO" //写入IO #define VLOG "Vlog" //上传日志 #define HOMECT 60000 //测试治具回原时间 #define TAKECT 5000 //取放单颗料预估时间 #define VPORT 6051 //视觉服务器起始端口 #define VPORTEST 6081 //测试侧相机服务端口 cstr GetTestMode(cstr p); enum VisionSence {//视觉客户端类型 EVInput = 0, //M1 取料盘拍照 EVHamal, //M2 搬运相机拍照 EVOkTray, //M3 ok仓拍照 EVNGTray, //M4 NG仓拍照 EVNGTakeOne, //M5 NG取一拍一 EVNGPutOne, //M6 NG放一拍一 EVTestTake, //M7 标定块场景 EVTestPut, //M8 治具放 EVSize, //客户端总数量 }; struct MachineInfo {//治具结构 TestMachine data; //治具数据 int index; //治具索引 uint start; //开始测试时间 int lastct; //最后一次CT uint qstatus; //查询状态时间 }; struct TPosxy {//取料放料拍照 char sn[MAX_NAME_LEN]; double x; double y; int index; TPosxy() { memset(this, 0, sizeof(TPosxy)); } }; struct TGRMsg {//转发给治具的消息 int tindex; char* s; }; class CProduct { public: CProduct(int sindex = LocationInput); int _t1; //第一次治具序号 int _t2; //第二次 int _t3; TProduct data; void Clear(); //测试次数 int tCount() { return data.count; } //是否测试ok bool IsOk() { return 1 == data.status; } //是否需要继续测试 bool NeedTest(cstr s = 0) { return data.count < 3 && 0 == data.status && !IsSameBin(s); } //是否Bin信息相同 bool IsSameBin(cstr s) { return s && 0 == strcmp(s, data.level); } //获取重测模式标识字符串 -- 发送开始指令时 cstr getRetryModelS(); //获取重测模式标识字符串 -- 获取结果时 cstr getRetryModelE(); char* Ate(); //当前测试治具编码指针 void SetIndex(int t); //设置当前测试治具序号 int lastIndex(); const char* LastAte(); bool CanTestAAB(const char* ate); bool CanTestABC(const char* ate); }; class CTest; class CManage { public: static CManage* Get_Instance(); static void ReleaseInstance(); CManage(void); ~CManage(void); int Init(); int Deinit(); int IsRun() { return m_brun ? 1 : 0; } //治具通信任务是否在运行 //治具通信 int StartRun(); int StopRun(); cstr GetTestModel(); int SetConfig(CoreConfig* pcfg); const CoreConfig* getCfg() const { return &m_cfg; } void GetConfig(CoreConfig* pcfg) { memcpy(pcfg, &m_cfg, sizeof(m_cfg)); } int SummaryLog(const char* title, const char* content); int BreakdownLog(const char* psztype, const char* pszmsg); int UnitTracker(const char* sn, const char* ate, const char* lot, int result, const char* RetryUsage); int EventTracker(const char* keyword, int errcode, const char*errmsg, const char*msg); int GetProduct(const char* sn, TProduct* pdata); int GetAllProduct(TProduct* pdata/* = 0*/, int nsize/* = 0*/); int GetProductByPos(EMapPos pos, int index, TProduct* pdata/* = 0*/); int GetProductList(EMapPos pos, TProduct* pdata/* = 0*/, int nsize/* = 0*/); int GetMachine(int index, TestMachine* pdata); int TestEnable(int index, int benable); int TestDebug(int index, const char* sn); int TestHome(int testIndex); int TestReset(int testIndex); int TestClear(int testIndex); int SendCustomCmd(const char* msg, char* res = NULL); int RecvCustomCmd(const char* msg, char* res, int timeout/* = 0*/); int GetCommandDesc(char* pszcmddesc); cstr GetVersion(); cstr getBinA() { return m_cfg.BinA; } //获取BinA设置 cstr getLot() { return m_cfg.lot; } //获取批次号 cstr getMachine() { return m_cfg.machine; } bool NodeLog() { return 0 != m_cfg.bNodeLog; } bool IsMakeDir() { return 0 != m_cfg.bDirDate; } bool IsFourpic() { return 0 != m_cfg.bFourPic; } bool IsSavePos() { return 0 != m_cfg.bSavePos; } bool testLog() { return 0 != m_cfg.bTestlog; } bool visionLog() { return 0 != m_cfg.bVisionlog; } bool IsBindTest() { return 0 != m_cfg.bBindB; } //B组是否为绑定模式 TC1->TCB1 TC2->TCB2 bool IsPassToB() { return 0 != m_cfg.bPassTestB; } //是否测试pass才进入B组测试 uint getFail() { return 100 - m_cfg.iSimYield; } //失败率 uint getSimCT() { return m_cfg.iSimCT; } //模拟测试机台CT //治具注册时,检测治具编码是否ok bool ChkAteValid(int index, const char* pszate); //发送给视觉处理指令 int SendTestGR(int tindex, const char* s = 0); int PostReplyGR(int tindex, const char* s); //上报日志 void Report(const char *pszFormat, ...); void PostWarn(const char *pszFormat, ...); int regist_callback(callback fun); callback get_callback() { return m_callback; } protected: void Release(); void ReadConfig(); void RestorePos(int sindex); //模拟生成全盘数据 void MakeInput(); //确保缓冲区够大 void Resize(vector& vec, int nsize); //判断料盘某个位置是否有料?无料则创建一个 void MakeProduct(int sindex, int index); //判断料盘某个位置是否有料?有料则释放 void ReleaseProduct(int sindex, int index); //拍照数据 int GetPosxy(int sindex); //获取拍照位置索引,并从队列删除 int SetPosxy(int sindex); //设置拍照数据到变量 int PosMap(int sindex); //通过3点数据计算矩阵 int ReleasePosxy(int sindex); //释放拍照数据 int SetPosxy(int sindex, char* pszcmd); void MakeDate(char* pszdate); //创建变量,返回ID int CreateVar(const char* pszname, const char* pszdesc, int keep = 0); void SetVarInit(const char* pszname, int ival); //创建变量并锁定 ipvar* getVar(const char* pszname, const char* pszdesc, bool block = true); ipvar* getVar(const char* pszname, const char* pszdesc, const char* pszval); int GetTestIndex(const char* ate); //通过编码查找测试机台序号 //产品 CProduct* GetFromInput(); //从进料仓获取物料 CProduct* FindProduct(const char* sn); void FreeProduct(CProduct* p); //释放产品 void PutToStock(int sindex, CProduct* p); //放入料仓 //未加保护 int GetVacmCount(); //获取吸嘴现在有多少颗物料 int FindTest(CProduct* p, bool bchkp, int aend = TESTCNT); //获取空闲治具 失败返回0 int FindTestDual(CProduct* p, bool bchkp, int aend = TESTCNT); //获取空闲治具 失败返回0 -- 双测模式 int M1(); int M2(); int M3(); int M4(); int M5(); int M6(); int M7(); int M8(); int Test(const char* pszcmd); //测试接口 int SimTest(int tindex, int benable); int VacmReset(); int StockReset(int sindex); int VacmTake(); int TestPut(); int TestTake(); int StockPut(); int WhereToGo(); int TakeFromInput(const char* sn, int vacmIndex); int MovetoTest(int vacmIndex, int testIndex); int MovetoVacm(int testIndex, int vacmIndex); int MovetoStock(int vacmIndex, int sindex); int WaitTestIdle(int testIndex, int timeout); int WaitM2Result(int sindex, char* szres, int timeout); //双测模式接口 bool NeedTestDual(CProduct* p, int t = 0); void GetTestPutDual(int &v, int &t, int aend, bool bchkp = false); bool IsAAB() { return m_cfg.testType == 1; } bool IsABC() { return m_cfg.testType == 2; } bool IsDefault() { return m_cfg.testType == 0; } void GetTestTake(int &v, int &t); void GetNotestPut(int &v, int &t); //如果4个吸嘴满了,卡住了,需要借治具进行缓存 void GetPutByTest(int &v, int t, bool bchkp); void GetPutByTestB(int &v, int t, bool bchkp); //按治具找产品 - B组 void GetTestPut(int &v, int &t, bool bchkp = false); //加保护 int M1B(); int M2B(); int VacmResetB(); int StockResetB(int sindex); int VacmTakeB(); int TestPutB(); int TestTakeB(); int StockPutB(); int WhereToGoB(); int TestPause(int testIndex, int bpause); int GripEnable(int testIndex, int benable); int CreateProductB(const char* sn, int vacmIndex); int MovetoVacmB(int testIndex, int vacmIndex); int MovetoStockB(int vacmIndex, int sindex); int GetProductByPosB(EMapPos pos, int index, TProduct* pdata/* = 0*/); int GetProductListB(EMapPos pos, TProduct* pdata/* = 0*/, int nsize/* = 0*/); static int GreaterThenProduct(const void* a,const void* b); //治具通信 void AcceptNew(); //等待新连接 void ProcessMsg(); //消息处理 void RecvTestMsg(); void CalcUph(); //计算UPH void UpdateVarProduct(); void UploadReport(); int Process(); //线程函数 static int WINAPI ThreadFun(void* param); void ProcessSendGR(); static int WINAPI PoolGR(void* param); ulong _logct; //用于记录上一次日志时间 ulong GetLastCT(ulong curct); private: static CManage *m_pInstance; Handle m_hSection; //临界区 CoreConfig m_cfg; list m_lsgMsg; bool m_tstRun; //转发线程是否在执行? list m_tstMsg; //转发给治具的消息,需要额外的线程执行 vector m_vecStock[STOCKCNT]; //料盘Input OK NG1 NG2 NG3 CProduct** m_vacm_lst; //吸嘴产品 int m_vacm_cnt; //提前拍照存储位置信息 list m_lst_pos[STOCKCNT]; list m_lst_posTmp[STOCKCNT]; int m_lst_index[STOCKCNT]; //缓存上一次取位置时的索引 //测试信息 int m_prePut; //上一次放治具编号 CTest* m_ptest[TESTCNT]; //治具 CTest* m_pconn; //新连接对象 bool m_brun; //线程运行标识 Handle m_hThread; //线程句柄 hash_map m_hash_lst; //所有产品数据 //视觉连接 CVision* m_pVision[EVSize]; CVision* m_pVisionTest; //测试侧相机 //模拟 CSimTest* m_psimTest[TESTCNT]; //变量 ipvar* m_pv; //吸嘴编号 ipvar* m_pt; //治具/料仓编号 ipvar* m_pclear; //清料信号 ipvar* m_pFour; //是否一拍4 ipvar* m_pntake; //要取的料数量 ipvar* m_pnput; //要放OK仓的料数量 ipvar* m_pUph; //最近一分钟实时UPH ipvar* m_pAllUph; //本次总的UPH ipvar* m_pOutput; //工作产量 ipvar* m_pLot; //料盘换料次数 ipvar* m_pEnda; //A组最后序号 ipvar* m_pPause; //暂停信号 ipvar* m_pBin; //分bin信息 ipvar* m_pCastoff; //抛弃产品索引 //测试数据 bool m_bupdatevar; //是否更新产品数据到变量 ipvar* m_pvar_vacm[4]; ipvar* m_pvar_test[TESTCNT]; callback m_callback; //回调函数 }; #endif //防止重复包含