c - 从 PLC(OPC 客户端服务器 Kepware)传输到 MS Access,C

标签 c ms-access variables opc plc

我完全不熟悉 PLC,但我有一个项目需要从 OPC 客户端服务器获取数据,然后将其发送到 Access 数据库表。减去 OPCWriteGroupItems 的大部分代码来自其他人。我只是迷失了将从 OPCReadGroupItems 获取的数据传输到我的函数 OPCWriteGroupItems 中的适当变量的过程。我只想获取读入变量的值。谢谢。 供引用。 我知道我的查询语句需要进行调整,以便它能够正确读取变量,但这是我正在处理的另一个问题。这是更紧迫的问题。

下面是我提到的两个函数:

//---------------------------------------------------------
// Read items from an OPC Group
//---------------------------------------------------------

OPCStat OPCReadGroupItems (int iGrp, struct Var_Stru v[] ) 
{

HRESULT r1;
HRESULT *hr;
OPCITEMSTATE *is;
int iItem;

OPCStat RetVal=OPCSuccess;

if (pGRPTagSIO[iGrp]) {

    if (bOPCDebug) printf("Reading data .... \n");
    r1 = pGRPTagSIO[iGrp]->Read(OPC_DS_CACHE, 
        OPCDataGroup[iGrp].iNumItems, 
        OPCDataGroup[iGrp].hItem,
        &is, 
        &hr);

    if (FAILED(r1)) {
        printf("Error from Read(%lx)\n", r1);
        RetVal = OPCError;
    } else {

        // if the read worked then copy results to the v structure based on type
        for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem++ ) {
            //printf("Read item= %d, hr= %lx, Quality= %2x", iItem, hr[iItem], is[iItem].wQuality);
            if(!FAILED(hr[iItem])) {
            //  printf("%d", is[iItem].vDataValue.vt);
                //printf("%d", iGrp);
                switch(is[iItem].vDataValue.vt) {

                    case VT_I2:             //   2
                        v[iItem].iVal = is[iItem].vDataValue.iVal;
                        break;
                    case VT_I4:             //   3
                        v[iItem].lVal = is[iItem].vDataValue.lVal;
                        break;
                    case VT_R4:             //   4
                    //  printf("Z");
                        v[iItem].fVal = is[iItem].vDataValue.fltVal;
                        break;
                    case VT_R8:             //   5
                        v[iItem].dblVal = is[iItem].vDataValue.dblVal;
                        break;
                    case VT_BOOL:           //  11
                        v[iItem].bVal = is[iItem].vDataValue.boolVal;
                        break;
                    case VT_UI1:            //  11
                        printf("TEST");
                        sprintf(v[iItem].cVal, "%s", is[iItem].vDataValue.cVal);
                        printf("%s", v[iItem].cVal);
                        printf("%c", v[iItem].cVal);
                        break;
                    case VT_BSTR:           //   8
                    //  printf("TEST");
                        sprintf(v[iItem].cVal,"%-.*ls", kOPCStringSize,is[iItem].vDataValue.bstrVal );
                        //printf("\n STRING STRING  %s \n", v[iItem].cVal);
                        break;
                    default:
                        break;
                }
            }
                if(iGrp >= 0 && iGrp <=)
                {
                stuct_double[iGrp-1][iItem] = v[iItem].dblVal;
                //  printf("group %d  ", iGrp);
                //  printf("Tag %i: %10.2f\n", iItem, root_plc[iItem]);
                }
                if(iGrp > 0 && iGrp <= 44)
                {
                struc_floats[iGrp-1][iItem] = v[iItem].fVal;
                //printf("GROUP %d  ", iGrp);
                //printf("Tag %i: %10.2f\n", iItem, struc_floats[iGrp-1][iItem]);
                } 

                else
                {
                printf("Error reading data item %d\n", iItem);
                //RetVal=OPCError;  //Make not as severe -- rjf 06/03/02
                RetVal=OPCWarning;
                //break;        //Escape the for-loop -- rjf- 5/13/02
                }
                */

                pIMalloc->Free(hr);
                for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem)
                {
                    VariantClear($is[iItem].vdatavalue)
                }
                pIMalloc->Free(is);
            }
        }
    else{
        RetVal=OPCError;
        }

    return (RetVal);
}



