Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Archived » Eclipse SmartHome » Dynamic configuration information
Dynamic configuration information [message #1694226] Sat, 02 May 2015 18:45 Go to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
I can call getConfigDescriptionRegistry.getConfigDescriptions or one of the other methods to get the configuration descriptions for an thing-type. If I wanted to modify these at runtime, and provide my own configuration provider, can I do this? I'm not sure what happens deeper in the system - I assume that only 1 provider can respond to any uri? Or maybe not - if so, how is this managed?

I have two needs -:
1) To be able to add some configuration options into a parameters [options] array. These are only derived at runtime and are system/network dependant, so can't go in the XML.
2) To be able to add additional parameters to the configuration. Again, these are derived at runtime depending on how a device is configured (for example).

I can easily create my own provider and completely avoid using the XML provider, but I'd kind of like to be able to lever off the existing infrastructure and just add to/modify the static configuration rather than have to reimplement everything...

I guess I could (probably!?!) use getConfigDescriptionRegistry.getConfigDescriptions to get the static data, and then create my own provider that appends my data and modified the data that needs to be changed? I would guess it needs a different uri, although I suspect that this might then break something else when the system tries to link thing-types to the configuration provider? This seems a little messy though so maybe there's a better way?

Are there any pointers on how this might be achieved? I'm thinking it might be easier to do it all in my own config provider which is what I'm currently doing (mostly for test and concepts), but I want to work out the best way for a the final implementation...

