Чтение, управляемое событиями Twincat ADS, перестает работать через некоторое время (Java)
Мы разработали приложение Java, которое использует библиотеку TwinCat ADS (DLL) для чтения, записи и обработки событий из ПЛК Beckhoff (CX5120). Мы успешно выполнили это на нескольких машинах, но, к сожалению, в настоящее время у нас возникла проблема, когда обработка событий внезапно прекращается. Это точный сценарий, через который мы прошли:
- Читать, писать и события обрабатываются правильно.
- Внезапно мы больше не получаем никаких событий, хотя чтение и запись по-прежнему работают правильно.
- Заменил ПЛК на другой, снова начал успешно работать. Мы предполагали, что тогда это была проблема с лицензированием.
- После недели автоматического запуска снова возникла та же проблема: библиотека PLC/ADS, похоже, больше не вызывает события, и мы никак не можем заставить ее работать снова. Чтение / запись по-прежнему работает как надо.
Протестировано на другом ПК с приложением Java, та же проблема. Так что что-то в ПЛК, кажется, зависает / перестает работать.
Вот как мы настроили обработку событий:
// Implementation of the CallbackListenerAdsState interface
public class ADSEventController implements CallbackListenerAdsState {
......
// Register itself as listener for the ADS events (in constructor)
callObject = new AdsCallbackObject();
callObject.addListenerCallbackAdsState(this);
....
// Event handling
public void onEvent(AmsAddr addr, AdsNotificationHeader notification, long user) {
log.info("Got ADS event for handle[{}] and with raw data[{}]", user, notification.getData());
......
// Registering notification handles for PLC variables
// If we already assigned a notification, delete it first (while reconnecting)
JNILong notification = new JNILong();
if(var.getNotification() != null) {
notification = var.getNotification();
AdsCallDllFunction.adsSyncDelDeviceNotificationReq(addr,notification);
}
// Specify attributes of the notificationRequest
AdsNotificationAttrib attr = new AdsNotificationAttrib();
attr.setCbLength(var.getSize());
attr.setNTransMode(AdsConstants.ADSTRANS_SERVERONCHA);
attr.setDwChangeFilter(1000); // 0.01 sec
attr.setNMaxDelay(2000); // 0.02 sec
// Create notificationHandle
long err = AdsCallDllFunction.adsSyncAddDeviceNotificationReq(
addr,
AdsCallDllFunction.ADSIGRP_SYM_VALBYHND, // IndexGroup
var.getHandle(), // IndexOffset
attr, // The defined AdsNotificationAttrib object
var.getHandle(), // Choose arbitrary number
notification);
var.setNotification(notification);
if (err != 0) {
log.error("Error: Add notification: 0x{} for var[{}]", Long.toHexString(err), var.getId());
}
1 ответ
Нам удалось найти причину. Когда мы регистрируем переменную, мы получаем дескриптор (long) из ПЛК, который в нашем случае неожиданно начал принимать отрицательные значения через некоторое время. Мы также использовали это длинное значение в качестве пользовательской ссылки для уведомлений, однако обнаружили, что пользовательская ссылка является длинной без знака в библиотеке ADS.
Таким образом, если мы установим отрицательное значение, например, -1258290964 как "произвольное число" в вызове adsSyncAddDeviceNotificationReq, то в методе CallbackListenerAdsState onEvent 'user' (Long) будет получено длинное представление без знака нашей подписанной длинной пользовательской ссылки, которая равна 3036676332. В нашем В приложении Java мы использовали эту ссылку пользователя, чтобы сопоставить событие с определенной переменной plc с помощью этого дескриптора. Поскольку в нашем примере мы ожидали -1258290964, но получили 3036676332, мы никогда не обрабатывали никаких событий.