Ignition 8.0.12
@Kevin.Herron
I try to create devices with system.device.addDevice.
I create modbus devices and other devices from my own module.
It’s OK but I have problem with devices types containing some password field:
These fields are declared with:
public static final EncodedStringField AUTH_PASS_PHRASE = new EncodedStringField(META, "AuthPassphrase", SFieldFlags.SDESCRIPTIVE);
I suppose I need a special encoding for password props in the deviceProps dictionnary ?
system.device.addDevice(deviceType=deviceType,deviceName=deviceName,deviceProps=deviceProps)
I don’t think you have to do anything, just pretend it’s a StringField.
When I try to create the device with an EncodedStringField (position 11) I have the following error in the gateway:
public static final EncodedStringField PRIV_PASS_PHRASE = new EncodedStringField(META, "PrivPassphrase", SFieldFlags.SDESCRIPTIVE);
DeviceManagerNamespace
12May2020 13:29:41
Device ‘TRAP_SNMP’ failed to start
simpleorm.utils.SException$Jdbc: Getting Field 11 from simpleorm.sessionjdbc.SSessionJdbcHelper@29058fce
at simpleorm.sessionjdbc.SSessionJdbcHelper.retrieveRecord(SSessionJdbcHelper.java:491)
at simpleorm.sessionjdbc.SQueryExecute.findOrCreateFromResultSet(SQueryExecute.java:196)
at simpleorm.sessionjdbc.SQueryExecute.executeQuery(SQueryExecute.java:68)
at simpleorm.sessionjdbc.SSessionJdbc.queryNoFlush(SSessionJdbc.java:525)
at simpleorm.sessionjdbc.SSessionJdbc.query(SSessionJdbc.java:534)
at com.inductiveautomation.ignition.gateway.localdb.persistence.PersistenceSession.queryOne(PersistenceSession.java:48)
at com.inductiveautomation.ignition.gateway.model.BaseExtensionPointType.findProfileSettingsRecord(BaseExtensionPointType.java:109)
at com.bouyguesenergiesservices.ignition.snmp.atd.configuration.ATDTrapDriverTypeV1V2cV3.createDriver(ATDTrapDriverTypeV1V2cV3.java:33)
at com.inductiveautomation.ignition.gateway.opcua.server.DriverAdapter.startup(DriverAdapter.kt:128)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManagerNamespace$DeviceAddressSpace.onStartup(DeviceManagerNamespace.kt:313)
at com.inductiveautomation.ignition.common.lifecycle.AbstractLifecycle.startup(AbstractLifecycle.java:18)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManagerNamespace.createAndStartupDevice(DeviceManagerNamespace.kt:198)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManagerNamespace.access$createAndStartupDevice(DeviceManagerNamespace.kt:44)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManagerNamespace$DeviceSettingsRecordListener$recordAdded$1.invokeSuspend(DeviceManagerNamespace.kt:258)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:271)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:79)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManagerNamespace$DeviceSettingsRecordListener.recordAdded(DeviceManagerNamespace.kt:257)
at com.inductiveautomation.ignition.gateway.opcua.server.DeviceManagerNamespace$DeviceSettingsRecordListener.recordAdded(DeviceManagerNamespace.kt:255)
at com.inductiveautomation.ignition.gateway.localdb.PersistenceInterfaceImpl.notifyRecordAdded(PersistenceInterfaceImpl.java:168)
at com.inductiveautomation.ignition.gateway.redundancy.RedundantPersistenceInterfaceImpl.doNotifyRecordAdded(RedundantPersistenceInterfaceImpl.java:98)
at com.inductiveautomation.ignition.gateway.redundancy.RedundantPersistenceInterfaceImpl$RecordUpdateListener.recordAdded(RedundantPersistenceInterfaceImpl.java:398)
at com.inductiveautomation.ignition.gateway.redundancy.RedundantPersistenceInterfaceImpl$RecordAddedMessage.notify(RedundantPersistenceInterfaceImpl.java:474)
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:912)
at com.inductiveautomation.ignition.gateway.redundancy.RedundancyManagerImpl$ExecuteTask.run(RedundancyManagerImpl.java:984)
at com.inductiveautomation.ignition.common.execution.impl.BasicExecutionEngine$ThrowableCatchingRunnable.run(BasicExecutionEngine.java:518)
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.IllegalArgumentException: Bad Hex Character
at com.inductiveautomation.ignition.common.HexUtils.convert(HexUtils.java:70)
at com.inductiveautomation.ignition.common.GatewaySec.decrypt(GatewaySec.java:70)
at com.inductiveautomation.ignition.gateway.localdb.persistence.EncodedStringField.queryFieldValue(EncodedStringField.java:36)
at simpleorm.sessionjdbc.SSessionJdbcHelper.retrieveRecord(SSessionJdbcHelper.java:488)
... 38 common frames omitted
line 33 is findProfileSettingsRecord
package com.bouyguesenergiesservices.ignition.snmp.atd.configuration;
import com.bouyguesenergiesservices.ignition.snmp.atd.ATDTrapDriverV1V2cV3;
import com.bouyguesenergiesservices.ignition.snmp.atd.configuration.settings.ATDTrapDriverV1V2cV3Settings;
import com.inductiveautomation.ignition.gateway.localdb.persistence.PersistentRecord;
import com.inductiveautomation.ignition.gateway.localdb.persistence.RecordMeta;
import com.inductiveautomation.ignition.gateway.localdb.persistence.ReferenceField;
import com.inductiveautomation.ignition.gateway.opcua.server.api.DeviceSettingsRecord;
import com.inductiveautomation.xopc.driver.api.Driver;
import com.inductiveautomation.xopc.driver.api.DriverContext;
import com.inductiveautomation.xopc.driver.api.configuration.DriverType;
/**
* ATDTrapDriverTypeV1V2cV3
*/
public class ATDTrapDriverTypeV1V2cV3 extends DriverType {
public static final String TYPE_ID = "ATDTrapDriverV1V2cV3";
public ATDTrapDriverTypeV1V2cV3() {
/* DisplayName and Description are retrieved from ATDTrapDriverV1V2cV3.properties */
super(TYPE_ID, "ATDTrapDriverV1V2cV3.Meta.DisplayName", "ATDTrapDriverV1V2cV3.Meta.Description");
}
@Override
public RecordMeta<? extends PersistentRecord> getSettingsRecordType() {
return ATDTrapDriverV1V2cV3Settings.META;
}
@Override
public Driver createDriver(DriverContext driverContext, DeviceSettingsRecord deviceSettings) {
ATDTrapDriverV1V2cV3Settings settings =
findProfileSettingsRecord(driverContext.getGatewayContext(), deviceSettings);
return new ATDTrapDriverV1V2cV3(driverContext, settings);
}
@Override
public ReferenceField<?> getSettingsRecordForeignKey() {
return ATDTrapDriverV1V2cV3Settings.DEVICE_SETTINGS;
}
}
Hmm. Okay well you shouldn’t have to do this but I think maybe the reflective way that system.opc.addDevice sets properties on records is bypassing it, so…
Try calling GatewaySec.encrypt()
on the password value before creating the record?
That’s probably not something that should be on the forum… I know, security by obscurity is not a great approach, but that class offers particularly acute mischief.
Thanks @Kevin.Herron , I’ve found my issue.
I don’t need GatewaySec.encrypt() for EncodedStringField.
You’re right : system.device.addDevice is doing the job.
My issue was due to the fact that those fields was not passed to the deviceProps dictionnary (because I checked field value was not None before adding them to the deviceProps dictionnary)
In my use case I simply added the None value for those fields and the device is created without error.