Cheers
Chris
Re: Dynamic configuration information [message #1694428 is a reply to message #1694226] Tue, 05 May 2015 09:13 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Hi Chris,

Indeed, the idea is that you either use XML or implement your own ConfigDescriptionProvider. Starting with XML and modifying this during runtime is not supported.
Accessing a config description (defined as XML) with another URI and serving this modified through your own provider sounds a bit hacky...
Maybe we could think about adding priorities to the providers, so that XML comes last, if no other provider had a description for a given URI - this would allow to "override" the static answer.

Best regards,
Kai
Re: Dynamic configuration information [message #1694458 is a reply to message #1694428] Tue, 05 May 2015 12:31 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Thanks Kai. i do think it would be worth considering having a way to override the static declarations, but the current implementation is fine with me for now. I just wanted to make sure I wasn't missing something.

Alternatively, is it possible to override the current XML provider - I know the config descriptions are exported and used in the thing XML reader - it would be good to be able to override the thing reader here to add / remove, or just intercept the default function...

I might take a look at this - I don't want to duplicate anything if I can avoid it, so the option to extend seems nice...

Chris
Re: Dynamic configuration information [message #1694470 is a reply to message #1694458] Tue, 05 May 2015 14:01 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Sure, have a look at it yourself - you are probably already deeper in this code than I am Smile
Re: Dynamic configuration information [message #1696195 is a reply to message #1694470] Fri, 22 May 2015 17:34 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hi Kai,
So, getting back to this issue as once the channel parameters gets merged this is probably the last thing holding back the zwave binding...

I see the following options to allow bindings to provide dynamic updates to config data -:

  1. Override the XML provider as per my previous PR. This would allow the binding to provide its own XML in either the same, or slightly different formats. I know you're not keen on this...
  2. As #1 - allow the binding to override the XML reader, but not allow changes to the XML format. I think this should be do-able in a similar way to #1.
  3. Allow the binding to register a 'secondary' provider that can get the ConfigDescriptions from the XML file and change them.
  4. Change the ConfigDescriptionRegistry class so that it appends all responses together rather than returning with the first response it gets.


I still favour #1 or #2 - I think this is most flexible, and it's simple to implement (as per my previous PR). I know it means people can create their own file formats, but if your plan was/is to allow custom readers, then this still seems to be to be better than pushing people to do their own thing completely and ending up with lots of different formats...

#3 would be a substantial change to the interface - probably a separate service to allow an 'over-ride' type service that can be called after the XML reader to allow updating of the static data.

#4 is a relatively simple change to append config descriptions from all providers into a single description. It would allow additional dynamic configuration to be added, but doesn't allow the binding to update the information in the XML dynamically, which is what I also need...

My use case for the updating of static data is that I need to define some configuration in the XML (or somewhere - it's static), but the options available need to be dynamic as they are dependant on the network configuration...

I'm happy to look at any of the options above, or others if you have other thoughts - I think this is the last stumbling block for me so I'd quite like to find a way forward Smile

Cheers
Chris
Re: Dynamic configuration information [message #1696654 is a reply to message #1696195] Wed, 27 May 2015 16:20 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Hi Chris,

I think I can come up with a #5 (at least I will have a try):

In your thing-type.xmls you can use a config-description-ref instead of a config-description section (see here). This is simply a named reference and the config-descriptions can be defined elsewhere - e.g. in your own ConfigDescriptionProvider. If you still want to use static XML to define the main structure, you can put such XMLs in ESH-INF/config. You could e.g. use an ID like "zwave-template1" for them, request it from the ConfigDescriptionRegistry within your provider and modify it (or rather create a modified clone). The result you provide under the id that you reference within your thing types.

Would this fullfil your requirements?

Regards,
Kai

Re: Dynamic configuration information [message #1696688 is a reply to message #1696654] Wed, 27 May 2015 22:37 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hi Kai,
Hmmm - this might do the trick. I've seen these references, but I'm not sure I understand how the URI is used here and how to load config with the XML and then tell the system that the config URI for this thing is something different - can I put all the static config with a URI of 'zwave-template1' for example, and then does the system then use a 'standard' URI for the thing (based on the thing UID)? In which case, in my ConfigDescriptionProvider I can listen to the standard URI, and then do the call to the registery for the non standard URI...

If so, that would work I think Smile

Chris
Re: Dynamic configuration information [message #1696784 is a reply to message #1696688] Thu, 28 May 2015 14:28 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Let me give you an example:

You could have thing types like
<thing:thing-descriptions bindingId="zwave"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:thing="http://eclipse.org/smarthome/schemas/thing-description/v1.0.0"
	xsi:schemaLocation="http://eclipse.org/smarthome/schemas/thing-description/v1.0.0 http://eclipse.org/smarthome/schemas/thing-description-1.0.0.xsd">

	<thing-type id="thermostat">
		<supported-bridge-type-refs>
			<bridge-type-ref id="dongle" />
		</supported-bridge-type-refs>

		<label>Thermostat</label>
		<description>This is a thermostat</description>

		<channels>
			<channel id="actual_temp" typeId="actual_temp" />
			<channel id="set_temp" typeId="set_temp" />
		</channels>

		<config-description-ref uri="thing-type:zwave:thermostat" />
	</thing-type>
</thing:thing-descriptions>


Then you can have in ESH-INF/config/zwave-templates.xml:
<?xml version="1.0" encoding="UTF-8"?>
<config-description:config-descriptions
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:config-description="http://eclipse.org/smarthome/schemas/config-description/v1.0.0"
    xsi:schemaLocation="http://eclipse.org/smarthome/schemas/config-description/v1.0.0
        http://eclipse.org/smarthome/schemas/config-description-1.0.0.xsd">

  <config-description uri="thing-type:zwave:template-thermostat">
  ...
  </config-description>
</config-description:config-descriptions>

Then you can implement your own ConfigDescriptionProvider that provides "thing-type:zwave:thermostat" and internally does a ConfigDescriptionRegistry.getConfigDescription("thing-type:zwave:template-thermostat").

So far the theory Smile
Kai
Re: Dynamic configuration information [message #1696839 is a reply to message #1696784] Thu, 28 May 2015 22:34 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Thanks Kai - sounds good. I'll try and give this a try over the next few days...

Cheers
Chris
Re: Dynamic configuration information [message #1697025 is a reply to message #1696839] Sun, 31 May 2015 16:15 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hi Kai,
I've just digested what you've suggested - I like the concept, and also think this should work. However I see one problem that I would like to try and avoid if possible... With this approach, we're splitting the thing-type definition and the config definition into separate files, which makes it a bit of a pain to maintain the files, and we end up with an extra few hundred files in the case of zwave Sad. Also, if/when we add an index, we'd possibly need to account for this split if we're somehow dynamically loading files...

There are a few possible options I can think of to solve this -:


  1. Add a section to the XML to define a config description template. So we would have <config-description uri=""> followed by <config-description-template uri="">. The reader would then register both URIs but only the 'template' version actually has any description. This is effectively the same as your suggestion, but adding the extra element to allow the description to be incorporated into the same file.
  2. Change the XML schema so that it can take a choice of <config-description>, <config-description-ref> or <config-description-template> (instead of the two choices currently defined). If the template version is provided, then it adds -template to the end of the uri and registers both URIs - as in #1.
  3. We leave the elements alone, but in the <config-description> element, add a template="true" attribute - then the same as above.
  4. Or add your option here Smile


What do you think - there's little difference in all three as far as implementation - it's really just how it looks in the XML and possibly conventions for URIs if they aren't defined...

I will look at a PR for this (hopefully you agree that the descriptions and thing-type needs to be together) and we can discuss the XML...

Cheers
Chris
Re: Dynamic configuration information [message #1697145 is a reply to message #1697025] Mon, 01 June 2015 22:04 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Quote:

Then you can implement your own ConfigDescriptionProvider that provides "thing-type:zwave:thermostat" and internally does a ConfigDescriptionRegistry.getConfigDescription("thing-type:zwave:template-thermostat").

Unfortunately, this doesn't work - it might be possible to make it work, but calling ConfigDescriptionRegistry.getConfigDescription from within another ConfigDescriptionProvider results in recursion.

So, before I continue looking at trying to solve this, I thought I'd make sure you're happy with the approach(es) above?

Any thoughts...

Cheers
Chris


Re: Dynamic configuration information [message #1697169 is a reply to message #1697145] Tue, 02 June 2015 07:22 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Hi Chris,

In the absence of any better idea, yes, we would still suggest this approach. I think the recursion should be simple to solve by making sure that your provider returns when it sees that a template is requested (for which it obviously cannot provide a description). Or am I missing something?

Regards,
Kai
Re: Dynamic configuration information [message #1697247 is a reply to message #1697169] Tue, 02 June 2015 16:58 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
You're right - it was late Smile

Since you're happy with the approach, I'll generate a PR for further discussion...

Chris
Re: Dynamic configuration information [message #1697405 is a reply to message #1697247] Wed, 03 June 2015 16:46 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Hi Chris,

I must admit that I have completely overlooked your comment https://www.eclipse.org/forums/index.php?t=msg&th=1066227&goto=1697025&#msg_1697025, so I actually never commented on your suggested options - sorry for this. I was still of the opinion that we are talking here about a solution for zwave that does not make it necessary to introduce yet a new concept. I discussed this with Dennis briefly today and we would prefer if we could find a way around adding "config description templates" as a general feature.
If I get you right the problem is that you do not want to maintain a separate file for the config descriptions. I haven't tried it out, but would it work to simply put an uri to the embedded config descriptions within the thing type definitions? Something like:

        <channels>
            <channel id="color" typeId="color" />
        </channels>

        <config-description uri="thing-type:zwave:template-lightbulb">
            <parameter name="lightId" type="text">
                <label>Light ID</label>
                <required>true</required>
            </parameter>
        </config-description>


Did you try this?

Regards,
Kai
Re: Dynamic configuration information [message #1697409 is a reply to message #1697405] Wed, 03 June 2015 17:05 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hi Kai,
Yes - I did try this, and it didn't immediately work (I did think it should). However I didn't try tracing through the code to find out why this didn't work (or maybe I just made a mistake somewhere!).

While I don't know that I especially like the template concept, I don't think I'll be the only one who wants to provide dynamic configuration, so I do think that a standard approach should be developed. Using something like the fragment part of the URI at least allows this to be clearly identified. Of course this could still be done if we could specify the uri directly, but adding the template as an attribute does make this standard...

I'll take another look at this if you like...

Chris
Re: Dynamic configuration information [message #1697416 is a reply to message #1697409] Wed, 03 June 2015 17:45 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
So, I confirm this doesn't work. I don't understand why, but I guess by specifying uri="thing-type:zwave:template-lightbulb" in the XML, that this uri is used instead of the default which would have been "thing-type:zwave:lightbulb" based on the thing name.

I can see the requests in the XML provider coming in for the template version - not the default version, so it matches and there's no possibility to intercept.... Adding the template breaks this link, although I can't quite see where.

Sad
Re: Dynamic configuration information [message #1698630 is a reply to message #1697416] Tue, 16 June 2015 19:00 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hi Kai,
Any further thoughts on this issue?

Cheers
Chris
Re: Dynamic configuration information [message #1698685 is a reply to message #1698630] Wed, 17 June 2015 09:14 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Not really - I still think that the suggested approach is the best. Why it does not work, I would have to analyze in detail - did you get any further when debugging?
Re: Dynamic configuration information [message #1698735 is a reply to message #1698685] Wed, 17 June 2015 14:29 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hi Kai,
I didn't debug it further as I wasn't sure where to start. As per my earlier post, if you change the uri, then the system uses this uri, which does make some sense (I think?). I assume that whoever designed the config-parameters, and added the uri, intended the uri="xxx", then xxx should be used, not the default uri? This is what is happening anyway, so it's not possible to use the uri="xxx" to add an intermediary.

Chris
Re: Dynamic configuration information [message #1699365 is a reply to message #1698735] Tue, 23 June 2015 16:48 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hi Kai,
Is this something you think we can solve soon? I'm really keen to get on with the zwave binding - if there's no solution expected for this then I will stick with the OH1 database in order to allow me to proceed with getting an OH2 zwave binding for the next OH2 release.

Cheers
Chris
Re: Dynamic configuration information [message #1699367 is a reply to message #1699365] Tue, 23 June 2015 16:57 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Chris, I will try to find some time tomorrow to debug into it myself. I hope that I will be successful... Neutral
Re: Dynamic configuration information [message #1699389 is a reply to message #1699367] Tue, 23 June 2015 23:41 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Thanks Kai.
Re: Dynamic configuration information [message #1699504 is a reply to message #1699389] Wed, 24 June 2015 16:02 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Chris, I didn't yet succeed, but I found a very severe bug in all the XML parsing regarding config description uris, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=470901
We will try to fix this and I'll further investigate on how to get the templating idea working.

Regards,
Kai
Re: Dynamic configuration information [message #1699687 is a reply to message #1699504] Thu, 25 June 2015 19:56 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Ok, here is some more in depth feedback after digging into things:
1. You are right, when providing an config-desc-uri within a thing type, this uri is considered to be used both for the thing type as well as for the config description; so defining a config description (as a template) that is not directly meant to be the one for the thing type where it is embedded in is simply not possible, so my suggestion led to a dead end.
2. Rereading your initial requirements that you want to solve, I actually think that your suggestion (4) from above might be the way to go for adding parameters dynamically besides the statically defined ones, i.e. if you simply implement another ConfigDescriptionProvider that has answers for the same uris, these could be merged with the ones from the XMLCDProvider within the registry. We just would have to rule out that both provide parameters with the same key and we would have to discuss, if we need any ordering of parameters from different providers.
3. Wrt your second requirement, the dynamic options, I agreed with Dennis that this definitely qualifies for a new kind of service, something like a "ParameterOptionProvider" - this is something that we will probably need very often and which should not require implementing a full ConfigDescriptionProvider.

Would you agree with these points? If so, how about starting with implementing (2)? Would you want to give it a go?

Best regards,
Kai
Re: Dynamic configuration information [message #1699697 is a reply to message #1699687] Thu, 25 June 2015 23:16 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hi Kai,
Thanks for looking into this.

Yes - I think this sounds ok to me and I'll take a look at implementing #2. Regarding ordering, this might be a good idea actually - however maybe it is sufficient to do this at group level (ie order the groups rather than each parameter)?

Cheers
Chris
Re: Dynamic configuration information [message #1699713 is a reply to message #1699697] Fri, 26 June 2015 06:35 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
In the model we deliberately did not define any ordering as we didn't want to have UI related information in it. Nonetheless, the providers can implicitly determine an order as they return a list.
So I am not sure how we should deal with this here the best way. I think I would stay with not officially do sorting, but simply merging things together. It should be possible to dynamically add parameters to statically defined groups as well, so the groups can stay the feature for organizing parameters. Btw, shouldn't we also have a method like ConfigDescription.getParameters(String parameterGroupName)?
Re: Dynamic configuration information [message #1701771 is a reply to message #1699687] Wed, 15 July 2015 13:59 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Kai Kreuzer wrote on Thu, 25 June 2015 21:56
3. Wrt your second requirement, the dynamic options, I agreed with Dennis that this definitely qualifies for a new kind of service, something like a "ParameterOptionProvider" - this is something that we will probably need very often and which should not require implementing a full ConfigDescriptionProvider.


As the first requirement has been implemented by now, it is probably time to also further discuss this one!

I'd suggest to introduce something like

package org.eclipse.smarthome.config.core;

public interface ParameterOptionProvider {

    List<ParameterOption> getOptions(URI parameterURI, Locale locale);

    Set<URI> getSupportedURIs();
}


The ConfigDescriptionRegistry could then check, whether there is any provider registered for a given URL (which might be just a complete config description ("thing-type:hue:LCT001") or a reference to a specific parameter ("thing-type:hue:LCT001#parameterKey") of such a description.

These options should imho be added to the already statically defined options. Or would you see the need to dynamically delete some? I think adding would be in line with how config descriptions themselves are merged as well.

On the REST API, we could additionally add a sub-resource on thing type config descriptions to directly be able to request parameter options; not sure if we will need that in a first step though. Probably only makes real sense if changes would also be evented, which can not easily be done through the suggested architecture.

Looking forward to your feedback!

Cheers,
Kai
Re: Dynamic configuration information [message #1702058 is a reply to message #1701771] Sat, 18 July 2015 14:47 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hi Kai,
I think your suggestion is ok - I've had a bit of a think about it and for me it would work...

I don't (currently) have a need to delete options. I would likely not populate any options for my current use case, and then just add. IF there was a need for statically defined options, then again your thought to only add options is still fine.

I don't see a need for eventing the change in options - and I'm not sure I see the need to request the options separate from the configuration / thingType either. Maybe you're thinking of a possible use case for this, but I can't currently think of one (maybe one day though Smile ). So I would say the additional rest resource is not high priority.

Cheers
Chris
Re: Dynamic configuration information [message #1702068 is a reply to message #1702058] Sat, 18 July 2015 15:30 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hmm - just to be clear - is this working on the thingType, or the thing? At the moment, all the config description stuff is related to the thingType - the issue here is that these options need to be changes depending on the thing - not the thingType (well, the thingType is obviously linked here, but the options need to be changed depending on the thing.

I'm coming up against the same issue in other areas at the moment - some devices, or versions even, have a different 'maximum' for example - this gets read back from the device, and at the moment, the configDescription doesn't provide me this information when the provider gets called so it can't be modified based on the device in question...
Re: Dynamic configuration information [message #1702150 is a reply to message #1702058] Mon, 20 July 2015 10:48 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Quote:
Maybe you're thinking of a possible use case for this, but I can't currently think of one


My use case was e.g. to populate an option list with Wifi SSIDs while they are being discovered, which could take a while. Especially when we are talking about options for a thing and not a thing-type, this means that you are likely to request them FROM the thing on demand, so that the information might not be available immediately. But nonetheless, I hope that we can treat this case with a low priority...

Quote:
I'm not sure I see the need to request the options separate from the configuration / thingType either


According to your last comment, you know see a need to request it separate from the thingType Smile
But this is indeed a good point - currently the config-descriptions are on the thing-type rest endpoint and this is also where we need them: If you create a new thing, all you have is its thing-type, so all meta-data must be available here - potentially also dynamically provided data.

To accomplish the same on things, we might have to add another method to the ParameterOptionProvider like:
    List<ParameterOption> getOptions(ThingUID uid, String parameterId, Locale locale);

and this options would have to be made available somewhere (through getConfigDescription() on the Thing? Only on a new REST endpoint?). I am not quite sure yet, what would be the best approach Sad Any suggestions?

Regards,
Kai
Re: Dynamic configuration information [message #1702211 is a reply to message #1702150] Mon, 20 July 2015 16:28 Go to previous messageGo to next message
Dennis Nobel is currently offline Dennis NobelFriend
Messages: 166
Registered: September 2014
Senior Member
Quote:
To accomplish the same on things, we might have to add another method to the ParameterOptionProvider like:


Well, that´s not possible, at least not if the ParameterOptionProvider should be put inside the config.core bundle. If we want reference a ThingUID we need a specific ThingParameterOptionProvider. Not sure, how that fit´s to the general concept of config descriptions. We would also need multiple REST endpoints depending on the context.

Quote:
If you create a new thing, all you have is its thing-type, so all meta-data must be available here - potentially also dynamically provided data.


I think here the question raises again if configuration parameters can only be set for an existing thing. I´m not sure if there is a need having dynamic parameter options for thing types only.
Re: Dynamic configuration information [message #1702429 is a reply to message #1702211] Wed, 22 July 2015 09:44 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Quote:
I´m not sure if there is a need having dynamic parameter options for thing types only.


What you are trying to say is that the idea of the ParameterOptionProvider applies to any ConfigDescriptions (e.g. in future for rule modules) and not just for thing types.
So yes, introducing a dependency on Things is indeed a no-go.
Which leaves us with Chris' problem that he would like to offer options specific to a certain device at a specific moment. The use case with the WLAN SSIDs is actually also such a case, so I guess sooner or later we need to address this.
Re: Dynamic configuration information [message #1703338 is a reply to message #1702429] Thu, 30 July 2015 17:17 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Kai Kreuzer wrote on Wed, 22 July 2015 10:44

Which leaves us with Chris' problem that he would like to offer options specific to a certain device at a specific moment. The use case with the WLAN SSIDs is actually also such a case, so I guess sooner or later we need to address this.


Where do we go with this one? It's my next target to hit Smile

So, if we don't want to link this to things (and I totally agree with the rationale), then we need an alternative. Currently, we have configDescriptions to describe the configuration options, but the 'other side' of the interface (the actual setting of the config) is done differently for different classes (I think that's true). For example, in the thingHandler, we have the handleConfigurationUpdate method - maybe in the channelHandler there's a similar method (I've not checked) - I don't know what other classes use the configDescriptions (rules I think?) but I guess every implementation is different?

Why aren't there standard interfaces for handling the various configuration related functions. We could have had (eg) ...
// Handle the updates of any configuration
interface ConfigConsumer() {
    void handleConfigurationUpdate(Map<String, Object>);
}

// Handle dynamic configuration updates
interface ConfigDescriptionUpdate() {
    List<ParameterOption> getOptions(String parameterId, Locale locale);
}


A thingHandler, or ruleHandler, or whatever wants to implement configuration implements these interfaces. Then, all configuration, both description, dynamic changes, and handling of changes, could all go through a central provider (and even REST interface!).

As far as implementation (and looking specifically at things here - other implementations would be similar): For registration, when the thingHandler is created, a check could be made to see if it implements this/these interfaces, then to register this handler with the configDescriptionProvider (along with it's UID). When the config descriptions are updated, the configDescriptionRegistry can request the updates from the handler if there's one registered.

One thing I'm unsure of here is the use of the UID. For things/channels etc, it seems a good idea to include the thingUID as it makes it a simple lookup in the configProvider (and if you didn't use the thingUID, I'm not sure how you'd link it). However, will all implementations of configDescriptions have a UID - eg I think I read rules will use the same config services - will they have a UID?

I realise I've probably confused matters by suggesting a common interface for handling of config changes as well as just covering the issue at hand, but I thought I'd mention it since it does in some ways seem a shame to have a common config description provider, but no common way of handling configuration updates/changes etc... Anyway, I hope that didn't confuse matters (too much!) - we could ignore the handleConfigurationUpdate side, and just look at the ConfigDescriptionUpdate, which is the current issue at hand...

What do you think? I've not thought this through in massive detail, but if you think this is workable, I'd be happy to look at the ConfigDescriptionUpdate impementation further...

Chris
Re: Dynamic configuration information [message #1703457 is a reply to message #1703338] Fri, 31 July 2015 16:33 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Sounds like an interesting and good idea to provide a config update mechanism that is independent from the thingtypes, but rather works as a general concept. We can discuss with Dennis, but as you say, it is not the issue at hand.

For that, I do not really see if you just suggested a possible solution? Imho the problem is that we currently have config descriptions for thing type UIDs, but not for thing UIDs. So how could we possibly bridge this gap?

Regards,
Kai
Re: Dynamic configuration information [message #1703491 is a reply to message #1703457] Sat, 01 August 2015 08:38 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Quote:

Imho the problem is that we currently have config descriptions for thing type UIDs, but not for thing UIDs. So how could we possibly bridge this gap?


I believe the above concept should work (but maybe I miss something)... To try and be clearer -:

We define the following interface-:
// Handle dynamic configuration updates
interface ConfigDescriptionUpdate() {
    List<ParameterOption> getOptions(String parameterId, Locale locale);
}


This interface gets implemented by the thingHandler if it wants to support dynamic config options.

In the BaseThingHandlerFactory, when the thing is created (in registerHandler), we check if this interface is implemented by the handler. If it is, then we register this handlers UID with the configDescriptionRegistry. In one view, this is a new registry, but it's linked into the configDescriptionRegistry as in my view we're trying to build a single configDescription registry, that is dynamically customisable for each implementation (you might have a different view - it's not the end of the world to split it - it's just more work to link things together...).

A new method is added to the ConfigDescriptionRegistry -:

void registerUIDUpdata(UID, handler) {
 map.add(UID, handler);
}


This keeps a simple map of UID to handler. Additionally, we add a new method -:
ConfigDescription getConfigDescription(UID genericUID, URI uri, Locale locale) {
  // Get the config descriptions for this URI

  // Get the handler from the map for this UID

  // Call the handler to add the dynamic config changes
  for(parameter : allParameters) {
    parameter.options = handler.getOptions(parameter.Id, locale);
  }
}


Then in the REST interface (or anywhere we need the config information), we can call this new method if it's for a concrete thing, or anything else that uses configDescriptions - so long as they have a UID!

This registration has therefore registered a UID to a handler that implements the ConfigDescriptionUpdate interface - no links between things and config description are specifically made but we have a link from configDescriptions to UIDs implementing the interface.

I think this works, and I think it meets the requirement of not linking concrete classes directly to configDescriptions. However, as above, I've not looked at it in detail - only the concept - so I might miss something... One area I'm slightly concerned about is that UIDs may not be unique, or may not exist in some implementations that support configDescriptions?

Chris
Re: Dynamic configuration information [message #1703900 is a reply to message #1703491] Wed, 05 August 2015 17:03 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hi Kai - I was just wondering if you'd had a chance to consider this?
Re: Dynamic configuration information [message #1703963 is a reply to message #1703900] Thu, 06 August 2015 08:03 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Hi Chris, sorry, no, didn't find the time yet to think about this in detail. From a first glance, I still feel that your proposal mixes config descriptions for thing types and things too much - what we currently have are descriptions for thing types, but by adding a request parameter genericUID, you implicitly make the request to ask for the description of a specific thing of that type. I wonder if we shouldn't rather introduce config descriptions for things explicitly, so that there is no need for some ugly workarounds. Maybe we could have a ConfigDescriptionProvider which simply delegates requests for things to the thing type (and additionally could have the getOptions() callback hook)?

@Dennis, Do you have any ideas or opinions?
Re: Dynamic configuration information [message #1703981 is a reply to message #1703963] Thu, 06 August 2015 11:42 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Hi Kai,
Quote:

I wonder if we shouldn't rather introduce config descriptions for things explicitly

Maybe I misunderstand, but isn't this then moving away from the generic config descriptions? If we do that, then there's no issue with linking it to things of course, but you've lost your generic configDescriptions?

Anyway, expanding on what I think you're suggesting - it could (I think?) be as simple as adding a getConfigDescription method in BaseThingHandler. This calls the configDescriptionProvider to get the configuration descriptions for the thingType, and then calls the getOptions() method which can be overridden by the binding to update the options.

We would then need a new REST endpoint {thingUID}/config to get the config descriptions for the thing.

Chris
Re: Dynamic configuration information [message #1704082 is a reply to message #1703981] Fri, 07 August 2015 08:34 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Quote:
Maybe I misunderstand, but isn't this then moving away from the generic config descriptions?


No, what I mean is that we simply HAVE config descriptions for things and not only for thing type. Having a CD simply means having a CD URI. According to https://www.eclipse.org/smarthome/documentation/development/bindings/xml-reference.html#configuration-descriptions, the URI is uri="{binding|thing-type|bridge-type|channel-type|any_other}:bindingID:...". So for "any_other", we could also add "thing" here, which means that we can reference CDs specific for things and not only for a thing type. This does NOT introduce any kind of dependency from the CDs to things.

Quote:
it could (I think?) be as simple as adding a getConfigDescription method in BaseThingHandler.


No, I wouldn't want to do this. Rather have a system service forwarding config description requests for a thing to its thing type (no impact on ThingHanders and binding API at all).
Then we could have a new interface like your ConfigDescriptionUpdate for providing dynamic option lists, that can be registered on ANY config description uri (i.e. again no impact or dependency on the things).

Quote:
We would then need a new REST endpoint {thingUID}/config to get the config descriptions for the thing.


Yes, so that the UI has a chance to get the specific version for the thing - since every thing of the same thing type might have different dynamic options.

@Dennis: I would appreciate your view as well to make sure I am not missing anything important in this discussion Smile
Re: Dynamic configuration information [message #1704102 is a reply to message #1704082] Fri, 07 August 2015 10:40 Go to previous messageGo to next message
Dennis Nobel is currently offline Dennis NobelFriend
Messages: 166
Registered: September 2014
Senior Member
Hi guys,

sorry for late response.

I´m trying to catch up the discussion:

1) Chris proposal for common configuration mechanism

In general it is something we can think about. But this would be major change to the framework and also makes the recent change about the handleConfigurationUpdate obsolete. I think it is also not that easy. The binding configuarion, which is at the moment handled by the OSGi config admin would be a case for another configuration. But here you have to take the lifecycle into account. What happens if the service is not yet present? You would begin to reimplement something like the configuration admin. Because of this we originally decided to not have a common configuration mechanism and just share the description.

2) Having config descriptions for Things

I think this is possible in general. But what you missed is the mapping between the URI and the thing UID. At the moment the thing type has a method getConfigDescriptionURI. We would need the same for the thing unless we assume an implicit mapping here. But question is, if you want to provide a specific ConfigDescription for a thing, how does the developer does it? In most cases it will be a variant of the Thing Type Config Description. So the binding developer has to register a ConfigDescriptionProvider, get the CD from the ThingType, modify it and return it. Possible, but sounds complex.

Moreover if you want to support dynamic option lists, but you don´t have a need to specify a specific thing CD, you are forced to do it, otherwise you don´t have the concrete context. This will make the implementation of dynamic value providers quite hard.

3) Proposal for a third option

I think what would work if we just introduce a context ID for the DynamicOptionProvider. So taking the initial interface and just adding a new parameter:

package org.eclipse.smarthome.config.core;

public interface ParameterOptionProvider {

    List<ParameterOption> getOptions(URI parameterURI, ContextID contextID /* or maybe UID contextUID */, Locale locale);

    Set<URI> getSupportedURIs();
}


We could introduce a new interface ContextID and UID will inherit from it or just us UID. But the binding id is not a UID for example.

We can have a generic REST endpoint an the UI just have to send the thingUID as context for thing configuration.

For me this seems to be a less invasive solution, than the other two

Regards

Dennis
Re: Dynamic configuration information [message #1704112 is a reply to message #1704102] Fri, 07 August 2015 11:30 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Quote:
Moreover if you want to support dynamic option lists, but you don´t have a need to specify a specific thing CD, you are forced to do it


I think you misunderstood my proposal here. I was talking about "a system service forwarding config description requests for a thing to its thing type" - so binding developers don't have to do anything here (and yes, this ThingConfigDescriptionProvider would have to use an implicit URI, most likely the ThingUID). To provide dynamic options, you would only have to implement a ParameterOptionProvider and register it for the ThingUID CD URI (maybe this could even be done by the framework automatically, if the ThingHandler implements this interface).

Your option 3 does a similar thing, but now somehow implicitly introduces CD variants, by returning different results for the same URI on different requests. How would you map that to the REST API? /thing-types/<type>/config/<context>? Simply offering /things/<thing>/config looks much cleaner to me.

Regards,
Kai
Re: Dynamic configuration information [message #1704123 is a reply to message #1704112] Fri, 07 August 2015 13:14 Go to previous messageGo to next message
Dennis Nobel is currently offline Dennis NobelFriend
Messages: 166
Registered: September 2014
Senior Member
Quote:
To provide dynamic options, you would only have to implement a ParameterOptionProvider and register it for the ThingUID CD URI (maybe this could even be done by the framework automatically, if the ThingHandler implements this interface).


I think typically you´ll have one implementation for a thing type, so you only need on service registration. This implementation must then permanently update the list of supported URIs. Or instead of getSupportedURIs we change it to a method "supportsURI", as we have for most of the other services. Implementation can just check for the thing type UID or the binding id. But with this it will be possibly work. Only the Paper UI needs to be adapted to use CD from thing instead of thing type (guess also HABmin would need an update).

Quote:
Your option 3 does a similar thing, but now somehow implicitly introduces CD variants, by returning different results for the same URI on different requests. How would you map that to the REST API? /thing-types/<type>/config/<context>? Simply offering /things/<thing>/config looks much cleaner to me.


No I was thinking of a general REST endpoint " /config/options/<configDescriptionURI>/<parameter>/<context>". The context parameter might be optional. This is a generic solution for all kind of dynamic value lists, not for thing types or things only. But a general REST endpoint should also work with your solution. The UI only needs to know, that it has to use the thing UID to build up the correct config description URI.
Re: Dynamic configuration information [message #1704125 is a reply to message #1704123] Fri, 07 August 2015 13:25 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Hm, I thought we once agreed that we do not want a general /config REST endpoint, but rather always only have configs underneath some entity. Or are you making a difference between configurations and configuration descriptions?
Re: Dynamic configuration information [message #1704133 is a reply to message #1704125] Fri, 07 August 2015 14:39 Go to previous messageGo to next message
Dennis Nobel is currently offline Dennis NobelFriend
Messages: 166
Registered: September 2014
Senior Member
Yes. I see the the list of valid options as part of the Config Description. It´s just something that is needed to render the UI. So it fit´s to the concept. The components to render UI input fields can be reused for binding or rule configuration in the future.

I also would introduce a ConfigDescription REST endpoint. As the CD is independent of things or anything else, there is no need to have specific endpoints. We just did not had the need so far, as I added config descriptions for convenient reasons to the ThingType. Maybe it should better have the URL " /config-description/options/<configDescriptionURI>/<parameter>/<context>" instead of "config/".

But at the end the config must be sent to a thing specific rest endpoint. So we have common mechanism for config descriptions and central place to get all config descriptions (ConfigDescriptionRegistry), but no central Configuration mechanism. At least this was the idea.
Re: Dynamic configuration information [message #1705416 is a reply to message #1704133] Fri, 14 August 2015 21:25 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
I think we do not need a url as " /config-description/options/<configDescriptionURI>/<parameter>/<context>" which specifically allows the UI to retrieve only the dynamic options. If the dynamic options are merged on the server side into the returned CD, this should imho be good enough.
This leaves us with the choice to either have "/config-description/<configDescriptionURIofThingType>/<context>" or to use "/config-description/<configDescriptionURIofThing>". The first option brings a bit more complexity into the REST interface as there are now two parameters passed in (thingTypeUID and context (which effectively is the thingUID in our case)), while the second option requires some implicit convention, namely that a Thing always has a CD URI that matches its ThingUID (which is otherwise not the case).
I am rather indifferent about these two options. @Chris, what do you prefer? Or do you even have any third option to consider?
Re: Dynamic configuration information [message #1709323 is a reply to message #1705416] Sat, 26 September 2015 09:40 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Sorry it's been a while getting back to this one...

I think it needs to be linked to the Thing rather than the ThingType since this is definately specific to a particular device (in zwave at least).

Chris
Re: Dynamic configuration information [message #1709577 is a reply to message #1709323] Tue, 29 September 2015 11:11 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Yes, I think both options that I mention make it possible to retrieve a config description specific for a thing. So it is rather a question, how the URL endpoint should be designed.
Re: Dynamic configuration information [message #1710130 is a reply to message #1709577] Sun, 04 October 2015 20:47 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Kai, is the intention that this is implemented as a separate service? So the REST interface queries the CD registry, then queries the option service, merges them and supplies them to the user? And then when you say "URL endpoint" - you're talking about a URI rather than a REST endpoint? (or do I get it wrong Smile ).
Re: Dynamic configuration information [message #1710165 is a reply to message #1710130] Mon, 05 October 2015 07:24 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Quote:
Kai, is the intention that this is implemented as a separate service? So the REST interface queries the CD registry, then queries the option service, merges them and supplies them to the user?


What exactly do you mean by separate service? I think it could be implemented directly in the CD registry, similar to what it currently does by merging multiple CDs into one. If a CD UID is requested that belongs to a Thing, it will take the CD of the thing type and merge it with the infos provided by the option providers.
Re: Dynamic configuration information [message #1710238 is a reply to message #1710165] Mon, 05 October 2015 13:20 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Aren't we then linking both thingTypes and things in the CD registry? ie we'd need to call the 'get config description' method with a thing URI rather than the thingType URI which I thought you wanted to avoid? (or maybe I'm confused Smile ).
Re: Dynamic configuration information [message #1710244 is a reply to message #1710238] Mon, 05 October 2015 13:44 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Maybe we are both confused Smile
Right, Dennis point was that the CDR should not have any dependencies to Things or Thing types, so the code must not be in the registry itself.
Still, we can implement a ConfigDescriptionProvider, which provides CDs for URIs of Things and which internally delegates the call to the thing type and merges it with the options. Wouldn't that work?
Re: Dynamic configuration information [message #1710251 is a reply to message #1710244] Mon, 05 October 2015 14:11 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
So you mean call the registry with the URI of the thing instead of the thingType, and then just have an implementation of a CD provider in the binding that knows it's looking at things rather than thingTypes? I guess that works, but seems a bit "bodgy".
Re: Dynamic configuration information [message #1710255 is a reply to message #1710251] Mon, 05 October 2015 14:38 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Well, the implementation will depend on which version of the URI (https://www.eclipse.org/forums/index.php?t=msg&th=1066227&goto=1705416&#msg_1705416) we decide to use. So what is your favorite?
Re: Dynamic configuration information [message #1710260 is a reply to message #1710255] Mon, 05 October 2015 14:58 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
The first option with the two parameters seems more structured to me?
Re: Dynamic configuration information [message #1710261 is a reply to message #1710260] Mon, 05 October 2015 15:09 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Why more structured? It is more verbose as it duplicates information (the thing type), with the potential problem that the thing you provide as context is actually of a different thing type than the one you list in the url...
I think it would be more straight forward to simply request CDs for things and that's it.
Re: Dynamic configuration information [message #1710266 is a reply to message #1710261] Mon, 05 October 2015 15:27 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
It just feels like it makes the distinction between the two calls - a thing and a thingType - a bit clearer?

At the end of the day though I don't mind - they are almost the same as far as implementation...
Re: Dynamic configuration information [message #1710344 is a reply to message #1710266] Tue, 06 October 2015 07:59 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Maybe a direct example is better. According to https://www.eclipse.org/smarthome/documentation/development/bindings/xml-reference.html, the CD URI looks like this in a REST uri:

thing type:
/config-descriptions/thing-type:hue:bridge


Thing:
/config-descriptions/thing:hue:bridge:1


Something else:
/config-descriptions/something:myuniqueid

Re: Dynamic configuration information [message #1710736 is a reply to message #1710344] Thu, 08 October 2015 18:28 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
I'm not really sure what you're trying to show in the example? I understand the URI, and I understand what the thing URI, but what is the relationship to your 'something else' with respect to the options?
Re: Dynamic configuration information [message #1710951 is a reply to message #1710736] Sun, 11 October 2015 18:21 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
I just wanted to make clear the the config-descriptions url is a generic one, which is independent from things, types etc. And that from the url, you can already clearly distinguish between an url for a thing and the url for a thing type.
Re: Dynamic configuration information [message #1711088 is a reply to message #1710951] Mon, 12 October 2015 21:49 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Ok, I understood that before the confusion Smile

So where do we go from here? Personally, I don't mind which solution is implemented, but it would be good to get this functionality into the system...
Re: Dynamic configuration information [message #1711309 is a reply to message #1711088] Wed, 14 October 2015 20:09 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Ok, so we all agree about the general concept, hence all we need is a volunteer to create a PR for it. I won't have the chance in the next weeks for it, so either jump on it yourself or try to convince Dennis Smile
Re: Dynamic configuration information [message #1711569 is a reply to message #1711309] Sat, 17 October 2015 13:06 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
I'll take a look at it over the weekend hopefully....
Re: Dynamic configuration information [message #1711614 is a reply to message #1711569] Sun, 18 October 2015 11:24 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
I've now implemented 'something' Smile

I've added a ConfigOptionProvider to the config.core -:

public interface ConfigOptionProvider {
    Collection<ParameterOption> getParameterOptions(URI uri, String param, Locale locale);
}


Then in the ConfigDescriptionRegistry I've added new methods -:
    public ConfigDescription getConcreteConfigDescription(URI configUri, URI concreteUri);
    public ConfigDescription getConcreteConfigDescription(URI configUri, URI concreteUri, Locale locale);


Currently the user would need to statically register the service - I did consider adding something into the ThingManager to do this automatically if the thing handler implements this interface. I think this possible, but it's maybe something for later (I don't need this for zwave at least)

I decided to split the two URIs rather than derive one from the other as it's not simple to do this - you need to remove the ID off the end, but also modify the initial part of the URI. To use Kais example above -:

thing-type:hue:bridge
thing:hue:bridge:1


So to derive the thing from the thing-type, I need to remove the id, and change 'thing-type' to thing. Maybe we could have made some assumptions about the format of thing-type/thing but this becomes another constraint when using the CDs.

This leaves the implementation of the config descriptions and the concrete implementation up to implementation rather than using assumptions and constraining implementation.

The next problem is that (currently) config descriptions are served up through the thing-type REST interface and this is no longer appropriate as we also need to pass in the URI of the thing. I have therefore added a GET thing/{thingUID}/config interface.

This is (IMHO) also nice in that the REST interface for thing configuration is then GET thing/{thingUID}/config and PUT thing/{thingUID}/config.

In the REST interface, the code gets the thing-type CD URI, and passes the thing URI as the concrete implementation -:

getConcreteConfigDescription("thing-type:hue:bridge", "hue:bridge:1");


If this is broadly inline with what you were thinking, I'll create an initial PR. I've not added any tests yet, and also not tested it properly in the zwave binding (it's just hacked in at the moment), but at least you can comment on what I've done...

Chris
Re: Dynamic configuration information [message #1711618 is a reply to message #1711614] Sun, 18 October 2015 12:33 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
I've created https://github.com/eclipse/smarthome/pull/495 for comment...
Re: Dynamic configuration information [message #1711637 is a reply to message #1711618] Sun, 18 October 2015 20:28 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Quote:
I have therefore added a GET thing/{thingUID}/config interface.


I am either missing something important here or you are mixing something up.
All discussion was around /config-description/... urls, why are you now introducing a things/{thingUID}/config url? This is the right url for Configurations, but not for ConfigDescriptions.
I am feeling a bit lost...
Re: Dynamic configuration information [message #1711638 is a reply to message #1711637] Sun, 18 October 2015 20:35 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
What REST interface would you expect? Currently, the CD is provided through the GET /thingtype/{thingTypeID} interface, however now we need a specific CD for an actual thing - not the thing type. This is needed as the options will be different for each thing.

As above, I thought it was a bad idea to use the same interface (ie the thing-type interface) and instead change it to provide a CD for a specific thing.

I'm open to suggestions, but I thought we agreed above that the CD needed to be linked to the thing, not the thing type, so I'm not sure what API you would like to expose?
Re: Dynamic configuration information [message #1711640 is a reply to message #1711638] Sun, 18 October 2015 20:42 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Sorry - re-reading, are you expecting a new REST interface for GET /config-description/{uid} ? I'm happy to change to this, but I'm not sure if we can actually make a generic interface at REST level - the implementation is generic, but something needs to decide how to interpret the generic and concrete URIs. We could do this in the UI, but it doesn't seem nice.

To me, having the GET thing/{thingUID}/config alongside the PUT thing/{thingUID}/config which is already implemented seems logical?
Re: Dynamic configuration information [message #1711802 is a reply to message #1711640] Mon, 19 October 2015 20:00 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Correct, I am following Dennis' arguments from https://www.eclipse.org/forums/index.php?t=msg&th=1066227&goto=1704133&#msg_1704133 here which I think make sense.
I do not see any reasons why it should not be possible to implement this as a generic service as neither the CDProviders nor the OptionProviders have any dependency to a specific type of entity.
Maybe this is a good time for Dennis to join the discussion again Smile
Re: Dynamic configuration information [message #1711804 is a reply to message #1711802] Mon, 19 October 2015 20:31 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Quote:

I do not see any reasons why it should not be possible to implement this as a generic service as neither the CDProviders nor the OptionProviders have any dependency to a specific type of entity.

Absolutely - and this is what I've done. The provider is absolutely type agnostic and the implementation of the provider is not type dependant.

However, as I mentioned above, we are now working on a concrete implementation, so in the REST interface (or somewhere!) we need to pass (for example) the thing URI, and the thing-type URI since the resulting ConfigDescription is a combination of the two. Or, we perform a conversion between them but here we would need to constrain the way CDs and concrete URIs are defined so that there's a standard conversion between them.

To me, there are 3 options -:


  • A generic REST interface, and have the conversion between CD URI and concrete URI performed in the UI (and the UI passes both the type, and the concrete URI).
  • A generic implementation, but a specific REST interface that knows how to convert the CD URI and concrete URI for the specific data type (and the UI passes just the concrete URI)
  • A generic implementation and generic REST, but somehow constraining the conversion from CD URI to concrete URI (and the UI passes just the concrete URI)


I chose the second option as I think requiring the UI to know how to do the conversion is wrong, and constraining the URIs also doesn't seem like a good idea.

Or... Maybe I misunderstand something and am missing the point somewhere? Smile

Re: Dynamic configuration information [message #1711811 is a reply to message #1711804] Mon, 19 October 2015 21:04 Go to previous messageGo to next message
Dennis Nobel is currently offline Dennis NobelFriend
Messages: 166
Registered: September 2014
Senior Member
Quote:

* A generic REST interface, and have the conversion between CD URI and concrete URI performed in the UI (and the UI passes both the type, and the concrete URI).
* A generic implementation, but a specific REST interface that knows how to convert the CD URI and concrete URI for the specific data type (and the UI passes just the concrete URI)
* A generic implementation and generic REST, but somehow constraining the conversion from CD URI to concrete URI (and the UI passes just the concrete URI)


I thought we agreed on option 3, which means:

* No additional REST interface
* No additional public API
* But UIs have to change behaviour to request a thing specific CD instead of thing type.
* So UIs will call "rest/config-descriptions/thing:mybinding:mythingtype:thingid" where "thing:mybinding:mythingtype:thingid" is the Config Description URI for a concrete thing
* A default implementation (this can be thing specific e.g. ThingDelegatingConfigDescrptionProvider) will delegate to "thing-type:mybinding:mythingtype". Yes you have to transform the URI, but this shouldn´t be a big deal. The ConfigDescriptionProvider only checks for "thing-type" URIs and therefore will not cause any problems for other ConfigDescriptionProviders

In general this has nothing to do with dynamic options, but gives a binding in general the possibility to add thing specific configuration. This was one additional requirement as far as I know.

Moreover we will introduce the interface "ConfigOptionProvider" to allow an override of the static values. I guess only the ConfigDescriptionRegistry could perfom the resolvement. Therefore it has to subscribe for ConfigOptionProvider OSGi services and if there is such for a concrete URI, it has to change the values before it gives out the object.

With this approach we solve two problems: Thing specific ConfigDescriptions and dynamic option list either for thing types or things.

This was my understanding of the discussion.

Regards

Dennis
Re: Dynamic configuration information [message #1711812 is a reply to message #1711811] Mon, 19 October 2015 21:09 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Yes, this is also my understanding.
What might irritate Chris though is the fact that the url /rest/config-descriptions does not exist yet - this is something that anyhow should be introduced (and is a prerequisite for this feature then).
Re: Dynamic configuration information [message #1711813 is a reply to message #1711812] Mon, 19 October 2015 21:16 Go to previous messageGo to next message
Dennis Nobel is currently offline Dennis NobelFriend
Messages: 166
Registered: September 2014
Senior Member
Yes I agree, the REST endpoint does not exist has to be introduced. Even if we do not change the Java API it has impact on the Paper UI. The way how and when config description are requested definitely needs to be changed.
Re: Dynamic configuration information [message #1711815 is a reply to message #1711811] Mon, 19 October 2015 21:30 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Quote:

No additional REST interface

But the /config-description REST interface doesn't exist now does it? So you mean you want this interface added but no other interface? (sorry - confused!)

Quote:

A default implementation

So how does this actually work? In the REST interface, we pass the thing URI (or another concrete URI). In the /config-description REST interface, it detects the URI is a thing (somehow?) and gets the thing-type URI (which can not currently be derived from the thing URI).

Quote:

Moreover we will introduce the interface "ConfigOptionProvider"

This is what I've implemented...


Quote:

Yes you have to transform the URI, but this shouldn´t be a big deal.

How do you propose to do this? You need to derive the type from the concrete URI which I don't think is possible at the moment without calling thing.getConfigURI (for things at least). Do we now assume that the type and concrete URI are directly derivable?

So, we have to have a system that can take the thing URI (thing:hue:bridge:1) and convert to the thing-type URI (thing-type:hue:bridge). I agree that this isn't difficult, but it is not how it's currently implemented. Do you want to define a class within the REST interface that knows these conversions - again, this is what I've basically done, I've just used a specific REST API.

You and Kai are obviously discussing this, but I'm obviously not clear on exactly how you see this implemented. Maybe you should review what I've implemented as I think it's 90% the same as you want, it's just the REST API that's different (I hope Smile ).

Chris

Re: Dynamic configuration information [message #1711816 is a reply to message #1711815] Mon, 19 October 2015 21:35 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Quote:

What might irritate Chris though is the fact that the url /rest/config-descriptions does not exist yet

Not 'irritate' but certainly confuse when everyone keeps talking about there being 'no additional REST interface' Smile

Quote:

The way how and when config description are requested definitely needs to be changed.

Absolutely - this needs to change. I think what I've implemented is what you want - it's just the REST API that isn't consistent with your thoughts. Personally, I still think that it's clearer and cleaner to use an interface through the /thing API, but if you think otherwise, then no problem... It's only a few lines of code in the REST API that is thing specific - everything below that is generic.........
Re: Dynamic configuration information [message #1712056 is a reply to message #1711816] Wed, 21 October 2015 06:43 Go to previous messageGo to next message
Dennis Nobel is currently offline Dennis NobelFriend
Messages: 166
Registered: September 2014
Senior Member
Quote:
Not 'irritate' but certainly confuse when everyone keeps talking about there being 'no additional REST interface' Smile


OK sorry for that - indeed confusing. I meant we don´t have to introduce an additional API, we just have to expose the existing ConfigDescriptionRegistry.

Quote:
How do you propose to do this? You need to derive the type from the concrete URI which I don't think is possible at the moment without calling thing.getConfigURI (for things at least). Do we now assume that the type and concrete URI are directly derivable?


The structure of a Thing UID always contains the Thing Type UID. So we can grep it without making assumptions. With this thing type UID you can get a thing type from the ThingTypeRegistry and get the concrete ConfigDescriptionURI from it. Then you can just delegate the call to the existing ConfigDescriptionProviders (Mostly the XMLConfigDescirptionProvider). I don´t see a problem there and we don´t make any assumptions.

Quote:
I think what I've implemented is what you want - it's just the REST API that isn't consistent with your thoughts. [...] It's only a few lines of code in the REST API that is thing specific - everything below that is generic


But the REST Api don´t have to be thing specific, so I would really prefer to just give in the Thing UID and internally delegating it to the Thing Type CD, if no other ConfigDescription exists.
Re: Dynamic configuration information [message #1712108 is a reply to message #1712056] Wed, 21 October 2015 10:50 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Quote:

The structure of a Thing UID always contains the Thing Type UID. So we can grep it without making assumptions

Yes, I know, but my point was that if you are making a completely generic REST interface, then you can't make this assumption since to do this you already know you're dealing with a thing. What you are (I think?) actually saying is that there is only a simgle REST endpoint, but the implementation gets programmed to know about things, channels, rules (or anything else that might use CDs) - as per my option 2 below. This isn't quite the definition of generic that I had in mind since the implementation still has to know what's happening.

Quote:

But the REST Api don´t have to be thing specific, so I would really prefer to just give in the Thing UID and internally delegating it to the Thing Type CD, if no other ConfigDescription exists.

This is what I've done, but something still needs to convert the thing to thing type...

Maybe I try and explain in psuedo code...

Option 1:

// Reset API for GET /thing/ThingUID/config
getThingConfig(thingURI) {
  thingTypeURI = thingRegistry.getThing(thingURI).getConfigURI();
  ConfigDescription cd = configRegistry.getConcreteConfigDescription(thingTypeURI, thingURI);
  return cd; // REST response
}


This would then get repeated for the different types of data using the CD (rules, channels, things....) this different REST endpoint.


Option 2 -:
// Reset API for GET /config-description/UID
getGenericConfig(genericURI) {
  // Detect the type of the URI
  if(type of URI is thing) {
    typeURI = thingRegistry.getThing(genericURI).getConfigURI();
  }

  else if(type of URI is channel) {
    typeURI = channelRegistry.getChannel(genericURI).getConfigURI();
  }

  // repeated for other types
  ....

  ConfigDescription cd = configRegistry.getConcreteConfigDescription(typeURI, genericURI);
  return cd; // REST response
}

This option could be implemented slightly differently than calling the getConfigURI which is available for things - we could make some assumption about the mapping of thingTypes and things which I think Kai suggested, but ultimately the implementation looks pretty similar to the psuedo code...

Or... Do you have an option 3?

What I've currently implemented is option 1, and what I think you're suggesting is option 2? Is that correct or am I still missing something? At the end of the day, the low level implementation (ie the getConcreteConfigDescription method) is the same - it's just the REST endpoint and implementation that's changing.

To me, option 1 is cleaner. In my opinion, neither option is 100% generic and it's cleaner to make the clear distinction rather than make the code implementing the endpoint messy. However, if you think option 2 is better, then I don't mind...
Re: Dynamic configuration information [message #1712181 is a reply to message #1712108] Wed, 21 October 2015 19:03 Go to previous messageGo to next message
Dennis Nobel is currently offline Dennis NobelFriend
Messages: 166
Registered: September 2014
Senior Member
Yes, I see Option 3):

Just implement a ConfigDescriptionProvider and register it as OSGi service (probably named ThingConfigDescriptionProvider). The REST interface calls the ConfigDescriptionRegistry, which calls every ConfigDescriptionProvider. Nothing has to be changed there. The ThingConfigDescriptionProvider checks if the URI is a thing URI (begins with "thing:") and then does transformation looks up the thing type URI and delegates it to the other ConfigDescriptionProviders. For all other URIs it returns null.
Re: Dynamic configuration information [message #1712187 is a reply to message #1712181] Wed, 21 October 2015 19:59 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Do you want all this registered in the REST resource (ie the new /config-description), or do you want the REST resource and the ThingConfigDescriptionProvider split across multiple sources/packages?

Do you still want the ConfigOptionProvider type interface as discussed previously - if so, I'm not sure how this fits in as it sounds from your explanation above that there are no changes to the ConfigDescriptionRegistry (you say "nothing has to change there"). If we don't change the service registry, then how do you propose to merge options? Do we just assume that if multiple ConfigDescriptionProviders return the same config descriptions that we merge them together? Previously we've said multiple providers are not allowed to return the same descriptions (ie with the same name) - can you confirm how this is merged (are we now just allowing two providers to return data for the same config description so long as one only returns config options?
Re: Dynamic configuration information [message #1712198 is a reply to message #1712187] Wed, 21 October 2015 21:03 Go to previous messageGo to next message
Dennis Nobel is currently offline Dennis NobelFriend
Messages: 166
Registered: September 2014
Senior Member
Quote:
Do you want all this registered in the REST resource (ie the new /config-description), or do you want the REST resource and the ThingConfigDescriptionProvider split across multiple sources/packages?


I think the REST resource can really simply delegate the calls "getConfigDescription" and "getConfigDescriptions". The ThingConfigDescriptionProvider should go into the org.eclipse.smarthome.thing.internal package.

Quote:
Do you still want the ConfigOptionProvider type interface as discussed previously - if so, I'm not sure how this fits in as it sounds from your explanation above that there are no changes to the ConfigDescriptionRegistry (you say "nothing has to change there")


OK, sorry for confusing you again. I try to be more precise: We don´t have to change it for the feature "thing specific config descriptions". For the other requirement (which this topic is about) of course we need to add logic into the ConfigDescriptionRegistry. We should still use the interface and just request ConfigOptions from all ConfigOptionProvider and merge that together. Please read https://www.eclipse.org/forums/index.php?t=msg&th=1066227&goto=1711811&#msg_1711811 again:

Moreover we will introduce the interface "ConfigOptionProvider" to allow an override of the static values. I guess only the ConfigDescriptionRegistry could perfom the resolvement. Therefore it has to subscribe for ConfigOptionProvider OSGi services and if there is such for a concrete URI, it has to change the values before it gives out the object.
Re: Dynamic configuration information [message #1713897 is a reply to message #1712198] Sat, 07 November 2015 17:40 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Ok, just getting back this one...

I've implemented the ThingConfigDescriptionProvider as suggested, but have a question on how you would prefer the implementation, since I don't think the ConfigOptionProvider service is really necessary now (even though I implemented it first time around).

With the ConfigOptionProvider service we have to register a new service for each thing that wants to implement configurable options - or - we register the service for the binding and let the binding sort out the thing. Either way, it's another service to register - in itself this is not a problem, but when we come to resolve options, we need to loop through all the option providers to find the one we're looking for... This is going to get slow - we already have to loop through the ConfigDescriptionProviders list twice (once to get the thingType, and the other to get the thing).

The other option which I think is simpler is in the ThingConfigDescriptionProvider.getConfigDescription method, we already get the thing - we could easily perform a check to see if a specific interface is implemented (ConfigOptionProvider interface) and if it is, then we call thing.getConfigOption(Parameter p);.

In my opinion, this is simpler for binding implementers (they just need to implement an interface) and it's quicker as we don't have to loop through another list of providers. It doesn't (IMHO) break the requirement not to link the CD with a specific type (ie things in this case) since that is handled within the ThingConfigDescriptionProvider which is by design providing this link.

Does that sound ok? The only downside that I can see is it doesn't allow multiple dynamic option providers. It allows options from the CD providers, and the thing to be merged (so we still have static and dynamic options) but it doesn't allow multiple sources of options for a thing. Personally I can't see why this would be necessary?

I'll update the PR on this basis and we can discuss further since at the end of the day either implementation is ok by me.

Chris
Re: Dynamic configuration information [message #1714073 is a reply to message #1713897] Mon, 09 November 2015 17:31 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
Thanks, Chris.

I mainly see two downsides of this implementation option:
1. It requires the handler to be available. But I assume this is a fair assumption as this is likely anyhow in the same bundle as an registered OptionProvider would be.
2. We do not have a general solution, i.e. we cannot simply register a ConfigOptionProvider as a service for certain configURIs and have it working right away. Where ever we want to use this feature, we would have to specifically implement it (as you did within the ThingConfigDescriptionProvider. As long as we only want to do it for Things, this looks ok. But I am a bit worried if we might not regret it some when in the future (e.g. already for the rule engine)...

So to answer your concerns about the more generic option: It definitely should only be one ConfigOptionProvider service per binding, not one per entity. And as it won't be too many bindings using this feature, we might have a handful of services to iterate through. Since requesting config descriptions is not a very regular operation (rather a one time call triggered through the UI), I don't think that performance is something we need to worry about here.

Kai
Re: Dynamic configuration information [message #1714079 is a reply to message #1714073] Mon, 09 November 2015 18:02 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Quote:

It requires the handler to be available. But I assume this is a fair assumption as this is likely anyhow in the same bundle as an registered OptionProvider would be.

Yes - my assumption is that whatever we want to provide the options, is in some way linked to the handler - or at least the binding, since dynamic option information is most likely (or only?) going to come from something with detailed knowledge of the concrete implementation (be it a thing, or rule, or ...).

Quote:

We do not have a general solution,

Ok - this is a fair point...

I'll change it back to the previous implementation with the ConfigOptionProvider service...
Re: Dynamic configuration information [message #1714102 is a reply to message #1714079] Mon, 09 November 2015 22:26 Go to previous messageGo to next message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Sorry - there's another problem with this concept Sad

We can add the ConfigOptionsProvider into the ConfigDescriptionRegistry - this works fine and provides a generic interface. However, it now doesn't work for the ThingConfigDescriptionProvider....

The problem with the ThingConfigDescriptionProvider is that it needs to get the config description for the thing-type. So, it intercepts the call for the thing, gets the thing-type, and re-calls the ConfigDescriptionRegistry. Because the CD comes from the URI of the thing-type, and the options comes the URI of the thing, it's not possible to combine them within the Registry. This is of course a specific case where we have this proxy provider...

There are a few options that I can see (although I'm sure you'll think of another !Smile )...

1. We could use the interface option as per my current PR - leaving the internal methods as well so that it works generically for types that don't require this conversion.
2. We find some way to combine parameters, and then use a public method in the registry to add the options
3. We completely change the CD provider to support this (!!)
4. Your option here...

#2 sounds horrible - calling back into the provider doesn't sound nice, and #4 is I'm sure out of the question (it's not a serious option!)....
#4 I'm sure is best Smile



Re: Dynamic configuration information [message #1714103 is a reply to message #1714102] Mon, 09 November 2015 22:34 Go to previous messageGo to next message
Kai Kreuzer is currently offline Kai KreuzerFriend
Messages: 673
Registered: December 2011
Senior Member
ok, then let me try #4:
- you call ConfigDescriptionRegistry.get("thing:x:y")
- it finds the ThingConfigDescriptionProvider providing CDs for thing:x:y and calls it
- the ThingConfigDescriptionProvider resolved the thing-type x and retrieves the CD for it
- the ThingConfigDescriptionProvider returns the CD to the ConfigDescriptionRegistry (it does NOT have any custom options yet)
- the ConfigDescriptionRegistry sees that there are ConfigOptionsProviders for thing:x:y and merges their options into the CD before returning it to the caller.

Am I missing some point...?
Re: Dynamic configuration information [message #1714629 is a reply to message #1714103] Sat, 14 November 2015 09:59 Go to previous message
Chris Jackson is currently offline Chris JacksonFriend
Messages: 256
Registered: December 2013
Senior Member
Sorry Kai,
You're right - I didn't look at what was happening well enough. I'd done something wrong in the zwave options handler with the processing of the URI - I've fixed this now and it works so I'll update the PR...

Cheers
Chris
Previous Topic:Minimal set of ESM bundles?
Next Topic:Cannot resolve project dependencies: org.eclipse.xtend.lib.macro
Goto Forum:
  


Current Time: Thu Apr 25 06:24:08 GMT 2024

Powered by FUDForum. Page generated in 0.08052 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top