//-----------------------------------------
// Write items contained in an OPC Group 
//-----------------------------------------
OPCStat OPCWriteGroupItems (int iGrp, struct Var_Stru vOut[] ) 
{

/* Data Access Method used in this sample */
const char* DAM = "Direct ODBC";

/* Connection string for Direct ODBC */
char szDSN[256] = "DSN=Gas_Meter_check;";

HRESULT r1,r2;
HRESULT *hr;
VARIANT v[nMaxOPCItems];
int iItem;
OPCStat RetVal=OPCSuccess;

if (pGRPTagSIO[iGrp]) {

    for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem++) {

        v[iItem].vt = OPCDataGroup[iGrp].iType;

        switch(OPCDataGroup[iGrp].iType) {

            case VT_I2:                     //   2
                v[iItem].iVal = vOut[iItem].iVal;
                break;
            case VT_I4:                     //   3
                v[iItem].lVal = vOut[iItem].lVal;
                break;
            case VT_R4:                     //   4
                v[iItem].fltVal = vOut[iItem].fVal;
                break;
            case VT_R8:                     //   5

                v[iItem].dblVal = vOut[iItem].dblVal;
                 HENV    hEnv;    HDBC    hDbc;

                /* ODBC API return status */    RETCODE rc;

int     iConnStrLength2Ptr;
char    szConnStrOut[256];
int i= 0;
char datetime[256];
double HMCO=1.0;
double HMR,HMT;
unsigned char* InsertQuery = "INSERT INTO Data ( [Date / Time], [Hot Strip Mill rate], [Hot Strip Mill Comm Okay], [Hot Strip Mill Total] ) SELECT #datetime# AS Expr1, HMR AS Expr2, 1 AS Expr3, HMCO AS Expr4, HMT AS Expr5;";

SQLCHAR         chval1[128], chval2[128], colName[128];
int             ret1;
int             ret2;

/* Number of rows and columns in result set */
SQLINTEGER      rowCount = 0;
SQLSMALLINT     fieldCount = 0, currentField = 0;
HSTMT           hStmt;

/* Allocate an environment handle */
rc = SQLAllocEnv(&hEnv);
/* Allocate a connection handle */
rc = SQLAllocConnect(hEnv, &hDbc);

/* Connect to the TakeCharge database */
rc = SQLDriverConnect(hDbc, NULL, (unsigned char*)szDSN, 
    SQL_NTS, (unsigned char*)szConnStrOut, 
    255, (SQLSMALLINT*)&iConnStrLength2Ptr, SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(rc)) 
{
    printf("%s: Successfully connected to database. Data source name: \n  %s\n", 
       DAM, szConnStrOut);

    /* Prepare SQL query */
    printf("%s: SQL InsertQuery:\n  %s\n", DAM, InsertQuery);

    rc = SQLAllocStmt(hDbc,&hStmt);
    rc = SQLPrepare(hStmt, InsertQuery, SQL_NTS);

    /* Excecute the query and create a record set */
    rc = SQLExecute(hStmt); 
    if (SQL_SUCCEEDED(rc)) 
    {
       printf("Executing query...");
       printf("\n");
        }

        while (SQL_SUCCEEDED(rc)) 
        {
            printf(" insert passed\n");
            rc = SQLFetch(hStmt);
            rowCount++;
        };         
    }
else
{
    printf("%s: Couldn't connect to %s.\n", DAM, szDSN);
}

/* Disconnect*/
SQLDisconnect(hDbc);

printf("%s: Cleanup. Done.\n", DAM);


                break;
            case VT_BOOL:                   //  11
                v[iItem].bVal = vOut[iItem].bVal;
                break;
            case VT_BSTR:                   //   8
            //  printf(" In Message value (VT_BSTR) = %s \n",vOut[iItem].cVal );

                r2 = LPTSTR_to_BSTR ( &v[iItem].bstrVal , vOut[iItem].cVal);
                if ( r2 != S_OK ) {
                    printf ("error in memory \n");
                    RetVal = OPCError;
                }

            //  printf(" Write Msg value(VT_BSTR) = %ls \n", v[iItem].bstrVal );
                report(0,0,0, "STRINGS data %s",vOut[iItem].cVal);

                break;
            default:
                printf(" value(unknown type:%d) ", OPCDataGroup[iGrp].iType );
                RetVal = OPCError;
                break;
        }
        //if (bOPCDebug) DumpVariant(OPCDataGroup[iGrp].cTagNames[iItem], &v[iItem]);
    }

    r1 = pGRPTagSIO[iGrp]->Write(
        OPCDataGroup[iGrp].iNumItems,
        OPCDataGroup[iGrp].hItem, 
        v, 
        &hr);

    if (FAILED(r1))
    {
        printf("Error from Write(%lx)\n", r1);
        RetVal = OPCError;

    } else  {
        //if (bOPCDebug) printf("Successful Write ... \n");

        // Clear the Variant
        for (iItem=0;iItem<OPCDataGroup[iGrp].iNumItems;iItem++) {
            VariantClear(&v[iItem]);
        }

        pIMalloc->Free(hr);     
    }
} else {
    RetVal = OPCError;
}

return(RetVal);
}

最佳答案

C/C++ 不是我的第一语言,我不熟悉你的特定 OPC 库(有这么多),但根据我对代码的理解,你正在阅读某种变体变量,并且带有大小写您确定其类型的语句并将其存储到 v[iItem] 的适当属性中。您对该组中的所有标签循环重复该操作。一定有一些属性告诉你刚刚读取的标签的名称,你可以用它来解决问题。

比如你当前读取的标签是single float类型,那么会执行这个case部分:

   case VT_R4:
     v[iItem].fVal = is[iItem].vDataValue.fltVal;
     break;

所以 v[iItem].fVal 包含 OPC 标签的 4 字节单浮点值。如果你当前阅读的标签是double float类型,那么这个case部分就会被执行:

   case VT_R8:
     v[iItem].dblVal = is[iItem].vDataValue.dblVal;
     break;

v[iItem].dblVal 包含OPC 标签的8 字节双浮点值。我想你明白了。

您真的应该花一些时间在 http://www.opcfoundation.org 上学习 OPC DA 教程.

关于c - 从 PLC(OPC 客户端服务器 Kepware)传输到 MS Access,C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6666480/

相关文章:

c - 为什么从 int 转换为 float 值?

c++ - OpenMP 矩阵乘法嵌套循环

javascript - 为什么不需要在这里定义这些?

成员变量的C++类型名

c - 共享库文件大小

c - 获取 LU 分解的 nxn 矩阵时堆损坏

sql-server - 请求的 ODBC 记录

mysql - MS Access 等效查询

mysql - 适用于 MySQL 和 MS Access 的多对多复选框字段

iphone - 离开 View 后保留/保留变量