📄 opcsvr.cpp
字号:
tv[i].tvState.tsQuality = OPC_QUALITY_DEVICE_FAILURE;
tv[i].tvState.tsError = S_FALSE;
tv[i].tvState.tsTime = ft;
if ( master_err && errs )
{
*master_err = S_FALSE;
errs[ii] = S_FALSE;
LogMsg( 1, "Failed to ReadTags(Rt=%u Ti=%u %s%02d)",
taglist[ii].tpRt, taglist[ii].tpTi,
tcn[tg[i]], tin[i]);
}
}
}
}
LeaveCriticalSection(&lk_values);
return loDR_CACHED; /* perform actual reading from cache */
}
/* OPTIONAL: example of dynamic tag creation */
HRESULT AskItemID(const loCaller *ca, loTagId *ti,
void **acpa, const loWchar *itemid,
const loWchar *accpath, int vartype, int goal) /* Dynamic tags */
{
HRESULT hr = S_OK;
VARIANT var;
VariantInit(&var);
V_R4(&var) = 3; /* God likes 3 */
V_VT(&var) = VT_R4;
UL_NOTICE((LOGID, "AskItemID %ls type = %u(0x%x)", itemid, vartype, vartype));
if (VT_EMPTY != vartype) /* check conversion */
hr = VariantChangeType(&var, &var, 0, vartype);
if (S_OK == hr) /* we got a value of requested type */
{
int rv;
rv =
loAddRealTag_aW(ca->ca_se, ti, 0, itemid, 0,
OPC_READABLE | OPC_WRITEABLE, &var, 0, 100);
if (rv)
{
if (rv == EEXIST) *ti = 0; /* Already there? - Use existing one! */
else hr = E_OUTOFMEMORY;
}
}
VariantClear(&var);
return hr;
}
/******* ******* ******* ******* ******* ******* ******* *******/
int driver_init(int lflags)
{
loDriver ld;
VARIANT var;
int ecode;
setlocale(LC_CTYPE, "");
if (my_service)
{
UL_ERROR((LOGID, "Driver already initialized!"));
return 0;
}
memset(&ld, 0, sizeof(ld)); /* basic server parameters: */
// ld.ldRefreshRate = 3;//10;
ld.ldSubscribe = activation_monitor;
ld.ldWriteTags = WriteTags;
ld.ldReadTags = ReadTags;
ld.ldConvertTags = ConvertTags;
#if 0
ld.ldAskItemID = AskItemID;
#endif
ld.ldFlags = lflags | loDF_IGNCASE | /*loDf_FREEMARSH | loDf_BOTHMODEL | */
/*loDF_NOCOMP| */ loDf_NOFORCE & 0 /*| loDF_SUBSCRIBE_RAW*/;
/*Fix the Bug in ProTool *//*|loDF_IGNCASE */ ;
ld.ldBranchSep = '/'; /* Hierarchial branch separator */
ecode = loServiceCreate(&my_service, &ld, TI_MAX /* number of tags in the cache */);
/* 500000 is ok too */
UL_TRACE((LOGID, "%!e loCreate()=", ecode));
if (ecode) return -1;
InitializeCriticalSection(&lk_values);
memset(tv, 0, sizeof(tv)); /* instead of VariantInit() for each of them */
memset(ta, 0, sizeof(ta)); /* instead of VariantInit() for each of them */
VariantInit(&var);
/* OPTIONAL: Tags creation. */
{
char name[64];
unsigned int ii, i;
memset(name, 0, sizeof(name));
V_I2(&var) = 0;
V_VT(&var) = VT_I2; //all tags are 2-byte integers
ii = i = 0;
for(; ii < i + tnum[TI_holding_register] && !ecode; ii++)
{
sprintf(name, "%s / %s%02u", ttn, tcn[TI_holding_register], ii-i);
V_I2(&var) = 0;
V_VT(&var) = VT_I2;
ecode = loAddRealTag(my_service, /* actual service context */
&ti[ii+1], /* returned TagId */
(loRealTag) (ii+1), /* != 0 driver's key */
name, /* tag name */
0, /* loTF_ Flags */
OPC_READABLE | OPC_WRITEABLE, &var, 0, 0);
tg[ii+1] = TI_holding_register;
tin[ii+1] = ii-i;
}
UL_TRACE((LOGID, "%!e num of loAddRealTag(%s) = %u ", ecode, tcn[TI_holding_register], ii-i));
LogMsg( 0, "Added %d tags to group %s ", ii-i, tcn[TI_holding_register] );
i = ii;
for(; ii < i+ tnum[TI_output_coil] && !ecode; ii++)
{
sprintf(name, "%s / %s%02u", ttn, tcn[TI_output_coil], ii-i);
ecode = loAddRealTag(my_service, /* actual service context */
&ti[ii+1], /* returned TagId */
(loRealTag)(ii+1), /* != 0 driver's key */
name, /* tag name */
0, /* loTF_ Flags */
OPC_READABLE | OPC_WRITEABLE, &var, 0, 0);
tg[ii+1] = TI_output_coil;
tin[ii+1] = ii-i;
}
UL_TRACE((LOGID, "%!e num of loAddRealTag(%s) = %u ", ecode, tcn[TI_output_coil], ii-i));
LogMsg( 0, "Added %d tags to group %s ", ii-i, tcn[TI_output_coil] );
i = ii;
for(; ii < i + tnum[TI_input_status] && !ecode; ii++)
{
sprintf(name, "%s / %s%02u", ttn, tcn[TI_input_status], ii-i);
V_I2(&var) = 0;
V_VT(&var) = VT_I2;
ecode = loAddRealTag(my_service, /* actual service context */
&ti[ii+1], /* returned TagId */
(loRealTag) (ii+1), /* != 0 driver's key */
name, /* tag name */
0, /* loTF_ Flags */
OPC_READABLE, &var, 0, 0);
tg[ii+1] = TI_input_status;
tin[ii+1] = ii-i;
}
UL_TRACE((LOGID, "%!e num of loAddRealTag(%s) = %u ", ecode, tcn[TI_input_status], ii-i));
LogMsg( 0, "Added %d tags to group %s ", ii-i, tcn[TI_input_status] );
i = ii;
for(; ii < i + tnum[TI_input_register] && !ecode; ii++)
{
sprintf(name, "%s / %s%02u", ttn, tcn[TI_input_register], ii-i);
V_I2(&var) = 0;
V_VT(&var) = VT_I2;
ecode = loAddRealTag(my_service, /* actual service context */
&ti[ii+1], /* returned TagId */
(loRealTag) (ii+1), /* != 0 driver's key */
name, /* tag name */
0, /* loTF_ Flags */
OPC_READABLE, &var, 0, 0);
tg[ii+1] = TI_input_register;
tin[ii+1] = ii-i;
}
UL_TRACE((LOGID, "%!e num of loAddRealTag(%s) = %u ", ecode, tcn[TI_input_register], ii-i));
LogMsg( 0, "Added %d tags to group %s ", ii-i, tcn[TI_input_register] );
}
return 0;
}
void driver_destroy(void)
{
if (my_service)
{
int ecode = loServiceDestroy(my_service);
UL_INFO((LOGID, "%!e loDelete(%p) = ", ecode));
for(ecode = 0; ecode < sizeof(tv) / sizeof(tv[0]); ecode++)
VariantClear(&tv[ecode].tvValue);
DeleteCriticalSection(&lk_values);
my_service = 0;
}
}
/********* Data workloop stuff ************************************************/
void work_loop(unsigned pause, unsigned *nTerminate)
{
DWORD hitime = 0;
unsigned starttime = GetTickCount();
FILETIME ft;
GetSystemTimeAsFileTime(&ft); /* awoke */
UL_WARNING((LOGID, "Workloop Started..."));
EnterCriticalSection(&lk_values);
/* Set up initial values for the tags we didn't initialized in driver_init(): */
int ii = 0;
for (ii = 0; ii < TI_MAX;ii++)
{
tv[ii+1].tvTi = ti[ii+1];
tv[ii+1].tvState.tsError = S_OK;
tv[ii+1].tvState.tsQuality = OPC_QUALITY_UNCERTAIN;
V_VT(&tv[ii+1].tvValue) = VT_I2;
V_I2(&tv[ii+1].tvValue) = 0;
tv[ii+1].tvState.tsTime = ft;
}
loCacheUpdate(my_service, TI_MAX, tv, 0);
LeaveCriticalSection(&lk_values);
/**** Then do simulate ***********/
while(0 != my_CF.server_inuse && !(*nTerminate) ) /* still working? */
{
Sleep(10);
GetSystemTimeAsFileTime(&ft); /* awoke */
/* OPTIONAL: reload log's configuration fromtime to time */
if (hitime != (ft.dwLowDateTime & 0xf8000000)) /* 13.5 sec */
{ /* 0xff000000 is about 1.67 sec */
hitime = ft.dwLowDateTime & 0xf8000000;
#if 0
unilog_Refresh(0); /* all logs */
#else
unilog_Refresh("XXX-OPC");
unilog_Refresh("XXX-OPC-MODBUS-EXE");
#endif
}
/***** The main job: poll data from PLC, update the values ******/
int ii = 0;
for (ii = 0; ii < TI_MAX; )
{
if ( !ta[ii+1] )
{
ii++;
continue;
}
//read 10 words a time, speed up polling
EnterCriticalSection(&lk_values);
WORD wa[10]={0};
if ( GetDrvData10( DEVICE_ID, tg[ii+1], tin[ii+1], wa ))
{
for ( int i = 0 ; i < 10; i++)
{
V_I2(&tv[ii+1+i].tvValue) = (short)wa[i];
V_VT(&tv[ii+1+i].tvValue) = VT_I2;
tv[ii+1+i].tvState.tsQuality = OPC_QUALITY_GOOD;
tv[ii+1+i].tvState.tsError = S_OK;
tv[ii+1+i].tvState.tsTime = ft;
}
}
else
{
for ( int i = 0 ; i < 10; i++)
{
V_VT(&tv[ii+1+i].tvValue) = VT_EMPTY;
tv[ii+1+i].tvState.tsQuality = OPC_QUALITY_DEVICE_FAILURE;
tv[ii+1+i].tvState.tsError = S_FALSE;
tv[ii+1+i].tvState.tsTime = ft;
}
}
ii += 10;
/** MANDATORY: send all the values into the cache: */
loCacheUpdate(my_service, TI_MAX, tv, 0);
LeaveCriticalSection(&lk_values);
Sleep(10); /* main delay */
}
if (pause)
{
/* IMPORTANT: force unloading of an out-of-proc
if not connected during PAUSE millisec */
unsigned tnow = GetTickCount();
if (tnow - starttime >= pause)
{
pause = 0;
my_CF.serverRemove();
}
}
} /* end of loop */
if (0 != my_CF.server_inuse && (*nTerminate) )
{
loSetState( my_service, 0, loOP_SHUTDOWN, 0, "User aborted" );
}
if ( *nTerminate )
UL_MESSAGE((LOGID, "Aborting..."));
else
UL_MESSAGE((LOGID, "All clean. exiting..."));
}
/***************************************************************************
EXE-specefic stuff
***************************************************************************/
const char eClsidName[] = "XXX OPC Server for Modbus";
const char eProgID[] = "XXX.OPC.MODBUS";
HMODULE server_module = 0;
int callsvr(HINSTANCE hInstance, unsigned *nTerminate, BOOL bEmbedding, unsigned nRegister );
int callsvr(HINSTANCE hInstance, unsigned *nTerminate, BOOL bEmbedding, unsigned nRegister )
{
int main_rc = 0;
DWORD objid;
int daemon = 0, pause = 20;
const char *exit_msg = "Exiting...";
server_module = hInstance;
log = unilog_Create("XXX-OPC-exe", "|XXX-OPC-exe", "%!T", -1, /* Max filesize: -1 unlimited, -2 -don't change */
ll_MESSAGE); /* level [ll_FATAL...ll_DEBUG] */
unilog_Redirect("XXX-OPC-exe", "XXX-OPC", 0);
unilog_Delete(log);
log = unilog_Create("XXX-OPC-MODBUS-EXE", "|XXX-OPC-MODBUS-EXE", "", -1, /* Max filesize: -1 unlimited, -2 -don't change */
ll_TRACE); /* level [ll_FATAL...ll_DEBUG] */
//UL_DEBUG((LOGID, "WinMain(%s) invoked...", argv[0]));
if ( 1 == nRegister )
{
char np[FILENAME_MAX + 32];
GetModuleFileName(NULL, np + 1, sizeof(np) - 8);
np[0] = '"'; strcat(np, "\"");
if (loServerRegister(&CLSID_XXXOPCServerEXE,
eProgID, eClsidName, np, 0))
{
UL_ERROR((LOGID, "%!L Reg <%s> <%s> Failed", eProgID, np));
main_rc = 1;
LogMsg( 0, "Failed to register server to system" );
}
else
{
UL_INFO((LOGID, "Reg <%s> <%s> Ok", eProgID, np));
LogMsg( 0, "Registered server to system" );
}
}
else if ( 2 == nRegister )
{
if (loServerUnregister(&CLSID_XXXOPCServerEXE, eProgID))
{
UL_WARNING((LOGID, "%!L UnReg <%s> Failed", eProgID));
main_rc = 1;
}
else
{
UL_DEBUG((LOGID, "UnReg <%s> Ok", eProgID));
}
}
/* Attempt to start the server */
my_CF.is_out_of_proc = my_CF.server_inuse = 1;
if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
{
exit_msg = "CoInitializeEx() failed. Exiting...";
UL_ERROR((LOGID, exit_msg));
goto Finish;
}
if ( bEmbedding )
pause = 6; /* 3 sec can be too short for remote connections */
else
pause = 0;
if (driver_init(0))
{
exit_msg = "driver_init() failed. Exiting...";
UL_ERROR((LOGID, exit_msg));
}
else if (FAILED(CoRegisterClassObject(CLSID_XXXOPCServerEXE, &my_CF,
CLSCTX_LOCAL_SERVER |
CLSCTX_REMOTE_SERVER |
CLSCTX_INPROC_SERVER,
REGCLS_MULTIPLEUSE, &objid)))
{
exit_msg = "CoRegisterClassObject() failed. Exiting...";
UL_ERROR((LOGID, exit_msg));
}
else
{
if (daemon)
pause = 0; // infinite
my_CF.serverAdd(); /* Oops. This will prewent our server from unloading
till PAUSE elapsed and simulate() do my_CF.serverRemove() */
/* STARTing the workloop */
work_loop(pause * 1000, nTerminate); /* sec -> millisec; */
/* FINISHED */
if (FAILED(CoRevokeClassObject(objid)))
UL_WARNING((LOGID, "CoRevokeClassObject() failed..."));
}
driver_destroy();
CoUninitialize();
Finish:
LogMsg( 0, "Exiting...");
unilog_Delete(log);
log = 0;
return main_rc;
}
/******************* This is the end... ************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -