#include "stdio.h"
#include "stdlib.h"
#include "afx.h"
#include "OPCDA.H"
#include "OPCError.h"
#include "opcda_i.c"
#include "string.h"
#include "ATLCONV.H"
#define LOCALE_ID    0x409	// Code 0x409 = ENGLISH
	IOPCServer		*m_IOPCServer;
	IOPCItemMgt		*m_IOPCItemMgt;
	IOPCSyncIO		*m_IOPCSyncIO;
	OPCITEMDEF		m_Items[20];
	OPCITEMRESULT	*m_ItemResult;
	OPCHANDLE		m_GrpSrvHandle;
	HRESULT			*m_pErrors;
	CString m_readQulitay;
	double m_readValue;
	CString m_readTs;
	HRESULT		r1;
	CString m_writeValue;
	CLSID		clsid;
	LONG		TimeBias = 0;
	FLOAT		PercentDeadband = 0.0;
	DWORD		RevisedUpdateRate;
	CString		szErrorText;
	char item_name[100][50];
	int item_num;

extern "C" _declspec(dllexport)  void opc_connect(char *server) 
{
	r1 = CoInitialize(NULL);
	if (r1 != S_OK)
	{	if (r1 == S_FALSE)
		{
			MessageBox(NULL,"COM Library Initial Succes","Succes",MB_OK);
		}
		else
		{
			MessageBox(NULL,"COM Library Initial Error","Erroer",MB_OK);			
			return;
		}
	}	
	USES_CONVERSION; 
	r1=CLSIDFromProgID(A2W(server),&clsid); 
	if (r1 != S_OK)
	{	
		MessageBox(NULL,"Get CLSID Failure","Error",MB_OK);
		CoUninitialize();
		return;
	}
	r1 = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER ,IID_IOPCServer, (void**)&m_IOPCServer);
	if (r1 != S_OK)
	{	
		MessageBox(NULL,"Create OPC Server Object Failure","Error",MB_OK);
		m_IOPCServer = NULL;
		CoUninitialize();
		return;
	}
}


extern "C" _declspec(dllexport)  void opc_add_group(char *group) 
{
	USES_CONVERSION; 
	r1=m_IOPCServer->AddGroup(A2W(group),			//	[in] group name
						TRUE,					//	[in] active
						500,					//	[in] request this Update Rate from Server
						1,						//	[in] Client handle
						&TimeBias,				//	[in] no time interval to system UTC time
						&PercentDeadband,		//	[in] no deadband, so all data changes are reported	
						LOCALE_ID,				//	[in] Server uses English language for text values
						&m_GrpSrvHandle,		//	[out] Server handle to identify this group in later calls
						&RevisedUpdateRate,		//	[out] the answer form the Server to the requested update rate
					    IID_IOPCItemMgt,		//	[in] requested interface type of the group object
						(LPUNKNOWN*)&m_IOPCItemMgt);	//	[out] pointer to the requested interface
	
	if (r1 == OPC_S_UNSUPPORTEDRATE)
	{	
		MessageBox(NULL,"The Fresh Speed Error","Error",MB_OK);
	}
	else
		if (FAILED(r1))
		{
		MessageBox(NULL,"Add Group Failure","Error",MB_OK);
		m_IOPCServer->Release();
			m_IOPCServer = NULL;
			CoUninitialize();		
			return;
		}
}


extern "C" _declspec(dllexport)  void copy_item(int *index_item,char *item) 
{
	 strcpy(item_name[*index_item],item);
//item_name[*index_item]=item;
//MessageBox(NULL,item_name[*index_item],"Add Item",MB_OK);
//	MessageBox(NULL,item_name[0],item_name[0],MB_OK);
}


extern "C" _declspec(dllexport)  void opc_add_item(int *item_i) 
{
	m_ItemResult = NULL;
//	item_name[0]="UNIT1.TRAIN1.NODE1.TAG1.SP";
//	item_name[1]="UNIT1.TRAIN1.NODE1.TAG2.SP";
//	MessageBox(NULL,item_name[0],item_name[0],MB_OK);
//	MessageBox(NULL,item_name[1],item_name[1],MB_OK);
	item_num=*item_i;
	for(int item_i_temp=0;item_i_temp<*item_i;item_i_temp++)
	{
	m_Items[item_i_temp].szAccessPath		  = L"";			//	Accesspath not needed
	USES_CONVERSION; 
	m_Items[item_i_temp].szItemID			  = A2W(item_name[item_i_temp]);		//	ItemID, see above
	m_Items[item_i_temp].bActive			  = TRUE;			
	m_Items[item_i_temp].hClient			  = 1;
	m_Items[item_i_temp].dwBlobSize		  = 0;
	m_Items[item_i_temp].pBlob			  = NULL;
	m_Items[item_i_temp].vtRequestedDataType = 0;				//	return values in native (cannonical) datatype 
													//	defined by the item itself
	}

	r1 = m_IOPCItemMgt->AddItems(*item_i,				   //	[in] add one item
							m_Items,				//	[in] see above
							&m_ItemResult,			//	[out] array with additional information about the item
							&m_pErrors);			//	[out] tells which of the items was successfully added.
													//	For any item which failed it provides a reason

	if ( (r1 != S_OK) && (r1 != S_FALSE) )
	{	
		MessageBox(NULL,"Add Items Failure","Error",MB_OK);
		m_IOPCItemMgt->Release();
		m_IOPCItemMgt = NULL;
		m_GrpSrvHandle = NULL;
		m_IOPCServer->Release();
		m_IOPCServer = NULL;
		CoUninitialize();		
		return;
	}
	else if(r1==S_OK)
	{	
		MessageBox(NULL,"Add Items Success","Success",MB_OK);
	}

	for(int item_write_read=0;item_write_read<*item_i;item_write_read++)
	{
		if (m_ItemResult[item_write_read].dwAccessRights != (OPC_READABLE + OPC_WRITEABLE))
		{
		MessageBox(NULL,"Can't Write and Read Items","Error",MB_OK);
		break;
		}
	}

	r1 = m_IOPCItemMgt->QueryInterface(IID_IOPCSyncIO, (void**)&m_IOPCSyncIO);
	if (r1 < 0)
	{	
		MessageBox(NULL,"IOPCSyncIO Not Found!","Error",MB_OK);
		CoTaskMemFree(m_ItemResult);
		m_IOPCItemMgt->Release();
		m_IOPCItemMgt = NULL;
		m_GrpSrvHandle = NULL;
		m_IOPCServer->Release();
		m_IOPCServer = NULL;
		CoUninitialize();
		return;
	}

}


