Device Config Update Live Edit

I've been squashing designer RPC bugs in my EtherNet/IP module and noticed a catch-22: I can't "Save Running XML" without triggering a device restart.

In v8.1, this config was gzipped and written to an auxiliary internal DB table that the OPC server doesn't monitor.

In v8.3, I've moved this XML to the resource system as another file alongside the normal config.json as Config.xml.

I rewrote my "Save Running XML" function to end with this:

        Resource asLocal = devContext.getDecodedResource().resource();
        ResourceBuilder builder = asLocal.toBuilder();
        builder.setResourceCollectionName(asLocal.getDefiningCollectionName());
        Resource asDefined = builder.build();
        builder = asDefined.toBuilder();
        builder.putData("Config.xml", baos.toByteArray());
        Resource modified = builder.build();
        try {
            devContext.getGatewayContext().getConfigurationManager().push(
                    List.of(ChangeOperation.newModifyOp(modified, asDefined.getResourceSignature())));
        } catch (PushException e) {
            iLogger.warn("Unable to save Config.xml", e);
        }

This does put the new snapshot into the resource, but immediately restarts the device itself. Which was already running the changes--that's the point of the live editing, it doesn't persist until deliberately saved. Restart isn't instant, so this will disrupt fast data collection processes. :frowning:

However, I do want the new config propagated to the peer in a redundant pair...

Ideas/options?

Sounds consistent with how the custom SVG libraries are now working.

This line in particular...

  1. Restart the gateway (or POST the /data/api/v1/scan/config endpoint) to pick up the changed resource.

Edit:
Although, updating it with a post probably will still trigger the restart you're trying to avoid.

No, when push a list of changes to the config manager, no scanning is required. If I wrote directly to Config.xml in the resource folder, that might produce the effect I want on the master system, but I don't think it will propagate without scanning. And any random later scan for other purposes would restart the live device at that point.

I suppose I could make an entirely separate resource tree for this, under my own module ID (devices are under the OPC server ID). Blegh.

This is in line with my quick/dirty suggestion: use SystemManager::getModuleConfigDir for these files.

Yeah. In either case, I would have to maintain a "foreign key" from devices into the module config. How stable is the resource UUID?

Hmm, not sure what UUID you're talking about.

In resource.json.

Oh jeez... that's not even a part of the core resource system, it's added by NamedResourceHandler::create. It does seem stable though... and looks to be used by a couple other things as a FK. Might have been its intent.

edit: no I remember now, the intent had something to do with assisting the handlers with renames.

Makes sense. Renames is why I wouldn't want to use the device name.

Yeah, the UUID is added to all "named" resources (as distinct from singletons) by various layers of the system. I wouldn't assume it's always present, but the intention is for it to be stable once created, precisely to handle renames.

OK. My plan (not for today):

  • Divert the write of Config.xml when live to the module config dir as ${uuid}.xml, unconditionally overwriting anything there, creating folders as needed.
  • Check during device startup if there is a resource uuid, and if there is a module config dir, and it holds an XML file for that uuid. If so:
  1. Load the alternate file as the config for the device, and
  2. Schedule an independent runnable for a few millis in the future to:
  • Push the new config into the resource collection, and
  • Delete the alternate file.

That will cause a quick extra restart when a live config is present.

My future WebUI will need to unconditionally delete an alternate when directly importing a new Config.xml.