OPC-UA Device - Replacement for ConfigurationUILink

In my driver module i used the deprecated? xopc.driver api. For Ignition 8 i am now converting to the new opcua.server api, but i can’t find a replacement for the configuration links (com.inductiveautomation.xopc.driver.api.configuration.links.ConfigurationUILink).

Can a developer please give me a hint how to implement custom settings pages with the new api?

There’s no replacement right now.

It does look like the DeviceType can override addRecordInstanceActions, which is what the previous API used under the hood, but there’s no direct replacement yet.

Here’s a replacement:


private static class ConfigurationUIAction extends AbstractRecordInstanceAction<DeviceSettingsRecord> {

    private final ConfigurationUILink link;
    private final RecordModel<PersistentRecord> recordModel;

    private ConfigurationUIAction(
        String id,
        IConfigPage configPage,
        ConfigPanel parentPanel,
        DeviceSettingsRecord record,
        PersistentRecord subRecord,
        ConfigurationUILink link) {

        super(id, configPage, parentPanel, record);

        this.link = link;

        recordModel = new RecordModel<>(subRecord);
    }

    @Override
    protected void onDetach() {
        super.onDetach();

        recordModel.detach();
    }

    @Override
    protected ConfigPanel createPanel(DeviceSettingsRecord record) {
        PersistentRecord subRecord = recordModel.getObject();
        return link.getConfigurationUI(getConfigPage(), getParentPanel(), subRecord, new ConfigCallback(record));
    }

    @Override
    public IModel getLabel() {
        return Model.of(link.getLinkText(getLocale()));
    }

    @Override
    protected String getCssClass() {
        return "";
    }
}

Then override in DeviceType:

@Override
public void addRecordInstanceActions(
    RepeatingView view,
    IConfigPage configPage,
    ConfigPanel parentPanel,
    PersistentRecord mainRecord,
    PersistentRecord subRecord) {

    driverType.getLinks().stream()
        .filter(link -> link instanceof ConfigurationUILink)
        .forEach(link -> {
            ConfigurationUIAction action = new ConfigurationUIAction(
                view.newChildId(),
                configPage,
                parentPanel,
                (DeviceSettingsRecord) mainRecord,
                subRecord,
                (ConfigurationUILink) link);

            view.add(action);
        });
}

Wow, you are fast!

Where do you import ConfigCallback from?

I'm cheating and just copying old code :wink:

Oops, left that out:

private static class ConfigCallback implements ConfigurationUILink.Callback {

    private final String tableName;
    private final KeyValue key;

    private ConfigCallback(DeviceSettingsRecord parentRecord) {
        tableName = parentRecord.getMeta().getTableName();
        key = new KeyValue(parentRecord);
    }

    @Override
    public void save(PersistentRecord record) {
        GatewayContext context = <somehow get this>;

        context.getPersistenceInterface().save(record);

        if (tableName != null) {
            try {
                RecordMeta meta = (RecordMeta) context.getSchemaUpdater().findRecordMeta(tableName);
                PersistentRecord parentRecord = context.getPersistenceInterface().find(meta, key.getKeyValues());

                context.getPersistenceInterface().notifyRecordUpdated(parentRecord);
            } catch (Throwable t) {
                Logger.getLogger("ConfigCallback").warn("Error during notifyRecordUpdated().", t);
            }
        }
    }

}