Changing imported configurations during record migration

Does anyone know if there is a way to change the values during the 8.1 update process to 8.3? I’m in a weird position where my 8.3 device config needs a FormFieldType.SELECT as a dropdown option. When I save it, the value that is saved is the Enum’s name() field, so I get values stored as “GenericDevice”. The problem becomes that field in 8.1 is stored as a string, like “Generic device”. When applying my migration strategy, the 8.1 value is stored as is.

I’ve chased this from both ends, trying to get my 8.3 devices to save by overriding the Enum’s toString, but that hasn’t worked. I’ve also looked at DefaultRecordEncodingDelegate.withFieldEncoder, but I’m not sure what instance I would provide the function. If anyone has any suggestions I’d appreciate it.

You can do anything you want in your migration strategy. What does it currently look like?

Hi Paul,

Following Kevin’s example mentioned here: IdbMigrationStrategy for Device ExtensionPoints

something like this:

strategies.add(ExtensionPointRecordMigrationStrategy
        .newBuilder(SnmpV1DeviceExtensionPoint.TYPE_ID)
        .resourceType(DeviceExtensionPoint.DEVICE_RESOURCE_TYPE)
        .profileMeta(DeviceSettingsRecord.META)
        .settingsRecordForeignKey((SFieldReference<?>) SnmpV1DriverSettings.DEVICE_SETTINGS)
        .settingsMeta(SnmpV1DriverSettings.META)
        .settingsEncoder(encoder ->
                encoder.withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.SNMP_HOST_NAME, "connectivity.snmphostname")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.SNMP_PORT, "connectivity.snmpport")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.SNMP_TRANSPORT, "connectivity.snmptransport")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.SNMP_COMMUNITY, "security.snmpcommunity")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.MAX_ITEMS_PER_READ_REQUEST, "advanced.maxitemsperreadrequest")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.READ_TIMEOUT, "advanced.readtimeout")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.WRITE_TIMEOUT, "advanced.writetimeout")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.RETRIES, "advanced.retries")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.CONCURRENT_REQUESTS, "advanced.concurrentrequests")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.ENABLE_CONNECT_CHECK, "advanced.enabledconnectcheck")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.INDEX_CHECK_RATE, "advanced.indexcheckrate")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.MIB_TYPE, "advanced.mibtype")
                        .withCustomFieldName((SFieldMeta) SnmpV1DriverSettings.CUSTOM_MIB_PATH, "advanced.custommibpath"))
        .build());

The field I’m concerned with is the MIB type.

withFieldEncoder is probably gonna be the answer here.

If you squint a little at the syntax, you can see how the OPC UA module upgrades on of its fields from a String containing a comma-separated list to a JSON array:

withFieldEncoder(OpcUaServerSettingsRecord.BIND_ADDRESS_LIST) { record, jsonObject ->
    val field: SFieldMeta =
        record.meta.getField(OpcUaServerSettingsRecord.BIND_ADDRESS_LIST.fieldName)

    val bindAddresses: JsonArray = JsonArray().apply {
        record.getString(field).commaSeparatedList().forEach { add(it) }
    }

    jsonObject.getAsJsonObject("endpoint").add("bindAddresses", bindAddresses)
}

edit: though I'm not sure why it's overcomplicating getting the field value, could just be:

record.getString(OpcUaServerSettingsRecord.BIND_ADDRESS_LIST).commaSeparatedList().forEach { add(it) }

probably an artifact of some refactoring or API change a while ago.

Hi Kevin,

Thanks for that. I was able to figure out I can do something like the following:

                                .withFieldEncoder(SnmpV1DriverSettings.META.getField(SnmpV1DriverSettings.MIB_TYPE.getFieldName()), (PersistentRecord record, JsonObject jsonObject) -> { // record arg is instance of PersistentRecord getting converted, jsonObject is the config.json file being made for this device
                                    String oldRecord = record.getString(SnmpV1DriverSettings.MIB_TYPE); // access your field

// your logic here
                                    jsonObject.getAsJsonObject("outerKey").addProperty("innerKey", newValue); // outerKey is a json object under the settings json object, and innerKey maps to a string

                                })