Another BETA. Cleaned out some stray references to com.inductiveautomation.xopc, and made my generic shim a little more generic. (Discovered some conflicts when I started applying these classes to my EtherNet/IP driver.)
For Ignition v8.1.7+: v1.1.13.250341606
This one is solid. Seems more performant than v1.1.12. Will declare it production-grade soon, I think.
Well, I didn't declare it production grade, as I found a couple minor items in the DriverAdapter to Device conversion. I also refactored my CSV versus binary serialization format in the internal database to make it easier to excise the latter in v8.3. Which enabled a feature I've been cogitating on for a while: mitigating the bad behavior of some devices when abutting register ranges cannot be spanned. My config will no longer merge configured ranges of addresses that abut without overlapping, and those boundaries will be honored by the underlying optimizer. This is another BETA.
For Ignition v8.1.7+: v1.1.13.250681940
{ Side note: I had to restart the service after upgrading due to Wicket weirdness. Die! }
We're trying to test out the ELAM mode, and when checking the Extended Lufkin box in the device configuration page, the status immediately goes to N/A and the following error appears in our logs
java.lang.ArrayIndexOutOfBoundsException: Index 256 out of bounds for length 256
at com.automation_pros.modbus.driver.ModbusClient.(ModbusClient.java:83)
at com.automation_pros.modbus.config.ModbusClientDeviceType.createDevice(ModbusClientDeviceType.java:33)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager.createDevice(DeviceManager.kt:240)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager.createAndStartupDevice(DeviceManager.kt:259)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager.access$createAndStartupDevice(DeviceManager.kt:75)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager$DeviceSettingsRecordListener$recordUpdated$1.invokeSuspend(DeviceManager.kt:429)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager$DeviceSettingsRecordListener.recordUpdated(DeviceManager.kt:371)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager$DeviceSettingsRecordListener.recordUpdated(DeviceManager.kt:346)
at com.inductiveautomation.ignition.gateway.localdb.PersistenceInterfaceImpl.notifyRecordUpdated(PersistenceInterfaceImpl.java:177)
at com.inductiveautomation.ignition.gateway.redundancy.RedundantPersistenceInterfaceImpl.doNotifyRecordUpdated(RedundantPersistenceInterfaceImpl.java:111)
at com.inductiveautomation.ignition.gateway.redundancy.RedundantPersistenceInterfaceImpl$RecordUpdateListener.recordUpdated(RedundantPersistenceInterfaceImpl.java:407)
at com.inductiveautomation.ignition.gateway.redundancy.RedundantPersistenceInterfaceImpl$RecordUpdateMessage.notify(RedundantPersistenceInterfaceImpl.java:457)
at com.inductiveautomation.ignition.gateway.redundancy.RedundantPersistenceInterfaceImpl$RecordUpdateListener.receiveCall(RedundantPersistenceInterfaceImpl.java:390)
at com.inductiveautomation.ignition.gateway.redundancy.QueueableMessageReceiver.receiveCall(QueueableMessageReceiver.java:47)
at com.inductiveautomation.ignition.gateway.redundancy.RedundancyManagerImpl.dispatchMessage(RedundancyManagerImpl.java:1044)
at com.inductiveautomation.ignition.gateway.redundancy.RedundancyManagerImpl$ExecuteTask.run(RedundancyManagerImpl.java:1112)
at com.inductiveautomation.ignition.common.execution.impl.BasicExecutionEngine$ThrowableCatchingRunnable.run(BasicExecutionEngine.java:550)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Error is from version: 1.1.13 (b250681940)
But we saw essentially the same error on 1.1.12 (b250132149)
So, good news is that it no longer errors out when checking that box
Bad news is that after setting up the Device Configuration (I was trying to configure the address ranges for my unit in hopes it would let me pull data), now the module wont start/restart. I can't even remove my created device as it disappeared from the Device Connections page
java.lang.Exception: Exception while starting up module "com.automation_pros.modbus".
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$LoadedModule.startup(ModuleManagerImpl.java:2452)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.startup(ModuleManagerImpl.java:423)
at com.inductiveautomation.ignition.gateway.IgnitionGateway.startupInternal(IgnitionGateway.java:1334)
at com.inductiveautomation.ignition.gateway.redundancy.RedundancyManagerImpl.startup(RedundancyManagerImpl.java:307)
at com.inductiveautomation.ignition.gateway.IgnitionGateway.initRedundancy(IgnitionGateway.java:777)
at com.inductiveautomation.ignition.gateway.IgnitionGateway.lambda$initInternal$1(IgnitionGateway.java:700)
at com.inductiveautomation.ignition.common.execution.impl.BasicExecutionEngine$ThrowableCatchingRunnable.run(BasicExecutionEngine.java:550)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassCastException: class com.automation_pros.modbus.config.ModbusUnitDetails cannot be cast to class com.automation_pros.modbus.config.ModbusClientUnitDetails (com.automation_pros.modbus.config.ModbusUnitDetails and com.automation_pros.modbus.config.ModbusClientUnitDetails are in unnamed module of loader com.inductiveautomation.ignition.gateway.modules.ModuleClassLoader @b9a400a)
at com.automation_pros.modbus.driver.ModbusClient.<init>(ModbusClient.java:84)
at com.automation_pros.modbus.config.ModbusClientDeviceType.createDevice(ModbusClientDeviceType.java:33)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager.createDevice(DeviceManager.kt:240)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager.createAndStartupDevice(DeviceManager.kt:259)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager.registerDeviceType(DeviceManager.kt:204)
at com.inductiveautomation.ignition.gateway.opcua.OpcUaExtensionManager.registerDeviceType(OpcUaExtensionManager.kt:35)
at com.inductiveautomation.ignition.gateway.opcua.server.api.AbstractDeviceModuleHook.serviceReady(AbstractDeviceModuleHook.kt:50)
at com.inductiveautomation.ignition.gateway.services.ModuleServicesManagerImpl.subscribe(ModuleServicesManagerImpl.java:96)
at com.inductiveautomation.ignition.gateway.opcua.server.api.AbstractDeviceModuleHook.startup(AbstractDeviceModuleHook.kt:37)
at com.automation_pros.modbus.GatewayHook.startup(GatewayHook.java:62)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$LoadedModule.startup(ModuleManagerImpl.java:2446)
... 12 more
8.1.44 (b2024102210)
Azul Systems, Inc. 17.0.12
I've had this happen a few times now where editing the device will not seem to do anything because the threads are blocking one another, if interested I can send you a thread dump
heh I seem to have a knack for breaking this, this was accomplished by disabling then re-enabling a device.
So far, I haven't been successful in pulling any data from any devices, I am able to pull valid data using modpoll, still testing the driver to see if i can figure out if it's a configuration issue or not though
java.lang.Exception: Exception while starting up module "com.automation_pros.modbus".
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$LoadedModule.startup(ModuleManagerImpl.java:2452)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.startupModule(ModuleManagerImpl.java:1188)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$4.call(ModuleManagerImpl.java:847)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.executeModuleOperation(ModuleManagerImpl.java:913)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.restartModuleInternal(ModuleManagerImpl.java:827)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl.restartModule(ModuleManagerImpl.java:819)
at com.inductiveautomation.ignition.gateway.web.pages.config.ModulePage$RestartAction.execute(ModulePage.java:575)
at com.inductiveautomation.ignition.gateway.web.components.ConfirmationPanel$1.onClick(ConfirmationPanel.java:49)
at org.apache.wicket.markup.html.link.Link.onLinkClicked(Link.java:190)
at jdk.internal.reflect.GeneratedMethodAccessor109.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.wicket.RequestListenerInterface.internalInvoke(RequestListenerInterface.java:258)
at org.apache.wicket.RequestListenerInterface.invoke(RequestListenerInterface.java:216)
at org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.invokeListener(ListenerInterfaceRequestHandler.java:243)
at org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.respond(ListenerInterfaceRequestHandler.java:236)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:890)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:261)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:218)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:289)
at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:259)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:201)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:282)
at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:210)
at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:527)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:131)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:598)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:223)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1580)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1384)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1553)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1306)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
at com.inductiveautomation.catapult.handlers.RemoteHostNameLookupHandler.handle(RemoteHostNameLookupHandler.java:121)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
at org.eclipse.jetty.rewrite.handler.RewriteHandler.handle(RewriteHandler.java:301)
at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:51)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
at org.eclipse.jetty.server.Server.handle(Server.java:563)
at org.eclipse.jetty.server.HttpChannel$RequestDispatchable.dispatch(HttpChannel.java:1598)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:753)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:501)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:287)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:421)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:390)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:277)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:199)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:411)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:969)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1194)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1149)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NumberFormatException: For input string: "true"
at java.base/java.lang.NumberFormatException.forInputString(Unknown Source)
at java.base/java.lang.Integer.parseInt(Unknown Source)
at java.base/java.lang.Integer.parseUnsignedInt(Unknown Source)
at java.base/java.lang.Integer.parseUnsignedInt(Unknown Source)
at com.automation_pros.modbus.config.ModbusUnitDetails.parseUnsignedDefault(ModbusUnitDetails.java:308)
at com.automation_pros.modbus.config.ModbusUnitDetails.applyCsvItem(ModbusUnitDetails.java:339)
at com.automation_pros.modbus.config.ModbusClientUnitDetails.applyCsvItem(ModbusClientUnitDetails.java:171)
at com.automation_pros.modbus.config.settings.AbstractModbusSettings.decodeUnitsCsv(AbstractModbusSettings.java:92)
at com.automation_pros.modbus.config.settings.AbstractModbusSettings.getUnitDetails(AbstractModbusSettings.java:117)
at com.automation_pros.modbus.driver.ModbusClient.<init>(ModbusClient.java:80)
at com.automation_pros.modbus.config.ModbusClientDeviceType.createDevice(ModbusClientDeviceType.java:33)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager.createDevice(DeviceManager.kt:240)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager.createAndStartupDevice(DeviceManager.kt:259)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManager.registerDeviceType(DeviceManager.kt:204)
at com.inductiveautomation.ignition.gateway.opcua.OpcUaExtensionManager.registerDeviceType(OpcUaExtensionManager.kt:35)
at com.inductiveautomation.ignition.gateway.opcua.server.api.AbstractDeviceModuleHook.serviceReady(AbstractDeviceModuleHook.kt:50)
at com.inductiveautomation.ignition.gateway.services.ModuleServicesManagerImpl.subscribe(ModuleServicesManagerImpl.java:96)
at com.inductiveautomation.ignition.gateway.opcua.server.api.AbstractDeviceModuleHook.startup(AbstractDeviceModuleHook.kt:37)
at com.automation_pros.modbus.GatewayHook.startup(GatewayHook.java:62)
at com.inductiveautomation.ignition.gateway.modules.ModuleManagerImpl$LoadedModule.startup(ModuleManagerImpl.java:2446)
... 63 more
8.1.44 (b2024102210)
Azul Systems, Inc. 17.0.12
Thank you!
I was able to disable with system.device.setDeviceEnabled('<DeviceName>', False)
then delete it by following your instructions
These settings cause it to break again (i get Internal Error, subsequent restart of module causes it to fault), giving the blanks a 0-0 range is successful.
I'm trying to communicate with a Lufkin SAM controller and I can only achieve it if I use a Modbus ID=2 (i.e. in ModbusRTU mode), but when I try to do it using ID=300 (ELAM Mode) I only get Bad quality on my TAGs.