Professional OPC
Development Tools

logos

Random Disconnect from OPC server

More
09 May 2012 15:11 #853 by algorithmica
My apologies. I am not sure what you want me to do. Can you supply the statement to "print out the HResult and Source properties", i.e. what properties? Thank you!

Please Log in or Create an account to join the conversation.

More
09 May 2012 15:08 #852 by support
Hello,
thanks for the code. Since you are using ReadMultipleItems and the errors are therefore already converted to objects, it's even easier to figure out the details. Can you please extend the code that prints out the properties from IComExceptionPtr, so that it also prints out the HResult and Source properties?
Thank you

Please Log in or Create an account to join the conversation.

More
09 May 2012 14:24 #851 by algorithmica
Thank you for that. I'm using C++. I know that my code is very basic but I quote it here so that you can get an idea of what it is doing. The program sets up the instance of the OPC object at the begining and then calls the functions get_point(...) and out(...) once every loop. I have removed the code for the function setup(...) as it just contains the definition of the ItemArrays and server names and such and thus there is propriatary info in there.Once the output is "unknown error", it keeps outputting just that at every single read attempt.******************************************************************Header File opc.h#ifndef OPC_H#define OPC_H#include "archive.h"#include "conversion.h"#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit#include #include #include #include #include #include #include #include #include #include #import "libid:FAB7A1E3-3B79-4292-9C3A-DF39A6F65EC1" version(5.1) // EasyOpcLibusing namespace EasyOpcLib;using namespace std;class OPC{ private: bool toggle; int number_in_items; int number_out_items; string machine; string server; CComSafeArray *ItemInArray; CComSafeArray *ItemOutArray; CComVariant vMissing; CComSafeArray * values; basic_info * info; time_t now; conversion conv; IEasyDAClientPtr *dac; public: OPC(); ~OPC(); void log_in() { dac = new IEasyDAClientPtr(__uuidof(EasyDAClient)); }; void setup(basic_info *in); bool get_point(archive_entry * entry); void out(archive_entry * entry, vector *opt, bool suggest);};#endif******************************************************************Code file opc.cpp#include "OPC.h"OPC::OPC(){ toggle = true; vMissing.vt = VT_ERROR; dac = NULL; CoInitialize(NULL); // Initialize the COM library}OPC::~OPC(){ CoUninitialize();}bool OPC::get_point(archive_entry * entry){ int i; double value = 0.0; if(dac == NULL) log_in(); CComVariant vResults((*dac)->ReadMultipleItems(machine.c_str(), server.c_str(), CComVariant(LPSAFEARRAY(*ItemInArray)), vMissing)); time(&now); // get the current time for the newly read point. entry->time = now; CComSafeArray ResultArray(vResults.parray); for(i = ResultArray.GetLowerBound(0); i <= ResultArray.GetUpperBound(0); ++i) { IDAVtqResultPtr DAVtqResultPtr(ResultArray); if(DAVtqResultPtr->Exception == NULL) // only if this is NULL, is the result valid. { IDAVtqPtr DAVtqPtr(DAVtqResultPtr->Vtq); // contains value, timestamp, quality. value = DAVtqPtr->Value.dblVal; // retrieves the value. It *must* be a double as the variant will contain an R8 value! entry->data = (float) value; // now save values to the passed entry. } else // we have an exception. { // Handle failure here: you can use properties such as COMExceptionPtr->HResult, COMExceptionPtr->Message. ICOMExceptionPtr COMExceptionPtr = DAVtqResultPtr->Exception; printf("%s at ", conv.convert_time(now).c_str()); _tprintf(_T("%d: failure: %s\n"), i, COLE2T(COMExceptionPtr->Message)); entry->data = info->special_value; } } ResultArray.Destroy(); // Release all interface pointers BEFORE calling CoUninitialize() vResults.Clear(); return true;}void OPC::out(archive_entry * entry, vector *opt, bool suggest){ if(suggest == true) { values->SetAt(0, CComVariant(opt->at(45))); values->SetAt(1, CComVariant(opt->at(42))); } else { values->SetAt(0, CComVariant(entry->data[info->column_map[8872]])); values->SetAt(1, CComVariant(entry->data[info->column_map[8704]])); } values->SetAt(2, CComVariant(entry->data[info->column_map[9002]])); values->SetAt(3, CComVariant(entry->data[info->column_map[1030]])); if(toggle == true) { values->SetAt(4, CComVariant(1.0)); toggle = false; } else { values->SetAt(4, CComVariant(0.0)); toggle = true; } CComSafeArray saResults; saResults.Attach((*dac)->WriteMultipleItemValues(machine.c_str(), server.c_str(), CComVariant(*ItemOutArray), CComVariant(*values)).parray);}

Please Log in or Create an account to join the conversation.

More
09 May 2012 10:48 #848 by support
Hello.
"Unknown error" most likely corresponds to an HRESULT of E_FAIL, numerically 0x80004005, or (decimal) -2147467259. Can you please verify this first.
This error does not tell anything its cause or source - it is a general error used for many things. For precisely this reason, we are trying to avoid generating it anywhere inside QuickOPC - that is, we (almost) always use our own specific error codes. The error can still be returned by QuickOPC method calls, if it is returned by the target OPC server (more likely), or some of the supporting system calls made by QuickOPC (possible, but unlikely).
The first we should therefore do is to determine where are the origins of the error. One way to do it is to examine the Source property of the error. This information is provided in the standard way by the IErrorInfo interface. Different tools/languages expose this in different ways (for example, in VB or VBScript, it corresponds to the Err object and its Source property). If the Source contains the ProgID of the OPC Server, the origins of the error are in the server, and we should switch our attention to the server. If the Source contains "OPCLabs.EasyDAClient.5.1", the origins of the error are in QuickOPC component.
If you do not know how to access the error Source, please let me know which language/tool you are using. and I will try to supply a corresponding example.
Note that even for E_FAIL-s generated by the server, QuickOPC should try to reconnect. This, however, only applies to certain server-level method calls (i.e. it does not apply, for example, if the server starts returning this error on each subscribed item individually), and, if the server is in some "bad"state, reconnecting may not help. I actually suspect that this could be the situation, but need to go step by step (by determining the Source first) in order to verify it.
Best regards

Please Log in or Create an account to join the conversation.

More
08 May 2012 07:27 #846 by support
Hello.
I apologize for the delay - will answer by tomorrow.
Best regards,

Please Log in or Create an account to join the conversation.

More
06 May 2012 18:03 #843 by algorithmica
Hi there,
I have a very simple program that reads some items from an OPC server every few seconds based on the simple read item sample provided with QuickOPC COM. This goes well for some time. Sometimes I get exceptions and then I output the message like in the example. Whenever the message actually contains a real message all is well. At random intervals however (roughly once in two weeks) the exception message says "unknown error" and then the read process never recovers. The connection to the server seems to be broken. However both the server and the client application are still running and the network is fine. Thus the error must somehow be internal to QuickOPC. I have tried to re-connect but after I do this for a few times, the connection is irreparably severed and I need to reboot my client machine. After that it runs fine again. What can I do?
Thank you! Best, Patrick

Please Log in or Create an account to join the conversation.

Moderators: support
Time to create page: 0.191 seconds

      

 Recommend this on Google