Ignition Settings Next Page

Im killing ya here. Again I appreciate your help thus far.

What is the .idb?

data/db/config.idb in the install directory - it’s the actual SQLite file that holds all gateway configuration.

I did that, and then restarted the gateway… to no avail

This is my base record:

What’s happening in your startup hook that’s calling a query? You’re no longer getting an error on setup(), at least…

image

This is my startup. Used to only use a “MirSettingsRecord”

Perhaps I should comment this out?

I know I have to refactor this method to maybe check for existence of MirSettingsRecord’s before attempting a query… the idea is I will have a bunch of “***SettingsRecord’s” sub things to query and then launch specific agents.

OK I commented out my terrible query code thats useless now.

I got my base record action table. When I click the create new link, it gives the internal error

I am wondering if this is because I have supplied to configPageChoice thing in the ExtensionPointType. You did say that above.

image

I think the eventual refactor would be to query for all SCMBaseRecords, then look up the extension point type (via the type field on the base record) and create the child instances. I’m not sure why you’re getting the no such column error with the way your code is written, though - the column should absolutely exist. You can try looking at the actual database structure to verify the columns match what you expect? You can use any SQLite compatible tool (most IDEs, DB Browser For SQLite, sqlite’s command line interface, etc).

What’s the stack trace when you try to create a new instance?

Are you implementing getExtensionPoints() on your ExtensionPointManager, or just returning null?

@PGriffith

Returning null :blush: I am not the best module developer out there I guess.

How do I ‘implement’ this? i.e. what should I be returning?

Return a list of constructed objects - in your case, something like List.of(new MirExtensionPoint()) or whatever your class that extends ExtensionPointType is.

Ok. So adding that worked.

I now have this:

I returned List.of(new SCMBaseType(“SCMBase”, “BaseType”, “BaseTypeDesc”)

However this isn’t really how I thought this was going to work. What I need is a selectable item for “MIRSettingsRecord”… and any other things I make. Whats the point of the base type? Is that only for storing metadata from each record in the base recordActionTable? If so, Im assuming I will have to create an ExtensionPointType for each of my subthings? For example: 1 for ‘MirSettingsRecord’ in this case?

Edit: I have to stop working for today. Can continue this tomorrow. Thanks for the help today

Yes, exactly that. The base record will only have common values (at the most generic, just the name) - the individual records have whatever configuration details are appropriate for each subclass.
For instance, device drivers each have name and description at the common level, but it makes no sense to have a Reverse Word Order setting from the Modbus driver on the TCP driver - that's the value of extension points and the 'subrecords'.

Ok great. I am dangerously close now. Only problem now is an ‘internal error’ when its supposed to pull of my MirSettings for the MirExtensionType

Maybe this is caused by the verifySchema() func failing…

Heres what I have now.

Base type:

Mir sub type (im supposed to extend SCMBaseType here right?)

image

Extension point manager

MirSettingsRecord has the profile stuff

SCMBaseRecord for storing common data across sub types

SCMBaseSettingsPage as main interface

Gateway hook sets up the SCMBaseSettingsPage

Errors:

when I try to create a record of my sub type

Update:

I completely reset ignition, stopped the service deleted config.idb…

Now I actually get through to the record. When I create the record however, this happens:

@PGriffith
No record is created, even though it says success :frowning:

Please consider pasting code and tracebacks and any other text results here as text in a code block (the </> button). Screenshots are unreadable on small screens and unfriendly to those who might otherwise copy/edit/paste your code samples as new samples… ):

Sure thing.

Summary from the top:

Step1: Implement the IConfigTab in your gateway hook, and to ensure your panel shows, override getConfigPanels() AND getConfigCategories()

    public static final ConfigCategory CONFIG_CATEGORY = new ConfigCategory("JMPSCMCONFIG", "config.nav.header");

    // Setup Tab Items (pages)
    public static final IConfigTab CONFIG_ENTRY = DefaultConfigTab.builder()
            .category(CONFIG_CATEGORY)
            .name("mirconfig")
            .i18n("config.nav.settings.title")
            .page(SCMBaseSettingsPage.class)
            .terms("AMR settings")
            .build();
    /** 
     * @return List<? extends IConfigTab> a list of configuration panels to present in the gateway settings panel
     */
    @Override
    public List<? extends IConfigTab> getConfigPanels() {
        return List.of(CONFIG_ENTRY);
    }


    /** 
     * @return List<ConfigCategory> a list of configuration categories to present in the gateway settings panel
     */

    @Override
    public List<ConfigCategory> getConfigCategories() {
        return List.of(CONFIG_CATEGORY);
    }

