BTW, this ended up being very helpful. I stumbled around on this for quite a while until I figured out how to use the augmenter. (Due to some oddities in my modules to work around Wicket. And to continue using XML for some stuff.)
I'll probably have a pile of v8.3 alphas to share next week.
There's a PR waiting on QA that breaks some Milo API stuff (just a simple Search and Replace), and after that is merged and published I'll update the example with the API changes and see about adding config validation as well.
Yeah, boatloads of ugly annotations that eventually make their way into the JSON schema for that resource type. But at least you don't have to create the schema by hand.
public record Connectivity(
@FormCategory("CONNECTIVITY")
@FormField(FormFieldType.TEXT)
@Label("Hostname *")
@Required
@Description("Hostname/IP address of the device.")
String hostname,
@FormCategory("CONNECTIVITY")
@Label("Port *")
@FormField(FormFieldType.NUMBER)
@Maximum("65535")
@Minimum("1")
@DefaultValue("102")
@Required
@Description("Port to connect to.")
int port,
@FormCategory("CONNECTIVITY")
@Label("Timeout *")
@FormField(FormFieldType.NUMBER)
@DefaultValue("30000")
@Required
@Description("Maximum amount of time to wait for a response in milliseconds.")
Duration timeout
) {
private void validate(ValidationErrors.Builder errors) {
errors.requireNotBlank(
"connectivity.hostname",
hostname
).checkField(
port >= 1 && port <= 65535,
"connectivity.port",
"Port must be between 1 and 65535"
).checkField(
timeout.toMillis() >= 1 && timeout.toMillis() <= Integer.MAX_VALUE,
"connectivity.timeout",
"Timeout must not be negative and must be less than 24 days" // Int.MAX_VALUE in millis is ~24 days
);
}
}
Perhaps, I have no idea how the web stuff hooks up yet, or even if it’s a different story for third vs first party modules. I’ll have to look into this a bit.
I’ve only verified my Modbus Server driver compiles for 8.3 at this point.
maybe some kind of menu action returned from your impl of DeviceExtensionPoint?
public List<MenuAction> getMenuActions() {
return List.of(new MenuAction(
"Addresses",
"Device Configuration",
new ReactComponentInfo("DeviceConfiguration", JS_MODULE))
);
}
as for what is actually expected of your JS file... no idea. Probably some kind of react BS. I'll have to talk to some front end guys to see where we are at with an SDK example I guess.
Made progress, and now have config UIs showing up for both your module and mine.
However. Neither actually works. Unlike in v8.1, my Device implementation is getting called to browse/gather nodes that do not belong to my driver, and to read attributes that don't exist for variable nodes (UserExecutable and EventNotifier, in particular), and I can't seem get past that to get to a working subscription item.
(Your modbus server driver makes folders on browse where I expected variables, like HR0.)
This is expected, there are some places in the server implementation where attributes are read indiscriminately before the NodeClass is known.
A call to gather is expected - gather is called when some Node you don't control is being browsed to see if you have a reference to contribute. browse should only get called for Nodes that pass the AddressSpaceFilter, though... I think.