//ModuleKernal.cpp #include "stdafx.h" #include "ModuleKernal.h" //#include #include "WinConAgent.h" #include #include #include #include #include #include #include #define CONFIG_FILEPATH "\\Compact Flash\\IceTechnology\\Config\\i" #define MAX_SLOTS 8 #define DEVICE_TYPE_UNKNOWN 0 #define DEVICE_TYPE_DIGITAL_INPUT 1 #define DEVICE_TYPE_DIGITAL_OUTPUT 2 #define DEVICE_TYPE_DIGITAL_BOTH 3 #define DEVICE_TYPE_ANALOG_INPUT 4 #define DEVICE_TYPE_ANALOG_OUTPUT 5 #define DEVICE_TYPE_ANALOG_BOTH 6 typedef struct _SLOT_INFO { char strDeviceName[80]; char strPostfix[224]; unsigned char ucDigitalState[32]; float fAnalogState[32]; int nDeviceType; float fDiff; int nFrequency; int nFreqCounter; TagContainer *lpTagContainer; }SLOT_INFO, *LP_SLOT_INFO; //common global variables here, you should not modify them. bool g_bRefresh = false; int g_nMyID=-1; HANDLE g_hEventStart=NULL; HANDLE g_hEventStop=NULL; HANDLE g_hEventTerminate=NULL; HANDLE g_hMutexContainer=NULL; HANDLE g_hThread=NULL; CBPublish g_procCBPublish=NULL; CBWriteLog g_procCBWriteLog=NULL; //device depended gloable variables here, modify if you need. int g_nCheckFrequency=100; SLOT_INFO g_arSlotInfo[MAX_SLOTS]; int g_nCurSlot=-1; TagObject* MyTagCreateHandler(const char **atts) { if(g_nCurSlot < 0 || g_nCurSlot >= MAX_SLOTS) return NULL; char *strName=TagContainer::AttrGetValue(atts, "name"); char *strType=TagContainer::AttrGetValue(atts, "type"); char *strChannel=TagContainer::AttrGetValue(atts, "channel"); if(strName && /*strType &&*/ strChannel) { if(strcmp(strType, "DigitalOutput")==0) { TagDigitalOutput *lpDigitalTag=new TagDigitalOutput; lpDigitalTag->SetName(strName); return lpDigitalTag; } else if(strcmp(strType, "BitOutput")==0) { TagBitOutput *lpBitTag=new TagBitOutput(atoi(strChannel)); lpBitTag->SetName(strName); return lpBitTag; } else if(strcmp(strType, "DigitalInput")==0) { TagDigitalInput *lpDigitalTag=new TagDigitalInput; lpDigitalTag->SetName(strName); return lpDigitalTag; } else if(strcmp(strType, "BitInput")==0) { TagBitInput *lpBitTag=new TagBitInput(atoi(strChannel)); lpBitTag->SetName(strName); return lpBitTag; } else if(strcmp(strType, "AnalogInput")==0) { TagAnalogInput *lpTag=new TagAnalogInput(strName, atoi(strChannel), g_arSlotInfo[g_nCurSlot].fDiff); return lpTag; } else if(strcmp(strType, "AnalogOutput")==0) { TagAnalogOutput *lpTag=new TagAnalogOutput(strName, atoi(strChannel)); return lpTag; } else { char strLog[512]; sprintf(strLog, "Unknown Tag type=%s", strType); g_procCBWriteLog(g_nMyID, strLog); } } else g_procCBWriteLog(g_nMyID, "Error Tag profile data."); return NULL; } void MyPropertyHandler(char *strPropertyName, char *strPropertyValue) { if(g_nCurSlot < 0 || g_nCurSlot >= MAX_SLOTS) return; if(strcmp(strPropertyName, "Frequency")==0) { //g_nCheckFrequency=atoi(strPropertyValue); g_arSlotInfo[g_nCurSlot].nFrequency = atoi(strPropertyValue); // Frequency必須是100的倍數 int nRemain = g_arSlotInfo[g_nCurSlot].nFrequency % 100; int nMultiple = g_arSlotInfo[g_nCurSlot].nFrequency / 100; if(nRemain != 0) nMultiple += 1; g_arSlotInfo[g_nCurSlot].nFrequency = nMultiple * 100; g_arSlotInfo[g_nCurSlot].nFreqCounter = g_arSlotInfo[g_nCurSlot].nFrequency; char strLog[512]; sprintf(strLog, "Change Slot%d Frequency property value=%d", g_nCurSlot, g_arSlotInfo[g_nCurSlot].nFrequency); g_procCBWriteLog(g_nCurSlot/*g_nMySlot*/, strLog); } else if(strcmp(strPropertyName, "Diff")==0) { //g_fDiff=(float)atof(strPropertyValue); g_arSlotInfo[g_nCurSlot].fDiff = (float)atof(strPropertyValue); char strLog[512]; sprintf(strLog, "Change Slot%d Diff property value=%f", g_nCurSlot, g_arSlotInfo[g_nCurSlot].fDiff); g_procCBWriteLog(g_nCurSlot/*g_nMySlot*/, strLog); } /* else if(strcmp(strPropertyName, "DiffCurrent")==0) { g_fDiffCurrent=(float)atof(strPropertyValue); char strLog[512]; sprintf(strLog, "Change DiffCurrent property value=%f", g_fDiffCurrent); g_procCBWriteLog(g_nMySlot, strLog); } */ } //CheckDevice //Thread Worker call this function each g_nCheckFrequency m.seconds. //Do device check and publish any needed information here. //A developer could modify this function if needed. void CheckDevice() { char strName[80]; unsigned char iAtri[8]; for(int i=1; iLoadProfile(i, (char*)LPCTSTR(strProfileName), MyPropertyHandler, MyTagCreateHandler)) { char strLog[256]; sprintf(strLog, "Load profile %s FAIL.", strProfileName); g_procCBWriteLog(g_nMyID, strLog); } else {//load OK if(iAtri[0] && iAtri[1])//Digital Device { g_arSlotInfo[i].nDeviceType=DEVICE_TYPE_DIGITAL_BOTH; GetMultiDIO(i, g_arSlotInfo[i].ucDigitalState, 1); g_arSlotInfo[i].lpTagContainer->SetState((LPVOID)g_arSlotInfo[i].ucDigitalState); } else if(iAtri[0]) { g_arSlotInfo[i].nDeviceType=DEVICE_TYPE_DIGITAL_INPUT; GetMultiDIO(i, g_arSlotInfo[i].ucDigitalState, 1); g_arSlotInfo[i].lpTagContainer->SetState((LPVOID)g_arSlotInfo[i].ucDigitalState); } else if(iAtri[1]) { g_arSlotInfo[i].nDeviceType=DEVICE_TYPE_DIGITAL_OUTPUT; GetMultiDIO(i, g_arSlotInfo[i].ucDigitalState, 1); g_arSlotInfo[i].lpTagContainer->SetState((LPVOID)g_arSlotInfo[i].ucDigitalState); } else if(iAtri[2] && iAtri[3])//Analog Device { g_arSlotInfo[i].nDeviceType=DEVICE_TYPE_ANALOG_BOTH; GetMultiAIO(i, g_arSlotInfo[i].fAnalogState, 1); g_arSlotInfo[i].lpTagContainer->SetState((LPVOID)g_arSlotInfo[i].fAnalogState); } else if(iAtri[2])//Analog Device { g_arSlotInfo[i].nDeviceType=DEVICE_TYPE_ANALOG_INPUT; GetMultiAIO(i, g_arSlotInfo[i].fAnalogState, 1); g_arSlotInfo[i].lpTagContainer->SetState((LPVOID)g_arSlotInfo[i].fAnalogState); } else if(iAtri[3])//Analog Device { g_arSlotInfo[i].nDeviceType=DEVICE_TYPE_ANALOG_OUTPUT; GetMultiAIO(i, g_arSlotInfo[i].fAnalogState, 0); g_arSlotInfo[i].lpTagContainer->SetState((LPVOID)g_arSlotInfo[i].fAnalogState); } } } else g_procCBWriteLog(g_nMyID, "Module container allocate FAIL."); g_procCBPublish(g_nMyID, MESSAGE_TYPE_SUBJECT, strPostfix, &MsgObj); } } else {//device not exist if(strlen(g_arSlotInfo[i].strDeviceName)) {//device removed //publish DeviceRemoved message MessageObject MsgObj; MsgObj.setStringProperty("DeviceRemove", g_arSlotInfo[i].strDeviceName); char strPostfix[224]; sprintf(strPostfix, "%s_%d", strName, i); g_procCBPublish(g_nMyID, MESSAGE_TYPE_SUBJECT, strPostfix, &MsgObj); delete g_arSlotInfo[i].lpTagContainer; memset(&g_arSlotInfo[i], 0, sizeof(SLOT_INFO)); } } } g_bRefresh = false; } void CheckState() { for(int nSlot=1; nSlot<8; nSlot++) { bool bUpdateState = false; g_arSlotInfo[nSlot].nFreqCounter -= 100; if(g_arSlotInfo[nSlot].nFreqCounter <= 0) { g_arSlotInfo[nSlot].nFreqCounter = g_arSlotInfo[nSlot].nFrequency; bUpdateState = true; } if(g_arSlotInfo[nSlot].lpTagContainer && bUpdateState) { switch(g_arSlotInfo[nSlot].nDeviceType) { case DEVICE_TYPE_DIGITAL_INPUT: GetMultiDIO(nSlot, g_arSlotInfo[nSlot].ucDigitalState, 1); break; case DEVICE_TYPE_DIGITAL_OUTPUT: GetMultiDIO(nSlot, g_arSlotInfo[nSlot].ucDigitalState, 0); break; case DEVICE_TYPE_DIGITAL_BOTH: GetMultiDIO(nSlot, g_arSlotInfo[nSlot].ucDigitalState, 1); break; case DEVICE_TYPE_ANALOG_INPUT: GetMultiAIO(nSlot, g_arSlotInfo[nSlot].fAnalogState, 1); break; case DEVICE_TYPE_ANALOG_OUTPUT: GetMultiAIO(nSlot, g_arSlotInfo[nSlot].fAnalogState, 0); break; case DEVICE_TYPE_ANALOG_BOTH: GetMultiAIO(nSlot, g_arSlotInfo[nSlot].fAnalogState, 1); break; default: break; } char strPath[224]; strcpy(strPath, g_arSlotInfo[nSlot].strPostfix); MessageObject MsgObj; while(g_arSlotInfo[nSlot].lpTagContainer->GetMessageObject(strPath, &MsgObj)) { if(strlen(strPath)) { char strPostfix[224]; sprintf(strPostfix, "%s.%s", g_arSlotInfo[nSlot].strPostfix, strPath); g_procCBPublish(g_nMyID, MESSAGE_TYPE_SUBJECT, strPostfix, &MsgObj); } else g_procCBPublish(g_nMyID, MESSAGE_TYPE_SUBJECT, g_arSlotInfo[nSlot].strPostfix, &MsgObj); strPath[0]='\0'; } } } } //ThreadWorker //This thread wait on ServiceStart to begin working, and wait on ServiceStop and SystemShutdown // to stop working. //It will call CheckDevice each g_nCheckFrequency m.seconds. //A developer may not modify this function. DWORD WINAPI ThreadWorker(LPVOID param) { HANDLE hArray[2]; hArray[0]=g_hEventTerminate; while(TRUE) { hArray[1]=g_hEventStart; DWORD dwRet=WaitForMultipleObjects(2, hArray, FALSE, INFINITE); if(dwRet==WAIT_OBJECT_0) break; else if(dwRet==WAIT_FAILED) break; while(TRUE) { hArray[1]=g_hEventStop; dwRet=WaitForMultipleObjects(2, hArray, FALSE, g_nCheckFrequency); if(dwRet==WAIT_TIMEOUT)//begin check { CheckDevice(); CheckState(); } else//terminate or stop or wait fail break; } } return 0; } //DoInit //This function call by Service when the servcice was be loaded. //A developer could add his own initial procedures in it. BOOL DoInit(int nID, DWORD dwParam, CBPublish procCBPublish, CBWriteLog procCBWriteLog) { if(nID<0) return FALSE; g_nMyID=nID; // g_nMySlot=dwParam; g_procCBPublish=procCBPublish; g_procCBWriteLog=procCBWriteLog; memset(g_arSlotInfo, 0, sizeof(SLOT_INFO)*MAX_SLOTS); for(int i=0; i< MAX_SLOTS;i++) g_arSlotInfo[i].fDiff = 0.0; g_hEventStart=CreateEvent(NULL, FALSE, FALSE, NULL); if(!g_hEventStart) { g_procCBWriteLog(g_nMyID, "Module Init fail(0)."); return FALSE; } g_hEventStop=CreateEvent(NULL, FALSE, FALSE, NULL); if(!g_hEventStop) { CloseHandle(g_hEventStart); g_procCBWriteLog(g_nMyID, "Module Init fail(1)."); return FALSE; } g_hEventTerminate=CreateEvent(NULL, TRUE, FALSE, NULL); if(!g_hEventTerminate) { CloseHandle(g_hEventStart); CloseHandle(g_hEventStop); g_procCBWriteLog(g_nMyID, "Module Init fail(2)."); return FALSE; } g_hMutexContainer=CreateMutex(NULL, FALSE, NULL); if(!g_hMutexContainer) { CloseHandle(g_hEventStart); CloseHandle(g_hEventStop); CloseHandle(g_hEventTerminate); g_procCBWriteLog(g_nMyID, "Module Init fail(2)."); return FALSE; } g_hThread=CreateThread(NULL, 0, ThreadWorker, (LPVOID)NULL, 0, NULL); if(!g_hThread) { CloseHandle(g_hEventStart); CloseHandle(g_hEventStop); CloseHandle(g_hEventTerminate); CloseHandle(g_hMutexContainer); g_procCBWriteLog(g_nMyID, "Module Init fail(3)."); return FALSE; } CloseHandle(g_hThread); // Add your initial procedures here unsigned char ret=StartAgent(3, 0); if(ret==0) g_procCBWriteLog(g_nMyID, "ScanKernal Agent start successfully."); else g_procCBWriteLog(g_nMyID, "ScanKernal Agent has been started."); Sleep(10000); g_procCBWriteLog(g_nMyID, "Module Initialized."); return TRUE; } //DoStart //Call by Service when service was been start working. BOOL DoStart() { if(!g_hEventStart) return FALSE; SetEvent(g_hEventStart); g_procCBWriteLog(g_nMyID, "Module Started."); return TRUE; } //DoStop //call by Service when service was been stopped. void DoStop() { if(g_hEventStop) SetEvent(g_hEventStop); g_procCBWriteLog(g_nMyID, "Module Stopped."); } //DoFinalize //call by Service when service was be unloaded. void DoFinalize() { if(g_hEventTerminate) SetEvent(g_hEventTerminate); WaitForSingleObject(g_hThread, 5000); CloseHandle(g_hEventStart); CloseHandle(g_hEventStop); CloseHandle(g_hEventTerminate); CloseHandle(g_hMutexContainer); for(int i=0; iLoadProfile(g_nMySlot, CONFIG_FILEPATH, MyPropertyHandler, MyTagCreateHandler)) { g_procCBWriteLog(g_nMyID, "Load profile FAIL."); return; } WaitForSingleObject(g_hMutexContainer, INFINITE); TagContainer *lpOldContainer=g_lpTagContainer; g_lpTagContainer=lpNewTagContainer; ReleaseMutex(g_hMutexContainer); delete lpOldContainer; */ g_bRefresh = true; g_procCBWriteLog(g_nMyID, "Module Refreshed."); } void DoReport() { char strName[80]; unsigned char iAtri[8]; for(int i=1; iisPropertyExist("Report") && (!strTagPath || !strlen(strTagPath))) { DoReport(); } int nIDLen; WaitForSingleObject(g_hMutexContainer, INFINITE); for(int i=1; iProcessMessage(NULL, i, lpMsgObj); } else if(strncmp(g_arSlotInfo[i].strPostfix, strTagPath, nIDLen)==0) { if(strTagPath[nIDLen]=='.') { g_arSlotInfo[i].lpTagContainer->ProcessMessage(strTagPath+nIDLen+1, i, lpMsgObj); } else if(strTagPath[nIDLen]=='\0') { g_arSlotInfo[i].lpTagContainer->ProcessMessage(NULL, i, lpMsgObj); } } } } ReleaseMutex(g_hMutexContainer); }