Step 2: Add Your exntesion of BaseExtensionPointType

@SuppressWarnings("serial")
public class SCMBaseType extends BaseExtensionPointType {

    public SCMBaseType(String typeId, String nameKey, String descriptionKey) {
        super(typeId, nameKey, descriptionKey);
    }

    @Override
    public RecordMeta<? extends PersistentRecord> getSettingsRecordType() {
        return SCMBaseRecord.META;
    }

    @Override
    public ConfigPanel newRecordConfigPanel(PersistentRecord[] records, IConfigPage configPage,
            ConfigPanel parentPanel) {
        return super.newRecordConfigPanel(records, configPage, parentPanel);
    }
}

Step 3: Add subclasses for the sub things you want to model..

@SuppressWarnings("serial")
public class MirExtensionType extends SCMBaseType {

    public MirExtensionType(String typeId, String nameKey, String descriptionKey) {
        super(typeId, nameKey, descriptionKey);
    }
    @Override
    public RecordMeta<? extends PersistentRecord> getSettingsRecordType() {
        return MirSettingsRecord.META;
    }
}

Step 4: Create SettingsRecords for all your types.

At this step it is important to note that your sub record must contain a reference field pointing back to the base record. This is done with the below fields:

// Link to the base record type
    public static final LongField ProfileId = new LongField(META, "ProfileId", SFieldFlags.SPRIMARY_KEY);
    public static final ReferenceField<SCMBaseRecord> Profile = new     ReferenceField<(META,SCMBaseRecord.META, "Profile", ProfileId);

Base record stores the common things from your sub records.. ex. below

@SuppressWarnings("serial")
public class SCMBaseRecord extends PersistentRecord {

    public static final RecordMeta<SCMBaseRecord> META = new RecordMeta<>(SCMBaseRecord.class, "SCMBaseRecord").setNounKey("SCMBaseRecord.Noun").setNounPluralKey("SCMBaseRecord.Noun.Plural");
    public static final IdentityField Id = new IdentityField(META);
    public static final StringField Type = new StringField(META, "Type", SFieldFlags.SMANDATORY, SFieldFlags.SDESCRIPTIVE);
    static final Category Configuration1 = new Category("SCMBaseRecord.Category.Category1", 1000).include(Id, Type);

    @Override
    public RecordMeta<?> getMeta() {
        return META;
    }
}

Step 5: Create an ExtensionPointManager

This will 'manange' your extensionpoints, getExtensionPoints() is where you insert your Sub types. This will allow a list to pop when you go the the ExtensionPointPage wizard.

public class SCMExtensionPointManager implements ExtensionPointManager {

    @Override
    public @Nullable ExtensionPointType getExtensionPoint(String typeId) {
        return null;

    }

    @Override
    public List<? extends ExtensionPointType> getExtensionPoints() {
        return List.of(new MirExtensionType("MIR", "MIR Fleet", "SCM For MIRFleet Control"),  new         OTTOExtensionType("OTTO", "OTTO Fleet", "SCM For Controlling an OTTO Fleet"));
    }
}

Step 6: Create an ExtensionPointPage

This is where your tabbuilder from the gateway hook links to your base settings page.

public class SCMBaseSettingsPage extends ExtensionPointPage<SCMBaseRecord> {

    public static final Pair<String, String> MENU_LOCATION = 
Pair.of(GatewayHook.CONFIG_CATEGORY.getName(), "mirconfig");

    public SCMBaseSettingsPage(IConfigPage configPage) {
        super(configPage);
    }

    @Override
    protected ExtensionPointManager getExtensionPointManager() {
        return new SCMExtensionPointManager();
    }
    @Override
    public Pair<String, String> getMenuLocation() {
        return MENU_LOCATION;
    }

    @Override
    protected RecordMeta<SCMBaseRecord> getRecordMeta() {
        return SCMBaseRecord.META;
    }
}

NOTE: This still does not work yet. I am missing something since nothing gets added to my base record when I create a subrecord. Do not know what I am missing :frowning: