You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

399 lines
12 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#pragma once
#ifndef _INCLUDE_COREWORK_MANAGE_H
#define _INCLUDE_COREWORK_MANAGE_H
#include "sysapi.h"
#include <list>
#include <hash_map>
#include <string>
#include <vector>
#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<CProduct*>& 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<char*> m_lsgMsg;
bool m_tstRun; //转发线程是否在执行?
list<TGRMsg*> m_tstMsg; //转发给治具的消息,需要额外的线程执行
vector<CProduct*> m_vecStock[STOCKCNT]; //料盘Input OK NG1 NG2 NG3
CProduct** m_vacm_lst; //吸嘴产品
int m_vacm_cnt;
//提前拍照存储位置信息
list<TPosxy*> m_lst_pos[STOCKCNT];
list<TPosxy*> 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<string, CProduct*> 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 //防止重复包含