【问题标题】:UTGARD opc client: Read multiple items repeatedlyUTGARD opc 客户端:重复读取多个项目
【发布时间】:2023-03-25 08:34:01
【问题描述】:

我使用 Utgard OPC 库编写了以下代码。

我需要每 15 秒从 OPC 服务器读取一次数据。但是,我不确定这是否是实现它的最佳方式。在我的场景中,我需要从服务器读取超过 300 个标签。

有什么建议吗?

package opcClientSalem;
import java.util.concurrent.Executors;

import org.jinterop.dcom.common.JIException;
//import org.jinterop.dcom.core.JIVariant;
import org.openscada.opc.lib.common.ConnectionInformation;
import org.openscada.opc.lib.common.NotConnectedException;
import org.openscada.opc.lib.da.AccessBase;
import org.openscada.opc.lib.da.AddFailedException;
import org.openscada.opc.lib.da.AutoReconnectController;
import org.openscada.opc.lib.da.DataCallback;
import org.openscada.opc.lib.da.DuplicateGroupException;
import org.openscada.opc.lib.da.Item;
import org.openscada.opc.lib.da.ItemState;
import org.openscada.opc.lib.da.Server;
import org.openscada.opc.lib.da.SyncAccess;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;


public class opcClientSalem {
    public static void main(String[] args) throws Exception {
        // create connection information
        System.out.println("**********Initializing OPC Client**********");
        java.util.logging.Logger.getLogger("org.jinterop").setLevel(java.util.logging.Level.OFF);
        final ConnectionInformation ci = new ConnectionInformation("myusername","mypassword");
        ci.setHost("myhost");
        ci.setDomain("");
        ci.setProgId("Matrikon.OPC.Simulation.1");
        ci.setClsid("F8582CF2-88FB-11D0-B850-00C0F0104305");
        String itemIdArr[] = {"Random.Real8","Random.Int2"}; // This is where I would have an array of all items
        // create a new server
        final Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());
        AutoReconnectController controller = new AutoReconnectController(server);

        try {
            // connect to server
            System.out.println("**********Attempting to connect to OPC**********");
            controller.connect();
            System.out.println("**********Successfully connected to OPC**********");
            // add sync access, poll every 15000 ms
            final AccessBase access = new SyncAccess(server, 15000);

            while(true){
                for(final String str : itemIdArr){
                    access.addItem(str, new DataCallback() {
                        @Override
                        public void changed(Item item, ItemState state) {
                            // Building a JSON string with value recieved
                            String record = "[ {" +"\""+"name"+"\" :\""+str + "\",\""+"timestamp"+"\" :"+ state.getTimestamp().getTime().getTime()+ ",\""+"value"+"\" : "+value.replace("[", "").replace("]", "")  +",\"tags\":{\"test\":\"test1\"}} ]";

                            try {
                                // Post JSON string to my API which ingests this data
                                new opcClientSalem().restpost(record);
                            } catch (ClientProtocolException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    });
                }
                // start reading
                access.bind();
                Thread.sleep(5000);
            }
            // wait a little bit

            // stop reading
            //access.unbind();
        } catch (final JIException e) {
            //System.out.println(String.format("%08X: %s", e.getErrorCode(), server.getErrorMessage(e.getErrorCode())));
        }
    }

    private void restpost(String record) throws ClientProtocolException, IOException{

        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost("http://localhost/myapi/datapoints");
        StringEntity input = new StringEntity(record);
        post.setEntity(input);
        HttpResponse response = client.execute(post);
        System.out.println("Post success::"+record);
    }

}

【问题讨论】:

  • 您实际面临哪些问题?
  • 这段代码运行得很好。我想知道是否有更好的方法来请求大量标签而不是使用 for 循环。

标签: java opc j-interop


【解决方案1】:

我不确定您是否需要在您的 while 组中一遍又一遍地添加项目。

在其他库(.net 或原生 c++)中,通常您只需要添加一次项目,并且每当项目的值发生更改时都会调用回调。

在 .net 或 c++ 中,我们得到每个组的全局回调,这似乎比每个项目的单独回调更有效。可能 SyncAccess 有全局回调,找找吧。

所以可能的优化:

  • 删除 while 部分,只添加一次项目,让线程无限休眠。
  • 查找所有项目的全局回调

【讨论】:

  • 我会尝试您的建议,即删除 while 循环,看看是否仍然有效。
  • 我将 while 循环移动到只执行 thread.sleep(5000)。有用。谢谢你。
【解决方案2】:

在这种情况下,您应该创建订阅。

【讨论】:

  • 你有任何关于如何设置订阅的参考或代码sn-p吗?我只使用 OPC UA 订阅。
  • 我对您正在使用的库一无所知,但 SyncAccess 实际上可能正在幕后创建订阅。我不知道为什么你在这里有一个 while(true) 循环......
  • 我刚刚发现 AsyncAccess 作为 SyncAccess 的替代品。会尝试一下,如果它解决了我的问题,请告诉您。
  • 在 opc 警报事件中使用的订阅。要读取写入数据,您需要创建组、项目等。
猜你喜欢
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-24
  • 2013-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多