⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 opcsvr.cpp

📁 一个modbus协议的opc server
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                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 + -