#ifndef _CONTACTLESS_FSM_H #define _CONTACTLESS_FSM_H #pragma once #include "SpFSM.h" #include "CommEntityUtil.hpp" #include "DevFSMCommBase.hpp" #include "RFICClass.h" #include "CardAssist.h" #include "ICDataElement.h" #include "ContactlessCard_server_g.h" #include "ContactlessCard_msg_g.h" #include "ContactlessCard_UserErrorCode.h" #include "json/json.h" enum EvtType { USER_EVT_TEST = EVT_USER+1, USER_EVT_QUIT, USER_EVT_INIT, USER_EVT_INITFINISHED, USER_EVT_ACCEPT, USER_EVT_ACCEPT_CANCEL, USER_EVT_ACCEPTFINISHED, USER_EVT_EJECT, USER_EVT_EJECTFINISHED, USER_EVT_WAITFINISHED, USER_EVT_CAPTUREFINISHED, USER_EVT_WAITFETCHINGTIMEOUT, USER_EVT_PREONLINE, USER_EVT_POSTONLINE, USER_EVT_PREONLINEFINISHED, USER_EVT_POSTONLINEFINISHED, USER_EVT_RESET, USER_EVT_RESETFINISHED, USER_EVT_EXIT, USER_EVT_READ, USER_EVT_READ_FINISHED, USER_EVT_QUERY_CARD_INFO, USER_EVT_QUERY_CARD_INFO_FINISHED, //new USER_EVT_JS_READ, USER_EVT_JS_READ_FINISHED, USER_EVT_JS_EJECT, USER_EVT_JS_EJECTFINISHED, USER_EVT_JS_POSTONLINE, USER_EVT_JS_POSTONLINEFINISHED, USER_EVT_JS_READ_CANCEL }; using namespace ContactlessCard; #ifdef RVC_OS_WIN typedef int(*lpCMBdecodeMag2)(char* Mag2Data, char * data); typedef int(*lpCMBdecodeEx)( char* MagData, char * type, char * data); #else using lpCMBdecodeMag2 = int(*)(char* mag2Data, char* data); using lpCMBdecodeEx = int(*)(char* magData, char* type, char* data); #endif class CContactlessCardEntity; class CContactlessCardFSM; struct Track2Data { int status; CSimpleStringA t2Account; CSimpleStringA t2Region; CSimpleStringA t2CardSerial; CSimpleStringA t2CVC; CSimpleStringA t2ExpireDate; }; struct CMBBin { CSimpleStringA bin;//6 byte long bool bIC;//IC:true or mag:false bool bDC;//debit:true,credit:false }; class CardAcceptEvent : public FSMEvent { public: CardAcceptEvent() : FSMEvent(USER_EVT_ACCEPT){} ~CardAcceptEvent(){} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER)("card accept unhandled"); ctx->Answer(Error_InvalidState); } } }; class PreOnlineEvent : public FSMEvent { public: PreOnlineEvent() : FSMEvent(USER_EVT_PREONLINE){} ~PreOnlineEvent(){} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) ctx->Answer(Error_InvalidState); } protected: private: }; class PostOnlineEvent : public FSMEvent { public: PostOnlineEvent() : FSMEvent(USER_EVT_POSTONLINE){} ~PostOnlineEvent(){} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) ctx->Answer(Error_InvalidState); } protected: private: }; class CardEjectEvent : public FSMEvent { public: CardEjectEvent() : FSMEvent(USER_EVT_EJECT){} ~CardEjectEvent(){} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) ctx->Answer(Error_InvalidState); } protected: private: }; class ResetDeviceEvent : public FSMEvent { public: ResetDeviceEvent() : FSMEvent(USER_EVT_RESET){} ~ResetDeviceEvent(){} protected: private: }; class ResetFinishedEvent : public FSMEvent { public: ResetFinishedEvent() : FSMEvent(USER_EVT_RESETFINISHED){} ~ResetFinishedEvent(){} protected: private: }; class QueryCardInfoEvent : public FSMEvent { public: QueryCardInfoEvent() : FSMEvent(USER_EVT_QUERY_CARD_INFO){} ~QueryCardInfoEvent(){} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) ctx->Answer(Error_InvalidState); } protected: private: }; //new class EjectJSEvent : public FSMEvent { public: EjectJSEvent() : FSMEvent(USER_EVT_JS_EJECT) {} ~EjectJSEvent() {} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("EjectJS unhandled"); //ctx->Answer(Error_InvalidState); } } protected: private: }; class PostOnlineJSEvent : public FSMEvent { public: PostOnlineJSEvent() : FSMEvent(USER_EVT_JS_POSTONLINE) {} ~PostOnlineJSEvent() {} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("PostOnlineJS unhandled"); //ctx->Answer(Error_InvalidState); } } protected: private: }; class ReadJSEvent : public FSMEvent { public: ReadJSEvent() : FSMEvent(USER_EVT_JS_READ) {} ~ReadJSEvent() {} SpReqAnsContext::Pointer ctx; virtual void OnUnhandled() { if (ctx != NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("ReadJS unhandled"); //ctx->Answer(Error_InvalidState); } } protected: private: }; class CContactlessCardFSM : public CCommDevFSM { public: enum {s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11}; BEGIN_FSM_STATE(CContactlessCardFSM) FSM_STATE_ENTRY(s0, "Init", s0_on_entry, s0_on_exit, s0_on_event) FSM_STATE_ENTRY(s1, "Initializing", s1_on_entry, s1_on_exit, s1_on_event) FSM_STATE_ENTRY(s2, "Idle", s2_on_entry, s2_on_exit, s2_on_event) FSM_STATE_ENTRY(s3, "Accepting", s3_on_entry, s3_on_exit, s3_on_event) FSM_STATE_ENTRY(s4, "Hold", s4_on_entry, s4_on_exit, s4_on_event) FSM_STATE_ENTRY(s5, "Reading", s5_on_entry, s5_on_exit, s5_on_event) FSM_STATE_ENTRY(s6, "Ejecting", s6_on_entry, s6_on_exit, s6_on_event) FSM_STATE_ENTRY(s7, "WaitFetching", s7_on_entry, s7_on_exit, s7_on_event) FSM_STATE_ENTRY(s8, "Capturing", s8_on_entry, s8_on_exit, s8_on_event) FSM_STATE_ENTRY(s9, "Failed", s9_on_entry, s9_on_exit, s9_on_event) FSM_STATE_ENTRY(s10, "ReadJs", s10_on_entry, s10_on_exit, s10_on_event) FSM_STATE_ENTRY(s11, "EjectJs", s11_on_entry, s11_on_exit, s11_on_event) END_FSM_STATE() BEGIN_FSM_RULE(CContactlessCardFSM,s0) FSM_RULE_ENTRY(s0,s1,USER_EVT_INIT,0) FSM_RULE_ENTRY(s0, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s1,s2,USER_EVT_INITFINISHED,0) FSM_RULE_ENTRY(s1,s9,USER_EVT_INITFINISHED,1) FSM_RULE_ENTRY(s1, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s2,s3,USER_EVT_ACCEPT,0) FSM_RULE_ENTRY(s2, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s2, s6, USER_EVT_EJECT, 0) FSM_RULE_ENTRY(s2, s10, USER_EVT_JS_READ, 0)//JS ¶Á¿¨ FSM_RULE_ENTRY(s2, s10, USER_EVT_JS_POSTONLINE, 0)//JS Áª»úºó FSM_RULE_ENTRY(s2, s11, USER_EVT_JS_EJECT, 0)//JS Í¿¨ FSM_RULE_ENTRY(s3,s4,USER_EVT_ACCEPTFINISHED,0) FSM_RULE_ENTRY(s3,s9,USER_EVT_ACCEPTFINISHED,1) FSM_RULE_ENTRY(s3,s2,USER_EVT_ACCEPTFINISHED,2) FSM_RULE_ENTRY(s3,s2,USER_EVT_ACCEPTFINISHED,3) FSM_RULE_ENTRY(s3,s7,USER_EVT_ACCEPTFINISHED,4) FSM_RULE_ENTRY(s3, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s4,s6,USER_EVT_EJECT,0) FSM_RULE_ENTRY(s4,s6,USER_EVT_EXIT,0) FSM_RULE_ENTRY(s4,s2,USER_EVT_QUERY_CARD_INFO_FINISHED,0) FSM_RULE_ENTRY(s4, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s5,s4,USER_EVT_READ_FINISHED,0) FSM_RULE_ENTRY(s5,s9,USER_EVT_READ_FINISHED,1) FSM_RULE_ENTRY(s5,s2,USER_EVT_READ_FINISHED,2) FSM_RULE_ENTRY(s5, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s5, s6, USER_EVT_EXIT, 0) FSM_RULE_ENTRY(s6,s7,USER_EVT_EJECTFINISHED,1) FSM_RULE_ENTRY(s6,s7,USER_EVT_EJECTFINISHED,0) FSM_RULE_ENTRY(s6,s7,USER_EVT_EJECTFINISHED,2) FSM_RULE_ENTRY(s6,s2,USER_EVT_EXIT,0) FSM_RULE_ENTRY(s6, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s7,s2,USER_EVT_WAITFINISHED,0) FSM_RULE_ENTRY(s7,s2,USER_EVT_WAITFINISHED,2) FSM_RULE_ENTRY(s7, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s8, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s9, FSM_STATE_EXIT, USER_EVT_QUIT, 0) FSM_RULE_ENTRY(s9, s2, USER_EVT_RESETFINISHED, 0) FSM_RULE_ENTRY(s9, s2, USER_EVT_RESETFINISHED, 1) FSM_RULE_ENTRY(s10, s2, USER_EVT_JS_READ_FINISHED, 0) FSM_RULE_ENTRY(s10, s2, USER_EVT_JS_POSTONLINEFINISHED, 0) FSM_RULE_ENTRY(s11, s2, USER_EVT_JS_EJECTFINISHED, 0) FSM_RULE_ENTRY(s11, s2, USER_EVT_JS_EJECTFINISHED, 1) FSM_RULE_ENTRY(s11, s2, USER_EVT_JS_EJECTFINISHED, 2) END_FSM_RULE() CContactlessCardFSM() : m_bCancelAccept(false), m_bWaitingAccept(false), m_bWaitAccepteMore(false), m_bExit(false), m_resetTimes(0), m_testResult(Error_Succeed) , m_bCDA(false), m_pDataToARQC(NULL), m_csMachineType(true), m_csDevNo(""), m_devInit(false), m_repeatErrTimes(0), m_bCancelRead(false),m_bPageExit(false), m_bNeedReset(true) { HARDWARE_ENTITY_RESET_ENTITYID(m_entCode, 0x213); cmdDecodeMag2 = NULL; cmdDecodeEx = NULL; m_aidList.Init(3); m_aidList[0] = "A000000333"; m_aidList[1] = "A0000000108888"; m_aidList[2] = "A000000790"; } ~CContactlessCardFSM(){} virtual ErrorCodeEnum OnInit(); virtual ErrorCodeEnum OnExit(); void s0_on_entry(); void s0_on_exit(); unsigned int s0_on_event(FSMEvent* event); void s1_on_entry(); void s1_on_exit(); unsigned int s1_on_event(FSMEvent* event); void s2_on_entry(); void s2_on_exit(); unsigned int s2_on_event(FSMEvent* event); void s3_on_entry(); void s3_on_exit(); unsigned int s3_on_event(FSMEvent* event); void s4_on_entry(); void s4_on_exit(); unsigned int s4_on_event(FSMEvent* event); void s5_on_entry(); void s5_on_exit(); unsigned int s5_on_event(FSMEvent* event); void s6_on_entry(); void s6_on_exit(); unsigned int s6_on_event(FSMEvent* event); void s7_on_entry(); void s7_on_exit(); unsigned int s7_on_event(FSMEvent* event); void s8_on_entry(); void s8_on_exit(); unsigned int s8_on_event(FSMEvent* event); void s9_on_entry(); void s9_on_exit(); unsigned int s9_on_event(FSMEvent* event); void s10_on_entry(); void s10_on_exit(); unsigned int s10_on_event(FSMEvent* event); void s11_on_entry(); void s11_on_exit(); unsigned int s11_on_event(FSMEvent* event); int Initial(); ErrorCodeEnum Load(); bool GetDevStatus(bool bPrint=true); int InternalAcceptCard(); int AcceptCard(SpReqAnsContext::Pointer ctx); //int ReadCard(SpReqAnsContext::Pointer ctx); int PreOnline(SpReqAnsContext::Pointer ctx); int PostOnline(SpReqAnsContext::Pointer ctx); int EjectCard(SpReqAnsContext::Pointer ctx); int Reset(); int WaitFetchingCard(); int QueryCardInfo(SpReqAnsContext::Pointer ctx); bool GetWaitFlag(){return m_bWaitingAccept;} void SetWaitMore(){m_bWaitAccepteMore = true;} void SetExitFlag(bool bFlag=true){m_bExit = bFlag;} bool LoadCMBPrint(CSimpleStringA csBinPath); void GetCardProcessLastErr(ErrorCodeEnum& eErrCode, CSimpleStringA& lastApiName, CSimpleStringA& alarmMsg, CSimpleStringA& csErrMsgWithReturnCode); void SelfTest(EntityTestEnum eTestType,CSmartPointer pTransactionContext) { pTransactionContext->SendAnswer(m_testResult); } //new interface int GetFSMState() { //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("m_currentFSMState:%d", m_currentFSMState); return m_currentFSMState; } DWORD GetFsmStateErrCode(); void QueryHasCardJS(SpReqAnsContext::Pointer ctx); int EjectJS(SpReqAnsContext::Pointer ctx); int ReadJS(SpReqAnsContext::Pointer ctx); int PostOnlineJS(SpReqAnsContext::Pointer ctx); int InternalAcceptCardJS(); int PreOnlineJS(SpReqAnsContext::Pointer ctx); protected: int m_iInsertTries; int m_resetTries; int m_ejectTries; private: /// int m_resetTimes; lpCMBdecodeMag2 cmdDecodeMag2; lpCMBdecodeEx cmdDecodeEx; bool m_devInit, m_bCancelAccept, m_bWaitingAccept, m_bWaitAccepteMore, m_bExit, m_bIssued; ErrorCodeEnum m_testResult; CSimpleStringA m_csMachineType; DevCategoryInfo m_devCatInfo; int m_CardInit,m_CardRemains,m_CardIssued,m_CardCaptured,m_CardMixed,m_CardPercent; RFICReaderStatus devStatus; CCardProcess *m_pCardProcess; char *m_pDataToARQC; long xxTest; CAutoArray m_aidList; char m_AuthCode[2]; bool m_bCDA; CSimpleStringA m_csDevNo; int SplitTrack2(CSimpleStringA pTrack2,Track2Data &decodeData); int m_repeatErrTimes; int m_currentFSMState; //new bool m_bCancelRead; bool m_bPageExit; bool m_bNeedReset; }; struct InitTask : public ITaskSp { CContactlessCardFSM* fsm; InitTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_INITFINISHED); e->param1 = fsm->Initial(); fsm->PostEventFIFO(e); } }; struct AcceptTask : public ITaskSp { CContactlessCardFSM* fsm; SpReqAnsContext::Pointer ctx; AcceptTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { LOG_FUNCTION(); FSMEvent *e = new FSMEvent(USER_EVT_ACCEPTFINISHED); e->param1 = fsm->AcceptCard(ctx); fsm->PostEventFIFO(e); } }; struct PreOnlineTask : public ITaskSp { SpReqAnsContext::Pointer ctx; CContactlessCardFSM* fsm; PreOnlineTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_PREONLINEFINISHED); e->param1 = fsm->PreOnline(ctx); fsm->PostEventFIFO(e); } }; struct PostOnlineTask : public ITaskSp { SpReqAnsContext::Pointer ctx; CContactlessCardFSM* fsm; PostOnlineTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_POSTONLINEFINISHED); e->param1 = fsm->PostOnline(ctx); fsm->PostEventFIFO(e); } }; struct EjectTask : public ITaskSp { SpReqAnsContext::Pointer ctx; CContactlessCardFSM* fsm; EjectTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_EJECTFINISHED); e->param1 = fsm->EjectCard(ctx); fsm->PostEventFIFO(e); } }; struct WaitFetchingTask : public ITaskSp { CContactlessCardFSM* fsm; WaitFetchingTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_WAITFINISHED); e->param1 = fsm->WaitFetchingCard(); fsm->PostEventFIFO(e); } }; struct ResetTask : public ITaskSp { CContactlessCardFSM* fsm; ResetTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { ResetFinishedEvent *e = new ResetFinishedEvent(); e->param1 = fsm->Reset(); fsm->PostEventFIFO(e); } }; struct QueryCardInfoTask : public ITaskSp { SpReqAnsContext::Pointer ctx; CContactlessCardFSM* fsm; QueryCardInfoTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent *e = new FSMEvent(USER_EVT_QUERY_CARD_INFO_FINISHED); e->param1 = fsm->QueryCardInfo(ctx); fsm->PostEventFIFO(e); } }; struct EjectJSTask : public ITaskSp { SpReqAnsContext::Pointer ctx; CContactlessCardFSM* fsm; EjectJSTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent* e = new FSMEvent(USER_EVT_JS_EJECTFINISHED); e->param1 = fsm->EjectJS(ctx); fsm->PostEventFIFO(e); } }; struct ReadJSTask : public ITaskSp { SpReqAnsContext::Pointer ctx; CContactlessCardFSM* fsm; ReadJSTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent* e = new FSMEvent(USER_EVT_JS_READ_FINISHED); e->param1 = fsm->ReadJS(ctx); fsm->PostEventFIFO(e); } }; struct PostOnlineJSTask : public ITaskSp { SpReqAnsContext::Pointer ctx; CContactlessCardFSM* fsm; PostOnlineJSTask(CContactlessCardFSM* f) : fsm(f) {} void Process() { FSMEvent* e = new FSMEvent(USER_EVT_JS_POSTONLINEFINISHED); e->param1 = fsm->PostOnlineJS(ctx); fsm->PostEventFIFO(e); } }; #endif //_CONTACTLESS_FSM_H