使用org.openscada.utgard java opcda库做opc客户端时长期运行存在的若干问题

牛11月09日反馈东区存在以下问题,由于在现场未来得及处理。11月10日反馈西区亦存在此问题。经排查此问题已存在相当长一段时间(最长为9月底即存在)。

1、读报错Value: [[org.jinterop.dcom.core.VariantBody$EMPTY@212c0aff]], Timestamp: Mon Jan 01 08:00:00 CST 1601, Quality: 0, ErrorCode: c0040001,不能自恢复,其它可以自恢复。

2、写亦有失败,是否均与1中读报错有关待查,既1中读报错时肯定写失败

3、OPC_E_INVALIDHANDLE 0xC0040001 The value of the handle is invalid. Note: a client should never pass an invalid handle to a server. If this error o

ccurs, it is due to a programming error in the client or possibly in the server.

4、重启可解决,少数点有此问题,第三方工具正常

5、短时读不到报错Value: [[org.jinterop.dcom.core.VariantBody$EMPTY@7e2f16bd]], Timestamp: Fri Nov 10 15:28:27 CST 2023, Quality: 8, ErrorCode: e004823e

Value: [[org.jinterop.dcom.core.VariantBody$EMPTY@212c0aff]], Timestamp: Tue Nov 14 14:04:52 CST 2023, Quality: 8, ErrorCode: e2450006

Value: [[org.jinterop.dcom.core.VariantBody$EMPTY@212c0aff]], Timestamp: Sat Nov 11 16:34:51 CST 2023, Quality: 8, ErrorCode: e2450001

6、写失败西区K-F3-3-CO2.PresentValue writefailed时,第三方工具也写失败报错E0048150(此时读正常)

7、多个写时若其中一个点如6中情形,则整批写均会失败(此时读正常),补救措施待考虑(退化到单点写则会非常慢,报错找出不可写点不放批量里或者不去写为佳)

经验教训:

1、因钉钉消息太多无法肉眼排查且无错误明细详情信息,故完全依赖钉钉报警发现问题不可取。拟通过定期执行cat opcda.log |grep writefailed(docker logs -f --tail 10000 opcda  |grep ErrorCode -b2)查看异常情况;

Utgard 是一个Java,用于连接 OPC DA 服务器,如果你想在Linux环境下使用C++调用Utgard访问OPC DA服务器,你需要使用Java Native Interface(JNI)。 以下是一些步骤: 1.首先,在Linux系统上安装Java Development Kit(JDK)。 2.然后创建一个Java类来连接OPC DA服务器并实现所需的功能。 3.编译Java类并生成一个Java动态链接(.so文件)。 4.在C++代码中使用JNI调用Java动态链接。 下面是一个简单的示例: Java类: ```java import org.jinterop.dcom.common.JIException; import org.jinterop.dcom.core.JIVariant; import org.jinterop.dcom.core.JIString; import org.openscada.opc.lib.common.ConnectionInformation; 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; public class OPCClient { public static void main(String[] args) throws Exception { // connect to an OPC DA server ConnectionInformation ci = new ConnectionInformation(); ci.setHost("localhost"); ci.setUser("user"); ci.setPassword("password"); ci.setClsid("B3AF0BF6-4C0C-4804-A122-6F3B160F4397"); Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor()); // create an item and read its value Item item = server.getItemManager().getItem("Random.Int1"); SyncAccess syncAccess = new SyncAccess(server, 1000); syncAccess.addItem(item); syncAccess.bind(); ItemState itemState = item.read(syncAccess.getTransactionId()).get(); JIVariant jiVariant = itemState.getValue(); int value = jiVariant.getObjectAsInt(); System.out.println(value); // write a value to the item item.write(new JIVariant(new JIString("new value"))); // disconnect from the server server.dispose(); } } ``` 编译Java类并生成一个Java动态链接: ```bash javac -cp .:utgard.jar OPCClient.java javah -classpath .:utgard.jar -jni OPCClient gcc -shared -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -o libOPCClient.so OPCClient.c -L. -lutgard ``` C++代码: ```c++ #include <jni.h> int main() { JavaVM *jvm; JNIEnv *env; JavaVMInitArgs vm_args; vm_args.version = JNI_VERSION_1_8; vm_args.nOptions = 0; vm_args.ignoreUnrecognized = JNI_FALSE; JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args); jclass cls = env->FindClass("OPCClient"); jmethodID mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V"); jobjectArray args = env->NewObjectArray(0, env->FindClass("java/lang/String"), NULL); env->CallStaticVoidMethod(cls, mid, args); jvm->DestroyJavaVM(); } ``` 在编译C++代码需要链接utgard和jni,如下所示: ```bash g++ -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -L. -lutgard -ljvm -o main main.cpp ``` 注意:以上示例仅演示了如何使用JNI调用Java动态链接,具体的OPC DA连接实现需要根据自己的需求进行编写。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值