Detecting how a Thing was created?

I am doing some modification work on a binding. My question is: is there any way that the Thing Handler code can determine how a Thing was created – a) from a .things file, b) from the Inbox, or c) created manually by the user in the UI ??

No. At least none that is obvious.

There must at least be a (non obvious) way, since the standard UI Thing configuration page marks the parameters as read only if the Thing was created via a .things file. Or ??

You could try to determine which provider created the thing (or check the REST API), but I doubt you can find a difference between a user-created managed thing and a thing added from the inbox.

Why do you need that information?

If you get the JSON representation via REST API, there is a property ‘editable’ or ‘managed’, if that’s false it was file-based.

1 Like

I am actually trying differentiate legacy vs new behavior depending on how the Thing was created. I am using a Config Param which is absent in legacy .things files, but can be created in new Inbox auto discovered Things. But the difficult case is is new Things manually created in the UI.

But what happens if someone creates a new thing in .things files?

Then they can include the respective Config Param in it.

Note: this is a slight change of meaning from the subject line of the original post, but I am posting here because it follows my logical chain of thought from which the original question arose.

=> Do you guys have any thoughts on the following idea? …

I am wondering if instead of having a Config Param to differentiate the legacy/new behaviour of a single class of Thing, I might instead have two classes of shade – namely “mything” (legacy) and (say) “mything2”. The latter’s Thing handler would extend the former’s having 99% the same functionality, with minor overrides to replace legacy with new behaviour. Then all new Things could be created as instances of “mything2” whereas legacy ones would have already been created as instances of “mything”.

I might still have a config param on “thing” which, if set, would force migrateThingType() to “mything2” if the config param is expressly set. Or something like that… ??

/**
 * Informs the framework that the ThingType of the given {@link Thing} should be changed.
 *
 * @param thing thing that should be migrated to another ThingType (must not be null)
 * @param thingTypeUID the new type of the thing (must not be null)
 * @param configuration a configuration that should be applied to the given {@link Thing}
 */
void migrateThingType(Thing thing, ThingTypeUID thingTypeUID, Configuration configuration);

PS I think in this case if would be nice if there was a way to hide “mything” from the Thing creation options in Main UI; so that new users would only be able to create “mything2” instances.

You can always label it “obsolete do not use”, is that an XML thing?

Separate new and old Thing types is less likely to lead to the user problems seen with e.g. zwave, where a binding update can cause stuff to just stop working until Thing delete/recreate.

2 Likes

Good point.

Yes it has a thing-types xml description. I have not tried it yet, but the schema mentions a ‘listed’ attribute that might be what I need…

thing-type.listed	Denotes if user interfaces should list the bridge/Thing, e.g. for pairing

I think I found the solution…

  • I implemented two Thing types shade (legacy) & shade2 (new functionality) – the latter overrides a single method on the former.
  • The Thing description xml declares shade with attribute listed=false and shade2 with attribute listed=true. Otherwise all Channels etc are the same.
  • Thing type shade has a config param newSecondaryMode. And if this is set, it triggers a call to changeThingType() as shown in the code below…
/*
 * If the ThingTypeUid is THING_TYPE_SHADE (i.e. a "legacy secondary mode" Thing) and there is a
 * newSecondaryMode configuration parameter with the value TRUE, then change our ThingTypeUid to
 * THING_TYPE_SHADE2 (i.e. to a "new secondary mode" Thing).
 */
if (THING_TYPE_SHADE.equals(getThing().getThingTypeUID())) {
    Boolean newSecModeParam = getConfigAs(HDPowerViewShadeConfiguration.class).newSecondaryMode;
    boolean newSecModeValue = newSecModeParam != null ? newSecModeParam.booleanValue() : false;
    logger.trace("New Secondary Mode: Config Param value:{}, Final value:{}", newSecModeParam, newSecModeValue);
    if (newSecModeValue) {
        Configuration configuration = getConfig();
        configuration.remove(HDPowerViewShadeConfiguration.NEW_SECONDARY_MODE);
        changeThingType(THING_TYPE_SHADE2, configuration);
    }
}