Professional OPC
Development Tools

logos

Subscription error when connecting - Too many subscriptions

More
23 Oct 2019 16:50 #7866 by janderscu
Great, thank you for the information. Yes, I will work on cleaning up the number of clients and combine into one.

As for disabling the status subscription, I will also add that in ... would I do this just prior to calling the SubscribeMultipleMonitoredItems method in the code below?

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

More
23 Oct 2019 16:32 #7864 by support
Thank you.

Ad 1 and 2: Although this is probably not related to the problem with too many subscriptions: I think you can safely replace all the EasyUAClient instances by a single instance. The EasyUAClient acts as a broker. Each operation already includes the target server data - one instance is not tied to a single server. You can call operations with different target servers on the same EasyUAClient without problems - in fact, this is what it is designed for, to save you coding. In fact, you can even combine operations on multiple servers in one operation (e.g. call SubscribeMultipleMonitorItems with items that target several different servers). The component will sort it out, group them together, and even make the operations to different server in parallel - without any extra effort on your side. In addition, the separate EasyUAClient instances require more resource consumption (memory, threads) on the client side.

Ad 3. The reason I asked this is that the rate is primary parameter of a subscription, and QuickOPC will create a separate subscription for each rate. So, if one wants to limit the number of subscriptions, he/she should not have too many different rates.

Ad 4. The BadTooManySubscriptions error is coming from the server. The servers in PLCs are typically quite limited in number of sessions, subscriptions etc. they support, so in a way it is not such a big surprise to receive this error from an embedded server/PLC. Check your rates (point 3 above). Also, QuickOPC (as mandated by OPC specs) creates one additional subscription to those of yours - to check the status of some server variables. This is not strictly necessary, so you can turn it off, and will have one down. To do so, set the EnableStatusSubscription property to 'false' ( opclabs.doc-that.com/files/onlinedocs/QuickOpc/Latest/User%2...~EnableStatusSubscription.html ), paying attention to Remarks on that class (quote):

In order to obtain or modify these parameters, in the default state (when OpcLabs.EasyOpc.UA.EasyUAClient.Isolated equals to false), access UAClientAdaptableParameters.SessionParameters property of static OpcLabs.EasyOpc.UA.EasyUAClient.AdaptableParameters. If you have set OpcLabs.EasyOpc.UA.EasyUAClient.Isolated to true, you need to access UAClientAdaptableParameters.SessionParameters property of OpcLabs.EasyOpc.UA.EasyUAClient.IsolatedParameters.


So unless you have changed the value of EasyUAClient.Isolated to 'true', you would do something like
OpcLabs.EasyOpc.UA.EasyUAClient.AdaptableParameters.SessionParameters.EnableStatusSubscription = false;
I hope this helps
Best regards

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

More
23 Oct 2019 13:47 #7858 by janderscu
1. Client initializing code below:
foreach (string add in addressArray)
            {
                clients_UA.Add(new EasyUAClient());
 
                foreach (String addIndex in address)
                {
                    if (Convert.ToInt16(addIndex) == i)
                    {
                        chanCountArray[i] = (Int16)((Int16)chanCountArray[i] + 1);
                    }
                }
                i++;
            }

2. Our software is used for testing that may require pulling from multiple servers simultaneously, so we have always provided that capability for user to enter multiple hosts\servers in one interface.
3. I wouldn't say the update rates vary too much ... typically, they are set to 0.01, 0.1, 0.5, or 1 sec... depending on the test data collection requirements. We just try to provide flexibility in the setup for future use if different systems are used for testing.
4. In this case, the target server is a PLC.

Thanks

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

More
23 Oct 2019 12:40 #7855 by support
Hello,

1. Can you please post the code that initializes the clients_UA variable,
2. Please explain why do you need an array of them? Normally, just one is sufficient.
3. Also, do your "requested update rates" vary a lot, or are you generally using just one or a handful of them?
4. What is the target OPC server you are connecting to? Is it in some kind of embedded device or PLC, or is it PC based?

Thank you

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

More
22 Oct 2019 19:26 #7853 by janderscu
So I have some simple code to subscribe to a few channels. Has been working fine for multiple connections. And now I'm getting the error (attached in screenshot). Looks like there it has hit a limit on the number of subscriptions ... but I am always unsubscribing when I close the software. This is done in the CloseDigitizer function. Is there something else I should be doing to clear or reset the connection to avoid this error? thanks


static void GetData_UA()
        {
 
            for (int j = 0; j < addressArray.Count; j++)
            {
                clients_UA[j].DataChangeNotification += client_ItemChanged_UA;
            }
 
            Console.WriteLine("Subscribing item...");
            int k = 0;
            for (int j = 0; j < addressArray.Count; j++)
            {
                EasyUAMonitoredItemArguments[] monitoredItemArgumentsArray = new EasyUAMonitoredItemArguments[(Int16)chanCountArray[j]];
 
                string address = (string)addressArray[j];
                string hostname = address.Split(",".ToCharArray())[0];
                string port = address.Split(",".ToCharArray())[1]; 
 
                UAEndpointDescriptor endpointDescriptor = "";
                endpointDescriptor.Host = hostname.Trim();
                endpointDescriptor.Port = Convert.ToInt32(port.Trim());
 
                int requestedUpdateRate = Convert.ToInt32(scanRateCopy * 1000);
                // Obtain variables under "Server" node
 
                for (int i = 0; i < (Int16)chanCountArray[j]; i++)
                {
                    UANodeDescriptor nodeDescriptor = "ns=2;s=" + labelListCopy.GetValue(k).ToString();
                    monitoredItemArgumentsArray[i] = new EasyUAMonitoredItemArguments(k, endpointDescriptor, nodeDescriptor, new UAMonitoringParameters(requestedUpdateRate, UADataChangeTrigger.StatusValue));
                    k++;
                }
 
                clients_UA[j].SubscribeMultipleMonitoredItems(monitoredItemArgumentsArray);
            }
 
            while (true)
            {
                Thread.Sleep(1000);
                if (runFlag == false) break;
            }
 
        }
 
        static void client_ItemChanged_UA(object sender, EasyUADataChangeNotificationEventArgs e)
        {
 
            //Console.WriteLine("DataChanged here e" + e.Arguments.State.ToString());
 
            if (e.Exception != null)
            {
                Console.WriteLine("e.state: " + e.Arguments.State.ToString() + " e.Exception: " + e.Exception + " EOL");
                buffer[(int)e.Arguments.State] = 9999.0;
            }
            else
            {
                try
                {
                    if (e.Succeeded)
                    {
                        Console.WriteLine("{0}: {1}", e.Arguments.NodeDescriptor, e.AttributeData.Value);
                        buffer[(int)e.Arguments.State] = Convert.ToDouble(e.AttributeData.Value);
                    }
                    else
                    {
                        Console.WriteLine("{0} *** Failure: {1}", e.Arguments.NodeDescriptor, e.ErrorMessageBrief);
                        buffer[(int)e.Arguments.State] = 9999.0;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(" ex.Exception: " + ex.Message + " EOL5");
                    buffer[(int)e.Arguments.State] = 9999.0;
                }
            }
        }
 
        public String CloseDigitizer()
        {
            String message = "CloseDigitizer : No Error\0";
            if (debug) return message;
 
            for (int j = 0; j < addressArray.Count; j++)
            {
                    clients_UA[j].UnsubscribeAllMonitoredItems();
                    clients_UA[j].Dispose();
            }
 
            return message;
        }
Attachments:

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

Moderators: support
Time to create page: 0.191 seconds

      

 Recommend this on Google