📄 opcdrvitem.cpp
字号:
// OPCDrvItem.cpp
//
// This file contains the implementation of the Item Object.
//
// Note that there is nothing in the Custom interface definition
// that actually requires the creation of a COM based Item Object.
// However doing so is consistant with the approach taken for the
// vendor specific Server and Group objects and,
// although not required, is certainly a reasonable approach.
// In addition it will provide a convenient place to attach
// the Item Automation interface.
//
// (c) COPYRIGHT 1996-1998, INTELLUTION INC.
// ALL RIGHTS RESERVED
//
//
// Functions defined in this module:
//
// COPCDrvItem::COPCDrvItem()
// COPCDrvItem::~COPCDrvItem()
// COPCDrvItem::AddRef()
// COPCDrvItem::Release()
// COPCDrvItem::QueryInterface()
// COPCDrvItem::Init()
// COPCDrvItem::SetActive()
// COPCDrvItem::GetActive()
// COPCDrvItem::SetHandle()
// COPCDrvItem::GetHandle()
// COPCDrvItem::SetDatatype()
// COPCDrvItem::GetDatatype()
// COPCDrvItem::Clone()
// COPCDrvItem::IAGet()
// COPCDrvItem::GetValue()
// COPCDrvItem::WriteValue()
// COPCDrvItem::UpdateDataCache()
// COPCDrvItem::ReadValue()
// COPCDrvItem::CheckDeviceRead()
// COPCDrvItem::CheckDeviceWrite()
// COPCDrvItem::MarkAsChanged()
// COPCDrvItem::Changed()
// COPCDrvItem::ClearChanged()
// COPCDrvItem::DidDataChange()
// COPCDrvItem::GetDataSize()
// COPCDrvItem::GetIoDataFromVariant()
// COPCDrvItem::SetupIoData()
// COPCDrvItem::ParseItemIDOptions()
// COPCDrvItem::GetNIOBlockType()
//
//
//
// Modification Log:
// Vers Date By Notes
// ---- -------- --- -----
// 1.0 08/26/97 jra Created
// 1.3 03/10/98 jra Modified to be wizard generated and driver specific.
// 7.11 01/22/99 jra Added checks to operator=() and IAGet() to make sure we
// have good pointers before cloning the strings.
//
#define WIN32_LEAN_AND_MEAN
#include "OpcStdAfx.h"
#include <math.h>
#include <afxconv.h> // used for ATL conversion functions
#include "OPC.h"
#include "OPCError.h"
#include "OPCVariantPack.h"
#include "NioFuncs.h"
#include <DrvSignal.h> // Used for Fix error codes returned by nio
////////////////////////////////////////////////////////////////
// External global variables
//
extern BOOL g_bAutoStart;
extern WORD g_wStringLength;
extern TCHAR g_tszAcronym[];
////////////////////////////////////////////////////////////////
// Seperators used to parse out the Item definition
////////////////////////////////////////////////////////////////
const char *g_psDrvNameFromAddressSeparator = ":";
const char *g_psAddressFromSignalCondSeperator = "|";
const char *g_psSignalCondParameterSeperator = ",";
const char *g_psDecimalPoint = ".";
////////////////////////////////////////////////////////////////
// External default values for Item parameters obtained from
// the registry.
////////////////////////////////////////////////////////////////
extern CString g_strDefaultSignalConditioning;
extern CString g_strDefaultHiEGU;
extern CString g_strDefaultLoEGU;
extern CString g_strDefaultHardwareOptions;
////////////////////////////////////////////////////////////////
// COPCDrvItem()
//
// Constructor for the Item.
//
////////////////////////////////////////////////////////////////
COPCDrvItem::COPCDrvItem(COPCDrvGroup *pUnkOuter)
{
m_lRefCount = 0;
// Record Parent Group
//
m_pParentGroup = pUnkOuter;
// init pointers
//
m_szItemID = NULL;
m_szAccessPath = NULL;
m_pTempBuff = NULL;
// Init data stuff
VariantInit(&m_vReturnedData);
m_vtCanonical = VT_EMPTY;
m_wQuality = WORD_QUALITY_BAD;
m_bLastKnown = FALSE;
m_AsyncMask = 0;
m_IodName.dhandle = 0;
strncpy(m_IodName.dname, "", 9);
m_IovSpec.dcb = &m_IodName;
_tcscpy(m_IovSpec.dcb->dname, g_tszAcronym);
memset(&m_IoRec, 0, sizeof(IOREC));
strncpy(m_IoRec.addr_string, "", 10);
m_IovSpec.iorec = &m_IoRec;
memset(&m_IoRec2, 0, sizeof(IOREC2));
strncpy(m_IoRec2.device_name, "", 10);
strncpy(m_IoRec2.aux_info, "", 127);
m_IovSpec.iorec2 = &m_IoRec2;
m_AEguRec.span = 65535.0;
m_AEguRec.lo = 0.0;
m_AEguRec.ef = 0;
strncpy(m_AEguRec.etag, "", 4);
strncpy(m_DEguRec.open, "OPEN", 4);
strncpy(m_DEguRec.close, "CLOSE", 5);
m_EguRec.type = EGU_A;
m_EguRec.dd = EGU_IN;
m_EguRec.AREC = m_AEguRec;
memset(&m_IoStat, 0, sizeof(IOSTAT));
InitializeCriticalSection(&this->m_Lock);
}
////////////////////////////////////////////////////////////////
// ~COPCDrvItem()
//
// Destructor for the OPC Item.
//
////////////////////////////////////////////////////////////////
COPCDrvItem::~COPCDrvItem(void)
{
this->Lock();
// Free memory associated with the Item
//
if (m_szItemID)
{
delete [] m_szItemID;
}
if (m_szAccessPath)
{
delete [] m_szAccessPath;
}
if (m_pTempBuff)
{
delete [] m_pTempBuff;
}
this->UnLock();
DeleteCriticalSection(&this->m_Lock);
}
/////////////////////////////////////////////////////////////////////////////
// IUnknown functions
//
////////////////////////////////////////////////////////////////
// IUnknown::AddRef()
//
// Standard IUnknown implementation
//
////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) COPCDrvItem::AddRef(void)
{
return InterlockedIncrement(&m_lRefCount);
}
////////////////////////////////////////////////////////////////
// IUnknown::Release()
//
// Standard IUnknown implementation
//
////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) COPCDrvItem::Release(void)
{
ASSERT(0 != m_lRefCount);
ULONG currentCount = InterlockedDecrement(&m_lRefCount);
// If no references left for this Item
if (currentCount == 0)
{
// Then delete this Item.
delete this;
}
return currentCount;
}
////////////////////////////////////////////////////////////////
// IUnknown::QueryInterface()
//
// Standard IUnknown implementation
//
////////////////////////////////////////////////////////////////
STDMETHODIMP COPCDrvItem::QueryInterface(REFIID iid,
LPVOID *ppInterface)
{
// Make sure that we got a good pointer.
//
if (NULL == ppInterface)
{
return E_INVALIDARG;
}
// IUnknown
if (iid == IID_IUnknown)
{
*ppInterface = (IUnknown *)this;
}
// No interface ava1lable
else
{
*ppInterface = NULL;
}
if (NULL == *ppInterface)
{
return E_NOINTERFACE;
}
((LPUNKNOWN)*ppInterface)->AddRef();
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// Member functions
//
////////////////////////////////////////////////////////////////
// operator=()
//
// Overloaded operator=
//
// Sets an OPCDrvItem members equal to another OPCDrvItem's members
//
// Returns:
// a reference to the object
//
////////////////////////////////////////////////////////////////
COPCDrvItem & COPCDrvItem::operator= (const COPCDrvItem &OtherItem)
{
// jra 012299
// Verify that the pointers are good before cloning
if (this->m_szItemID)
{
this->m_szItemID = WSTRClone(OtherItem.m_szItemID, NULL);
}
if (this->m_szAccessPath)
{
this->m_szAccessPath = WSTRClone(OtherItem.m_szAccessPath, NULL);
}
this->m_hClientItemHandle = OtherItem.m_hClientItemHandle;
this->m_vtRequested = OtherItem.m_vtRequested;
this->m_vtCanonical = OtherItem.m_vtCanonical;
this->m_wNumElements = OtherItem.m_wNumElements;
this->m_AsyncMask = OtherItem.m_AsyncMask;
this->m_IodName.dhandle = OtherItem.m_IodName.dhandle;
this->m_AEguRec.span = OtherItem.m_AEguRec.span;
this->m_AEguRec.lo = OtherItem.m_AEguRec.lo;
this->m_AEguRec.ef = OtherItem.m_AEguRec.ef;
this->m_EguRec.type = OtherItem.m_EguRec.type;
this->m_EguRec.dd = OtherItem.m_EguRec.dd;
this->m_EguRec.AREC = OtherItem.m_EguRec.AREC;
strcpy(this->m_IodName.dname, OtherItem.m_IodName.dname);
strcpy(this->m_IoRec.addr_string, OtherItem.m_IoRec.addr_string);
strcpy(this->m_IoRec2.device_name, OtherItem.m_IoRec2.device_name);
strcpy(this->m_IoRec2.aux_info, OtherItem.m_IoRec2.aux_info);
strcpy(this->m_AEguRec.etag, OtherItem.m_AEguRec.etag);
return *this;
}
////////////////////////////////////////////////////////////////
// Init()
//
// Initialize the ITEM per the OPCITEMDEF
//
// This function will parse out the supplied ItemID buffer and
// extract all of the needed data. It will then call the proper
// NIO functions to pass the data down to the driver for
// validation.
//
// Returns:
// HRESULT - S_OK if the function was successful.
// - OPC_E_INVALIDITEMID if the string is not in a
// valid format.
// - E_OUTOFMEMORY if a memory allocator failed.
//
////////////////////////////////////////////////////////////////
HRESULT COPCDrvItem::Init(int OPCHandle,
OPCITEMDEF *pItemDef,
OPCITEMRESULT *pItemResult)
{
HRESULT hr;
SYSTEMTIME SystemTime;
IOSTAT IoStat;
CString szAddr;
int nIndex = -1;
CString strSignalCond;
CString strLowEGU;
CString strHighEGU;
CString strHardwareOptions;
CString strStringLength;
CString strItemID;
CString strTmpID;
CString strMsg;
memset(&IoStat, 0, sizeof(IOSTAT));
memset(pItemResult, 0, sizeof(OPCITEMRESULT));
// Initialize data values
//
GetSystemTime(&SystemTime); // Get current UTC Time
SystemTimeToFileTime(&SystemTime, &m_ftLastWriteTime); // and store it
// Free memory associated with the Temp Item
// This is done because this function is used by ValidateItems() as well.
//
if (this->m_szItemID)
{
delete [] m_szItemID;
}
if (this->m_szAccessPath)
{
delete [] m_szAccessPath;
}
//
// Copy the ItemID and Accesspath
// Make sure that both the passed pointers are not NULL.
//
if (pItemDef->szItemID)
{
m_szItemID = WSTRClone(pItemDef->szItemID, NULL);
if (NULL == m_szItemID)
{
return E_OUTOFMEMORY;
}
}
else
{
strMsg.Format("OPC DLL: Item id passed as NULL");
m_pParentGroup->m_pParentServer->SendMessageToDriver(strMsg, MSG_DEBUG);
return OPC_E_INVALIDITEMID;
}
if (pItemDef->szAccessPath)
{
m_szAccessPath = WSTRClone(pItemDef->szAccessPath, NULL);
if (NULL == m_szAccessPath)
{
return E_OUTOFMEMORY;
}
}
else
{
m_szAccessPath = NULL;
}
strItemID = pItemDef->szItemID;
strItemID.MakeUpper();
if (strItemID.IsEmpty())
{
strMsg = "OPC DLL: Empty Item ID passed";
m_pParentGroup->m_pParentServer->SendMessageToDriver(strMsg, MSG_DEBUG);
// The item id is not syntactically valid, so return an error
return OPC_E_INVALIDITEMID;
}
strItemID.TrimLeft();
strItemID.TrimRight();
// Validate the requested datatype
//
if(FAILED(hr = SetDatatype(pItemDef->vtRequestedDataType, TRUE)))
{
strMsg.Format("OPC DLL: Invalid requested datatype (%d)", pItemDef->vtRequestedDataType);
m_pParentGroup->m_pParentServer->SendMessageToDriver(strMsg, MSG_DEBUG);
return hr;
}
//////////////////////////////////////////////////////////////////////
//
// Format of ItemID
//
// For analog and digital data:
// DEVICENAME:ADDRESS|SIGNALCONDITIONING,LOWEGU,HIGHEGU,HARDWAREOPTIONS
//
// For ASCII data:
// DEVICENAME:ADDRESS|NUMBEROFCHARACTERS
//
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
// Get 'I/O ADDRESS' portion of ItemID
//
//////////////////////////////////////////////////////////////////////
nIndex = strItemID.FindOneOf(g_psAddressFromSignalCondSeperator);
if (nIndex > 0)
{
szAddr = strItemID.Left(nIndex);
strTmpID = strItemID.Mid(nIndex + 1);
if (szAddr.IsEmpty())
{
strMsg.Format("OPC DLL: Empty I/O address passed");
m_pParentGroup->m_pParentServer->SendMessageToDriver(strMsg, MSG_DEBUG);
// The item id is not syntactically valid, so return an error
return OPC_E_INVALIDITEMID;
}
}
else
{
szAddr = strItemID;
strTmpID.Empty();
}
// Validate I/O Address through NIO
//
memset(&IoStat, 0, sizeof(IOSTAT));
nio_paddr(&IoStat, &m_IovSpec, &m_EguRec, (char *)LPCTSTR(szAddr));
if(IoStat.iostatus != FE_OK)
{
strMsg.Format("OPC DLL: Invalid item id passed to nio_paddr() (%s)", szAddr);
m_pParentGroup->m_pParentServer->SendMessageToDriver(strMsg, MSG_DEBUG);
// The item id is not syntactically valid, so return an error
return OPC_E_INVALIDITEMID;
}
//////////////////////////////////////////////////////////////////////
//
// Get the "SIGNAL_COND,LO_EGU,HI_EGU,HARDWARE_OPTS" portion of ItemID
//
//////////////////////////////////////////////////////////////////////
if (!strTmpID.IsEmpty())
{
// Signal Conditioning options.
// If should be in the following format:
// SIGNAL_COND,LO_EGU,HI_EGU,HARDWARE_OPTIONS
// where an example could be:
// LIN,0,100,UInt
if (EGU_X == m_EguRec.type) // Ascii data
{
//
// Get the number of characters to read
//
if((nIndex = strTmpID.FindOneOf(g_psSignalCondParameterSeperator)) == -1)
{
strStringLength = strTmpID;
}
else
{
strStringLength = strTmpID.Left(nIndex);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -