- Posts: 30
- Thank you received: 0
Online Forums
Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.
Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.
Do not use the Contact page for technical issues.
- Forum
- Discussions
- QuickOPC-Classic in COM
- Connections, Reconnections, COM/DCOM
- Random Disconnect from OPC server
Random Disconnect from OPC server
The heartbeat is simply writing a single integer value to a tag. Matching what it just read from the triggered event. That first parameter verSender is the object that I am using by reference in the heartbeat method.I do not see inside e.g. your Collector::heartbeat, so I cannot tell which EasyDAClient object you are using there
public static function heartbeat(&$opcSender, $plcVal)
{
$_SESSION['PLC_HB_TIME'] = time();
$tagHeartbeatAck = $_SESSION['serviceConfig']['opcDevicePath'] . '.Status.HB02';
return self::writeOpcItem($opcSender, $tagHeartbeatAck, $plcVal);
}
public static function writeOpcItem(&$opcSender, $tag, $val)
{
try {
$opcSender->WriteItemValue($_SESSION['config']['opc']['machine'], $_SESSION['config']['opc']['server'], $tag, $val);
} catch (Exception $e) {
$tmp = str_replace(array("\n","\t"," "), ' ', $e);
LogHandler::error(__METHOD__, __LINE__, "Fault to write '{$val}' to opc tag '{$tag}': {$e}");
return false;
}
return true;
}
Hopefully that helps clear up a few things. I'll add in and set the Isolated to true though.
Please Log in or Create an account to join the conversation.
I think that what is happening is similar to what has been reported to us by other customer as well. It appears that a background thread that is actually handling the OPC operations either hangs or terminates, which then causes the "read timeout", "write timeout", "or cannot connect topic" errors, which all basically indicate the same - that the background thread did not respond in a reasonable time. And, eventually, there is a crash, resulting from unhandled related condition to the first problem.
Unfortunately we were unable to repro it so far, but the hope is that the forthcoming stress test may reveal it.
I have one idea that you may try as a workaround. It is based on hypothesis that maybe the Write from the event handler is somehow colliding with the subscriptions or other stuff going on in parallel with it. Can you please try this:
1. Use two separate EasyDAClient objects. Separate out the object for operations you do from the event handler (I do not see inside e.g. your Collector::heartbeat, so I cannot tell which EasyDAClient object you are using there).
2. For both of these EasyDAClient objects, set their ClientMode->Isolated to true.
It is kind of desperate attempt, but I'd like to suggest at least something that can be done at the moment.
Please Log in or Create an account to join the conversation.
class DEasyDAClientEvents {
public $tagHeartbeat; //heartbeat
public $tagInFloatSeq1; //collect from the plc
public $tagCollectorFault; // fault bit written by the collector
public $MsSql;
public $Collector;
public function __construct()
{
$this->tagHeartbeat = $_SESSION['serviceConfig']['opcDevicePath'] . '.Status.HB01';
$this->tagCollectorFault = $_SESSION['serviceConfig']['opcDevicePath'] . '.Status.HB06';
$this->tagInFloatSeq1 = $_SESSION['serviceConfig']['opcDevicePath'] . '.In.FloatSeq1';
$this->MsSql = new MsSql();
$this->MsSql->openConnection();
return;
}
public function __destruct()
{
if (is_object($this->MsSql)) {
$this->MsSql->closeConnection();
unset($this->MsSql);
}
}
function ItemChanged($varSender, $varE)
{
try {
$itemId = $varE->ItemDescriptor->ItemId;
} catch (Exception $e) {
$tmp = str_replace(array("\n","\t"," "), ' ', $e);
LogHandler::error($_SESSION['serviceName'], __LINE__, "Failed to read subscribed item tag: {$tmp}");
return false;
}
try {
$itemVal = $varE->Vtq->value;
} catch (Exception $e) {
$tmp = str_replace(array("\n","\t"," "), ' ', $e);
LogHandler::error($_SESSION['serviceName'], __LINE__, "Failed to read subscribed item val: {$tmp}");
return false;
}
switch ($itemId) {
case $this->tagHeartbeat:
Collector::heartbeat($varSender, $itemVal);
break;
case $this->tagInFloatSeq1:
Collector::handshake($varSender, $this->MsSql, $itemVal);
break;
case $this->tagCollectorFault:
Collector::collectorFaultReset($varSender, $this->MsSql, $itemVal);
break;
default:
LogHandler::warning($_SESSION['serviceName'], __LINE__, "Unknown subscribed item '{$itemId}' changed to '$itemVal'");
break;
}
}
}
Please Log in or Create an account to join the conversation.
Is this happening always, often, seldom?
Can you post the DEasyDAClientEvents class?
Please Log in or Create an account to join the conversation.
exception 'com_exception' with message 'Source: OPCLabs.EasyDAClient.5.2 Description: Write not completed. This error indicates that it could not be verified that the requested write operation was completed during the timeout period. It is possible that the write operation will actually succeed or fail, but later. Increase the timeout period if you want to obtain positive or negative indication of the operation outcome. Other reason for this error may be that under heavy loads, topic request or response queue is overflowing. Check the event log for queue overflow errors (if event logging is supported by the product and enabled).
That is when I do a single tag write based off a subscribed ItemChanged event. Then afterward it looks like easyopcl.exe is crashed and subsequent opc comms fail. For example I'm writing a heartbeat and I get this:
exception 'com_exception' with message 'Source: OPCLabs.EasyDAClient.5.2 Description: Cannot connect topic (timeout).
Is it possible that I am subscribing to this improperly causing the failure? The snippet of code used for the services to subscribe is below:
$opcCom = new COM($_SESSION['config']['opc']['comObjName']);
$opcEvents = new DEasyDAClientEvents();
if (!com_event_sink($opcCom, $opcEvents, "DEasyDAClientEvents")) {
LogHandler::error($_SESSION['serviceName'], __LINE__, "com_event_sink failed");
}
// $opcCom->SubscribeItem($_SESSION['config']['opc']['machine'], $_SESSION['config']['opc']['server'], $opcEvents->tagHeartbeat, 10);
$tmp = array($opcEvents->tagHeartbeat, $opcEvents->tagInFloatSeq1, $opcEvents->tagCollectorFault);
$opcCom->SubscribeMultipleItems($_SESSION['config']['opc']['machine'], $_SESSION['config']['opc']['server'], $tmp, 100);
$_SESSION['PLC_HB_TIME'] = time(); // setting the inital time to start checking the PLC heartbeat to trigger a fault
while (WIN32_SERVICE_CONTROL_STOP != win32_get_last_control_message()) {
//User Loop
usleep(10000); //10000 micro seconds = .01 seconds
com_message_pump(1000);
if (time() - $_SESSION['PLC_HB_TIME'] > $_SESSION['serviceConfig']['plcHbFaultTimeout'] + 5) { // 5 is the hb cycling time
// GknDataCollector::writeOpcItem($opcCom, $opcEvents->tagCollectorFault, 1);
GknDataCollector::setCollectorFault($opcCom, 1);
$_SESSION['PLC_HB_TIME'] = time() + 60;
}
}
$opcCom->UnsubscribeAllItems();
LogHandler::trace($_SESSION['serviceName'], __LINE__, "Service now unsubscribed to all change events");
unset($opcCom);
unset($opcEvents);
Let me know if there is anything I can do to help. I need to figure out a way to get this working.
Please Log in or Create an account to join the conversation.
Or, it can be that EasyOPC component itself is not accessible to RPC - because it has crashed. In such case there will probably be no IErrorInfo associated with the HRESULT, and it will be returned directly even when calling methods that return multiple results (such as ReadMultipleItems).
It looks like that you have determined that this is the second case; in this case, EasyOpcl.exe should also disappear, and least temporarily, from the process list (which it should never normally do as long as it is in use by some client app).
There has been no specific resolution to the issue discussed in this thread. We can practically always fix problems that we can reproduce. Unfortunately, no repro has been achieved for this one. We are currently setting up a (networked) stress test with the intent to hunt for rare problems that we were not able to reproduce so far. It will take some time before any results come out of it, though.
Please Log in or Create an account to join the conversation.
I've been getting this same sort of issue occurring on my end. I have a service that lags out that uses this and in the display logs it shows that Easyopcl.exe crashed. The version I'm using is 5.22.397.1.
The com exception that is brought up is 'exception 'com_exception' with message 'Error [0x800706ba] The RPC server is unavailable.'
Please Log in or Create an account to join the conversation.
Please Log in or Create an account to join the conversation.
- algorithmica
- Topic Author
- Offline
- Elite Member
- Posts: 18
- Thank you received: 0
Please Log in or Create an account to join the conversation.
And, just to verify, the code is not "blocked" anywhere (specifically, in ReadMultipleItems) - that is, you know that the loop that calls this piece of code is running well, right? Or does it "hang" somewhere?
Please Log in or Create an account to join the conversation.
- Forum
- Discussions
- QuickOPC-Classic in COM
- Connections, Reconnections, COM/DCOM
- Random Disconnect from OPC server