extern "C" _declspec(dllexport)  void opc_read(int *item_i,float item_v[20]) 
{
	OPCHANDLE		*phServer;
	OPCITEMSTATE	*pItemValue;
	HRESULT			*pErrors;
	HRESULT			r1;
	UINT			qnr;	
		if (m_pErrors[0] != S_OK)		
		{	
		MessageBox(NULL,"Can't Sync OPC Item Read and Write","Error",MB_OK);
		}
	phServer = new OPCHANDLE[*item_i];
			for(int item_write_read=0;item_write_read<*item_i;item_write_read++)
		{
		phServer[item_write_read] = m_ItemResult[item_write_read].hServer;
		}
	r1 = m_IOPCSyncIO->Read(OPC_DS_DEVICE, *item_i, phServer, &pItemValue, &pErrors);
	delete [] phServer;
	if (r1 == S_OK) 
	{
		for(int item_write_read=0;item_write_read<*item_i;item_write_read++)
		{
		item_v[item_write_read]= pItemValue[item_write_read].vDataValue.fltVal;	
		qnr = pItemValue[item_write_read].wQuality;
		}
	}
	if (r1 == S_FALSE) 
	{	
		MessageBox(NULL,"Read() Error","Error",MB_OK);
	}
	if (FAILED(r1)) 
	{
		MessageBox(NULL,"Read Failure","Error",MB_OK);
	}
	else 
	{
		CoTaskMemFree(pErrors);
		CoTaskMemFree(pItemValue);
	}
	
}



extern "C" _declspec(dllexport)  void opc_write(int *item_index,float *value) 
{

	OPCHANDLE		*phServer;
	HRESULT			*pErrors;
	VARIANT			values[1];
	HRESULT			r1;
	LPWSTR			ErrorStr;
	CString			szOut;

	if (m_pErrors[*item_index] != S_OK)		//Item not available
	{	
		MessageBox(NULL,"Can't Sync OPC Item Read and Write","Error",MB_OK);
		return;
	}	
	
	phServer = new OPCHANDLE[1];
	phServer[0] = m_ItemResult[*item_index].hServer;

	values[0].vt = VT_R4;
	values[0].fltVal = *value;

		
	r1 = m_IOPCSyncIO->Write(1, phServer, values, &pErrors);
	
	delete[] phServer;

	if (FAILED(r1))
	{		
		MessageBox(NULL,"Write Item Error","Error",MB_OK);
	}
	else 
	{
		m_IOPCServer->GetErrorString(pErrors[*item_index], LOCALE_ID, &ErrorStr);
		CoTaskMemFree(pErrors);	
	}
	
}



extern "C" _declspec(dllexport)  void opc_disconnect() 
{

	HRESULT		r1;
	OPCHANDLE	*phServer;
	HRESULT		*pErrors;

			phServer = new OPCHANDLE[item_num];
			for(int item_write_read=0;item_write_read<item_num;item_write_read++)
		{
	phServer[item_write_read] = m_ItemResult[item_write_read].hServer;
		}

	r1 = m_IOPCItemMgt->RemoveItems(item_num,			//	[in] remove one item
							phServer,			//	[in] identified by server handle
							&pErrors);			//	[out] Errors for each item, returned by OPC server
	
	if ( (r1 != S_OK) && (r1 != S_FALSE) )
	{	
		MessageBox(NULL,"RemoveItems Failure","Error",MB_OK);
	}
	else if(r1==S_OK)
	{
		MessageBox(NULL,"RemoveItems() Success","Success",MB_OK);
	}

	delete[] phServer; 
	CoTaskMemFree(pErrors);
	CoTaskMemFree(m_ItemResult);
	m_ItemResult=NULL;
	CoTaskMemFree(m_pErrors);
	m_pErrors = NULL;

	m_IOPCSyncIO->Release();
	m_IOPCSyncIO = NULL;

	m_IOPCItemMgt->Release();
	m_IOPCItemMgt = NULL;
	
	r1=m_IOPCServer->RemoveGroup(m_GrpSrvHandle, TRUE);
	if (r1 != S_OK)
	{
		MessageBox(NULL,"RemoveGroup Failure","Error",MB_OK);
	}
	else
	{
		MessageBox(NULL,"RemoveGroup Success","Success",MB_OK);
	}
	m_GrpSrvHandle = NULL;

	m_IOPCServer->Release();
	m_IOPCServer = NULL;

	CoUninitialize();

	
}



